Mercurial > projects > ldc
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 |
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 } |