diff options
author | David Robillard <d@drobilla.net> | 2009-06-20 21:13:06 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-06-20 21:13:06 +0000 |
commit | 29e8db3d7c260d43d3721faea145cec1fbbf4144 (patch) | |
tree | 296e27cf335afb535e194e92e2c180ea87fe8955 | |
parent | d5556bc9a81ba5f5bd16f9c9d1d945f3e41355b7 (diff) | |
download | resp-29e8db3d7c260d43d3721faea145cec1fbbf4144.tar.gz resp-29e8db3d7c260d43d3721faea145cec1fbbf4144.tar.bz2 resp-29e8db3d7c260d43d3721faea145cec1fbbf4144.zip |
Make backend an object.
git-svn-id: http://svn.drobilla.net/resp/tuplr@142 ad02d1e2-f140-0410-9f75-f8b11f17cedd
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | llvm.cpp | 183 | ||||
-rw-r--r-- | tuplr.cpp | 22 | ||||
-rw-r--r-- | tuplr.hpp | 26 |
4 files changed, 115 insertions, 118 deletions
@@ -10,7 +10,7 @@ all: builddir build/tuplr builddir: mkdir -p build -build/tuplr: build/tuplr.o build/typing.o build/llvm.o build/gclib.so build/write.o build/gc.o +build/tuplr: build/tuplr.o build/typing.o build/llvm.so build/gclib.so build/write.o build/gc.o g++ -o $@ $^ $(LDFLAGS) build/%.o: %.cpp tuplr.hpp @@ -52,10 +52,10 @@ llType(const AType* t) /*************************************************************************** - * Engine * + * LLVM Engine * ***************************************************************************/ -struct LLVMEngine { +struct LLVMEngine : public Engine { LLVMEngine() : module(new Module("tuplr")) , engine(ExecutionEngine::create(module)) @@ -77,120 +77,103 @@ struct LLVMEngine { alloc = Function::Create(funcT, Function::ExternalLinkage, "tuplr_gc_allocate", module); } - Module* module; - ExecutionEngine* engine; - IRBuilder<> builder; - CFunction alloc; - ExistingModuleProvider emp; - FunctionPassManager opt; -}; -static LLVMEngine* -llEngine(CEnv& cenv) -{ - return reinterpret_cast<LLVMEngine*>(cenv.engine()); -} + CFunction startFunction(CEnv& cenv, + const std::string& name, const AType* retT, const ATuple& argsT, + const vector<string> argNames) + { + Function::LinkageTypes linkage = Function::ExternalLinkage; -#define LITERAL(CT, NAME, COMPILED) \ -template<> CValue ALiteral<CT>::compile(CEnv& cenv) { return (COMPILED); } \ -template<> void \ -ALiteral<CT>::constrain(TEnv& tenv, Constraints& c) const { \ - c.constrain(tenv, this, tenv.named(NAME)); \ -} + vector<const Type*> cprot; + for (size_t i = 0; i < argsT.size(); ++i) { + AType* at = argsT.at(i)->as<AType*>(); + THROW_IF(!llType(at), Cursor(), "function parameter is untyped") + cprot.push_back(llType(at)); + } -/// Literal template instantiations -LITERAL(int32_t, "Int", ConstantInt::get(Type::Int32Ty, val, true)) -LITERAL(float, "Float", ConstantFP::get(Type::FloatTy, val)) -LITERAL(bool, "Bool", ConstantInt::get(Type::Int1Ty, val, false)) + THROW_IF(!llType(retT), Cursor(), "function return is untyped"); + FunctionType* fT = FunctionType::get(llType(retT), cprot, false); + Function* f = Function::Create(fT, linkage, name, module); -CFunction -startFunction(CEnv& cenv, const std::string& name, const AType* retT, const ATuple& argsT, - const vector<string> argNames) -{ - Function::LinkageTypes linkage = Function::ExternalLinkage; + if (f->getName() != name) { + cenv.out << "DIFFERENT NAME: " << f->getName() << endl; + /*f->eraseFromParent(); + throw Error(Cursor(), (format("function `%1%' redefined") % name).str());*/ + } - vector<const Type*> cprot; - for (size_t i = 0; i < argsT.size(); ++i) { - AType* at = argsT.at(i)->as<AType*>(); - THROW_IF(!llType(at), Cursor(), "function parameter is untyped") - cprot.push_back(llType(at)); - } + // Set argument names in generated code + Function::arg_iterator a = f->arg_begin(); + if (!argNames.empty()) + for (size_t i = 0; i != argsT.size(); ++a, ++i) + a->setName(argNames.at(i)); - THROW_IF(!llType(retT), Cursor(), "function return is untyped"); - FunctionType* fT = FunctionType::get(llType(retT), cprot, false); - Function* f = Function::Create(fT, linkage, name, llEngine(cenv)->module); + BasicBlock* bb = BasicBlock::Create("entry", f); + builder.SetInsertPoint(bb); - if (f->getName() != name) { - cenv.out << "DIFFERENT NAME: " << f->getName() << endl; - /*f->eraseFromParent(); - throw Error(Cursor(), (format("function `%1%' redefined") % name).str());*/ + return f; } - // Set argument names in generated code - Function::arg_iterator a = f->arg_begin(); - if (!argNames.empty()) - for (size_t i = 0; i != argsT.size(); ++a, ++i) - a->setName(argNames.at(i)); + void finishFunction(CEnv& cenv, CFunction f, CValue ret) { + Value* retVal = llVal(ret); + builder.CreateRet(retVal); - BasicBlock* bb = BasicBlock::Create("entry", f); - llEngine(cenv)->builder.SetInsertPoint(bb); - - return f; -} + verifyFunction(*static_cast<Function*>(f)); + if (cenv.args.find("-g") == cenv.args.end()) + opt.run(*static_cast<Function*>(f)); + } -void -finishFunction(CEnv& cenv, CFunction f, CValue ret) -{ - Value* retVal = llVal(ret); - llEngine(cenv)->builder.CreateRet(retVal); + void eraseFunction(CEnv& cenv, CFunction f) { + if (f) + llFunc(f)->eraseFromParent(); + } - verifyFunction(*static_cast<Function*>(f)); - if (cenv.args.find("-g") == cenv.args.end()) - llEngine(cenv)->opt.run(*static_cast<Function*>(f)); -} + void writeModule(CEnv& cenv, std::ostream& os) { + AssemblyAnnotationWriter writer; + module->print(os, &writer); + } -void -eraseFunction(CEnv& cenv, CFunction f) -{ - if (f) - llFunc(f)->eraseFromParent(); -} + const string call(CEnv& cenv, CFunction f, AType* retT) { + void* fp = engine->getPointerToFunction(llFunc(f)); + const Type* t = llType(retT); + THROW_IF(!fp, Cursor(), "unable to get function pointer"); + THROW_IF(!t, Cursor(), "function with non-primitive return type called"); + + std::stringstream ss; + if (t == Type::Int32Ty) + ss << ((int32_t (*)())fp)(); + else if (t == Type::FloatTy) + ss << showpoint << ((float (*)())fp)(); + else if (t == Type::Int1Ty) + ss << (((bool (*)())fp)() ? "#t" : "#f"); + else + ss << ((void* (*)())fp)(); + return ss.str(); + } -void -writeModule(CEnv& cenv, std::ostream& os) -{ - AssemblyAnnotationWriter writer; - llEngine(cenv)->module->print(os, &writer); -} + Module* module; + ExecutionEngine* engine; + IRBuilder<> builder; + CFunction alloc; + ExistingModuleProvider emp; + FunctionPassManager opt; +}; -const string -call(CEnv& cenv, CFunction f, AType* retT) +static LLVMEngine* +llEngine(CEnv& cenv) { - void* fp = llEngine(cenv)->engine->getPointerToFunction(llFunc(f)); - const Type* t = llType(retT); - THROW_IF(!fp, Cursor(), "unable to get function pointer"); - THROW_IF(!t, Cursor(), "function with non-primitive return type called"); - - std::stringstream ss; - if (t == Type::Int32Ty) - ss << ((int32_t (*)())fp)(); - else if (t == Type::FloatTy) - ss << showpoint << ((float (*)())fp)(); - else if (t == Type::Int1Ty) - ss << (((bool (*)())fp)() ? "#t" : "#f"); - else - ss << ((void* (*)())fp)(); - return ss.str(); + return reinterpret_cast<LLVMEngine*>(cenv.engine()); } -CEngine +/// Shared library entry point +Engine* tuplr_new_engine() { return new LLVMEngine(); } +/// Shared library entry point void -tuplr_free_engine(CEngine engine) +tuplr_free_engine(Engine* engine) { delete (LLVMEngine*)engine; } @@ -200,6 +183,18 @@ tuplr_free_engine(CEngine engine) * Code Generation * ***************************************************************************/ +#define LITERAL(CT, NAME, COMPILED) \ +template<> CValue ALiteral<CT>::compile(CEnv& cenv) { return (COMPILED); } \ +template<> void \ +ALiteral<CT>::constrain(TEnv& tenv, Constraints& c) const { \ + c.constrain(tenv, this, tenv.named(NAME)); \ +} + +/// Literal template instantiations +LITERAL(int32_t, "Int", ConstantInt::get(Type::Int32Ty, val, true)) +LITERAL(float, "Float", ConstantFP::get(Type::FloatTy, val)) +LITERAL(bool, "Bool", ConstantInt::get(Type::Int1Ty, val, false)) + CValue ASymbol::compile(CEnv& cenv) { @@ -260,7 +255,7 @@ AFn::liftCall(CEnv& cenv, const AType& argsT) // Write function declaration const string name = (this->name == "") ? cenv.gensym("_fn") : this->name; - Function* f = llFunc(startFunction(cenv, name, + Function* f = llFunc(cenv.engine()->startFunction(cenv, name, thisType->at(thisType->size()-1)->to<AType*>(), *protT, argNames)); @@ -330,7 +325,7 @@ AFn::liftCall(CEnv& cenv, const AType& argsT) CValue retVal = NULL; for (size_t i = 2; i < size(); ++i) retVal = cenv.compile(at(i)); - finishFunction(cenv, f, retVal); + cenv.engine()->finishFunction(cenv, f, retVal); } catch (Error& e) { f->eraseFromParent(); // Error reading body, remove function cenv.pop(); @@ -264,21 +264,21 @@ eval(CEnv& cenv, const string& name, istream& is) } // Create function for top-level of program - CFunction f = startFunction(cenv, "main", resultType, ATuple(cursor)); + CFunction f = cenv.engine()->startFunction(cenv, "main", resultType, ATuple(cursor)); // Compile all expressions into it CValue val = NULL; for (list< pair<SExp, AST*> >::const_iterator i = exprs.begin(); i != exprs.end(); ++i) val = cenv.compile(i->second); - finishFunction(cenv, f, val); + cenv.engine()->finishFunction(cenv, f, val); - cenv.out << call(cenv, f, resultType) << " : " << resultType << endl; + cenv.out << cenv.engine()->call(cenv, f, resultType) << " : " << resultType << endl; Object::pool.collect(Object::pool.roots()); if (cenv.args.find("-d") != cenv.args.end()) - writeModule(cenv, cenv.out); + cenv.engine()->writeModule(cenv, cenv.out); } catch (Error& e) { cenv.err << e.what() << endl; @@ -315,17 +315,17 @@ repl(CEnv& cenv) CFunction f = NULL; try { // Create anonymous function to insert code into - f = startFunction(cenv, cenv.gensym("_repl"), bodyT, ATuple(cursor)); + f = cenv.engine()->startFunction(cenv, cenv.gensym("_repl"), bodyT, ATuple(cursor)); CValue retVal = cenv.compile(body); - finishFunction(cenv, f, retVal); - cenv.out << call(cenv, f, bodyT); + cenv.engine()->finishFunction(cenv, f, retVal); + cenv.out << cenv.engine()->call(cenv, f, bodyT); } catch (Error& e) { ADef* def = body->to<ADef*>(); if (def) cenv.out << def->sym(); else cenv.out << "?"; - eraseFunction(cenv, f); + cenv.engine()->eraseFunction(cenv, f); } cenv.out << " : " << cenv.type(body) << endl; @@ -337,7 +337,7 @@ repl(CEnv& cenv) cenv.tsubst = oldSubst; if (cenv.args.find("-d") != cenv.args.end()) - writeModule(cenv, cenv.out); + cenv.engine()->writeModule(cenv, cenv.out); } catch (Error& e) { cenv.err << e.what() << endl; @@ -375,7 +375,7 @@ main(int argc, char** argv) TEnv tenv(penv); initLang(penv, tenv); - CEngine engine = tuplr_new_engine(); + Engine* engine = tuplr_new_engine(); CEnv* cenv = new CEnv(penv, tenv, engine); cenv->push(); @@ -445,7 +445,7 @@ main(int argc, char** argv) if (output != "") { ofstream os(output.c_str()); if (os.good()) { - writeModule(*cenv, os); + cenv->engine()->writeModule(*cenv, os); } else { cerr << argv[0] << ": " << a->second << ": " << strerror(errno) << endl; ++ret; @@ -556,22 +556,24 @@ struct TEnv : public Env< const ASymbol*, pair<AST*, AType*> > { * Code Generation * ***************************************************************************/ -CFunction startFunction(CEnv& cenv, const std::string& name, - const AType* retT, const ATuple& argsT, - const vector<string> argNames=vector<string>()); +struct Engine { + virtual CFunction startFunction(CEnv& cenv, const std::string& name, + const AType* retT, const ATuple& argsT, + const vector<string> argNames=vector<string>()) = 0; -CEngine tuplr_new_engine(); -void tuplr_free_engine(CEngine engine); + virtual void finishFunction(CEnv& cenv, CFunction f, CValue ret) = 0; + virtual void eraseFunction(CEnv& cenv, CFunction f) = 0; + virtual void writeModule(CEnv& cenv, std::ostream& os) = 0; -void finishFunction(CEnv& cenv, CFunction f, CValue ret); -void eraseFunction(CEnv& cenv, CFunction f); -void writeModule(CEnv& cenv, std::ostream& os); + virtual const string call(CEnv& cenv, CFunction f, AType* retT) = 0; +}; -const string call(CEnv& cenv, CFunction f, AType* retT); +Engine* tuplr_new_engine(); +void tuplr_free_engine(Engine* engine); /// 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, Engine* e, ostream& os=std::cout, ostream& es=std::cerr) : out(os), err(es), penv(p), tenv(t), symID(0), _engine(e) {} @@ -580,7 +582,7 @@ struct CEnv { typedef Env<const ASymbol*, AST*> Code; typedef Env<const AST*, CValue> Vals; - CEngine engine() { return _engine; } + Engine* engine() { return _engine; } string gensym(const char* s="_") { return (format("%s%d") % s % symID++).str(); } void push() { tenv.push(); vals.push(); } void pop() { tenv.pop(); vals.pop(); } @@ -613,7 +615,7 @@ struct CEnv { map<string,string> args; private: - CEngine _engine; + Engine* _engine; }; |