aboutsummaryrefslogtreecommitdiffstats
path: root/src/llvm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm.cpp')
-rw-r--r--src/llvm.cpp259
1 files changed, 135 insertions, 124 deletions
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();
+}