aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-12-09 01:02:54 +0000
committerDavid Robillard <d@drobilla.net>2010-12-09 01:02:54 +0000
commite78acdecac3611299db12705c36bbc882efd42fe (patch)
tree7d1d964d9c2ba7e6d624782ef5bdc50603a16207 /src
parent82dc3a0291d993b5a1dd803aae8d166f263d7da2 (diff)
downloadresp-e78acdecac3611299db12705c36bbc882efd42fe.tar.gz
resp-e78acdecac3611299db12705c36bbc882efd42fe.tar.bz2
resp-e78acdecac3611299db12705c36bbc882efd42fe.zip
Clean up engine code.
git-svn-id: http://svn.drobilla.net/resp/resp@320 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src')
-rw-r--r--src/c.cpp263
-rw-r--r--src/compile.cpp6
-rw-r--r--src/llvm.cpp259
-rw-r--r--src/repl.cpp10
-rw-r--r--src/resp.hpp39
5 files changed, 311 insertions, 266 deletions
diff --git a/src/c.cpp b/src/c.cpp
index 0e3596d..b4089bb 100644
--- a/src/c.cpp
+++ b/src/c.cpp
@@ -27,20 +27,57 @@
using namespace std;
using boost::format;
-typedef string Type;
-typedef string Value;
+/** C Engine (Compiler only) */
+struct CEngine : public Engine {
+ CEngine()
+ : out(
+ "#include <stdint.h>\n"
+ "#include <stdbool.h>\n"
+ "void* resp_gc_allocate(unsigned size, uint8_t tag);\n\n")
+ {
+ }
-struct Function {
- string returnType;
- string name;
- string text;
+ CFunc startFn(CEnv& cenv, const string& name, const ATuple* args, const AType* type);
+ void pushFnArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc f);
+ void finishFn(CEnv& cenv, CFunc f, CVal ret);
+ void eraseFn(CEnv& cenv, CFunc f);
+
+ CVal compileCall(CEnv& cenv, CFunc f, const AType* funcT, const vector<CVal>& args);
+ CVal compileCons(CEnv& cenv, const AType* type, CVal rtti, const vector<CVal>& fields);
+ CVal compileDot(CEnv& cenv, CVal tup, int32_t index);
+ CVal compileGlobal(CEnv& cenv, const AType* type, const string& sym, CVal val);
+ CVal compileGlobalGet(CEnv& cenv, const string& sym, CVal val);
+ IfState compileIfStart(CEnv& cenv);
+ void compileIfBranch(CEnv& cenv, IfState state, CVal condV, const AST* then);
+ CVal compileIfEnd(CEnv& cenv, IfState state, CVal elseV, const AType* type);
+ CVal compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag);
+ CVal compileLiteral(CEnv& cenv, const AST* lit);
+ CVal compilePrimitive(CEnv& cenv, const ATuple* prim);
+ CVal compileString(CEnv& cenv, const char* str);
+
+ void writeModule(CEnv& cenv, std::ostream& os);
+
+ const string call(CEnv& cenv, CFunc f, const AType* retT);
+
+private:
+ typedef string Type;
+ typedef string Value;
+
+ struct Function {
+ string returnType;
+ string name;
+ string text;
+ };
+
+ inline Value* llVal(CVal v) { return static_cast<Value*>(v); }
+ inline Function* llFunc(CFunc f) { return static_cast<Function*>(f); }
+ const Type* llType(const AType* t);
+
+ std::string out;
};
-static inline Value* llVal(CVal v) { return static_cast<Value*>(v); }
-static inline Function* llFunc(CFunc f) { return static_cast<Function*>(f); }
-
-static const Type*
-llType(const AType* t)
+const CEngine::Type*
+CEngine::llType(const AType* t)
{
if (t == NULL) {
return NULL;
@@ -85,111 +122,18 @@ llType(const AType* t)
return new Type("void*");
}
-
-/***************************************************************************
- * LLVM Engine *
- ***************************************************************************/
-
-struct CEngine : public Engine {
- CEngine()
- : out(
- "#include <stdint.h>\n"
- "#include <stdbool.h>\n"
- "void* resp_gc_allocate(unsigned size, uint8_t tag);\n\n")
- {
- }
-
- CFunc startFunction(CEnv& cenv,
- const std::string& name, const ATuple* args, const AType* type)
- {
- const AType* argsT = type->prot()->as_type();
- const AType* retT = type->list_ref(2)->as_type();
-
- vector<const Type*> cprot;
- FOREACHP(ATuple::const_iterator, i, argsT) {
- const AType* at = (*i)->as_type();
- THROW_IF(!llType(at), Cursor(), string("non-concrete parameter :: ")
- + at->str())
- cprot.push_back(llType(at));
- }
-
- THROW_IF(!llType(retT), Cursor(),
- (format("return has non-concrete type `%1%'") % retT->str()).str());
-
- Function* f = new Function();
- f->returnType = *llType(retT);
- f->name = name;
- f->text += f->returnType + "\n" + f->name + "(";
- ATuple::const_iterator ai = argsT->begin();
- ATuple::const_iterator ni = args->begin();
- for (; ai != argsT->end(); ++ai, ++ni) {
- if (ai != argsT->begin())
- f->text += ", ";
- f->text += *llType((*ai)->as_type()) + " " + (*ni)->as_symbol()->cppstr;
- }
- f->text += ")\n{\n";
-
- out += f->text;
-
- return f;
- }
-
- void pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc f);
-
- void finishFunction(CEnv& cenv, CFunc f, CVal ret) {
- out += "return " + *(Value*)ret + ";\n}\n\n";
- }
-
- void eraseFunction(CEnv& cenv, CFunc f) {
- cenv.err << "C backend does not support JIT (eraseFunction)" << endl;
- }
-
- CVal compileCall(CEnv& cenv, CFunc func, const AType* funcT, const vector<CVal>& args) {
- Value* varname = new string(cenv.penv.gensymstr("x"));
- Function* f = llFunc(func);
- out += (format("const %s %s = %s(") % f->returnType % *varname % f->name).str();
- FOREACH(vector<CVal>::const_iterator, i, args)
- out += *llVal(*i);
- out += ");\n";
- return varname;
- }
-
- CVal compileCons(CEnv& cenv, const AType* type, CVal rtti, const vector<CVal>& fields);
- CVal compileDot(CEnv& cenv, CVal tup, int32_t index);
- CVal compileLiteral(CEnv& cenv, const AST* lit);
- CVal compileString(CEnv& cenv, const char* str);
- CVal compilePrimitive(CEnv& cenv, const ATuple* prim);
- CVal compileIf(CEnv& cenv, const ATuple* aif);
- CVal compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag) { return NULL; }
- CVal compileGlobal(CEnv& cenv, const AType* type, const string& sym, CVal val);
- CVal compileGlobalGet(CEnv& cenv, const string& sym, CVal val);
-
- IfState compileIfStart(CEnv& cenv) { return NULL; }
- void compileIfBranch(CEnv& cenv, IfState state, CVal condV, const AST* then) {}
- CVal compileIfEnd(CEnv& cenv, IfState state, CVal elseV, const AType* type) { return NULL; }
-
- void writeModule(CEnv& cenv, std::ostream& os) {
- os << out;
- }
-
- const string call(CEnv& cenv, CFunc f, const AType* retT) {
- cenv.err << "C backend does not support JIT (call)" << endl;
- return "";
- }
-
- std::string out;
-};
-
-Engine*
-resp_new_c_engine()
+CVal
+CEngine::compileCall(CEnv& cenv, CFunc func, const AType* funcT, const vector<CVal>& args)
{
- return new CEngine();
+ Value* varname = new string(cenv.penv.gensymstr("x"));
+ Function* f = llFunc(func);
+ out += (format("const %s %s = %s(") % f->returnType % *varname % f->name).str();
+ FOREACH(vector<CVal>::const_iterator, i, args)
+ out += *llVal(*i);
+ out += ");\n";
+ return varname;
}
-/***************************************************************************
- * Code Generation *
- ***************************************************************************/
-
CVal
CEngine::compileCons(CEnv& cenv, const AType* type, CVal rtti, const vector<CVal>& fields)
{
@@ -214,8 +158,43 @@ CEngine::compileString(CEnv& cenv, const char* str)
return new Value(string("\"") + str + "\"");
}
+CFunc
+CEngine::startFn(CEnv& cenv, const std::string& name, const ATuple* args, const AType* type)
+{
+ const AType* argsT = type->prot()->as_type();
+ const AType* retT = type->list_ref(2)->as_type();
+
+ vector<const Type*> cprot;
+ FOREACHP(ATuple::const_iterator, i, argsT) {
+ const AType* at = (*i)->as_type();
+ THROW_IF(!llType(at), Cursor(), string("non-concrete parameter :: ")
+ + at->str())
+ cprot.push_back(llType(at));
+ }
+
+ THROW_IF(!llType(retT), Cursor(),
+ (format("return has non-concrete type `%1%'") % retT->str()).str());
+
+ Function* f = new Function();
+ f->returnType = *llType(retT);
+ f->name = name;
+ f->text += f->returnType + "\n" + f->name + "(";
+ ATuple::const_iterator ai = argsT->begin();
+ ATuple::const_iterator ni = args->begin();
+ for (; ai != argsT->end(); ++ai, ++ni) {
+ if (ai != argsT->begin())
+ f->text += ", ";
+ f->text += *llType((*ai)->as_type()) + " " + (*ni)->as_symbol()->cppstr;
+ }
+ f->text += ")\n{\n";
+
+ out += f->text;
+
+ return f;
+}
+
void
-CEngine::pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc f)
+CEngine::pushFnArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc f)
{
cenv.push();
@@ -233,6 +212,19 @@ CEngine::pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFu
}
}
+void
+CEngine::finishFn(CEnv& cenv, CFunc f, CVal ret)
+{
+ out += "return " + *(Value*)ret + ";\n}\n\n";
+}
+
+void
+CEngine::eraseFn(CEnv& cenv, CFunc f)
+{
+ cenv.err << "C backend does not support JIT (eraseFn)" << endl;
+}
+
+#if 0
CVal
CEngine::compileIf(CEnv& cenv, const ATuple* aif)
{
@@ -264,6 +256,30 @@ CEngine::compileIf(CEnv& cenv, const ATuple* aif)
return varname;
}
+#endif
+
+IfState
+CEngine::compileIfStart(CEnv& cenv)
+{
+ return NULL;
+}
+
+void
+CEngine::compileIfBranch(CEnv& cenv, IfState s, CVal condV, const AST* then)
+{
+}
+
+CVal
+CEngine::compileIfEnd(CEnv& cenv, IfState s, CVal elseV, const AType* type)
+{
+ return NULL;
+}
+
+CVal
+CEngine::compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag)
+{
+ return NULL;
+}
CVal
CEngine::compilePrimitive(CEnv& cenv, const ATuple* prim)
@@ -306,3 +322,22 @@ CEngine::compileGlobalGet(CEnv& cenv, const string& sym, CVal val)
{
return NULL;
}
+
+void
+CEngine::writeModule(CEnv& cenv, std::ostream& os)
+{
+ os << out;
+}
+
+const string
+CEngine::call(CEnv& cenv, CFunc f, const AType* retT)
+{
+ cenv.err << "C backend does not support JIT (call)" << endl;
+ return "";
+}
+
+Engine*
+resp_new_c_engine()
+{
+ return new CEngine();
+}
diff --git a/src/compile.cpp b/src/compile.cpp
index 48c2b0a..6a6eb06 100644
--- a/src/compile.cpp
+++ b/src/compile.cpp
@@ -44,8 +44,8 @@ compile_fn(CEnv& cenv, const ATuple* fn) throw()
return f;
// Write function declaration and push stack frame
- f = cenv.engine()->startFunction(cenv, cenv.name(fn), fn->prot(), type);
- cenv.engine()->pushFunctionArgs(cenv, fn->prot(), type, f);
+ f = cenv.engine()->startFn(cenv, cenv.name(fn), fn->prot(), type);
+ cenv.engine()->pushFnArgs(cenv, fn->prot(), type, f);
cenv.currentFn = f;
// Write function body
@@ -54,7 +54,7 @@ compile_fn(CEnv& cenv, const ATuple* fn) throw()
retVal = resp_compile(cenv, *i);
// Write function conclusion and pop stack frame
- cenv.engine()->finishFunction(cenv, f, retVal);
+ cenv.engine()->finishFn(cenv, f, retVal);
cenv.pop();
cenv.currentFn = NULL;
diff --git a/src/llvm.cpp b/src/llvm.cpp
index df755b3..81d2fe8 100644
--- a/src/llvm.cpp
+++ b/src/llvm.cpp
@@ -16,7 +16,7 @@
*/
/** @file
- * @brief Compile to LLVM IR
+ * @brief Compile to LLVM IR and/or execute via JIT
*/
#define __STDC_LIMIT_MACROS 1
@@ -46,81 +46,34 @@ using namespace llvm;
using namespace std;
using boost::format;
-/***************************************************************************
- * LLVM Engine *
- ***************************************************************************/
-
+/** LLVM Engine (Compiler and JIT) */
struct LLVMEngine : public Engine {
- LLVMEngine()
- : builder(context)
- , labelIndex(1)
- {
- InitializeNativeTarget();
- module = new Module("resp", context);
- engine = EngineBuilder(module).create();
- opt = new FunctionPassManager(module);
-
- // Set up optimiser pipeline
- const TargetData* target = engine->getTargetData();
- opt->add(new TargetData(*target)); // Register target arch
- opt->add(createInstructionCombiningPass()); // Simple optimizations
- opt->add(createReassociatePass()); // Reassociate expressions
- opt->add(createGVNPass()); // Eliminate Common Subexpressions
- opt->add(createCFGSimplificationPass()); // Simplify control flow
-
- // Declare host provided allocation primitive
- std::vector<const Type*> argsT(1, Type::getInt32Ty(context)); // unsigned size
- FunctionType* funcT = FunctionType::get(PointerType::get(Type::getInt8Ty(context), 0), argsT, false);
- alloc = Function::Create(funcT, Function::ExternalLinkage,
- "resp_gc_allocate", module);
- }
-
- ~LLVMEngine()
- {
- delete engine;
- delete opt;
- }
-
- inline Value* llVal(CVal v) { return static_cast<Value*>(v); }
- inline Function* llFunc(CFunc f) { return static_cast<Function*>(f); }
- const Type* llType(const AType* t);
-
- CFunc startFunction(
- CEnv& cenv, const std::string& name, const ATuple* args, const AType* type);
-
- void pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc f);
-
- void finishFunction(CEnv& cenv, CFunc f, CVal ret);
-
- void eraseFunction(CEnv& cenv, CFunc f) {
- if (f)
- llFunc(f)->eraseFromParent();
- }
-
- void appendBlock(LLVMEngine* engine, Function* function, BasicBlock* block) {
- function->getBasicBlockList().push_back(block);
- engine->builder.SetInsertPoint(block);
- }
-
- CVal compileCall(CEnv& cenv, CFunc f, const AType* funcT, const vector<CVal>& args) {
- vector<Value*> llArgs(*reinterpret_cast<const vector<Value*>*>(&args));
- Value* closure = builder.CreateBitCast(llArgs[0],
- llType(funcT->prot()->head()->as_type()),
- cenv.penv.gensymstr("you"));
- llArgs[0] = closure;
- return builder.CreateCall(llFunc(f), llArgs.begin(), llArgs.end());
- }
-
- CVal compileCons(CEnv& cenv, const AType* type, CVal rtti, const vector<CVal>& fields);
- CVal compileDot(CEnv& cenv, CVal tup, int32_t index);
- CVal compileLiteral(CEnv& cenv, const AST* lit);
- CVal compileString(CEnv& cenv, const char* str);
- CVal compilePrimitive(CEnv& cenv, const ATuple* prim);
- CVal compileIf(CEnv& cenv, const ATuple* aif);
- CVal compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag);
- CVal compileGlobal(CEnv& cenv, const AType* type, const string& sym, CVal val);
- CVal compileGlobalGet(CEnv& cenv, const string& sym, CVal val);
+ LLVMEngine();
+ virtual ~LLVMEngine();
+
+ CFunc startFn(CEnv& cenv, const string& name, const ATuple* args, const AType* type);
+ void pushFnArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc f);
+ void finishFn(CEnv& cenv, CFunc f, CVal ret);
+ void eraseFn(CEnv& cenv, CFunc f);
+
+ CVal compileCall(CEnv& cenv, CFunc f, const AType* funcT, const vector<CVal>& args);
+ CVal compileCons(CEnv& cenv, const AType* type, CVal rtti, const vector<CVal>& fields);
+ CVal compileDot(CEnv& cenv, CVal tup, int32_t index);
+ CVal compileGlobal(CEnv& cenv, const AType* type, const string& sym, CVal val);
+ CVal compileGlobalGet(CEnv& cenv, const string& sym, CVal val);
+ IfState compileIfStart(CEnv& cenv);
+ void compileIfBranch(CEnv& cenv, IfState state, CVal condV, const AST* then);
+ CVal compileIfEnd(CEnv& cenv, IfState state, CVal elseV, const AType* type);
+ CVal compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag);
+ CVal compileLiteral(CEnv& cenv, const AST* lit);
+ CVal compilePrimitive(CEnv& cenv, const ATuple* prim);
+ CVal compileString(CEnv& cenv, const char* str);
+
+ void writeModule(CEnv& cenv, std::ostream& os);
+ const string call(CEnv& cenv, CFunc f, const AType* retT);
+
+private:
typedef pair<Value*, BasicBlock*> IfBranch;
typedef vector<IfBranch> IfBranches;
@@ -131,50 +84,14 @@ struct LLVMEngine : public Engine {
IfBranches branches;
};
- IfState compileIfStart(CEnv& cenv);
- void compileIfBranch(CEnv& cenv, IfState state, CVal condV, const AST* then);
- CVal compileIfEnd(CEnv& cenv, IfState state, CVal elseV, const AType* type);
-
- void writeModule(CEnv& cenv, std::ostream& os) {
- AssemblyAnnotationWriter writer;
- llvm::raw_os_ostream raw_stream(os);
- module->print(raw_stream, &writer);
- }
-
- const string call(CEnv& cenv, CFunc f, const 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-concrete return type called");
-
- std::stringstream ss;
- if (t == Type::getInt32Ty(context)) {
- ss << ((int32_t (*)())fp)();
- } else if (t == Type::getFloatTy(context)) {
- ss << showpoint << ((float (*)())fp)();
- } else if (t == Type::getInt1Ty(context)) {
- ss << (((bool (*)())fp)() ? "#t" : "#f");
- } else if (retT->head()->str() == "String") {
- const std::string s(((char* (*)())fp)());
- ss << "\"";
- for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
- switch (*i) {
- case '\"':
- case '\\':
- ss << '\\';
- default:
- ss << *i;
- break;
- }
- }
- ss << "\"";
- } else if (t != Type::getVoidTy(context)) {
- ss << ((void* (*)())fp)();
- } else {
- ((void (*)())fp)();
- }
- return ss.str();
+ void appendBlock(LLVMEngine* engine, Function* function, BasicBlock* block) {
+ function->getBasicBlockList().push_back(block);
+ engine->builder.SetInsertPoint(block);
}
+
+ inline Value* llVal(CVal v) { return static_cast<Value*>(v); }
+ inline Function* llFunc(CFunc f) { return static_cast<Function*>(f); }
+ const Type* llType(const AType* t);
LLVMContext context;
Module* module;
@@ -186,10 +103,34 @@ struct LLVMEngine : public Engine {
unsigned labelIndex;
};
-Engine*
-resp_new_llvm_engine()
+LLVMEngine::LLVMEngine()
+ : builder(context)
+ , labelIndex(1)
{
- return new LLVMEngine();
+ InitializeNativeTarget();
+ module = new Module("resp", context);
+ engine = EngineBuilder(module).create();
+ opt = new FunctionPassManager(module);
+
+ // Set up optimiser pipeline
+ const TargetData* target = engine->getTargetData();
+ opt->add(new TargetData(*target)); // Register target arch
+ opt->add(createInstructionCombiningPass()); // Simple optimizations
+ opt->add(createReassociatePass()); // Reassociate expressions
+ opt->add(createGVNPass()); // Eliminate Common Subexpressions
+ opt->add(createCFGSimplificationPass()); // Simplify control flow
+
+ // Declare host provided allocation primitive
+ std::vector<const Type*> argsT(1, Type::getInt32Ty(context)); // unsigned size
+ FunctionType* funcT = FunctionType::get(PointerType::get(Type::getInt8Ty(context), 0), argsT, false);
+ alloc = Function::Create(funcT, Function::ExternalLinkage,
+ "resp_gc_allocate", module);
+}
+
+LLVMEngine::~LLVMEngine()
+{
+ delete engine;
+ delete opt;
}
const Type*
@@ -247,10 +188,22 @@ bitsToBytes(size_t bits)
}
CVal
+LLVMEngine::compileCall(CEnv& cenv, CFunc f, const AType* funcT, const vector<CVal>& args)
+{
+ vector<Value*> llArgs(*reinterpret_cast<const vector<Value*>*>(&args));
+ Value* closure = builder.CreateBitCast(llArgs[0],
+ llType(funcT->prot()->head()->as_type()),
+ cenv.penv.gensymstr("you"));
+ llArgs[0] = closure;
+ return builder.CreateCall(llFunc(f), llArgs.begin(), llArgs.end());
+}
+
+CVal
LLVMEngine::compileCons(CEnv& cenv, const AType* type, CVal rtti, const vector<CVal>& fields)
{
// Find size of memory required
- size_t s = engine->getTargetData()->getTypeSizeInBits(PointerType::get(Type::getInt8Ty(context), NULL));
+ size_t s = engine->getTargetData()->getTypeSizeInBits(
+ PointerType::get(Type::getInt8Ty(context), NULL));
assert(type->begin() != type->end());
for (AType::const_iterator i = type->iter_at(1); i != type->end(); ++i)
s += engine->getTargetData()->getTypeSizeInBits(llType((*i)->as_type()));
@@ -301,7 +254,7 @@ LLVMEngine::compileString(CEnv& cenv, const char* str)
}
CFunc
-LLVMEngine::startFunction(
+LLVMEngine::startFn(
CEnv& cenv, const std::string& name, const ATuple* args, const AType* type)
{
const AType* argsT = type->prot()->as_type();
@@ -340,7 +293,7 @@ LLVMEngine::startFunction(
}
void
-LLVMEngine::pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc cfunc)
+LLVMEngine::pushFnArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc cfunc)
{
cenv.push();
@@ -360,7 +313,7 @@ LLVMEngine::pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type,
}
void
-LLVMEngine::finishFunction(CEnv& cenv, CFunc f, CVal ret)
+LLVMEngine::finishFn(CEnv& cenv, CFunc f, CVal ret)
{
builder.CreateRet(llVal(ret));
if (verifyFunction(*static_cast<Function*>(f), llvm::PrintMessageAction)) {
@@ -371,6 +324,13 @@ LLVMEngine::finishFunction(CEnv& cenv, CFunc f, CVal ret)
opt->run(*static_cast<Function*>(f));
}
+void
+LLVMEngine::eraseFn(CEnv& cenv, CFunc f)
+{
+ if (f)
+ llFunc(f)->eraseFromParent();
+}
+
IfState
LLVMEngine::compileIfStart(CEnv& cenv)
{
@@ -497,3 +457,54 @@ LLVMEngine::compileGlobalGet(CEnv& cenv, const string& sym, CVal val)
LLVMEngine* engine = reinterpret_cast<LLVMEngine*>(cenv.engine());
return engine->builder.CreateLoad(llVal(val), sym + "Ptr");
}
+
+void
+LLVMEngine::writeModule(CEnv& cenv, std::ostream& os)
+{
+ AssemblyAnnotationWriter writer;
+ llvm::raw_os_ostream raw_stream(os);
+ module->print(raw_stream, &writer);
+}
+
+const string
+LLVMEngine::call(CEnv& cenv, CFunc f, const 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-concrete return type called");
+
+ std::stringstream ss;
+ if (t == Type::getInt32Ty(context)) {
+ ss << ((int32_t (*)())fp)();
+ } else if (t == Type::getFloatTy(context)) {
+ ss << showpoint << ((float (*)())fp)();
+ } else if (t == Type::getInt1Ty(context)) {
+ ss << (((bool (*)())fp)() ? "#t" : "#f");
+ } else if (retT->head()->str() == "String") {
+ const std::string s(((char* (*)())fp)());
+ ss << "\"";
+ for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
+ switch (*i) {
+ case '\"':
+ case '\\':
+ ss << '\\';
+ default:
+ ss << *i;
+ break;
+ }
+ }
+ ss << "\"";
+ } else if (t != Type::getVoidTy(context)) {
+ ss << ((void* (*)())fp)();
+ } else {
+ ((void (*)())fp)();
+ }
+ return ss.str();
+}
+
+Engine*
+resp_new_llvm_engine()
+{
+ return new LLVMEngine();
+}
diff --git a/src/repl.cpp b/src/repl.cpp
index 247799b..ae49b00 100644
--- a/src/repl.cpp
+++ b/src/repl.cpp
@@ -132,14 +132,14 @@ eval(CEnv& cenv, Cursor& cursor, istream& is, bool execute)
const AType* fnT = tup<const AType>(cursor, cenv.tenv.Fn, new AType(cursor), type, 0);
// Create function for top-level of program
- f = cenv.engine()->startFunction(cenv, "main", new ATuple(cursor), fnT);
+ f = cenv.engine()->startFn(cenv, "main", new ATuple(cursor), fnT);
// Compile expressions (other than function definitions) into it
for (Code::const_iterator i = exprs.begin(); i != exprs.end(); ++i)
val = resp_compile(cenv, *i);
// Finish compilation
- cenv.engine()->finishFunction(cenv, f, val);
+ cenv.engine()->finishFn(cenv, f, val);
if (cenv.args.find("-S") != cenv.args.end()) {
cenv.engine()->writeModule(cenv, cenv.out);
@@ -179,14 +179,14 @@ repl(CEnv& cenv)
CFunc f = NULL;
try {
// Create function for this repl loop
- f = cenv.engine()->startFunction(cenv, replFnName, new ATuple(cursor), fnT);
- cenv.engine()->finishFunction(cenv, f, resp_compile(cenv, ast));
+ f = cenv.engine()->startFn(cenv, replFnName, new ATuple(cursor), fnT);
+ cenv.engine()->finishFn(cenv, f, resp_compile(cenv, ast));
callPrintCollect(cenv, f, ast, type, true);
if (cenv.args.find("-d") != cenv.args.end())
cenv.engine()->writeModule(cenv, cenv.out);
} catch (Error& e) {
cenv.out << e.msg << endl;
- cenv.engine()->eraseFunction(cenv, f);
+ cenv.engine()->eraseFn(cenv, f);
}
} catch (Error& e) {
diff --git a/src/resp.hpp b/src/resp.hpp
index a3117a0..5f0899c 100644
--- a/src/resp.hpp
+++ b/src/resp.hpp
@@ -702,32 +702,31 @@ struct Engine {
typedef const vector<CVal> ValVec;
- virtual CFunc startFunction(CEnv& cenv,
- const std::string& name,
- const ATuple* args,
- const AType* type) = 0;
+ virtual CFunc startFn(CEnv& cenv,
+ const std::string& name,
+ const ATuple* args,
+ const AType* type) = 0;
- virtual void pushFunctionArgs(CEnv& cenv,
- const ATuple* prot,
- const AType* type,
- CFunc f) = 0;
+ virtual void pushFnArgs(CEnv& cenv,
+ const ATuple* prot,
+ const AType* type,
+ CFunc f) = 0;
- virtual void finishFunction(CEnv& cenv, CFunc f, CVal ret) = 0;
- virtual void eraseFunction(CEnv& cenv, CFunc f) = 0;
+ virtual void finishFn(CEnv& cenv, CFunc f, CVal ret) = 0;
+ virtual void eraseFn(CEnv& cenv, CFunc f) = 0;
- virtual CVal compileCons(CEnv& cenv, const AType* t, CVal rtti, ValVec& f) = 0;
- virtual CVal compileDot(CEnv& cenv, CVal tup, int32_t index) = 0;
- virtual CVal compileLiteral(CEnv& cenv, const AST* lit) = 0;
- virtual CVal compileString(CEnv& cenv, const char* str) = 0;
- virtual CVal compileCall(CEnv& cenv, CFunc f, const AType* fT, ValVec& args) = 0;
- virtual CVal compilePrimitive(CEnv& cenv, const ATuple* prim) = 0;
- virtual CVal compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag) = 0;
- virtual CVal compileGlobal(CEnv& cenv, const AType* t, const string& sym, CVal val) = 0;
- virtual CVal compileGlobalGet(CEnv& cenv, const string& sym, CVal val) = 0;
-
+ virtual CVal compileCall(CEnv& cenv, CFunc f, const AType* fT, ValVec& args) = 0;
+ virtual CVal compileCons(CEnv& cenv, const AType* t, CVal rtti, ValVec& f) = 0;
+ virtual CVal compileDot(CEnv& cenv, CVal tup, int32_t index) = 0;
+ virtual CVal compileGlobal(CEnv& cenv, const AType* t, const string& sym, CVal val) = 0;
+ virtual CVal compileGlobalGet(CEnv& cenv, const string& sym, CVal val) = 0;
virtual IfState compileIfStart(CEnv& cenv) = 0;
virtual void compileIfBranch(CEnv& cenv, IfState state, CVal condV, const AST* then) = 0;
virtual CVal compileIfEnd(CEnv& cenv, IfState state, CVal elseV, const AType* type) = 0;
+ virtual CVal compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag) = 0;
+ virtual CVal compileLiteral(CEnv& cenv, const AST* lit) = 0;
+ virtual CVal compilePrimitive(CEnv& cenv, const ATuple* prim) = 0;
+ virtual CVal compileString(CEnv& cenv, const char* str) = 0;
virtual void writeModule(CEnv& cenv, std::ostream& os) = 0;