diff options
author | David Robillard <d@drobilla.net> | 2009-10-16 01:53:16 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-10-16 01:53:16 +0000 |
commit | c2d75892af2fdc6b9bf25365a15de5dc63bcc852 (patch) | |
tree | 22234de7261ca54f6c1d01e0ff271cbde5af0699 /src/llvm.cpp | |
parent | 474b2a748bfdb55aac43bba998bc79a5c9d18675 (diff) | |
download | resp-c2d75892af2fdc6b9bf25365a15de5dc63bcc852.tar.gz resp-c2d75892af2fdc6b9bf25365a15de5dc63bcc852.tar.bz2 resp-c2d75892af2fdc6b9bf25365a15de5dc63bcc852.zip |
Cons.
git-svn-id: http://svn.drobilla.net/resp/tuplr@235 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src/llvm.cpp')
-rw-r--r-- | src/llvm.cpp | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/src/llvm.cpp b/src/llvm.cpp index bb30cbc..bf00778 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -45,7 +45,9 @@ static inline Function* llFunc(CFunc f) { return static_cast<Function*>(f); } static const Type* llType(const AType* t) { - if (t->kind == AType::PRIM) { + if (t == NULL) { + return NULL; + } else if (t->kind == AType::PRIM) { if (t->head()->str() == "Nothing") return Type::VoidTy; if (t->head()->str() == "Bool") return Type::Int1Ty; if (t->head()->str() == "Int") return Type::Int32Ty; @@ -60,15 +62,23 @@ llType(const AType* t) vector<const Type*> cprot; FOREACHP(ATuple::const_iterator, i, protT) { - const AType* at = (*i)->to<const AType*>(); - const Type* lt = llType(at); + const Type* lt = llType((*i)->to<const AType*>()); if (!lt) return NULL; cprot.push_back(lt); } - FunctionType* fT = FunctionType::get(llType(retT), cprot, false); - return PointerType::get(fT, 0); + return PointerType::get(FunctionType::get(llType(retT), cprot, false), 0); + } else if (t->kind == AType::EXPR && t->head()->str() == "Tup") { + vector<const Type*> ctypes; + for (AType::const_iterator i = t->begin() + 1; i != t->end(); ++i) { + const Type* lt = llType((*i)->to<const AType*>()); + if (!lt) + return NULL; + ctypes.push_back(lt); + } + + return PointerType::get(StructType::get(ctypes, false), 0); } return NULL; // non-primitive type } @@ -95,7 +105,6 @@ struct LLVMEngine : public Engine { // Declare host provided allocation primitive std::vector<const Type*> argsT(1, Type::Int32Ty); // unsigned size - argsT.push_back(Type::Int8Ty); // char tag FunctionType* funcT = FunctionType::get(PointerType::get(Type::Int8Ty, 0), argsT, false); alloc = Function::Create(funcT, Function::ExternalLinkage, "tuplr_gc_allocate", module); @@ -159,6 +168,7 @@ struct LLVMEngine : public Engine { CFunc compileFunction(CEnv& cenv, AFn* fn, const AType& argsT); + CVal compileTup(CEnv& cenv, const AType* type, const vector<CVal>& fields); CVal compileLiteral(CEnv& cenv, AST* lit); CVal compilePrimitive(CEnv& cenv, APrimitive* prim); CVal compileIf(CEnv& cenv, AIf* aif); @@ -204,6 +214,36 @@ tuplr_new_llvm_engine() * Code Generation * ***************************************************************************/ +/** Convert a size in bits to bytes, rounding up as necessary */ +static inline size_t +bitsToBytes(size_t bits) +{ + return ((bits % 8 == 0) ? bits : (((bits / 8) + 1) * 8)) / 8; +} + +CVal +LLVMEngine::compileTup(CEnv& cenv, const AType* type, const vector<CVal>& fields) +{ + // Find size of memory required + size_t s = 0; + for (AType::const_iterator i = type->begin() + 1; i != type->end(); ++i) + s += llType((*i)->as<AType*>())->getPrimitiveSizeInBits(); + + // Allocate struct + Value* structSize = ConstantInt::get(Type::Int32Ty, bitsToBytes(s)); + Value* mem = builder.CreateCall(alloc, structSize, "tup"); + Value* structPtr = builder.CreateBitCast(mem, llType(type), "tupPtr"); + + // 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); + } + + return structPtr; +} + CVal LLVMEngine::compileLiteral(CEnv& cenv, AST* lit) { |