diff options
author | David Robillard <d@drobilla.net> | 2009-03-12 05:41:26 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-03-12 05:41:26 +0000 |
commit | ad582fa2ba18ca4391c3d6c084d902d3b1fd5ca5 (patch) | |
tree | 354cf474ce07c2fa7a7aa1733f37288cbe135f12 | |
parent | 251232bc3bbf6d98f9f6f91352bdcceef3b102f0 (diff) | |
download | resp-ad582fa2ba18ca4391c3d6c084d902d3b1fd5ca5.tar.gz resp-ad582fa2ba18ca4391c3d6c084d902d3b1fd5ca5.tar.bz2 resp-ad582fa2ba18ca4391c3d6c084d902d3b1fd5ca5.zip |
Consistent opaque backend types.
git-svn-id: http://svn.drobilla.net/resp/tuplr@84 ad02d1e2-f140-0410-9f75-f8b11f17cedd
-rw-r--r-- | llvm.cpp | 97 | ||||
-rw-r--r-- | tuplr.hpp | 31 |
2 files changed, 70 insertions, 58 deletions
@@ -38,14 +38,14 @@ using boost::format; inline Value* LLVal(CValue v) { return static_cast<Value*>(v); } inline Function* LLFunc(CFunction f) { return static_cast<Function*>(f); } -struct CEngine { - CEngine(); +struct LLVMEngine { + LLVMEngine(); Module* module; ExecutionEngine* engine; IRBuilder<> builder; }; -const Type* +static const Type* lltype(AType* t) { switch (t->kind) { @@ -67,17 +67,23 @@ lltype(AType* t) return NULL; // not reached } -CEngine::CEngine() +static LLVMEngine* +llengine(CEnv& cenv) +{ + return reinterpret_cast<LLVMEngine*>(cenv.engine()); +} + +LLVMEngine::LLVMEngine() : module(new Module("tuplr")) , engine(ExecutionEngine::create(module)) { } struct CEnv::PImpl { - PImpl(CEngine& engine) : module(engine.module), emp(module), opt(&emp) + PImpl(LLVMEngine* e) : engine(e), module(e->module), emp(module), opt(&emp) { // Set up the optimizer pipeline: - const TargetData* target = engine.engine->getTargetData(); + const TargetData* target = engine->engine->getTargetData(); opt.add(new TargetData(*target)); // Register target arch opt.add(createInstructionCombiningPass()); // Simple optimizations opt.add(createReassociatePass()); // Reassociate expressions @@ -85,14 +91,15 @@ struct CEnv::PImpl { opt.add(createCFGSimplificationPass()); // Simplify control flow } + LLVMEngine* engine; Module* module; ExistingModuleProvider emp; FunctionPassManager opt; Function* alloc; }; -CEnv::CEnv(PEnv& p, TEnv& t, CEngine& e, ostream& os, ostream& es) - : engine(e), penv(p), tenv(t), symID(0), alloc(0), log(os, es), _pimpl(new PImpl(e)) +CEnv::CEnv(PEnv& p, TEnv& t, CEngine e, ostream& os, ostream& es) + : penv(p), tenv(t), symID(0), alloc(0), log(os, es), _pimpl(new PImpl((LLVMEngine*)e)) { } @@ -101,6 +108,12 @@ CEnv::~CEnv() delete _pimpl; } +CEngine +CEnv::engine() +{ + return _pimpl->engine; +} + CValue CEnv::compile(AST* obj) { @@ -119,7 +132,7 @@ void CEnv::write(std::ostream& os) { AssemblyAnnotationWriter writer; - engine.module->print(os, &writer); + _pimpl->engine->module->print(os, &writer); } #define LITERAL(CT, NAME, COMPILED) \ @@ -148,7 +161,7 @@ compileFunction(CEnv& cenv, const std::string& name, const Type* retT, const ATu if (!retT) throw Error("function return is untyped"); FunctionType* fT = FunctionType::get(static_cast<const Type*>(retT), cprot, false); - Function* f = Function::Create(fT, linkage, name, cenv.engine.module); + Function* f = Function::Create(fT, linkage, name, llengine(cenv)->module); if (f->getName() != name) { f->eraseFromParent(); @@ -165,7 +178,7 @@ compileFunction(CEnv& cenv, const std::string& name, const Type* retT, const ATu a->setName(prot.at(i)->str()); BasicBlock* bb = BasicBlock::Create("entry", f); - cenv.engine.builder.SetInsertPoint(bb); + llengine(cenv)->builder.SetInsertPoint(bb); return f; } @@ -211,7 +224,7 @@ AClosure::lift(CEnv& cenv) try { cenv.precompile(this, f); // Define our value first for recursion CValue retVal = cenv.compile(at(2)); - cenv.engine.builder.CreateRet(LLVal(retVal)); // Finish function + llengine(cenv)->builder.CreateRet(LLVal(retVal)); // Finish function cenv.optimise(LLFunc(f)); funcs.push_back(make_pair(type, f)); } catch (Error& e) { @@ -287,7 +300,7 @@ ACall::compile(CEnv& cenv) for (size_t i = 1; i < size(); ++i) params[i-1] = LLVal(cenv.compile(at(i))); - return cenv.engine.builder.CreateCall(f, params.begin(), params.end(), "calltmp"); + return llengine(cenv)->builder.CreateCall(f, params.begin(), params.end(), "calltmp"); } void @@ -309,7 +322,7 @@ CValue AIf::compile(CEnv& cenv) { typedef vector< pair<Value*, BasicBlock*> > Branches; - Function* parent = cenv.engine.builder.GetInsertBlock()->getParent(); + Function* parent = llengine(cenv)->builder.GetInsertBlock()->getParent(); BasicBlock* mergeBB = BasicBlock::Create("endif"); BasicBlock* nextBB = NULL; Branches branches; @@ -319,29 +332,29 @@ AIf::compile(CEnv& cenv) nextBB = BasicBlock::Create((format("else%1%") % ((i+1)/2)).str()); - cenv.engine.builder.CreateCondBr(condV, thenBB, nextBB); + llengine(cenv)->builder.CreateCondBr(condV, thenBB, nextBB); // Emit then block for this condition parent->getBasicBlockList().push_back(thenBB); - cenv.engine.builder.SetInsertPoint(thenBB); + llengine(cenv)->builder.SetInsertPoint(thenBB); Value* thenV = LLVal(cenv.compile(at(i+1))); - cenv.engine.builder.CreateBr(mergeBB); - branches.push_back(make_pair(thenV, cenv.engine.builder.GetInsertBlock())); + llengine(cenv)->builder.CreateBr(mergeBB); + branches.push_back(make_pair(thenV, llengine(cenv)->builder.GetInsertBlock())); parent->getBasicBlockList().push_back(nextBB); - cenv.engine.builder.SetInsertPoint(nextBB); + llengine(cenv)->builder.SetInsertPoint(nextBB); } // Emit final else block - cenv.engine.builder.SetInsertPoint(nextBB); + llengine(cenv)->builder.SetInsertPoint(nextBB); Value* elseV = LLVal(cenv.compile(at(size() - 1))); - cenv.engine.builder.CreateBr(mergeBB); - branches.push_back(make_pair(elseV, cenv.engine.builder.GetInsertBlock())); + llengine(cenv)->builder.CreateBr(mergeBB); + branches.push_back(make_pair(elseV, llengine(cenv)->builder.GetInsertBlock())); // Emit merge block (Phi node) parent->getBasicBlockList().push_back(mergeBB); - cenv.engine.builder.SetInsertPoint(mergeBB); - PHINode* pn = cenv.engine.builder.CreatePHI(lltype(cenv.tenv.type(this)), "ifval"); + llengine(cenv)->builder.SetInsertPoint(mergeBB); + PHINode* pn = llengine(cenv)->builder.CreatePHI(lltype(cenv.tenv.type(this)), "ifval"); FOREACH(Branches::iterator, i, branches) pn->addIncoming(i->first, i->second); @@ -368,9 +381,9 @@ APrimitive::compile(CEnv& cenv) if (n == "/") op = isInt ? Instruction::SDiv : Instruction::FDiv; if (n == "%") op = isInt ? Instruction::SRem : Instruction::FRem; if (op != 0) { - Value* val = cenv.engine.builder.CreateBinOp(op, a, b); + Value* val = llengine(cenv)->builder.CreateBinOp(op, a, b); for (size_t i = 3; i < size(); ++i) - val = cenv.engine.builder.CreateBinOp(op, val, LLVal(cenv.compile(at(i)))); + val = llengine(cenv)->builder.CreateBinOp(op, val, LLVal(cenv.compile(at(i)))); return val; } @@ -384,9 +397,9 @@ APrimitive::compile(CEnv& cenv) if (n == "<=") pred = isInt ? CmpInst::ICMP_SLE : CmpInst::FCMP_OLE; if (pred != 0) { if (isInt) - return cenv.engine.builder.CreateICmp(pred, a, b); + return llengine(cenv)->builder.CreateICmp(pred, a, b); else - return cenv.engine.builder.CreateFCmp(pred, a, b); + return llengine(cenv)->builder.CreateFCmp(pred, a, b); } throw Error("unknown primitive", loc); @@ -421,7 +434,7 @@ AConsCall::lift(CEnv& cenv) } sz = (sz % 8 == 0) ? sz / 8 : sz / 8 + 1; - llvm::IRBuilder<>& builder = cenv.engine.builder; + llvm::IRBuilder<>& builder = llengine(cenv)->builder; StructType* sT = StructType::get(types, false); Type* pT = PointerType::get(sT, 0); @@ -456,7 +469,7 @@ AConsCall::compile(CEnv& cenv) for (size_t i = 1; i < size(); ++i) params[i-1] = LLVal(cenv.compile(at(i))); - return cenv.engine.builder.CreateCall(LLFunc(funcs.find(functionType(cenv))), + return llengine(cenv)->builder.CreateCall(LLFunc(funcs.find(functionType(cenv))), params.begin(), params.end()); } @@ -465,9 +478,9 @@ ACarCall::compile(CEnv& cenv) { AST* arg = maybeLookup(cenv, at(1)); Value* sP = LLVal(cenv.compile(arg)); - Value* s = cenv.engine.builder.CreateGEP(sP, ConstantInt::get(Type::Int32Ty, 0), "pair"); - Value* carP = cenv.engine.builder.CreateStructGEP(s, 0, "car"); - return cenv.engine.builder.CreateLoad(carP); + Value* s = llengine(cenv)->builder.CreateGEP(sP, ConstantInt::get(Type::Int32Ty, 0), "pair"); + Value* carP = llengine(cenv)->builder.CreateStructGEP(s, 0, "car"); + return llengine(cenv)->builder.CreateLoad(carP); } CValue @@ -475,9 +488,9 @@ ACdrCall::compile(CEnv& cenv) { AST* arg = maybeLookup(cenv, at(1)); Value* sP = LLVal(cenv.compile(arg)); - Value* s = cenv.engine.builder.CreateGEP(sP, ConstantInt::get(Type::Int32Ty, 0), "pair"); - Value* cdrP = cenv.engine.builder.CreateStructGEP(s, 1, "cdr"); - return cenv.engine.builder.CreateLoad(cdrP); + Value* s = llengine(cenv)->builder.CreateGEP(sP, ConstantInt::get(Type::Int32Ty, 0), "pair"); + Value* cdrP = llengine(cenv)->builder.CreateStructGEP(s, 1, "cdr"); + return llengine(cenv)->builder.CreateLoad(cdrP); } @@ -535,10 +548,10 @@ eval(CEnv& cenv, const string& name, istream& is) val = LLVal(cenv.compile(i->second)); // Finish function - cenv.engine.builder.CreateRet(val); + llengine(cenv)->builder.CreateRet(val); cenv.optimise(f); - cenv.log.out << call(resultType, cenv.engine.engine->getPointerToFunction(f)) + cenv.log.out << call(resultType, llengine(cenv)->engine->getPointerToFunction(f)) << " : " << resultType << endl; } catch (Error& e) { cenv.log.err << e.what() << endl; @@ -573,13 +586,13 @@ repl(CEnv& cenv) Function* f = compileFunction(cenv, cenv.gensym("_repl"), lltype(bodyT), ATuple()); try { Value* retVal = LLVal(cenv.compile(body)); - cenv.engine.builder.CreateRet(retVal); // Finish function + llengine(cenv)->builder.CreateRet(retVal); // Finish function cenv.optimise(f); } catch (Error& e) { f->eraseFromParent(); // Error reading body, remove function throw e; } - cenv.log.out << call(bodyT, cenv.engine.engine->getPointerToFunction(f)); + cenv.log.out << call(bodyT, llengine(cenv)->engine->getPointerToFunction(f)); } else { cenv.log.out << "; " << cenv.compile(body); } @@ -594,8 +607,8 @@ repl(CEnv& cenv) CEnv* newCenv(PEnv& penv, TEnv& tenv) { - CEngine* engine = new CEngine(); - CEnv* cenv = new CEnv(penv, tenv, *engine); + LLVMEngine* engine = new LLVMEngine(); + CEnv* cenv = new CEnv(penv, tenv, engine); // Host provided allocation primitive prototypes std::vector<const Type*> argsT(1, Type::Int32Ty); @@ -72,7 +72,7 @@ struct Exp { /*************************************************************************** - * Lexer: Text (istream) -> S-Expressions (SExp) (Prefix S for Syntactic) * + * Lexer: Text (istream) -> S-Expressions (SExp) * ***************************************************************************/ typedef Exp<string> SExp; ///< Textual S-Expression @@ -81,12 +81,12 @@ SExp readExpression(Cursor& cur, std::istream& in); /*************************************************************************** - * Backend (Prefix C for Compiled) * + * Backend * ***************************************************************************/ typedef void* CValue; ///< Compiled value (opaque) typedef void* CFunction; ///< Compiled function (opaque) -struct CEngine; ///< Backend data (opaque) +typedef void* CEngine; ///< Compiler Engine (opaque) /*************************************************************************** @@ -298,10 +298,10 @@ struct ACdrCall : public ACall { /*************************************************************************** - * Parser: S-Expressions (SExp) -> AST Nodes (AST) (Prefix P for Parsing) * + * Parser: S-Expressions (SExp) -> AST Nodes (AST) * ***************************************************************************/ -/// Parse Time Environment (symbol table) +/// Parse Time Environment (really just a symbol table) struct PEnv : private map<const string, ASymbol*> { typedef AST* (*PF)(PEnv&, const SExp&, void*); // Parse Function struct Handler { Handler(PF f, void* a=0) : func(f), arg(a) {} PF func; void* arg; }; @@ -403,7 +403,7 @@ struct Env : public list< map<K,V> > { /*************************************************************************** - * Typing (Prefix T for Type) * + * Typing * ***************************************************************************/ /// Type-Time Environment @@ -445,21 +445,21 @@ struct TEnv : public Env<const AST*,AType*> { /// Compile-Time Environment struct CEnv { - CEnv(PEnv& p, TEnv& t, CEngine& e, ostream& os=std::cout, ostream& es=std::cerr); + CEnv(PEnv& p, TEnv& t, CEngine e, ostream& os=std::cout, ostream& es=std::cerr); ~CEnv(); typedef Env<const ASymbol*, AST*> Code; typedef Env<const AST*, CValue> Vals; - string gensym(const char* s="_") { return (format("%s%d") % s % symID++).str(); } - void push() { code.push(); vals.push(); } - void pop() { code.pop(); vals.pop(); } - void precompile(AST* obj, CValue value) { vals.def(obj, value); } - CValue compile(AST* obj); - void optimise(CFunction f); - void write(std::ostream& os); + CEngine engine(); + string gensym(const char* s="_") { return (format("%s%d") % s % symID++).str(); } + void push() { code.push(); vals.push(); } + void pop() { code.pop(); vals.pop(); } + void precompile(AST* obj, CValue value) { vals.def(obj, value); } + CValue compile(AST* obj); + void optimise(CFunction f); + void write(std::ostream& os); - CEngine& engine; PEnv& penv; TEnv tenv; Code code; @@ -478,7 +478,6 @@ private: * EVAL/REPL/MAIN * ***************************************************************************/ -void initTypes(PEnv& penv, TEnv& tenv); void initLang(PEnv& penv, TEnv& tenv); CEnv* newCenv(PEnv& penv, TEnv& tenv); int eval(CEnv& cenv, const string& name, istream& is); |