@@ -61,11 +61,11 @@ llvm::Function *ConstructFunction(
61
61
62
62
} // namespace
63
63
64
- // ===----------------------------------------------------------------------=== //
65
- //
66
- // FunctionDeclaration
67
- //
68
- // ===----------------------------------------------------------------------=== //
64
+ // //////////////////////////////////////////////////////////////////////////// //
65
+ // /
66
+ // / FunctionDeclaration
67
+ // /
68
+ // //////////////////////////////////////////////////////////////////////////// //
69
69
70
70
FunctionDeclaration::FunctionDeclaration (
71
71
CodeContext &cc, const std::string &name,
@@ -84,11 +84,11 @@ FunctionDeclaration FunctionDeclaration::MakeDeclaration(
84
84
return FunctionDeclaration (cc, name, visibility, ret_type, args);
85
85
}
86
86
87
- // ===----------------------------------------------------------------------=== //
88
- //
89
- // FunctionBuilder
90
- //
91
- // ===----------------------------------------------------------------------=== //
87
+ // //////////////////////////////////////////////////////////////////////////// //
88
+ // /
89
+ // / FunctionBuilder
90
+ // /
91
+ // //////////////////////////////////////////////////////////////////////////// //
92
92
93
93
// We preserve the state of any ongoing function construction in order to be
94
94
// able to restore it after this function has been fully completed. Thus,
@@ -101,7 +101,8 @@ FunctionBuilder::FunctionBuilder(CodeContext &cc, llvm::Function *func_decl)
101
101
previous_insert_point_(cc.GetBuilder().GetInsertBlock()),
102
102
func_(func_decl),
103
103
overflow_bb_(nullptr ),
104
- divide_by_zero_bb_(nullptr ) {
104
+ divide_by_zero_bb_(nullptr ),
105
+ return_bb_(nullptr ) {
105
106
// At this point, we've saved the current position during code generation and
106
107
// we have a function declaration. Now:
107
108
// 1. We define the "entry" block and attach it to the function. At this
@@ -175,10 +176,11 @@ llvm::BasicBlock *FunctionBuilder::GetOverflowBB() {
175
176
return overflow_bb_;
176
177
}
177
178
178
- CodeGen codegen{ code_context_} ;
179
+ CodeGen codegen ( code_context_) ;
179
180
180
181
// Save the current position so we can restore after we're done
181
- auto *curr_position = codegen->GetInsertBlock ();
182
+ auto *curr_block = codegen->GetInsertBlock ();
183
+ auto curr_pos = codegen->GetInsertPoint ();
182
184
183
185
// Create the overflow block now, but don't attach to function just yet.
184
186
overflow_bb_ = llvm::BasicBlock::Create (codegen.GetContext (), " overflow" );
@@ -189,7 +191,7 @@ llvm::BasicBlock *FunctionBuilder::GetOverflowBB() {
189
191
codegen->CreateUnreachable ();
190
192
191
193
// Restore position
192
- codegen->SetInsertPoint (curr_position );
194
+ codegen->SetInsertPoint (curr_block, curr_pos );
193
195
194
196
return overflow_bb_;
195
197
}
@@ -204,10 +206,11 @@ llvm::BasicBlock *FunctionBuilder::GetDivideByZeroBB() {
204
206
return divide_by_zero_bb_;
205
207
}
206
208
207
- CodeGen codegen{ code_context_} ;
209
+ CodeGen codegen ( code_context_) ;
208
210
209
211
// Save the current position so we can restore after we're done
210
- auto *curr_position = codegen->GetInsertBlock ();
212
+ auto *curr_block = codegen->GetInsertBlock ();
213
+ auto curr_pos = codegen->GetInsertPoint ();
211
214
212
215
// Create the overflow block now, but don't attach to function just yet.
213
216
divide_by_zero_bb_ =
@@ -219,18 +222,42 @@ llvm::BasicBlock *FunctionBuilder::GetDivideByZeroBB() {
219
222
codegen->CreateUnreachable ();
220
223
221
224
// Restore position
222
- codegen->SetInsertPoint (curr_position );
225
+ codegen->SetInsertPoint (curr_block, curr_pos );
223
226
224
227
return divide_by_zero_bb_;
225
228
}
226
229
230
+ llvm::BasicBlock *FunctionBuilder::GetExitBlock () {
231
+ if (return_bb_ != nullptr ) {
232
+ return return_bb_;
233
+ }
234
+
235
+ CodeGen codegen (code_context_);
236
+
237
+ // Save the current position so we can restore after we're done
238
+ auto *curr_block = codegen->GetInsertBlock ();
239
+ auto curr_pos = codegen->GetInsertPoint ();
240
+
241
+ // Create the overflow block now, but don't attach to function just yet.
242
+ return_bb_ = llvm::BasicBlock::Create (codegen.GetContext (), " return" );
243
+
244
+ // Quickly switch into the return block
245
+ codegen->SetInsertPoint (return_bb_);
246
+ codegen->CreateRetVoid ();
247
+
248
+ // Restore position
249
+ codegen->SetInsertPoint (curr_block, curr_pos);
250
+
251
+ return return_bb_;
252
+ }
253
+
227
254
// Return the given value from the function and finish it
228
255
void FunctionBuilder::ReturnAndFinish (llvm::Value *ret) {
229
256
if (finished_) {
230
257
return ;
231
258
}
232
259
233
- CodeGen codegen{ code_context_} ;
260
+ CodeGen codegen ( code_context_) ;
234
261
235
262
if (ret != nullptr ) {
236
263
codegen->CreateRet (ret);
@@ -239,12 +266,17 @@ void FunctionBuilder::ReturnAndFinish(llvm::Value *ret) {
239
266
codegen->CreateRetVoid ();
240
267
}
241
268
242
- // Add the overflow error block if it exists
269
+ // Add the return block, if it exists
270
+ if (return_bb_ != nullptr ) {
271
+ return_bb_->insertInto (func_);
272
+ }
273
+
274
+ // Add the overflow error block, if it exists
243
275
if (overflow_bb_ != nullptr ) {
244
276
overflow_bb_->insertInto (func_);
245
277
}
246
278
247
- // Add the divide-by-zero error block if it exists
279
+ // Add the divide-by-zero error block, if it exists
248
280
if (divide_by_zero_bb_ != nullptr ) {
249
281
divide_by_zero_bb_->insertInto (func_);
250
282
}
@@ -261,23 +293,33 @@ void FunctionBuilder::ReturnAndFinish(llvm::Value *ret) {
261
293
}
262
294
263
295
llvm::Value *FunctionBuilder::GetOrCacheVariable (
264
- const std::string &name, const std::function<llvm::Value *()> &func) {
265
- auto iter = cached_vars_.find (name);
266
- if (iter != cached_vars_.end ()) {
267
- return iter->second ;
268
- } else {
269
- CodeGen codegen{code_context_};
270
- auto pos = codegen->GetInsertPoint ();
271
- if (entry_bb_->empty ()) {
272
- codegen->SetInsertPoint (entry_bb_);
273
- } else {
274
- codegen->SetInsertPoint (&entry_bb_->back ());
275
- }
276
- auto *val = func ();
277
- codegen->SetInsertPoint (&*pos);
278
- cached_vars_.emplace (name, val);
296
+ const std::string &name, const std::function<llvm::Value *()> &load_func) {
297
+ llvm::Value *&val = cached_vars_[name];
298
+ if (val != nullptr ) {
279
299
return val;
280
300
}
301
+
302
+ CodeGen codegen (code_context_);
303
+
304
+ // Save current position
305
+ auto *curr_block = codegen->GetInsertBlock ();
306
+ auto curr_pos = codegen->GetInsertPoint ();
307
+
308
+ // Move to start of function
309
+ if (entry_bb_->empty ()) {
310
+ codegen->SetInsertPoint (entry_bb_);
311
+ } else {
312
+ codegen->SetInsertPoint (&entry_bb_->back ());
313
+ }
314
+
315
+ // Generate loading code and save in cache
316
+ val = load_func ();
317
+
318
+ // Move back
319
+ codegen->SetInsertPoint (curr_block, curr_pos);
320
+
321
+ // Return value
322
+ return val;
281
323
}
282
324
283
325
} // namespace codegen
0 commit comments