@@ -61,11 +61,11 @@ llvm::Function *ConstructFunction(
6161
6262} // namespace
6363
64- // ===----------------------------------------------------------------------=== //
65- //
66- // FunctionDeclaration
67- //
68- // ===----------------------------------------------------------------------=== //
64+ // //////////////////////////////////////////////////////////////////////////// //
65+ // /
66+ // / FunctionDeclaration
67+ // /
68+ // //////////////////////////////////////////////////////////////////////////// //
6969
7070FunctionDeclaration::FunctionDeclaration (
7171 CodeContext &cc, const std::string &name,
@@ -84,11 +84,11 @@ FunctionDeclaration FunctionDeclaration::MakeDeclaration(
8484 return FunctionDeclaration (cc, name, visibility, ret_type, args);
8585}
8686
87- // ===----------------------------------------------------------------------=== //
88- //
89- // FunctionBuilder
90- //
91- // ===----------------------------------------------------------------------=== //
87+ // //////////////////////////////////////////////////////////////////////////// //
88+ // /
89+ // / FunctionBuilder
90+ // /
91+ // //////////////////////////////////////////////////////////////////////////// //
9292
9393// We preserve the state of any ongoing function construction in order to be
9494// able to restore it after this function has been fully completed. Thus,
@@ -101,7 +101,8 @@ FunctionBuilder::FunctionBuilder(CodeContext &cc, llvm::Function *func_decl)
101101 previous_insert_point_(cc.GetBuilder().GetInsertBlock()),
102102 func_(func_decl),
103103 overflow_bb_(nullptr ),
104- divide_by_zero_bb_(nullptr ) {
104+ divide_by_zero_bb_(nullptr ),
105+ return_bb_(nullptr ) {
105106 // At this point, we've saved the current position during code generation and
106107 // we have a function declaration. Now:
107108 // 1. We define the "entry" block and attach it to the function. At this
@@ -175,10 +176,11 @@ llvm::BasicBlock *FunctionBuilder::GetOverflowBB() {
175176 return overflow_bb_;
176177 }
177178
178- CodeGen codegen{ code_context_} ;
179+ CodeGen codegen ( code_context_) ;
179180
180181 // 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 ();
182184
183185 // Create the overflow block now, but don't attach to function just yet.
184186 overflow_bb_ = llvm::BasicBlock::Create (codegen.GetContext (), " overflow" );
@@ -189,7 +191,7 @@ llvm::BasicBlock *FunctionBuilder::GetOverflowBB() {
189191 codegen->CreateUnreachable ();
190192
191193 // Restore position
192- codegen->SetInsertPoint (curr_position );
194+ codegen->SetInsertPoint (curr_block, curr_pos );
193195
194196 return overflow_bb_;
195197}
@@ -204,10 +206,11 @@ llvm::BasicBlock *FunctionBuilder::GetDivideByZeroBB() {
204206 return divide_by_zero_bb_;
205207 }
206208
207- CodeGen codegen{ code_context_} ;
209+ CodeGen codegen ( code_context_) ;
208210
209211 // 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 ();
211214
212215 // Create the overflow block now, but don't attach to function just yet.
213216 divide_by_zero_bb_ =
@@ -219,18 +222,42 @@ llvm::BasicBlock *FunctionBuilder::GetDivideByZeroBB() {
219222 codegen->CreateUnreachable ();
220223
221224 // Restore position
222- codegen->SetInsertPoint (curr_position );
225+ codegen->SetInsertPoint (curr_block, curr_pos );
223226
224227 return divide_by_zero_bb_;
225228}
226229
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+
227254// Return the given value from the function and finish it
228255void FunctionBuilder::ReturnAndFinish (llvm::Value *ret) {
229256 if (finished_) {
230257 return ;
231258 }
232259
233- CodeGen codegen{ code_context_} ;
260+ CodeGen codegen ( code_context_) ;
234261
235262 if (ret != nullptr ) {
236263 codegen->CreateRet (ret);
@@ -239,12 +266,17 @@ void FunctionBuilder::ReturnAndFinish(llvm::Value *ret) {
239266 codegen->CreateRetVoid ();
240267 }
241268
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
243275 if (overflow_bb_ != nullptr ) {
244276 overflow_bb_->insertInto (func_);
245277 }
246278
247- // Add the divide-by-zero error block if it exists
279+ // Add the divide-by-zero error block, if it exists
248280 if (divide_by_zero_bb_ != nullptr ) {
249281 divide_by_zero_bb_->insertInto (func_);
250282 }
@@ -261,23 +293,33 @@ void FunctionBuilder::ReturnAndFinish(llvm::Value *ret) {
261293}
262294
263295llvm::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 ) {
279299 return val;
280300 }
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;
281323}
282324
283325} // namespace codegen
0 commit comments