From 0c3702ea34f9f63ecec3c78a18975d6d069599f9 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Mon, 9 Mar 2015 12:33:10 +0100 Subject: [PATCH] Single ret point in functions, so that a ret is always in the codepath. --- BitcodeEmitter.cpp | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/BitcodeEmitter.cpp b/BitcodeEmitter.cpp index dbd8c0a..b468ae2 100644 --- a/BitcodeEmitter.cpp +++ b/BitcodeEmitter.cpp @@ -49,6 +49,8 @@ using llvm::getGlobalContext; struct BitcodeEmitter::Private { llvm::Value *retval = nullptr; + llvm::AllocaInst *funcRetval = nullptr; + llvm::BasicBlock *funcExit = nullptr; llvm::IRBuilder<> builder = llvm::IRBuilder<>(getGlobalContext()); Scope scope; @@ -60,6 +62,12 @@ llvm::AllocaInst* allocateVar(llvm::Function *func, Id const& name, llvm::Type * return builder.CreateAlloca(type, 0, name.getValue().c_str()); } +static +llvm::AllocaInst* allocateReturnVariable(llvm::Function *func) { + llvm::IRBuilder<> builder(&func->getEntryBlock(), func->getEntryBlock().begin()); + return builder.CreateAlloca(func->getReturnType(), 0, "result"); +} + static llvm::Value* isTrue(llvm::IRBuilder<> &builder, llvm::Value* test, llvm::Twine const& label="") { return builder.CreateICmpNE( @@ -237,11 +245,12 @@ bool BitcodeEmitter::emit(Return const& node) { if (node.getExpression()) { GUARDED(node.getExpression()->emit(this)); llvm::Type *type = d->builder.GetInsertBlock()->getParent()->getReturnType(); - d->builder.CreateRet(coerce(d, d->retval, type)); - } else { - d->builder.CreateRetVoid(); + assert(d->funcRetval != nullptr); + d->builder.CreateStore(coerce(d, d->retval, type), d->funcRetval); } + d->builder.CreateBr(d->funcExit); + return true; } @@ -552,7 +561,6 @@ bool BitcodeEmitter::emit(Function const& node) { GUARDED(node.getPrototype().emit(this)); llvm::Function *func = dynamic_cast(d->retval); - d->scope.enter(); assert(func != nullptr); llvm::BasicBlock *bb = llvm::BasicBlock::Create( @@ -560,6 +568,13 @@ bool BitcodeEmitter::emit(Function const& node) { ); d->builder.SetInsertPoint(bb); + bool isNotVoid = node.getPrototype().getType() != Type::VOID; + + d->funcRetval = isNotVoid? allocateReturnVariable(func): nullptr; + d->funcExit = llvm::BasicBlock::Create(getGlobalContext(), "return"); + + d->scope.enter(); + auto argToAlloc = func->arg_begin(); for (FunArg const& arg: node.getPrototype().getArgs()) { llvm::AllocaInst *alloc = allocateVar( @@ -574,10 +589,20 @@ bool BitcodeEmitter::emit(Function const& node) { GUARDED(stat.emit(this)); } - verifyFunction(*func); - d->scope.leave(); + d->builder.CreateBr(d->funcExit); + func->getBasicBlockList().push_back(d->funcExit); + d->builder.SetInsertPoint(d->funcExit); + + if (isNotVoid) { + d->builder.CreateRet(d->builder.CreateLoad(d->funcRetval)); + } else { + d->builder.CreateRetVoid(); + } + + verifyFunction(*func); + return true; } @@ -601,7 +626,6 @@ bool BitcodeEmitter::emit(Program const& program) { if (program.getMain()) { GUARDED(program.getMain()->emit(this)); - d->builder.CreateRetVoid(); } return true;