llvm.org GIT mirror llvm / 98c86d7
Allow the use of functions as typeinfo in landingpad clauses This is one step towards supporting SEH filter functions in LLVM. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221954 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 5 years ago
9 changed file(s) with 83 addition(s) and 29 deletion(s). Raw diff Collapse all Expand all
2121 #include "llvm/IR/Instructions.h"
2222
2323 namespace llvm {
24 class GlobalVariable;
24 class GlobalValue;
2525 class TargetLoweringBase;
2626 class TargetLowering;
2727 class TargetMachine;
5858 uint64_t StartingOffset = 0);
5959
6060 /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V.
61 GlobalVariable *ExtractTypeInfo(Value *V);
61 GlobalValue *ExtractTypeInfo(Value *V);
6262
6363 /// hasInlineAsmMemConstraint - Return true if the inline asm instruction being
6464 /// processed uses a memory 'm' constraint.
126126 unsigned CurCallSite;
127127
128128 /// TypeInfos - List of C++ TypeInfo used in the current function.
129 std::vectorriable *> TypeInfos;
129 std::vectorlue *> TypeInfos;
130130
131131 /// FilterIds - List of typeids encoding filters used in the current function.
132132 std::vector FilterIds;
300300 /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad.
301301 ///
302302 void addCatchTypeInfo(MachineBasicBlock *LandingPad,
303 ArrayRefriable *> TyInfo);
303 ArrayReflue *> TyInfo);
304304
305305 /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad.
306306 ///
307307 void addFilterTypeInfo(MachineBasicBlock *LandingPad,
308 ArrayRefriable *> TyInfo);
308 ArrayReflue *> TyInfo);
309309
310310 /// addCleanup - Add a cleanup action for a landing pad.
311311 ///
313313
314314 /// getTypeIDFor - Return the type id for the specified typeinfo. This is
315315 /// function wide.
316 unsigned getTypeIDFor(const GlobalVariable *TI);
316 unsigned getTypeIDFor(const GlobalValue *TI);
317317
318318 /// getFilterIDFor - Return the id of the filter encoded by TyIds. This is
319319 /// function wide.
374374
375375 /// getTypeInfos - Return a reference to the C++ typeinfo for the current
376376 /// function.
377 const std::vectorriable *> &getTypeInfos() const {
377 const std::vectorlue *> &getTypeInfos() const {
378378 return TypeInfos;
379379 }
380380
108108 }
109109
110110 /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V.
111 GlobalVariable *llvm::ExtractTypeInfo(Value *V) {
111 GlobalValue *llvm::ExtractTypeInfo(Value *V) {
112112 V = V->stripPointerCasts();
113 GlobalVariable *GV = dyn_cast(V);
114
115 if (GV && GV->getName() == "llvm.eh.catch.all.value") {
116 assert(GV->hasInitializer() &&
113 GlobalValue *GV = dyn_cast(V);
114 GlobalVariable *Var = dyn_cast(V);
115
116 if (Var && Var->getName() == "llvm.eh.catch.all.value") {
117 assert(Var->hasInitializer() &&
117118 "The EH catch-all value must have an initializer");
118 Value *Init = GV->getInitializer();
119 GV = dyn_cast(Init);
119 Value *Init = Var->getInitializer();
120 GV = dyn_cast(Init);
120121 if (!GV) V = cast(Init);
121122 }
122123
107107 }
108108
109109 void ARMException::emitTypeInfos(unsigned TTypeEncoding) {
110 const std::vectorriable *> &TypeInfos = MMI->getTypeInfos();
110 const std::vectorlue *> &TypeInfos = MMI->getTypeInfos();
111111 const std::vector &FilterIds = MMI->getFilterIds();
112112
113113 bool VerboseAsm = Asm->OutStreamer.isVerboseAsm();
120120 Entry = TypeInfos.size();
121121 }
122122
123 for (std::vectorriable *>::const_reverse_iterator
123 for (std::vectorlue *>::const_reverse_iterator
124124 I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) {
125 const GlobalVariable *GV = *I;
125 const GlobalValue *GV = *I;
126126 if (VerboseAsm)
127127 Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--));
128128 Asm->EmitTTypeReference(GV, TTypeEncoding);
313313 /// 3. Type ID table contains references to all the C++ typeinfo for all
314314 /// catches in the function. This tables is reverse indexed base 1.
315315 void EHStreamer::emitExceptionTable() {
316 const std::vectorriable *> &TypeInfos = MMI->getTypeInfos();
316 const std::vectorlue *> &TypeInfos = MMI->getTypeInfos();
317317 const std::vector &FilterIds = MMI->getFilterIds();
318318 const std::vector &PadInfos = MMI->getLandingPads();
319319
648648 }
649649
650650 void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) {
651 const std::vectorriable *> &TypeInfos = MMI->getTypeInfos();
651 const std::vectorlue *> &TypeInfos = MMI->getTypeInfos();
652652 const std::vector &FilterIds = MMI->getFilterIds();
653653
654654 bool VerboseAsm = Asm->OutStreamer.isVerboseAsm();
661661 Entry = TypeInfos.size();
662662 }
663663
664 for (std::vectorriable *>::const_reverse_iterator
664 for (std::vectorlue *>::const_reverse_iterator
665665 I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) {
666 const GlobalVariable *GV = *I;
666 const GlobalValue *GV = *I;
667667 if (VerboseAsm)
668668 Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--));
669669 Asm->EmitTTypeReference(GV, TTypeEncoding);
426426 ///
427427 void MachineModuleInfo::
428428 addCatchTypeInfo(MachineBasicBlock *LandingPad,
429 ArrayRefriable *> TyInfo) {
429 ArrayReflue *> TyInfo) {
430430 LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
431431 for (unsigned N = TyInfo.size(); N; --N)
432432 LP.TypeIds.push_back(getTypeIDFor(TyInfo[N - 1]));
436436 ///
437437 void MachineModuleInfo::
438438 addFilterTypeInfo(MachineBasicBlock *LandingPad,
439 ArrayRefriable *> TyInfo) {
439 ArrayReflue *> TyInfo) {
440440 LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
441441 std::vector IdsInFilter(TyInfo.size());
442442 for (unsigned I = 0, E = TyInfo.size(); I != E; ++I)
505505
506506 /// getTypeIDFor - Return the type id for the specified typeinfo. This is
507507 /// function wide.
508 unsigned MachineModuleInfo::getTypeIDFor(const GlobalVariable *TI) {
508 unsigned MachineModuleInfo::getTypeIDFor(const GlobalValue *TI) {
509509 for (unsigned i = 0, N = TypeInfos.size(); i != N; ++i)
510510 if (TypeInfos[i] == TI) return i + 1;
511511
482482
483483 // Gather all the type infos for this landing pad and pass them along to
484484 // MachineModuleInfo.
485 std::vectorriable *> TyInfo;
485 std::vectorlue *> TyInfo;
486486 unsigned N = I.getNumArgOperands();
487487
488488 for (unsigned i = N - 1; i > 1; --i) {
540540 Value *Val = I.getClause(i - 1);
541541 if (I.isCatch(i - 1)) {
542542 MMI.addCatchTypeInfo(MBB,
543 dyn_castriable>(Val->stripPointerCasts()));
543 dyn_castlue>(Val->stripPointerCasts()));
544544 } else {
545545 // Add filters in a list.
546546 Constant *CVal = cast(Val);
547 SmallVectorriable*, 4> FilterList;
547 SmallVectorlue*, 4> FilterList;
548548 for (User::op_iterator
549549 II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II)
550 FilterList.push_back(castriable>((*II)->stripPointerCasts()));
550 FilterList.push_back(castlue>((*II)->stripPointerCasts()));
551551
552552 MMI.addFilterTypeInfo(MBB, FilterList);
553553 }
48464846
48474847 case Intrinsic::eh_typeid_for: {
48484848 // Find the type id for the given typeinfo.
4849 GlobalVariable *GV = ExtractTypeInfo(I.getArgOperand(0));
4849 GlobalValue *GV = ExtractTypeInfo(I.getArgOperand(0));
48504850 unsigned TypeID = DAG.getMachineFunction().getMMI().getTypeIDFor(GV);
48514851 Res = DAG.getConstant(TypeID, MVT::i32);
48524852 setValue(&I, Res);
0 ; RUN: llc -mtriple x86_64-pc-linux-gnu < %s | FileCheck %s
1
2 ; This test demonstrates that it is possible to use functions for typeinfo
3 ; instead of global variables. While __gxx_personality_v0 would never know what
4 ; to do with them, other EH schemes such as SEH might use them.
5
6 declare i32 @__gxx_personality_v0(...)
7 declare void @filt0()
8 declare void @filt1()
9 declare void @_Z1fv()
10 declare i32 @llvm.eh.typeid.for(i8*)
11
12 define i32 @main() uwtable {
13 entry:
14 invoke void @_Z1fv()
15 to label %try.cont unwind label %lpad
16
17 try.cont:
18 ret i32 0
19
20 lpad:
21 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
22 catch i8* bitcast (void ()* @filt0 to i8*)
23 catch i8* bitcast (void ()* @filt1 to i8*)
24 %sel = extractvalue { i8*, i32 } %0, 1
25 %id0 = call i32 @llvm.eh.typeid.for(i8* bitcast (void ()* @filt0 to i8*))
26 %is_f0 = icmp eq i32 %sel, %id0
27 br i1 %is_f0, label %try.cont, label %check_f1
28
29 check_f1:
30 %id1 = call i32 @llvm.eh.typeid.for(i8* bitcast (void ()* @filt1 to i8*))
31 %is_f1 = icmp eq i32 %sel, %id1
32 br i1 %is_f1, label %try.cont, label %eh.resume
33
34 eh.resume:
35 resume { i8*, i32 } %0
36 }
37
38 ; CHECK-LABEL: main:
39 ; CHECK: .cfi_startproc
40 ; CHECK: .cfi_personality 3, __gxx_personality_v0
41 ; CHECK: .cfi_lsda 3, .Lexception0
42 ; CHECK: .cfi_def_cfa_offset 16
43 ; CHECK: callq _Z1fv
44 ; CHECK: retq
45 ; CHECK: cmpl $2, %edx
46 ; CHECK: je
47 ; CHECK: cmpl $1, %edx
48 ; CHECK: je
49 ; CHECK: callq _Unwind_Resume
50 ; CHECK: .cfi_endproc
51 ; CHECK: GCC_except_table0:
52 ; CHECK: Lexception0: