aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-03-12 05:41:26 +0000
committerDavid Robillard <d@drobilla.net>2009-03-12 05:41:26 +0000
commitad582fa2ba18ca4391c3d6c084d902d3b1fd5ca5 (patch)
tree354cf474ce07c2fa7a7aa1733f37288cbe135f12
parent251232bc3bbf6d98f9f6f91352bdcceef3b102f0 (diff)
downloadresp-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.cpp97
-rw-r--r--tuplr.hpp31
2 files changed, 70 insertions, 58 deletions
diff --git a/llvm.cpp b/llvm.cpp
index 4fcc5b6..48e9849 100644
--- a/llvm.cpp
+++ b/llvm.cpp
@@ -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);
diff --git a/tuplr.hpp b/tuplr.hpp
index cc0b086..8afcee7 100644
--- a/tuplr.hpp
+++ b/tuplr.hpp
@@ -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);