aboutsummaryrefslogtreecommitdiffstats
path: root/src/llvm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm.cpp')
-rw-r--r--src/llvm.cpp90
1 files changed, 66 insertions, 24 deletions
diff --git a/src/llvm.cpp b/src/llvm.cpp
index a3882c8..e445650 100644
--- a/src/llvm.cpp
+++ b/src/llvm.cpp
@@ -85,7 +85,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 Type* llType(const AST* t, const char* name=NULL);
LLVMContext context;
Module* module;
@@ -95,7 +95,9 @@ private:
FunctionPassManager* opt;
CType objectT;
- typedef std::map<const std::string, CType> CTypes;
+ PATypeHolder* opaqueT;
+
+ typedef std::map<const std::string, const Type*> CTypes;
CTypes compiledTypes;
unsigned labelIndex;
@@ -103,6 +105,7 @@ private:
LLVMEngine::LLVMEngine()
: builder(context)
+ , opaqueT(NULL)
, labelIndex(1)
{
InitializeNativeTarget();
@@ -140,7 +143,7 @@ LLVMEngine::~LLVMEngine()
}
const Type*
-LLVMEngine::llType(const AST* t)
+LLVMEngine::llType(const AST* t, const char* name)
{
if (t == NULL) {
return NULL;
@@ -156,7 +159,26 @@ LLVMEngine::llType(const AST* t)
if (sym == "String") return PointerType::get(Type::getInt8Ty(context), NULL);
if (sym == "Symbol") return PointerType::get(Type::getInt8Ty(context), NULL);
if (sym == "Expr") return PointerType::get(Type::getInt8Ty(context), NULL);
- } else if (is_form(t, "Fn")) {
+ if (sym == "__REC") { if (!opaqueT) throw; return *opaqueT;}
+
+ CTypes::const_iterator i = compiledTypes.find(sym);
+ if (i != compiledTypes.end())
+ return i->second;
+
+ }
+
+ if (!AType::is_expr(t))
+ return NULL;
+
+ // 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));
+ }
+
+ const Type* ret;
+
+ if (is_form(t, "Fn")) {
ATuple::const_iterator i = t->as_tuple()->begin();
const ATuple* protT = (*++i)->to_tuple();
const AST* retT = (*++i);
@@ -171,8 +193,9 @@ LLVMEngine::llType(const AST* t)
cprot.push_back(lt);
}
- return PointerType::get(FunctionType::get(llType(retT), cprot, false), 0);
- } else if (AType::is_expr(t) && isupper(t->as_tuple()->fst()->str()[0])) {
+ ret = FunctionType::get(llType(retT), cprot, false);
+
+ } else if (isupper(t->as_tuple()->fst()->str()[0])) {
vector<const Type*> ctypes;
ctypes.push_back(PointerType::get(Type::getInt8Ty(context), NULL)); // RTTI
for (ATuple::const_iterator i = t->as_tuple()->iter_at(1); i != t->as_tuple()->end(); ++i) {
@@ -182,9 +205,26 @@ LLVMEngine::llType(const AST* t)
ctypes.push_back(lt);
}
- return PointerType::get(StructType::get(context, ctypes, false), 0);
+ ret = StructType::get(context, ctypes, false);
}
- return NULL;
+
+ if (!ret) {
+ cerr << "WARNING: No low-level type for " << t << endl;
+ return NULL;
+ }
+
+ // 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
+ opaqueT = NULL;
+ module->addTypeName(name, retT.get());
+ }
+
+ return ptrT;
}
/** Convert a size in bits to bytes, rounding up as necessary */
@@ -198,17 +238,13 @@ CVal
LLVMEngine::compileCall(CEnv& cenv, CFunc f, const ATuple* funcT, const vector<CVal>& args)
{
vector<Value*> llArgs(*reinterpret_cast<const vector<Value*>*>(&args));
- Value* closure = builder.CreateBitCast(llArgs[0],
- llType(funcT->prot()->fst()),
- cenv.penv.gensymstr("you"));
- llArgs[0] = closure;
return builder.CreateCall(llFunc(f), llArgs.begin(), llArgs.end());
}
CVal
LLVMEngine::compileCast(CEnv& cenv, CVal v, const AST* t)
{
- return builder.CreateBitCast(llVal(v), llType(t), "cast");
+ return builder.CreateBitCast(llVal(v), (const Type*)compileType(cenv, NULL, t), "cast");
}
CVal
@@ -219,7 +255,8 @@ LLVMEngine::compileCons(CEnv& cenv, const ATuple* type, CVal rtti, const vector<
PointerType::get(Type::getInt8Ty(context), NULL));
assert(type->begin() != type->end());
for (ATuple::const_iterator i = type->iter_at(1); i != type->end(); ++i)
- s += engine->getTargetData()->getTypeSizeInBits(llType(*i));
+ s += engine->getTargetData()->getTypeSizeInBits(
+ (const Type*)compileType(cenv, NULL, *i));
// Allocate struct
const std::string name = type->fst()->str();
@@ -277,13 +314,17 @@ LLVMEngine::compileString(CEnv& cenv, const char* str)
CType
LLVMEngine::compileType(CEnv& cenv, const char* name, const AST* expr)
{
- CTypes::const_iterator i = compiledTypes.find(name);
- if (i != compiledTypes.end())
- return i->second;
+ if (name) {
+ CTypes::const_iterator i = compiledTypes.find(name);
+ if (i != compiledTypes.end())
+ return i->second;
+ }
+
+ const Type* const type = llType(expr, name);
+
+ if (name)
+ compiledTypes.insert(make_pair(name, type));
- const Type* type = llType(expr);
- module->addTypeName(name, type);
- compiledTypes.insert(make_pair(name, type));
return type;
}
@@ -298,9 +339,10 @@ LLVMEngine::startFn(
vector<const Type*> cprot;
FOREACHP(ATuple::const_iterator, i, argsT) {
- THROW_IF(!llType(*i), Cursor(), string("non-concrete parameter :: ")
- + (*i)->str())
- cprot.push_back(llType(*i));
+ 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);
}
THROW_IF(!llType(retT), Cursor(),
@@ -340,7 +382,7 @@ LLVMEngine::pushFnArgs(CEnv& cenv, const ATuple* prot, const ATuple* type, CFunc
assert(prot->size() == f->num_args());
for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p, ++pT) {
const AST* t = cenv.resolveType(*pT);
- THROW_IF(!llType(t), (*p)->loc, "untyped parameter\n");
+// THROW_IF(!llType(t), (*p)->loc, "untyped parameter\n");
cenv.def((*p)->as_symbol(), *p, t, &*a);
}
}