diff options
Diffstat (limited to 'src/llvm.cpp')
-rw-r--r-- | src/llvm.cpp | 131 |
1 files changed, 69 insertions, 62 deletions
diff --git a/src/llvm.cpp b/src/llvm.cpp index c4744c3..7f521b7 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -30,22 +30,24 @@ #include <boost/format.hpp> -#include "llvm/Value.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/AssemblyAnnotationWriter.h" +#include "llvm/DefaultPasses.h" #include "llvm/DerivedTypes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/Instructions.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/PassManager.h" -#include "llvm/Support/raw_os_ostream.h" #include "llvm/Support/IRBuilder.h" -#include "llvm/Support/StandardPasses.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_os_ostream.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetSelect.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Value.h" #include "resp.hpp" @@ -54,22 +56,25 @@ using namespace std; using boost::format; struct IfRecord { - IfRecord(LLVMContext& context, unsigned labelIndex, const Type* t) + IfRecord(LLVMContext& context, unsigned labelIndex, Type* t) : type(t) , mergeBB(BasicBlock::Create(context, "endif")) , thenBB(BasicBlock::Create(context, (format("then%1%") % labelIndex).str())) , elseBB(BasicBlock::Create(context, (format("else%1%") % labelIndex).str())) , thenV(NULL) , elseV(NULL) + , nMergeBranches(0) {} - const Type* type; + Type* type; BasicBlock* mergeBB; BasicBlock* thenBB; BasicBlock* elseBB; Value* thenV; Value* elseV; + + unsigned nMergeBranches; }; /** LLVM Engine (Compiler and JIT) */ @@ -84,7 +89,7 @@ struct LLVMEngine : public Engine { CVal compileCall(CEnv& cenv, CFunc f, const ATuple* funcT, const vector<CVal>& args); CVal compileCast(CEnv& cenv, CVal v, const AST* t); - CVal compileCons(CEnv& cenv, const ATuple* type, CVal rtti, const vector<CVal>& fields); + CVal compileCons(CEnv& cenv, const char* tname, const ATuple* type, CVal rtti, const vector<CVal>& fields); CVal compileDot(CEnv& cenv, CVal tup, int32_t index); CVal compileGlobalSet(CEnv& cenv, const string& s, CVal v, const AST* t); CVal compileGlobalGet(CEnv& cenv, const string& s, CVal v); @@ -111,7 +116,7 @@ private: inline Value* llVal(CVal v) { return static_cast<Value*>(v); } inline Function* llFunc(CFunc f) { return static_cast<Function*>(f); } - const Type* llType(const AST* t, const char* name=NULL); + Type* llType(const AST* t, const char* name=NULL); LLVMContext context; Module* module; @@ -122,10 +127,10 @@ private: PassManager* modOpt; CType objectT; - PATypeHolder* opaqueT; - std::string opaqueName; + StructType* opaqueT; + std::string opaqueName; - typedef std::map<const std::string, const Type*> CTypes; + typedef std::map<const std::string, Type*> CTypes; CTypes compiledTypes; typedef std::stack<IfRecord*> IfStack; @@ -149,22 +154,22 @@ LLVMEngine::LLVMEngine() modOpt = new PassManager(); // Set up optimisers - unsigned optLevel = 3; - createStandardFunctionPasses(fnOpt, optLevel); - createStandardModulePasses(modOpt, optLevel, false, true, true, true, false, NULL); + PassManagerBuilder pmb; + pmb.OptLevel = 3; + pmb.populateFunctionPassManager(*fnOpt); + pmb.populateModulePassManager(*modOpt); // Declare host provided allocation primitive - std::vector<const Type*> argsT(1, Type::getInt32Ty(context)); // unsigned size + std::vector<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_alloc", module); // Build Object type (tag only, binary compatible with any constructed thing) - vector<const Type*> ctypes; + vector<Type*> ctypes; ctypes.push_back(PointerType::get(Type::getInt8Ty(context), 0)); // RTTI - StructType* cObjectT = StructType::get(context, ctypes, false); - module->addTypeName("Object", cObjectT); + StructType* cObjectT = StructType::create(context, ctypes, "Object", false); objectT = cObjectT; } @@ -175,7 +180,7 @@ LLVMEngine::~LLVMEngine() delete modOpt; } -const Type* +Type* LLVMEngine::llType(const AST* t, const char* name) { if (t == NULL) { @@ -191,7 +196,7 @@ LLVMEngine::llType(const AST* t, const char* name) if (sym == "Expr") return PointerType::get(Type::getInt8Ty(context), 0); if (sym == opaqueName) { THROW_IF(!opaqueT, t->loc, "Broken recursive type"); - return *opaqueT; + return PointerType::getUnqual(opaqueT); } CTypes::const_iterator i = compiledTypes.find(sym); @@ -205,15 +210,7 @@ LLVMEngine::llType(const AST* t, const char* name) THROW_IF(!isupper(t->as_tuple()->fst()->str()[0]), t->loc, "Lower-case type expression"); - // Define opaque type to stand for name in recursive type body - if (name) { - THROW_IF(opaqueT, t->loc, "Nested recursive types"); - opaqueT = new PATypeHolder(OpaqueType::get(context)); - opaqueName = name; - } - - const Type* ret; - + // Function type if (is_form(t, "Fn")) { ATuple::const_iterator i = t->as_tuple()->begin(); const ATuple* protT = (*++i)->to_tuple(); @@ -221,47 +218,48 @@ LLVMEngine::llType(const AST* t, const char* name) if (!llType(retT)) return NULL; - vector<const Type*> cprot; + vector<Type*> cprot; FOREACHP(ATuple::const_iterator, i, protT) { - const Type* lt = llType(*i); + Type* lt = llType(*i); if (!lt) return NULL; cprot.push_back(lt); } - ret = FunctionType::get(llType(retT), cprot, false); + return PointerType::getUnqual(FunctionType::get(llType(retT), cprot, false)); + } - } else { - vector<const Type*> ctypes; - ctypes.push_back(PointerType::get(Type::getInt8Ty(context), 0)); // RTTI - for (ATuple::const_iterator i = t->as_tuple()->iter_at(1); i != t->as_tuple()->end(); ++i) { - const Type* lt = llType(*i); - if (!lt) - return NULL; - ctypes.push_back(lt); - } + // Struct type + Type* ret = NULL; + vector<Type*> ctypes; - ret = StructType::get(context, ctypes, false); + // Define opaque type to stand for name in recursive type body + if (name) { + THROW_IF(opaqueT, t->loc, "Nested recursive types"); + opaqueT = StructType::create(context, name); + opaqueName = name; } - if (!ret) { - cerr << "WARNING: No low-level type for " << t << endl; - return NULL; + // Get member types + ctypes.push_back(PointerType::get(Type::getInt8Ty(context), 0)); // RTTI + for (ATuple::const_iterator i = t->as_tuple()->iter_at(1); i != t->as_tuple()->end(); ++i) { + Type* lt = llType(*i); + if (!lt) + return NULL; + ctypes.push_back(lt); } - // Tell LLVM opaqueT is actually ret* (for recursive types) - const PointerType* ptrT(PointerType::get(ret, 0)); - if (name) { - PATypeHolder retT(ret); - ((OpaqueType*)opaqueT->get())->refineAbstractTypeTo(ptrT); - ptrT = cast<PointerType>(opaqueT->get()); // update potentially invalidated type + // Resolve recursive type + opaqueT->setBody(ctypes); + ret = opaqueT; opaqueT = NULL; opaqueName = ""; - module->addTypeName(name, retT.get()); + } else { + ret = StructType::get(context, ctypes, false); } - return ptrT; + return PointerType::getUnqual(ret); } /** Convert a size in bits to bytes, rounding up as necessary */ @@ -275,17 +273,17 @@ CVal LLVMEngine::compileCall(CEnv& cenv, CFunc f, const ATuple* funcT, const vector<CVal>& args) { vector<Value*> llArgs(*reinterpret_cast<const vector<Value*>*>(&args)); - return builder.CreateCall(llFunc(f), llArgs.begin(), llArgs.end()); + return builder.CreateCall(llFunc(f), llArgs); } CVal LLVMEngine::compileCast(CEnv& cenv, CVal v, const AST* t) { - return builder.CreateBitCast(llVal(v), (const Type*)compileType(cenv, NULL, t), "cast"); + return builder.CreateBitCast(llVal(v), (Type*)compileType(cenv, NULL, t), "cast"); } CVal -LLVMEngine::compileCons(CEnv& cenv, const ATuple* type, CVal rtti, const vector<CVal>& fields) +LLVMEngine::compileCons(CEnv& cenv, const char* tname, const ATuple* type, CVal rtti, const vector<CVal>& fields) { // Find size of memory required size_t s = engine->getTargetData()->getTypeSizeInBits( @@ -293,13 +291,20 @@ LLVMEngine::compileCons(CEnv& cenv, const ATuple* type, CVal rtti, const vector< assert(type->begin() != type->end()); for (ATuple::const_iterator i = type->iter_at(1); i != type->end(); ++i) s += engine->getTargetData()->getTypeSizeInBits( - (const Type*)compileType(cenv, NULL, *i)); + (Type*)compileType(cenv, NULL, *i)); // Allocate struct const std::string name = type->fst()->str(); Value* structSize = ConstantInt::get(Type::getInt32Ty(context), bitsToBytes(s)); Value* mem = builder.CreateCall(alloc, structSize, name + "_mem"); - Value* structPtr = builder.CreateBitCast(mem, llType(type), name); + + StructType* consT = module->getTypeByName(tname); + Value* structPtr = NULL; + if (consT) { // Named type + structPtr = builder.CreateBitCast(mem, PointerType::getUnqual(consT), name); + } else { // Anonymous type + structPtr = builder.CreateBitCast(mem, llType(type), name); + } // Set struct fields if (rtti) @@ -357,7 +362,7 @@ LLVMEngine::compileType(CEnv& cenv, const char* name, const AST* expr) return i->second; } - const Type* const type = llType(expr, name); + Type* const type = llType(expr, name); if (name) compiledTypes.insert(make_pair(name, type)); @@ -374,12 +379,12 @@ LLVMEngine::startFn( Function::LinkageTypes linkage = Function::ExternalLinkage; - vector<const Type*> cprot; + vector<Type*> cprot; FOREACHP(ATuple::const_iterator, i, argsT) { const char* name = (*i)->to_symbol() ? (*i)->as_symbol()->sym() : NULL; CType iT = compileType(cenv, name, cenv.resolveType(*i)); THROW_IF(!iT, Cursor(), string("non-concrete parameter :: ") + (*i)->str()); - cprot.push_back((const Type*)iT); + cprot.push_back((Type*)iT); } THROW_IF(!llType(retT), Cursor(), @@ -511,6 +516,7 @@ LLVMEngine::compileIfElse(CEnv& cenv, CVal elseV) if (elseV) { engine->builder.CreateBr(rec->mergeBB); + ++rec->nMergeBranches; } else { engine->builder.CreateUnreachable(); } @@ -528,7 +534,8 @@ LLVMEngine::compileIfEnd(CEnv& cenv) // Emit merge block (Phi node) appendBlock(engine, parent, rec->mergeBB); - PHINode* pn = engine->builder.CreatePHI(rec->type, "ifval"); + ++rec->nMergeBranches; + PHINode* pn = engine->builder.CreatePHI(rec->type, rec->nMergeBranches, "ifval"); pn->addIncoming(rec->thenV, rec->thenBB); if (rec->elseV) pn->addIncoming(rec->elseV, rec->elseBB); |