diff options
author | David Robillard <d@drobilla.net> | 2010-12-09 01:02:54 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2010-12-09 01:02:54 +0000 |
commit | e78acdecac3611299db12705c36bbc882efd42fe (patch) | |
tree | 7d1d964d9c2ba7e6d624782ef5bdc50603a16207 /src/llvm.cpp | |
parent | 82dc3a0291d993b5a1dd803aae8d166f263d7da2 (diff) | |
download | resp-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/llvm.cpp')
-rw-r--r-- | src/llvm.cpp | 259 |
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(); +} |