diff options
Diffstat (limited to 'llvm.cpp')
-rw-r--r-- | llvm.cpp | 183 |
1 files changed, 89 insertions, 94 deletions
@@ -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(); |