aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-12-07 17:11:21 +0000
committerDavid Robillard <d@drobilla.net>2010-12-07 17:11:21 +0000
commitac4997fe53f37dd6ab7cf0d0591de481b2972f0e (patch)
treed1fb685b3ad7186821e789d8130a7cb72d209476 /src
parentfe836734a187a62c7b639ef87729c81d7996f264 (diff)
downloadresp-ac4997fe53f37dd6ab7cf0d0591de481b2972f0e.tar.gz
resp-ac4997fe53f37dd6ab7cf0d0591de481b2972f0e.tar.bz2
resp-ac4997fe53f37dd6ab7cf0d0591de481b2972f0e.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/llvm.cpp128
1 files changed, 83 insertions, 45 deletions
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<Function*>(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<Value*, BasicBlock*> IfBranch;
+ typedef vector<IfBranch> 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<Value*> 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,58 +374,73 @@ 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<Value*, BasicBlock*> > Branches;
- LLVMEngine* engine = reinterpret_cast<LLVMEngine*>(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<LLVMEngine*>(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<LLVMEngine*>(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<LLVMEngine*>(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)
{
typedef vector< pair<Value*, BasicBlock*> > Branches;
@@ -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);