|
@@ -1,4 +1,5 @@
|
|
#include "CodeGeneration.h"
|
|
#include "CodeGeneration.h"
|
|
|
|
+#include "Linking.h"
|
|
|
|
|
|
#include <llvm/IR/LLVMContext.h>
|
|
#include <llvm/IR/LLVMContext.h>
|
|
#include <llvm/IR/LegacyPassManager.h>
|
|
#include <llvm/IR/LegacyPassManager.h>
|
|
@@ -138,6 +139,7 @@ std::unique_ptr<llvm::Module> generateModule(sem::GlobalScope& semantic)
|
|
printf("verified function: %s\n", method->name.c_str());
|
|
printf("verified function: %s\n", method->name.c_str());
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
+ generateStartFunction(module.get(), semantic.getMethod("main")->llvmNode);
|
|
return module;
|
|
return module;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -152,18 +154,18 @@ llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
|
|
|
|
|
|
Type* returnType;
|
|
Type* returnType;
|
|
if (method->returnType)
|
|
if (method->returnType)
|
|
- returnType = semCtxt.getLlvmType(method->returnType, context);
|
|
|
|
|
|
+ returnType = method->returnType->getLlvmType(context);
|
|
else
|
|
else
|
|
returnType = llvm::Type::getVoidTy(context);
|
|
returnType = llvm::Type::getVoidTy(context);
|
|
|
|
|
|
std::vector<Type*> argumentTypes;
|
|
std::vector<Type*> argumentTypes;
|
|
if (method->thisExpression != nullptr) {
|
|
if (method->thisExpression != nullptr) {
|
|
- Type* enclosingType = semCtxt.getLlvmType(method->thisExpression->type, context);
|
|
|
|
|
|
+ Type* enclosingType = method->thisExpression->type->getLlvmType(context);
|
|
argumentTypes.push_back(enclosingType);
|
|
argumentTypes.push_back(enclosingType);
|
|
}
|
|
}
|
|
|
|
|
|
for (auto& arg : method->arguments) {
|
|
for (auto& arg : method->arguments) {
|
|
- Type* argumentType = semCtxt.getLlvmType(arg->type, context);
|
|
|
|
|
|
+ Type* argumentType = arg->type->getLlvmType(context);
|
|
argumentTypes.push_back(argumentType);
|
|
argumentTypes.push_back(argumentType);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -174,7 +176,14 @@ llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
|
|
#endif
|
|
#endif
|
|
if (returnType == nullptr)
|
|
if (returnType == nullptr)
|
|
throw "invalid return type";
|
|
throw "invalid return type";
|
|
- Function* func = Function::Create(funcType, Function::ExternalLinkage, method->name, module);
|
|
|
|
|
|
+ std::string symbolName;
|
|
|
|
+ if (method->isExtern) {
|
|
|
|
+ symbolName = qlow::getExternalSymbol(method->name);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ symbolName = method->name;
|
|
|
|
+ }
|
|
|
|
+ Function* func = Function::Create(funcType, Function::ExternalLinkage, symbolName, module);
|
|
method->llvmNode = func;
|
|
method->llvmNode = func;
|
|
|
|
|
|
// linking alloca instances for funcs
|
|
// linking alloca instances for funcs
|
|
@@ -203,6 +212,35 @@ llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
+llvm::Function* generateStartFunction(llvm::Module* module, llvm::Function* start)
|
|
|
|
+{
|
|
|
|
+ using llvm::Function;
|
|
|
|
+ using llvm::FunctionType;
|
|
|
|
+ using llvm::Type;
|
|
|
|
+ using llvm::IRBuilder;
|
|
|
|
+ using llvm::BasicBlock;
|
|
|
|
+ using llvm::Value;
|
|
|
|
+
|
|
|
|
+ FunctionType* startFuncType = FunctionType::get(
|
|
|
|
+ Type::getVoidTy(context), { Type::getInt32Ty(context), Type::getInt8PtrTy(context)->getPointerTo() }, false);
|
|
|
|
+ FunctionType* exitFuncType = FunctionType::get(
|
|
|
|
+ Type::getVoidTy(context), { Type::getInt32Ty(context) }, false);
|
|
|
|
+ Function* startFunction = Function::Create(startFuncType, Function::ExternalLinkage, "_qlow_start", module);
|
|
|
|
+ Function* exitFunction = Function::Create(exitFuncType, Function::ExternalLinkage, qlow::getExternalSymbol("exit"), module);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ IRBuilder<> builder(context);
|
|
|
|
+ BasicBlock* bb = BasicBlock::Create(context, "entry", startFunction);
|
|
|
|
+ builder.SetInsertPoint(bb);
|
|
|
|
+ builder.CreateCall(start, {});
|
|
|
|
+ builder.CreateCall(exitFunction, { llvm::ConstantInt::get(context, llvm::APInt(32, "0", 10)) });
|
|
|
|
+ builder.CreateRetVoid();
|
|
|
|
+
|
|
|
|
+ return startFunction;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Module> module, int optLevel)
|
|
void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Module> module, int optLevel)
|
|
{
|
|
{
|
|
using llvm::legacy::PassManager;
|
|
using llvm::legacy::PassManager;
|
|
@@ -219,7 +257,7 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
|
|
#endif
|
|
#endif
|
|
auto ostr = llvm::raw_os_ostream(printer);
|
|
auto ostr = llvm::raw_os_ostream(printer);
|
|
#ifdef DEBUGGING
|
|
#ifdef DEBUGGING
|
|
- //module->print(ostr, nullptr);
|
|
|
|
|
|
+ module->print(ostr, nullptr);
|
|
#endif
|
|
#endif
|
|
bool broken = llvm::verifyModule(*module);
|
|
bool broken = llvm::verifyModule(*module);
|
|
|
|
|
|
@@ -228,7 +266,6 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
|
|
|
|
|
|
llvm::InitializeNativeTarget ();
|
|
llvm::InitializeNativeTarget ();
|
|
llvm::InitializeNativeTargetAsmPrinter();
|
|
llvm::InitializeNativeTargetAsmPrinter();
|
|
- llvm::InitializeNativeTargetAsmParser();
|
|
|
|
//llvm::InitializeAllTargetInfos();
|
|
//llvm::InitializeAllTargetInfos();
|
|
//llvm::InitializeAllTargets();
|
|
//llvm::InitializeAllTargets();
|
|
//llvm::InitializeAllTargetMCs();
|
|
//llvm::InitializeAllTargetMCs();
|
|
@@ -270,17 +307,19 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
|
|
features, targetOptions, relocModel);
|
|
features, targetOptions, relocModel);
|
|
|
|
|
|
std::error_code errorCode;
|
|
std::error_code errorCode;
|
|
|
|
+
|
|
raw_fd_ostream dest(filename, errorCode, llvm::sys::fs::F_None);
|
|
raw_fd_ostream dest(filename, errorCode, llvm::sys::fs::F_None);
|
|
#ifdef DEBUGGING
|
|
#ifdef DEBUGGING
|
|
printer << "adding passes" << std::endl;
|
|
printer << "adding passes" << std::endl;
|
|
#endif
|
|
#endif
|
|
- bool success = targetMachine->addPassesToEmitFile(pm, dest,
|
|
|
|
|
|
+ targetMachine->addPassesToEmitFile(pm, dest,
|
|
// llvm::LLVMTargetMachine::CGFT_ObjectFile,
|
|
// llvm::LLVMTargetMachine::CGFT_ObjectFile,
|
|
|
|
+#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR >= 7
|
|
|
|
+ nullptr,
|
|
|
|
+#endif
|
|
// nullptr,
|
|
// nullptr,
|
|
llvm::TargetMachine::CGFT_ObjectFile);
|
|
llvm::TargetMachine::CGFT_ObjectFile);
|
|
|
|
|
|
- Printer::getInstance() << (success ? "SUCC!!" : "NO SUCC :(") << std::endl;
|
|
|
|
-
|
|
|
|
pm.run(*module);
|
|
pm.run(*module);
|
|
dest.flush();
|
|
dest.flush();
|
|
dest.close();
|
|
dest.close();
|
|
@@ -323,11 +362,11 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
|
|
for (auto& [name, var] : method.body->scope.getLocals()) {
|
|
for (auto& [name, var] : method.body->scope.getLocals()) {
|
|
if (var.get() == nullptr)
|
|
if (var.get() == nullptr)
|
|
throw "wtf null variable";
|
|
throw "wtf null variable";
|
|
- if (var->type == sem::NO_TYPE)
|
|
|
|
|
|
+ if (var->type == nullptr)
|
|
throw "wtf null type";
|
|
throw "wtf null type";
|
|
|
|
|
|
|
|
|
|
- llvm::AllocaInst* v = builder.CreateAlloca(semCtxt.getLlvmType(var->type, context));
|
|
|
|
|
|
+ llvm::AllocaInst* v = builder.CreateAlloca(var->type->getLlvmType(context));
|
|
var->allocaInst = v;
|
|
var->allocaInst = v;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -347,13 +386,9 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
|
|
|
|
|
|
builder.SetInsertPoint(getCurrentBlock());
|
|
builder.SetInsertPoint(getCurrentBlock());
|
|
//if (method.returnType->equals(sem::NativeType(sem::NativeType::Type::VOID))) {
|
|
//if (method.returnType->equals(sem::NativeType(sem::NativeType::Type::VOID))) {
|
|
- if (method.returnType == sem::NO_TYPE ||
|
|
|
|
- (semCtxt.getType(method.returnType).getKind() == sem::Type::Kind::NATIVE &&
|
|
|
|
- semCtxt.getType(method.returnType).getNativeKind() == sem::Type::Native::VOID)) {
|
|
|
|
- if (!getCurrentBlock()->getTerminator())
|
|
|
|
- builder.CreateRetVoid();
|
|
|
|
|
|
+ if (method.returnType == nullptr || method.returnType->isVoid()) {
|
|
|
|
+ builder.CreateRetVoid();
|
|
}
|
|
}
|
|
-
|
|
|
|
return func;
|
|
return func;
|
|
}
|
|
}
|
|
|
|
|