aboutsummaryrefslogtreecommitdiffstats
path: root/src/llvm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm.cpp')
-rw-r--r--src/llvm.cpp41
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);