From ac4997fe53f37dd6ab7cf0d0591de481b2972f0e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 7 Dec 2010 17:11:21 +0000 Subject: Factor if compilation into smaller bits (towards a more assembly like IR stage before actual backend code emission). git-svn-id: http://svn.drobilla.net/resp/resp@304 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- src/llvm.cpp | 128 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/llvm.cpp b/src/llvm.cpp index b6dea5d..b03713d 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -53,6 +53,7 @@ using boost::format; struct LLVMEngine : public Engine { LLVMEngine() : builder(context) + , labelIndex(1) { InitializeNativeTarget(); module = new Module("resp", context); @@ -168,6 +169,11 @@ struct LLVMEngine : public Engine { void pushFunctionArgs(CEnv& cenv, const ATuple* fn, const AType* type, CFunc f); + void appendBlock(LLVMEngine* engine, Function* function, BasicBlock* block) { + function->getBasicBlockList().push_back(block); + engine->builder.SetInsertPoint(block); + } + void finishFunction(CEnv& cenv, CFunc f, CVal ret) { builder.CreateRet(llVal(ret)); if (verifyFunction(*static_cast(f), llvm::PrintMessageAction)) { @@ -202,6 +208,25 @@ struct LLVMEngine : public Engine { CVal compileGlobal(CEnv& cenv, const AType* type, const string& sym, CVal val); CVal getGlobal(CEnv& cenv, const string& sym, CVal val); + typedef pair IfBranch; + typedef vector IfBranches; + + struct IfState { + IfState(BasicBlock* m, Function* p) : mergeBB(m), parent(p) {} + BasicBlock* mergeBB; + Function* parent; + IfBranches branches; + }; + + IfState* + compileIfStart(CEnv& cenv); + + void + compileIfBranch(CEnv& cenv, IfState* state, const AST* cond, const AST* then); + + CVal + compileIfEnd(CEnv& cenv, IfState* state, const AST* aelse, const AType* type); + void writeModule(CEnv& cenv, std::ostream& os) { AssemblyAnnotationWriter writer; llvm::raw_os_ostream raw_stream(os); @@ -253,6 +278,8 @@ struct LLVMEngine : public Engine { IRBuilder<> builder; Function* alloc; FunctionPassManager* opt; + + unsigned labelIndex; }; Engine* @@ -335,7 +362,7 @@ LLVMEngine::pushFunctionArgs(CEnv& cenv, const ATuple* fn, const AType* type, CF // Bind argument values in CEnv vector args; - ATuple::const_iterator p = fn->prot()->begin(); + ATuple::const_iterator p = fn->prot()->begin(); ATuple::const_iterator pT = argsT->begin(); assert(fn->prot()->size() == argsT->size()); assert(fn->prot()->size() == f->num_args()); @@ -347,57 +374,72 @@ LLVMEngine::pushFunctionArgs(CEnv& cenv, const ATuple* fn, const AType* type, CF } } -CVal -LLVMEngine::compileIf(CEnv& cenv, const ATuple* aif) +LLVMEngine::IfState* +LLVMEngine::compileIfStart(CEnv& cenv) { - typedef vector< pair > Branches; - LLVMEngine* engine = reinterpret_cast(cenv.engine()); - Function* parent = engine->builder.GetInsertBlock()->getParent(); - BasicBlock* mergeBB = BasicBlock::Create(context, "endif"); - BasicBlock* nextBB = NULL; - Branches branches; - size_t idx = 1; - for (ATuple::const_iterator i = aif->iter_at(1); ; ++i, idx += 2) { - ATuple::const_iterator next = i; - if (++next == aif->end()) - break; - - Value* condV = llVal(resp_compile(cenv, *i)); - BasicBlock* thenBB = BasicBlock::Create(context, (format("then%1%") % ((idx+1)/2)).str()); - - nextBB = BasicBlock::Create(context, (format("else%1%") % ((idx+1)/2)).str()); + LLVMEngine* engine = reinterpret_cast(cenv.engine()); + return new IfState(BasicBlock::Create(context, "endif"), + engine->builder.GetInsertBlock()->getParent()); +} - engine->builder.CreateCondBr(condV, thenBB, nextBB); +void +LLVMEngine::compileIfBranch(CEnv& cenv, IfState* state, const AST* cond, const AST* then) +{ + LLVMEngine* engine = reinterpret_cast(cenv.engine()); + Value* condV = llVal(resp_compile(cenv, cond)); - // Emit then block for this condition - parent->getBasicBlockList().push_back(thenBB); - engine->builder.SetInsertPoint(thenBB); - Value* thenV = llVal(resp_compile(cenv, *next)); - engine->builder.CreateBr(mergeBB); - branches.push_back(make_pair(thenV, engine->builder.GetInsertBlock())); + ++labelIndex; + + BasicBlock* thenBB = BasicBlock::Create(context, (format("then%1%") % labelIndex).str()); + BasicBlock* nextBB = BasicBlock::Create(context, (format("else%1%") % labelIndex).str()); - parent->getBasicBlockList().push_back(nextBB); - engine->builder.SetInsertPoint(nextBB); + engine->builder.CreateCondBr(condV, thenBB, nextBB); - i = next; // jump 2 each iteration (to the next predicate) - } + // Emit then block for this condition + appendBlock(engine, state->parent, thenBB); + Value* thenV = llVal(resp_compile(cenv, then)); + engine->builder.CreateBr(state->mergeBB); + state->branches.push_back(make_pair(thenV, thenBB)); + + appendBlock(engine, state->parent, nextBB); +} +CVal +LLVMEngine::compileIfEnd(CEnv& cenv, IfState* state, const AST* aelse, const AType* type) +{ + LLVMEngine* engine = reinterpret_cast(cenv.engine()); + // Emit final else block - Value* elseV = llVal(resp_compile(cenv, aif->list_last())); - engine->builder.CreateBr(mergeBB); - branches.push_back(make_pair(elseV, engine->builder.GetInsertBlock())); + Value* elseV = llVal(resp_compile(cenv, aelse)); + engine->builder.CreateBr(state->mergeBB); + state->branches.push_back(make_pair(elseV, engine->builder.GetInsertBlock())); // Emit merge block (Phi node) - parent->getBasicBlockList().push_back(mergeBB); - engine->builder.SetInsertPoint(mergeBB); - PHINode* pn = engine->builder.CreatePHI(llType(cenv.type(aif)), "ifval"); - - FOREACH(Branches::iterator, i, branches) + appendBlock(engine, state->parent, state->mergeBB); + PHINode* pn = engine->builder.CreatePHI(llType(type), "ifval"); + FOREACH(IfBranches::iterator, i, state->branches) pn->addIncoming(i->first, i->second); return pn; } +CVal +LLVMEngine::compileIf(CEnv& cenv, const ATuple* aif) +{ + IfState* state = compileIfStart(cenv); + for (ATuple::const_iterator i = aif->iter_at(1); ; ++i) { + ATuple::const_iterator next = i; + if (++next == aif->end()) + break; + + compileIfBranch(cenv, state, *i, *next); + + i = next; // jump 2 each iteration (to the next predicate) + } + + return compileIfEnd(cenv, state, aif->list_last(), cenv.type(aif)); +} + CVal LLVMEngine::compileMatch(CEnv& cenv, const ATuple* match) { @@ -428,14 +470,12 @@ LLVMEngine::compileMatch(CEnv& cenv, const ATuple* match) engine->builder.CreateCondBr(condV, thenBB, nextBB); // Emit then block for this condition - parent->getBasicBlockList().push_back(thenBB); - engine->builder.SetInsertPoint(thenBB); + appendBlock(engine, parent, thenBB); Value* thenV = llVal(resp_compile(cenv, body)); engine->builder.CreateBr(mergeBB); branches.push_back(make_pair(thenV, engine->builder.GetInsertBlock())); - parent->getBasicBlockList().push_back(nextBB); - engine->builder.SetInsertPoint(nextBB); + appendBlock(engine, parent, nextBB); } // Emit final else block (FIXME: n/a, what to do here?) @@ -443,10 +483,8 @@ LLVMEngine::compileMatch(CEnv& cenv, const ATuple* match) branches.push_back(make_pair(Constant::getNullValue(llType(cenv.type(match))), engine->builder.GetInsertBlock())); // Emit merge block (Phi node) - parent->getBasicBlockList().push_back(mergeBB); - engine->builder.SetInsertPoint(mergeBB); + appendBlock(engine, parent, mergeBB); PHINode* pn = engine->builder.CreatePHI(llType(cenv.type(match)), "mergeval"); - FOREACH(Branches::iterator, i, branches) pn->addIncoming(i->first, i->second); -- cgit v1.2.1