annotate ir/irlandingpad.cpp @ 355:d8357f7004ca trunk

[svn r376] Fix bug with finally blocks and labels. The labels would get emitted multiple times and conflict. It is now possible to add label scopes in IrFunction and all labels names will be prefixed accordingly. Also disallow goto into finally blocks. Fixes nocompile/finally_02 and others.
author ChristianK
date Mon, 14 Jul 2008 11:48:55 +0200
parents d22d8d63c1fd
children 672eb4893b55
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
319
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
1 #include "gen/llvm.h"
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
2 #include "gen/tollvm.h"
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
3 #include "gen/irstate.h"
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
4 #include "gen/runtime.h"
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
5 #include "gen/logger.h"
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
6 #include "gen/classes.h"
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
7 #include "gen/llvmhelpers.h"
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
8 #include "ir/irlandingpad.h"
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
9
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
10 IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
11 : finallyBody(NULL)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
12 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
13 target = llvm::BasicBlock::Create("catch", gIR->topfunc(), end);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
14 gIR->scope() = IRScope(target,end);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
15
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
16 // assign storage to catch var
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
17 if(catchstmt->var) {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
18 assert(!catchstmt->var->ir.irLocal);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
19 catchstmt->var->ir.irLocal = new IrLocal(catchstmt->var);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
20 LLValue* catch_var = gIR->func()->landingPad.getExceptionStorage();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
21 catchstmt->var->ir.irLocal->value = gIR->ir->CreateBitCast(catch_var, getPtrToType(DtoType(catchstmt->var->type)));
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
22 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
23
320
d772927ca496 [svn r341] Fix all regressions between [332] and [340]:
ChristianK
parents: 319
diff changeset
24 // emit handler, if there is one
d772927ca496 [svn r341] Fix all regressions between [332] and [340]:
ChristianK
parents: 319
diff changeset
25 // handler is zero for instance for 'catch { debug foo(); }'
332
d7e6ace5cca4 [svn r353] Fix typo. (fixes empty catch handlers, like catch_02.d)
ChristianK
parents: 320
diff changeset
26 if(catchstmt->handler)
320
d772927ca496 [svn r341] Fix all regressions between [332] and [340]:
ChristianK
parents: 319
diff changeset
27 catchstmt->handler->toIR(gIR);
319
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
28
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
29 if (!gIR->scopereturned())
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
30 gIR->ir->CreateBr(end);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
31
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
32 assert(catchstmt->type);
320
d772927ca496 [svn r341] Fix all regressions between [332] and [340]:
ChristianK
parents: 319
diff changeset
33 //TODO: Is toBasetype correct here? Should catch handlers with typedefed
d772927ca496 [svn r341] Fix all regressions between [332] and [340]:
ChristianK
parents: 319
diff changeset
34 // classes behave differently?
d772927ca496 [svn r341] Fix all regressions between [332] and [340]:
ChristianK
parents: 319
diff changeset
35 catchType = catchstmt->type->toBasetype()->isClassHandle();
d772927ca496 [svn r341] Fix all regressions between [332] and [340]:
ChristianK
parents: 319
diff changeset
36 assert(catchType);
319
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
37 DtoForceDeclareDsymbol(catchType);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
38 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
39
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
40 IRLandingPadInfo::IRLandingPadInfo(Statement* finallystmt)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
41 : target(NULL), finallyBody(finallystmt), catchType(NULL)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
42 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
43
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
44 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
45
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
46
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
47 void IRLandingPad::addCatch(Catch* catchstmt, llvm::BasicBlock* end)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
48 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
49 unpushed_infos.push_front(IRLandingPadInfo(catchstmt, end));
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
50 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
51
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
52 void IRLandingPad::addFinally(Statement* finallystmt)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
53 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
54 unpushed_infos.push_front(IRLandingPadInfo(finallystmt));
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
55 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
56
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
57 void IRLandingPad::push(llvm::BasicBlock* inBB)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
58 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
59 // store infos such that matches are right to left
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
60 nInfos.push(infos.size());
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
61 infos.insert(infos.end(), unpushed_infos.begin(), unpushed_infos.end());
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
62 unpushed_infos.clear();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
63
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
64 constructLandingPad(inBB);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
65
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
66 // store as invoke target
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
67 padBBs.push(inBB);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
68 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
69
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
70 void IRLandingPad::pop()
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
71 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
72 padBBs.pop();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
73
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
74 size_t n = nInfos.top();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
75 infos.resize(n);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
76 nInfos.pop();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
77 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
78
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
79 llvm::BasicBlock* IRLandingPad::get()
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
80 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
81 if(padBBs.size() == 0)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
82 return NULL;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
83 else
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
84 return padBBs.top();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
85 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
86
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
87 void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
88 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
89 // save and rewrite scope
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
90 IRScope savedscope = gIR->scope();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
91 gIR->scope() = IRScope(inBB,savedscope.end);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
92
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
93 // eh_ptr = llvm.eh.exception();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
94 llvm::Function* eh_exception_fn = GET_INTRINSIC_DECL(eh_exception);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
95 LLValue* eh_ptr = gIR->ir->CreateCall(eh_exception_fn);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
96
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
97 // build selector arguments
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
98 LLSmallVector<LLValue*, 6> selectorargs;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
99 selectorargs.push_back(eh_ptr);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
100
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
101 llvm::Function* personality_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_personality");
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
102 LLValue* personality_fn_arg = gIR->ir->CreateBitCast(personality_fn, getPtrToType(LLType::Int8Ty));
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
103 selectorargs.push_back(personality_fn_arg);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
104
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
105 bool hasFinally = false;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
106 // associate increasing ints with each unique classdecl encountered
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
107 std::map<ClassDeclaration*, int> catchToInt;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
108 std::deque<IRLandingPadInfo>::reverse_iterator it = infos.rbegin(), end = infos.rend();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
109 for(size_t i = infos.size() - 1; it != end; ++it, --i)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
110 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
111 if(it->finallyBody)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
112 hasFinally = true;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
113 else
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
114 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
115 if(catchToInt.find(it->catchType) == catchToInt.end())
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
116 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
117 int newval = catchToInt.size();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
118 catchToInt[it->catchType] = newval;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
119 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
120 assert(it->catchType);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
121 assert(it->catchType->ir.irStruct);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
122 selectorargs.push_back(it->catchType->ir.irStruct->classInfo);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
123 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
124 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
125 // if there's a finally, the eh table has to have a 0 action
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
126 if(hasFinally)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
127 selectorargs.push_back(llvm::ConstantInt::get(LLType::Int32Ty, 0));
320
d772927ca496 [svn r341] Fix all regressions between [332] and [340]:
ChristianK
parents: 319
diff changeset
128 // if there is a catch and some catch allocated storage, store exception object
d772927ca496 [svn r341] Fix all regressions between [332] and [340]:
ChristianK
parents: 319
diff changeset
129 if(catchToInt.size() && catch_var)
319
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
130 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
131 const LLType* objectTy = DtoType(ClassDeclaration::object->type);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
132 gIR->ir->CreateStore(gIR->ir->CreateBitCast(eh_ptr, objectTy), catch_var);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
133 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
134
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
135 // eh_sel = llvm.eh.selector(eh_ptr, cast(byte*)&_d_eh_personality, <selectorargs>);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
136 llvm::Function* eh_selector_fn;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
137 if (global.params.is64bit)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
138 eh_selector_fn = GET_INTRINSIC_DECL(eh_selector_i64);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
139 else
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
140 eh_selector_fn = GET_INTRINSIC_DECL(eh_selector_i32);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
141 LLValue* eh_sel = gIR->ir->CreateCall(eh_selector_fn, selectorargs.begin(), selectorargs.end());
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
142
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
143 // emit finallys and switches that branch to catches until there are no more catches
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
144 // then simply branch to the finally chain
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
145 llvm::SwitchInst* switchinst = NULL;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
146 for(it = infos.rbegin(); it != end; ++it)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
147 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
148 // if it's a finally, emit its code
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
149 if(it->finallyBody)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
150 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
151 if(switchinst)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
152 switchinst = NULL;
355
d8357f7004ca [svn r376] Fix bug with finally blocks and labels. The labels would get emitted multiple times and conflict.
ChristianK
parents: 349
diff changeset
153
d8357f7004ca [svn r376] Fix bug with finally blocks and labels. The labels would get emitted multiple times and conflict.
ChristianK
parents: 349
diff changeset
154 // since this may be emitted multiple times
d8357f7004ca [svn r376] Fix bug with finally blocks and labels. The labels would get emitted multiple times and conflict.
ChristianK
parents: 349
diff changeset
155 // give the labels a new scope
d8357f7004ca [svn r376] Fix bug with finally blocks and labels. The labels would get emitted multiple times and conflict.
ChristianK
parents: 349
diff changeset
156 gIR->func()->pushUniqueLabelScope("finally");
319
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
157 it->finallyBody->toIR(gIR);
355
d8357f7004ca [svn r376] Fix bug with finally blocks and labels. The labels would get emitted multiple times and conflict.
ChristianK
parents: 349
diff changeset
158 gIR->func()->popLabelScope();
319
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
159 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
160 // otherwise it's a catch and we'll add a switch case
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
161 else
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
162 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
163 if(!switchinst)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
164 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
165 switchinst = gIR->ir->CreateSwitch(eh_sel, llvm::BasicBlock::Create("switchdefault", gIR->topfunc(), gIR->scopeend()), infos.size());
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
166 gIR->scope() = IRScope(switchinst->getDefaultDest(), gIR->scopeend());
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
167 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
168 // catches matched first get the largest switchval, so do size - unique int
349
d22d8d63c1fd [svn r370] Fixed landing pads on 64bit was broken (hardcoded 32bit type, should be size_t)
lindquist
parents: 332
diff changeset
169 llvm::ConstantInt* switchval = llvm::ConstantInt::get(DtoSize_t(), catchToInt.size() - catchToInt[it->catchType]);
319
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
170 // and make sure we don't add the same switchval twice, may happen with nested trys
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
171 if(!switchinst->findCaseValue(switchval))
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
172 switchinst->addCase(switchval, it->target);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
173 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
174 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
175
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
176 // no catch matched and all finallys executed - resume unwind
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
177 llvm::Function* unwind_resume_fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_eh_resume_unwind");
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
178 gIR->ir->CreateCall(unwind_resume_fn, eh_ptr);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
179 gIR->ir->CreateUnreachable();
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
180
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
181 gIR->scope() = savedscope;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
182 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
183
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
184 LLValue* IRLandingPad::getExceptionStorage()
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
185 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
186 if(!catch_var)
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
187 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
188 Logger::println("Making new catch var");
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
189 const LLType* objectTy = DtoType(ClassDeclaration::object->type);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
190 catch_var = new llvm::AllocaInst(objectTy,"catchvar",gIR->topallocapoint());
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
191 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
192 return catch_var;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
193 }