diff options
Diffstat (limited to 'src/llvm.cpp')
-rw-r--r-- | src/llvm.cpp | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/src/llvm.cpp b/src/llvm.cpp index 795cd8c..93bf066 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -82,6 +82,7 @@ struct LLVMEngine : public Engine { LLVMEngine(); virtual ~LLVMEngine(); + CFunc compileProt(CEnv& cenv, const string& name, const ATuple* args, const ATuple* type); CFunc startFn(CEnv& cenv, const string& name, const ATuple* args, const ATuple* type); void finishFn(CEnv& cenv, CVal ret, const AST* retT); CFunc getFn(CEnv& cenv, const std::string& name); @@ -229,10 +230,9 @@ LLVMEngine::llType(const AST* t, const char* name) } // Struct type - Type* ret = NULL; + StructType* ret = NULL; vector<Type*> ctypes; - if (!name) { const ASymbol* tag = t->as_tuple()->fst()->as_symbol(); if (tag->str() != "Tup" && tag->str() != "Closure") { @@ -243,14 +243,18 @@ LLVMEngine::llType(const AST* t, const char* name) if (name) { CTypes::const_iterator i = compiledTypes.find(name); if (i != compiledTypes.end()) { - return i->second; + ret = (StructType*)((PointerType*)i->second)->getContainedType(0); } } + if (ret && !ret->isOpaque()) { + return PointerType::getUnqual(ret); + } + // 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); + opaqueT = (ret) ? ret : StructType::create(context, name); opaqueName = name; } @@ -383,11 +387,16 @@ LLVMEngine::compileType(CEnv& cenv, const std::string& name, const AST* expr) if (!name.empty()) { CTypes::const_iterator i = compiledTypes.find(name); if (i != compiledTypes.end()) { - return i->second; + if (!i->second->isPointerTy() || + !((StructType*)(((PointerType*)i->second)->getContainedType(0)))->isOpaque()) { + return i->second; + } } } - Type* const type = llType(expr, name.c_str()); + Type* const type = (expr) + ? llType(expr, name.c_str()) // Definition + : PointerType::getUnqual(StructType::create(context, name)); // Forward declaration if (!name.empty()) compiledTypes.insert(make_pair(name, type)); @@ -396,7 +405,7 @@ LLVMEngine::compileType(CEnv& cenv, const std::string& name, const AST* expr) } CFunc -LLVMEngine::startFn( +LLVMEngine::compileProt( CEnv& cenv, const std::string& name, const ATuple* args, const ATuple* type) { const ATuple* argsT = type->prot(); @@ -431,6 +440,24 @@ LLVMEngine::startFn( a->setName((*i)->as_symbol()->sym()); } + // Define function in the environment so any calls that get compiled before + // the definition will resolve correctly (e.g. parent calls from a child fn) + cenv.def(cenv.penv.sym(name), NULL, type, f); + + return f; +} + +CFunc +LLVMEngine::startFn( + CEnv& cenv, const std::string& name, const ATuple* args, const ATuple* type) +{ + // Use forward declaration if it exists + Function* f = module->getFunction(name); + if (!f) { + f = (Function*)compileProt(cenv, name, args, type); + } + + // Start the function body BasicBlock* bb = BasicBlock::Create(context, "entry", f); builder.SetInsertPoint(bb); |