aboutsummaryrefslogtreecommitdiffstats
path: root/llvm.cpp
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 /llvm.cpp
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
Diffstat (limited to 'llvm.cpp')
-rw-r--r--llvm.cpp183
1 files changed, 89 insertions, 94 deletions
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();