|
@@ -2,6 +2,7 @@
|
|
|
|
|
|
#include <llvm/IR/LLVMContext.h>
|
|
#include <llvm/IR/LLVMContext.h>
|
|
#include <llvm/IR/LegacyPassManager.h>
|
|
#include <llvm/IR/LegacyPassManager.h>
|
|
|
|
+#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
|
#include <llvm/IR/Type.h>
|
|
#include <llvm/IR/Type.h>
|
|
#include <llvm/IR/DerivedTypes.h>
|
|
#include <llvm/IR/DerivedTypes.h>
|
|
#include <llvm/IR/Constants.h>
|
|
#include <llvm/IR/Constants.h>
|
|
@@ -12,6 +13,7 @@
|
|
#include <llvm/Support/TargetRegistry.h>
|
|
#include <llvm/Support/TargetRegistry.h>
|
|
#include <llvm/Support/TargetSelect.h>
|
|
#include <llvm/Support/TargetSelect.h>
|
|
#include <llvm/Support/FileSystem.h>
|
|
#include <llvm/Support/FileSystem.h>
|
|
|
|
+#include <llvm/Support/raw_os_ostream.h>
|
|
|
|
|
|
|
|
|
|
using namespace qlow;
|
|
using namespace qlow;
|
|
@@ -60,6 +62,7 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
|
|
}
|
|
}
|
|
|
|
|
|
std::vector<llvm::Function*> functions;
|
|
std::vector<llvm::Function*> functions;
|
|
|
|
+ auto verifyStream = llvm::raw_os_ostream(logger.debug());
|
|
|
|
|
|
// create all llvm functions
|
|
// create all llvm functions
|
|
for (auto& [name, cl] : objects.classes) {
|
|
for (auto& [name, cl] : objects.classes) {
|
|
@@ -76,7 +79,10 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
|
|
for (auto& [name, method] : cl->methods) {
|
|
for (auto& [name, method] : cl->methods) {
|
|
FunctionGenerator fg(*method, module.get());
|
|
FunctionGenerator fg(*method, module.get());
|
|
Function* f = fg.generate();
|
|
Function* f = fg.generate();
|
|
- llvm::verifyFunction(*f, &llvm::errs());
|
|
|
|
|
|
+ logger.debug() << "verifying function: " << method->name << std::endl;
|
|
|
|
+ bool corrupt = llvm::verifyFunction(*f, &verifyStream);
|
|
|
|
+ if (corrupt)
|
|
|
|
+ throw "corrupt llvm function";
|
|
#ifdef DEBUGGING
|
|
#ifdef DEBUGGING
|
|
printf("verified function: %s\n", method->name.c_str());
|
|
printf("verified function: %s\n", method->name.c_str());
|
|
#endif
|
|
#endif
|
|
@@ -85,7 +91,10 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects)
|
|
for (auto& [name, method] : objects.functions) {
|
|
for (auto& [name, method] : objects.functions) {
|
|
FunctionGenerator fg(*method, module.get());
|
|
FunctionGenerator fg(*method, module.get());
|
|
Function* f = fg.generate();
|
|
Function* f = fg.generate();
|
|
- llvm::verifyFunction(*f, &llvm::errs());
|
|
|
|
|
|
+ logger.debug() << "verifying function: " << method->name << std::endl;
|
|
|
|
+ bool corrupt = llvm::verifyFunction(*f, &verifyStream);
|
|
|
|
+ if (corrupt)
|
|
|
|
+ throw "corrupt llvm function";
|
|
#ifdef DEBUGGING
|
|
#ifdef DEBUGGING
|
|
printf("verified function: %s\n", method->name.c_str());
|
|
printf("verified function: %s\n", method->name.c_str());
|
|
#endif
|
|
#endif
|
|
@@ -136,21 +145,26 @@ llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Module> module)
|
|
|
|
|
|
+void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Module> module, int optLevel)
|
|
{
|
|
{
|
|
using llvm::legacy::PassManager;
|
|
using llvm::legacy::PassManager;
|
|
|
|
+ using llvm::PassManagerBuilder;
|
|
using llvm::raw_fd_ostream;
|
|
using llvm::raw_fd_ostream;
|
|
using llvm::Target;
|
|
using llvm::Target;
|
|
using llvm::TargetMachine;
|
|
using llvm::TargetMachine;
|
|
using llvm::TargetRegistry;
|
|
using llvm::TargetRegistry;
|
|
using llvm::TargetOptions;
|
|
using llvm::TargetOptions;
|
|
|
|
|
|
-
|
|
|
|
- printf("verifying mod\n");
|
|
|
|
- module->print(llvm::errs(), nullptr);
|
|
|
|
- llvm::verifyModule(*module);
|
|
|
|
- printf("mod verified\n");
|
|
|
|
-
|
|
|
|
|
|
+ Logger& logger = Logger::getInstance();
|
|
|
|
+ logger.debug() << "verifying mod" << std::endl;
|
|
|
|
+ auto ostr = llvm::raw_os_ostream(logger.debug());
|
|
|
|
+ module->print(ostr, nullptr);
|
|
|
|
+ bool broken = llvm::verifyModule(*module);
|
|
|
|
+
|
|
|
|
+ if (broken)
|
|
|
|
+ throw "invalid llvm module";
|
|
|
|
+
|
|
|
|
+ logger.debug() << "mod verified" << std::endl;
|
|
|
|
|
|
llvm::InitializeAllTargetInfos();
|
|
llvm::InitializeAllTargetInfos();
|
|
llvm::InitializeAllTargets();
|
|
llvm::InitializeAllTargets();
|
|
@@ -159,6 +173,19 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
|
|
llvm::InitializeAllAsmPrinters();
|
|
llvm::InitializeAllAsmPrinters();
|
|
|
|
|
|
PassManager pm;
|
|
PassManager pm;
|
|
|
|
+
|
|
|
|
+ int sizeLevel = 0;
|
|
|
|
+ PassManagerBuilder builder;
|
|
|
|
+ builder.OptLevel = optLevel;
|
|
|
|
+ builder.SizeLevel = sizeLevel;
|
|
|
|
+ if (optLevel >= 2) {
|
|
|
|
+ builder.DisableUnitAtATime = false;
|
|
|
|
+ builder.DisableUnrollLoops = false;
|
|
|
|
+ builder.LoopVectorize = true;
|
|
|
|
+ builder.SLPVectorize = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ builder.populateModulePassManager(pm);
|
|
|
|
|
|
const char cpu[] = "generic";
|
|
const char cpu[] = "generic";
|
|
const char features[] = "";
|
|
const char features[] = "";
|
|
@@ -167,8 +194,9 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
|
|
std::string targetTriple = llvm::sys::getDefaultTargetTriple();
|
|
std::string targetTriple = llvm::sys::getDefaultTargetTriple();
|
|
const Target* target = TargetRegistry::lookupTarget(targetTriple, error);
|
|
const Target* target = TargetRegistry::lookupTarget(targetTriple, error);
|
|
|
|
|
|
- if (!target)
|
|
|
|
- fprintf(stderr, "could not create target: %s", error.c_str());
|
|
|
|
|
|
+ if (!target) {
|
|
|
|
+ logger.debug() << "could not create target: " << error << std::endl;
|
|
|
|
+ }
|
|
|
|
|
|
TargetOptions targetOptions;
|
|
TargetOptions targetOptions;
|
|
auto relocModel = llvm::Optional<llvm::Reloc::Model>();
|
|
auto relocModel = llvm::Optional<llvm::Reloc::Model>();
|
|
@@ -239,7 +267,10 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
|
|
//Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
|
|
//Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
|
|
|
|
|
|
builder.SetInsertPoint(getCurrentBlock());
|
|
builder.SetInsertPoint(getCurrentBlock());
|
|
- builder.CreateRetVoid();
|
|
|
|
|
|
+ if (method.returnType->equals(sem::Type::VOID)) {
|
|
|
|
+ if (!getCurrentBlock()->getTerminator())
|
|
|
|
+ builder.CreateRetVoid();
|
|
|
|
+ }
|
|
|
|
|
|
return func;
|
|
return func;
|
|
}
|
|
}
|