diff options
Diffstat (limited to 'src/llvm.cpp')
-rw-r--r-- | src/llvm.cpp | 88 |
1 files changed, 39 insertions, 49 deletions
diff --git a/src/llvm.cpp b/src/llvm.cpp index 5b6d69f..6243919 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -123,7 +123,7 @@ struct LLVMEngine : public Engine { return PointerType::get(StructType::get(context, ctypes, false), 0); } - return NULL; // non-primitive type + return PointerType::get(Type::getVoidTy(context), NULL); } CFunc startFunction(CEnv& cenv, @@ -161,13 +161,12 @@ struct LLVMEngine : public Engine { return f; } - void finishFunction(CEnv& cenv, CFunc f, const AType* retT, CVal ret) { - if (retT->concrete()) - builder.CreateRet(llVal(ret)); - else - builder.CreateRetVoid(); - - verifyFunction(*static_cast<Function*>(f)); + void finishFunction(CEnv& cenv, CFunc f, CVal ret) { + builder.CreateRet(llVal(ret)); + if (verifyFunction(*static_cast<Function*>(f), llvm::PrintMessageAction)) { + module->dump(); + throw Error(Cursor(), "Broken module"); + } if (cenv.args.find("-g") == cenv.args.end()) opt->run(*static_cast<Function*>(f)); } @@ -177,19 +176,23 @@ struct LLVMEngine : public Engine { llFunc(f)->eraseFromParent(); } - CVal compileCall(CEnv& cenv, CFunc f, const vector<CVal>& args) { - const vector<Value*>& llArgs = *reinterpret_cast<const vector<Value*>*>(&args); + 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<const AType*>()), + cenv.penv.gensymstr("you")); + llArgs[0] = closure; return builder.CreateCall(llFunc(f), llArgs.begin(), llArgs.end()); } - CFunc compileFunction(CEnv& cenv, AFn* fn, const AType& argsT); + CFunc compileFunction(CEnv& cenv, AFn* fn, const AType* type); CVal compileTup(CEnv& cenv, const AType* type, const vector<CVal>& fields); CVal compileDot(CEnv& cenv, CVal tup, int32_t index); CVal compileLiteral(CEnv& cenv, AST* lit); CVal compilePrimitive(CEnv& cenv, APrimitive* prim); CVal compileIf(CEnv& cenv, AIf* aif); - CVal compileGlobal(CEnv& cenv, AType* type, const string& name, CVal val); + CVal compileGlobal(CEnv& cenv, const AType* type, const string& name, CVal val); CVal getGlobal(CEnv& cenv, CVal val); void writeModule(CEnv& cenv, std::ostream& os) { @@ -197,7 +200,7 @@ struct LLVMEngine : public Engine { module->print(os, &writer); } - const string call(CEnv& cenv, CFunc f, AType* retT) { + 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"); @@ -248,8 +251,9 @@ LLVMEngine::compileTup(CEnv& cenv, const AType* type, const vector<CVal>& fields { // Find size of memory required size_t s = 0; + assert(type->begin() != type->end()); for (AType::const_iterator i = type->begin() + 1; i != type->end(); ++i) - s += llType((*i)->as<AType*>())->getPrimitiveSizeInBits(); + s += engine->getTargetData()->getTypeSizeInBits(llType((*i)->as<AType*>())); // Allocate struct Value* structSize = ConstantInt::get(Type::getInt32Ty(context), bitsToBytes(s)); @@ -259,8 +263,8 @@ LLVMEngine::compileTup(CEnv& cenv, const AType* type, const vector<CVal>& fields // Set struct fields size_t i = 0; for (vector<CVal>::const_iterator f = fields.begin(); f != fields.end(); ++f, ++i) { - Value* v = builder.CreateStructGEP(structPtr, i, (format("tup%1%") % i).str().c_str()); - builder.CreateStore(llVal(*f), v); + builder.CreateStore(llVal(*f), + builder.CreateStructGEP(structPtr, i, (format("tup%1%") % i).str().c_str())); } return structPtr; @@ -292,28 +296,13 @@ LLVMEngine::compileLiteral(CEnv& cenv, AST* lit) } CFunc -LLVMEngine::compileFunction(CEnv& cenv, AFn* fn, const AType& argsT) +LLVMEngine::compileFunction(CEnv& cenv, AFn* fn, const AType* type) { - LLVMEngine* engine = reinterpret_cast<LLVMEngine*>(cenv.engine()); - AType* genericType = cenv.type(cenv.resolve(fn)); - AType* thisType = genericType; - Subst argsSubst; - - // Build and apply substitution to get concrete type for this call - if (!genericType->concrete()) { - argsSubst = cenv.tenv.buildSubst(genericType, argsT); - thisType = argsSubst.apply(genericType)->as<AType*>(); - } + assert(type->concrete()); - THROW_IF(!thisType->concrete(), fn->loc, - string("call has non-concrete type %1%\n") + thisType->str()); - - Object::pool.addRoot(thisType); - Function* f = (Function*)fn->impls.find(thisType); - if (f) - return f; - - ATuple* protT = thisType->prot(); + LLVMEngine* engine = reinterpret_cast<LLVMEngine*>(cenv.engine()); + const AType* argsT = type->prot()->as<const AType*>(); + const AType* retT = type->last()->as<const AType*>(); vector<string> argNames; for (ATuple::const_iterator i = fn->prot()->begin(); i != fn->prot()->end(); ++i) @@ -321,39 +310,40 @@ LLVMEngine::compileFunction(CEnv& cenv, AFn* fn, const AType& argsT) // Write function declaration const string name = (fn->name == "") ? cenv.penv.gensymstr("_fn") : fn->name; - f = llFunc(cenv.engine()->startFunction(cenv, name, - thisType->last()->to<AType*>(), - *protT, argNames)); + Function* f = llFunc(cenv.engine()->startFunction(cenv, name, retT, *argsT, argNames)); cenv.push(); - Subst oldSubst = cenv.tsubst; - cenv.tsubst = Subst::compose(cenv.tsubst, argsSubst); // Bind argument values in CEnv vector<Value*> args; AFn::const_iterator p = fn->prot()->begin(); - ATuple::const_iterator pT = protT->begin(); + ATuple::const_iterator pT = argsT->begin(); + assert(fn->prot()->size() == argsT->size()); + assert(fn->prot()->size() == f->num_args()); for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p, ++pT) { - AType* t = (*pT)->as<AType*>(); - const Type* lt = llType(t); + const AType* t = (*pT)->as<const AType*>(); + const Type* lt = llType(t); THROW_IF(!lt, fn->loc, "untyped parameter\n"); cenv.def((*p)->as<ASymbol*>(), *p, t, &*a); } + assert(!cenv.currentFn); + // Write function body try { - fn->impls.push_back(make_pair(thisType, f)); + cenv.currentFn = f; CVal retVal = NULL; for (AFn::iterator i = fn->begin() + 2; i != fn->end(); ++i) retVal = (*i)->compile(cenv); - cenv.engine()->finishFunction(cenv, f, cenv.type(fn->last()), retVal); + cenv.engine()->finishFunction(cenv, f, retVal); } catch (Error& e) { f->eraseFromParent(); // Error reading body, remove function cenv.pop(); + cenv.currentFn = NULL; throw e; } - cenv.tsubst = oldSubst; cenv.pop(); + cenv.currentFn = NULL; return f; } @@ -456,12 +446,12 @@ LLVMEngine::compilePrimitive(CEnv& cenv, APrimitive* prim) } CVal -LLVMEngine::compileGlobal(CEnv& cenv, AType* type, const string& name, CVal val) +LLVMEngine::compileGlobal(CEnv& cenv, const AType* type, const string& sym, CVal val) { LLVMEngine* engine = reinterpret_cast<LLVMEngine*>(cenv.engine()); Constant* init = Constant::getNullValue(llType(type)); GlobalVariable* global = new GlobalVariable(*module, llType(type), false, - GlobalValue::ExternalLinkage, Constant::getNullValue(llType(type)), name); + GlobalValue::ExternalLinkage, Constant::getNullValue(llType(type)), sym); engine->builder.CreateStore(llVal(val), global); return global; |