aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/llvm.cpp214
1 files changed, 107 insertions, 107 deletions
diff --git a/src/llvm.cpp b/src/llvm.cpp
index eeb584c..df755b3 100644
--- a/src/llvm.cpp
+++ b/src/llvm.cpp
@@ -83,114 +83,25 @@ struct LLVMEngine : public Engine {
inline Value* llVal(CVal v) { return static_cast<Value*>(v); }
inline Function* llFunc(CFunc f) { return static_cast<Function*>(f); }
-
- const Type*
- llType(const AType* t)
- {
- if (t == NULL) {
- return NULL;
- } else if (t->kind == AType::PRIM) {
- if (t->head()->str() == "Nothing") return Type::getVoidTy(context);
- if (t->head()->str() == "Bool") return Type::getInt1Ty(context);
- if (t->head()->str() == "Int") return Type::getInt32Ty(context);
- if (t->head()->str() == "Float") return Type::getFloatTy(context);
- if (t->head()->str() == "String") return PointerType::get(Type::getInt8Ty(context), NULL);
- if (t->head()->str() == "Quote") return PointerType::get(Type::getInt8Ty(context), NULL);
- throw Error(t->loc, string("Unknown primitive type `") + t->str() + "'");
- } else if (t->kind == AType::EXPR && t->head()->str() == "Fn") {
- AType::const_iterator i = t->begin();
- const ATuple* protT = (*++i)->to_tuple();
- const AType* retT = (*++i)->as_type();
- if (!llType(retT))
- return NULL;
-
- vector<const Type*> cprot;
- FOREACHP(ATuple::const_iterator, i, protT) {
- const Type* lt = llType((*i)->to_type());
- if (!lt)
- return NULL;
- cprot.push_back(lt);
- }
-
- return PointerType::get(FunctionType::get(llType(retT), cprot, false), 0);
- } else if (t->kind == AType::EXPR && isupper(t->head()->str()[0])) {
- vector<const Type*> ctypes;
- ctypes.push_back(PointerType::get(Type::getInt8Ty(context), NULL)); // RTTI
- for (AType::const_iterator i = t->iter_at(1); i != t->end(); ++i) {
- const Type* lt = llType((*i)->to_type());
- if (!lt)
- return NULL;
- ctypes.push_back(lt);
- }
-
- return PointerType::get(StructType::get(context, ctypes, false), 0);
- } else if (t->kind == AType::NAME) {
- assert(false);
- }
- assert(false);
- return PointerType::get(Type::getInt8Ty(context), NULL);
- }
+ const Type* llType(const AType* t);
CFunc startFunction(
- CEnv& cenv, const std::string& name, const ATuple* args, const AType* type)
- {
- const AType* argsT = type->prot()->as_type();
- const AType* retT = type->list_last()->as_type();
-
- Function::LinkageTypes linkage = Function::ExternalLinkage;
-
- vector<const Type*> cprot;
- FOREACHP(ATuple::const_iterator, i, argsT) {
- const AType* at = (*i)->as_type();
- THROW_IF(!llType(at), Cursor(), string("non-concrete parameter :: ")
- + at->str())
- cprot.push_back(llType(at));
- }
-
- THROW_IF(!llType(retT), Cursor(),
- (format("return has non-concrete type `%1%'") % retT->str()).str());
+ CEnv& cenv, const std::string& name, const ATuple* args, const AType* type);
- const string llName = (name == "") ? cenv.penv.gensymstr("_fn") : name;
-
- FunctionType* fT = FunctionType::get(llType(retT), cprot, false);
- Function* f = Function::Create(fT, linkage, llName, module);
-
- // Note f->getName() may be different from llName
- // however LLVM chooses to mangle is fine, we keep a pointer
-
- // Set argument names in generated code
- Function::arg_iterator a = f->arg_begin();
- for (ATuple::const_iterator i = args->begin(); i != args->end(); ++a, ++i)
- a->setName((*i)->as_symbol()->cppstr);
+ void pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc f);
- BasicBlock* bb = BasicBlock::Create(context, "entry", f);
- builder.SetInsertPoint(bb);
+ void finishFunction(CEnv& cenv, CFunc f, CVal ret);
- return f;
+ void eraseFunction(CEnv& cenv, CFunc f) {
+ if (f)
+ llFunc(f)->eraseFromParent();
}
-
- void pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc f);
void appendBlock(LLVMEngine* engine, Function* function, BasicBlock* block) {
function->getBasicBlockList().push_back(block);
engine->builder.SetInsertPoint(block);
}
- void finishFunction(CEnv& cenv, CFunc f, CVal ret) {
- builder.CreateRet(llVal(ret));
- if (verifyFunction(*static_cast<Function*>(f), llvm::PrintMessageAction)) {
- module->dump();
- throw Error(Cursor(), "Broken module");
- }
- if (cenv.args.find("-g") == cenv.args.end())
- opt->run(*static_cast<Function*>(f));
- }
-
- void eraseFunction(CEnv& cenv, CFunc f) {
- if (f)
- llFunc(f)->eraseFromParent();
- }
-
CVal compileCall(CEnv& cenv, CFunc f, const AType* funcT, const vector<CVal>& args) {
vector<Value*> llArgs(*reinterpret_cast<const vector<Value*>*>(&args));
Value* closure = builder.CreateBitCast(llArgs[0],
@@ -220,14 +131,9 @@ struct LLVMEngine : public Engine {
IfBranches branches;
};
- IfState
- compileIfStart(CEnv& cenv);
-
- void
- compileIfBranch(CEnv& cenv, IfState state, CVal condV, const AST* then);
-
- CVal
- compileIfEnd(CEnv& cenv, IfState state, CVal elseV, const AType* type);
+ IfState compileIfStart(CEnv& cenv);
+ void compileIfBranch(CEnv& cenv, IfState state, CVal condV, const AST* then);
+ CVal compileIfEnd(CEnv& cenv, IfState state, CVal elseV, const AType* type);
void writeModule(CEnv& cenv, std::ostream& os) {
AssemblyAnnotationWriter writer;
@@ -286,9 +192,52 @@ resp_new_llvm_engine()
return new LLVMEngine();
}
-/***************************************************************************
- * Code Generation *
- ***************************************************************************/
+const Type*
+LLVMEngine::llType(const AType* t)
+{
+ if (t == NULL) {
+ return NULL;
+ } else if (t->kind == AType::PRIM) {
+ if (t->head()->str() == "Nothing") return Type::getVoidTy(context);
+ if (t->head()->str() == "Bool") return Type::getInt1Ty(context);
+ if (t->head()->str() == "Int") return Type::getInt32Ty(context);
+ if (t->head()->str() == "Float") return Type::getFloatTy(context);
+ if (t->head()->str() == "String") return PointerType::get(Type::getInt8Ty(context), NULL);
+ if (t->head()->str() == "Quote") return PointerType::get(Type::getInt8Ty(context), NULL);
+ throw Error(t->loc, string("Unknown primitive type `") + t->str() + "'");
+ } else if (t->kind == AType::EXPR && t->head()->str() == "Fn") {
+ AType::const_iterator i = t->begin();
+ const ATuple* protT = (*++i)->to_tuple();
+ const AType* retT = (*++i)->as_type();
+ if (!llType(retT))
+ return NULL;
+
+ vector<const Type*> cprot;
+ FOREACHP(ATuple::const_iterator, i, protT) {
+ const Type* lt = llType((*i)->to_type());
+ if (!lt)
+ return NULL;
+ cprot.push_back(lt);
+ }
+
+ return PointerType::get(FunctionType::get(llType(retT), cprot, false), 0);
+ } else if (t->kind == AType::EXPR && isupper(t->head()->str()[0])) {
+ vector<const Type*> ctypes;
+ ctypes.push_back(PointerType::get(Type::getInt8Ty(context), NULL)); // RTTI
+ for (AType::const_iterator i = t->iter_at(1); i != t->end(); ++i) {
+ const Type* lt = llType((*i)->to_type());
+ if (!lt)
+ return NULL;
+ ctypes.push_back(lt);
+ }
+
+ return PointerType::get(StructType::get(context, ctypes, false), 0);
+ } else if (t->kind == AType::NAME) {
+ assert(false);
+ }
+ assert(false);
+ return PointerType::get(Type::getInt8Ty(context), NULL);
+}
/** Convert a size in bits to bytes, rounding up as necessary */
static inline size_t
@@ -351,6 +300,45 @@ LLVMEngine::compileString(CEnv& cenv, const char* str)
return builder.CreateGlobalStringPtr(str);
}
+CFunc
+LLVMEngine::startFunction(
+ CEnv& cenv, const std::string& name, const ATuple* args, const AType* type)
+{
+ const AType* argsT = type->prot()->as_type();
+ const AType* retT = type->list_last()->as_type();
+
+ Function::LinkageTypes linkage = Function::ExternalLinkage;
+
+ vector<const Type*> cprot;
+ FOREACHP(ATuple::const_iterator, i, argsT) {
+ const AType* at = (*i)->as_type();
+ THROW_IF(!llType(at), Cursor(), string("non-concrete parameter :: ")
+ + at->str())
+ cprot.push_back(llType(at));
+ }
+
+ THROW_IF(!llType(retT), Cursor(),
+ (format("return has non-concrete type `%1%'") % retT->str()).str());
+
+ const string llName = (name == "") ? cenv.penv.gensymstr("_fn") : name;
+
+ FunctionType* fT = FunctionType::get(llType(retT), cprot, false);
+ Function* f = Function::Create(fT, linkage, llName, module);
+
+ // Note f->getName() may be different from llName
+ // however LLVM chooses to mangle is fine, we keep a pointer
+
+ // Set argument names in generated code
+ Function::arg_iterator a = f->arg_begin();
+ for (ATuple::const_iterator i = args->begin(); i != args->end(); ++a, ++i)
+ a->setName((*i)->as_symbol()->cppstr);
+
+ BasicBlock* bb = BasicBlock::Create(context, "entry", f);
+ builder.SetInsertPoint(bb);
+
+ return f;
+}
+
void
LLVMEngine::pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type, CFunc cfunc)
{
@@ -371,6 +359,18 @@ LLVMEngine::pushFunctionArgs(CEnv& cenv, const ATuple* prot, const AType* type,
}
}
+void
+LLVMEngine::finishFunction(CEnv& cenv, CFunc f, CVal ret)
+{
+ builder.CreateRet(llVal(ret));
+ if (verifyFunction(*static_cast<Function*>(f), llvm::PrintMessageAction)) {
+ module->dump();
+ throw Error(Cursor(), "Broken module");
+ }
+ if (cenv.args.find("-g") == cenv.args.end())
+ opt->run(*static_cast<Function*>(f));
+}
+
IfState
LLVMEngine::compileIfStart(CEnv& cenv)
{