diff options
author | David Robillard <d@drobilla.net> | 2010-12-31 04:53:23 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2010-12-31 04:53:23 +0000 |
commit | a94ba9d90a9fe48a3933f2932b7955b5b248b623 (patch) | |
tree | 77f7e5390d667361d51cc6b590e1decf7e78f46d /src/llvm.cpp | |
parent | 3b0975009a400cc41e9d975c6b81ab5965bbb0fa (diff) | |
download | resp-a94ba9d90a9fe48a3933f2932b7955b5b248b623.tar.gz resp-a94ba9d90a9fe48a3933f2932b7955b5b248b623.tar.bz2 resp-a94ba9d90a9fe48a3933f2932b7955b5b248b623.zip |
Define named (and possibly recursive) types for closures and functions.
Compile type definitions all the way to LLVM IR (including recursive types).
git-svn-id: http://svn.drobilla.net/resp/resp@388 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src/llvm.cpp')
-rw-r--r-- | src/llvm.cpp | 90 |
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); } } |