aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-06-20 21:13:06 +0000
committerDavid Robillard <d@drobilla.net>2009-06-20 21:13:06 +0000
commit29e8db3d7c260d43d3721faea145cec1fbbf4144 (patch)
tree296e27cf335afb535e194e92e2c180ea87fe8955
parentd5556bc9a81ba5f5bd16f9c9d1d945f3e41355b7 (diff)
downloadresp-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--Makefile2
-rw-r--r--llvm.cpp183
-rw-r--r--tuplr.cpp22
-rw-r--r--tuplr.hpp26
4 files changed, 115 insertions, 118 deletions
diff --git a/Makefile b/Makefile
index 53770bc..de198e1 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/llvm.cpp b/llvm.cpp
index ddd5832..54999fc 100644
--- a/llvm.cpp
+++ b/llvm.cpp
@@ -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();
diff --git a/tuplr.cpp b/tuplr.cpp
index eaf351c..a8c4612 100644
--- a/tuplr.cpp
+++ b/tuplr.cpp
@@ -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;
diff --git a/tuplr.hpp b/tuplr.hpp
index 2da326a..268d0b1 100644
--- a/tuplr.hpp
+++ b/tuplr.hpp
@@ -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;
};