aboutsummaryrefslogtreecommitdiffstats
path: root/src/llvm.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-10-16 01:53:16 +0000
committerDavid Robillard <d@drobilla.net>2009-10-16 01:53:16 +0000
commitc2d75892af2fdc6b9bf25365a15de5dc63bcc852 (patch)
tree22234de7261ca54f6c1d01e0ff271cbde5af0699 /src/llvm.cpp
parent474b2a748bfdb55aac43bba998bc79a5c9d18675 (diff)
downloadresp-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.cpp52
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)
{