annotate ir/irlandingpad.cpp @ 332:d7e6ace5cca4 trunk

[svn r353] Fix typo. (fixes empty catch handlers, like catch_02.d)
author ChristianK
date Fri, 11 Jul 2008 22:33:21 +0200
parents d772927ca496
children d22d8d63c1fd
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;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
153 it->finallyBody->toIR(gIR);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
154 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
155 // 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
156 else
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
157 {
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
158 if(!switchinst)
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 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
161 gIR->scope() = IRScope(switchinst->getDefaultDest(), gIR->scopeend());
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 // catches matched first get the largest switchval, so do size - unique int
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
164 llvm::ConstantInt* switchval = llvm::ConstantInt::get(LLType::Int32Ty, catchToInt.size() - catchToInt[it->catchType]);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
165 // 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
166 if(!switchinst->findCaseValue(switchval))
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
167 switchinst->addCase(switchval, it->target);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
168 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
169 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
170
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
171 // 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
172 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
173 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
174 gIR->ir->CreateUnreachable();
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 gIR->scope() = savedscope;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
177 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
178
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
179 LLValue* IRLandingPad::getExceptionStorage()
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 if(!catch_var)
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 Logger::println("Making new catch var");
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
184 const LLType* objectTy = DtoType(ClassDeclaration::object->type);
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
185 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
186 }
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
187 return catch_var;
e9c93739bc4c [svn r340] Rework exception handling to work with nested tryfinally and trycatch.
ChristianK
parents:
diff changeset
188 }