aboutsummaryrefslogtreecommitdiffstats
path: root/src/llvm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm.cpp')
-rw-r--r--src/llvm.cpp131
1 files changed, 69 insertions, 62 deletions
diff --git a/src/llvm.cpp b/src/llvm.cpp
index c4744c3..7f521b7 100644
--- a/src/llvm.cpp
+++ b/src/llvm.cpp
@@ -30,22 +30,24 @@
#include <boost/format.hpp>
-#include "llvm/Value.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/AssemblyAnnotationWriter.h"
+#include "llvm/DefaultPasses.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
-#include "llvm/Support/raw_os_ostream.h"
#include "llvm/Support/IRBuilder.h"
-#include "llvm/Support/StandardPasses.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_os_ostream.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Value.h"
#include "resp.hpp"
@@ -54,22 +56,25 @@ using namespace std;
using boost::format;
struct IfRecord {
- IfRecord(LLVMContext& context, unsigned labelIndex, const Type* t)
+ IfRecord(LLVMContext& context, unsigned labelIndex, Type* t)
: type(t)
, mergeBB(BasicBlock::Create(context, "endif"))
, thenBB(BasicBlock::Create(context, (format("then%1%") % labelIndex).str()))
, elseBB(BasicBlock::Create(context, (format("else%1%") % labelIndex).str()))
, thenV(NULL)
, elseV(NULL)
+ , nMergeBranches(0)
{}
- const Type* type;
+ Type* type;
BasicBlock* mergeBB;
BasicBlock* thenBB;
BasicBlock* elseBB;
Value* thenV;
Value* elseV;
+
+ unsigned nMergeBranches;
};
/** LLVM Engine (Compiler and JIT) */
@@ -84,7 +89,7 @@ struct LLVMEngine : public Engine {
CVal compileCall(CEnv& cenv, CFunc f, const ATuple* funcT, const vector<CVal>& args);
CVal compileCast(CEnv& cenv, CVal v, const AST* t);
- CVal compileCons(CEnv& cenv, const ATuple* type, CVal rtti, const vector<CVal>& fields);
+ CVal compileCons(CEnv& cenv, const char* tname, const ATuple* type, CVal rtti, const vector<CVal>& fields);
CVal compileDot(CEnv& cenv, CVal tup, int32_t index);
CVal compileGlobalSet(CEnv& cenv, const string& s, CVal v, const AST* t);
CVal compileGlobalGet(CEnv& cenv, const string& s, CVal v);
@@ -111,7 +116,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 char* name=NULL);
+ Type* llType(const AST* t, const char* name=NULL);
LLVMContext context;
Module* module;
@@ -122,10 +127,10 @@ private:
PassManager* modOpt;
CType objectT;
- PATypeHolder* opaqueT;
- std::string opaqueName;
+ StructType* opaqueT;
+ std::string opaqueName;
- typedef std::map<const std::string, const Type*> CTypes;
+ typedef std::map<const std::string, Type*> CTypes;
CTypes compiledTypes;
typedef std::stack<IfRecord*> IfStack;
@@ -149,22 +154,22 @@ LLVMEngine::LLVMEngine()
modOpt = new PassManager();
// Set up optimisers
- unsigned optLevel = 3;
- createStandardFunctionPasses(fnOpt, optLevel);
- createStandardModulePasses(modOpt, optLevel, false, true, true, true, false, NULL);
+ PassManagerBuilder pmb;
+ pmb.OptLevel = 3;
+ pmb.populateFunctionPassManager(*fnOpt);
+ pmb.populateModulePassManager(*modOpt);
// Declare host provided allocation primitive
- std::vector<const Type*> argsT(1, Type::getInt32Ty(context)); // unsigned size
+ std::vector<Type*> argsT(1, Type::getInt32Ty(context)); // unsigned size
FunctionType* funcT = FunctionType::get(
PointerType::get(Type::getInt8Ty(context), 0), argsT, false);
alloc = Function::Create(
funcT, Function::ExternalLinkage, "__resp_alloc", module);
// Build Object type (tag only, binary compatible with any constructed thing)
- vector<const Type*> ctypes;
+ vector<Type*> ctypes;
ctypes.push_back(PointerType::get(Type::getInt8Ty(context), 0)); // RTTI
- StructType* cObjectT = StructType::get(context, ctypes, false);
- module->addTypeName("Object", cObjectT);
+ StructType* cObjectT = StructType::create(context, ctypes, "Object", false);
objectT = cObjectT;
}
@@ -175,7 +180,7 @@ LLVMEngine::~LLVMEngine()
delete modOpt;
}
-const Type*
+Type*
LLVMEngine::llType(const AST* t, const char* name)
{
if (t == NULL) {
@@ -191,7 +196,7 @@ LLVMEngine::llType(const AST* t, const char* name)
if (sym == "Expr") return PointerType::get(Type::getInt8Ty(context), 0);
if (sym == opaqueName) {
THROW_IF(!opaqueT, t->loc, "Broken recursive type");
- return *opaqueT;
+ return PointerType::getUnqual(opaqueT);
}
CTypes::const_iterator i = compiledTypes.find(sym);
@@ -205,15 +210,7 @@ LLVMEngine::llType(const AST* t, const char* name)
THROW_IF(!isupper(t->as_tuple()->fst()->str()[0]), t->loc,
"Lower-case type expression");
- // 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));
- opaqueName = name;
- }
-
- const Type* ret;
-
+ // Function type
if (is_form(t, "Fn")) {
ATuple::const_iterator i = t->as_tuple()->begin();
const ATuple* protT = (*++i)->to_tuple();
@@ -221,47 +218,48 @@ LLVMEngine::llType(const AST* t, const char* name)
if (!llType(retT))
return NULL;
- vector<const Type*> cprot;
+ vector<Type*> cprot;
FOREACHP(ATuple::const_iterator, i, protT) {
- const Type* lt = llType(*i);
+ Type* lt = llType(*i);
if (!lt)
return NULL;
cprot.push_back(lt);
}
- ret = FunctionType::get(llType(retT), cprot, false);
+ return PointerType::getUnqual(FunctionType::get(llType(retT), cprot, false));
+ }
- } else {
- vector<const Type*> ctypes;
- ctypes.push_back(PointerType::get(Type::getInt8Ty(context), 0)); // RTTI
- for (ATuple::const_iterator i = t->as_tuple()->iter_at(1); i != t->as_tuple()->end(); ++i) {
- const Type* lt = llType(*i);
- if (!lt)
- return NULL;
- ctypes.push_back(lt);
- }
+ // Struct type
+ Type* ret = NULL;
+ vector<Type*> ctypes;
- ret = StructType::get(context, ctypes, false);
+ // 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);
+ opaqueName = name;
}
- if (!ret) {
- cerr << "WARNING: No low-level type for " << t << endl;
- return NULL;
+ // Get member types
+ ctypes.push_back(PointerType::get(Type::getInt8Ty(context), 0)); // RTTI
+ for (ATuple::const_iterator i = t->as_tuple()->iter_at(1); i != t->as_tuple()->end(); ++i) {
+ Type* lt = llType(*i);
+ if (!lt)
+ return NULL;
+ ctypes.push_back(lt);
}
- // 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
+ // Resolve recursive type
+ opaqueT->setBody(ctypes);
+ ret = opaqueT;
opaqueT = NULL;
opaqueName = "";
- module->addTypeName(name, retT.get());
+ } else {
+ ret = StructType::get(context, ctypes, false);
}
- return ptrT;
+ return PointerType::getUnqual(ret);
}
/** Convert a size in bits to bytes, rounding up as necessary */
@@ -275,17 +273,17 @@ CVal
LLVMEngine::compileCall(CEnv& cenv, CFunc f, const ATuple* funcT, const vector<CVal>& args)
{
vector<Value*> llArgs(*reinterpret_cast<const vector<Value*>*>(&args));
- return builder.CreateCall(llFunc(f), llArgs.begin(), llArgs.end());
+ return builder.CreateCall(llFunc(f), llArgs);
}
CVal
LLVMEngine::compileCast(CEnv& cenv, CVal v, const AST* t)
{
- return builder.CreateBitCast(llVal(v), (const Type*)compileType(cenv, NULL, t), "cast");
+ return builder.CreateBitCast(llVal(v), (Type*)compileType(cenv, NULL, t), "cast");
}
CVal
-LLVMEngine::compileCons(CEnv& cenv, const ATuple* type, CVal rtti, const vector<CVal>& fields)
+LLVMEngine::compileCons(CEnv& cenv, const char* tname, const ATuple* type, CVal rtti, const vector<CVal>& fields)
{
// Find size of memory required
size_t s = engine->getTargetData()->getTypeSizeInBits(
@@ -293,13 +291,20 @@ LLVMEngine::compileCons(CEnv& cenv, const ATuple* type, CVal rtti, const vector<
assert(type->begin() != type->end());
for (ATuple::const_iterator i = type->iter_at(1); i != type->end(); ++i)
s += engine->getTargetData()->getTypeSizeInBits(
- (const Type*)compileType(cenv, NULL, *i));
+ (Type*)compileType(cenv, NULL, *i));
// Allocate struct
const std::string name = type->fst()->str();
Value* structSize = ConstantInt::get(Type::getInt32Ty(context), bitsToBytes(s));
Value* mem = builder.CreateCall(alloc, structSize, name + "_mem");
- Value* structPtr = builder.CreateBitCast(mem, llType(type), name);
+
+ StructType* consT = module->getTypeByName(tname);
+ Value* structPtr = NULL;
+ if (consT) { // Named type
+ structPtr = builder.CreateBitCast(mem, PointerType::getUnqual(consT), name);
+ } else { // Anonymous type
+ structPtr = builder.CreateBitCast(mem, llType(type), name);
+ }
// Set struct fields
if (rtti)
@@ -357,7 +362,7 @@ LLVMEngine::compileType(CEnv& cenv, const char* name, const AST* expr)
return i->second;
}
- const Type* const type = llType(expr, name);
+ Type* const type = llType(expr, name);
if (name)
compiledTypes.insert(make_pair(name, type));
@@ -374,12 +379,12 @@ LLVMEngine::startFn(
Function::LinkageTypes linkage = Function::ExternalLinkage;
- vector<const Type*> cprot;
+ vector<Type*> cprot;
FOREACHP(ATuple::const_iterator, i, argsT) {
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);
+ cprot.push_back((Type*)iT);
}
THROW_IF(!llType(retT), Cursor(),
@@ -511,6 +516,7 @@ LLVMEngine::compileIfElse(CEnv& cenv, CVal elseV)
if (elseV) {
engine->builder.CreateBr(rec->mergeBB);
+ ++rec->nMergeBranches;
} else {
engine->builder.CreateUnreachable();
}
@@ -528,7 +534,8 @@ LLVMEngine::compileIfEnd(CEnv& cenv)
// Emit merge block (Phi node)
appendBlock(engine, parent, rec->mergeBB);
- PHINode* pn = engine->builder.CreatePHI(rec->type, "ifval");
+ ++rec->nMergeBranches;
+ PHINode* pn = engine->builder.CreatePHI(rec->type, rec->nMergeBranches, "ifval");
pn->addIncoming(rec->thenV, rec->thenBB);
if (rec->elseV)
pn->addIncoming(rec->elseV, rec->elseBB);