Compiler works even better now; we're missing a few functions at runtime, but at least the module appears to generate correctly
This commit is contained in:
@@ -14,7 +14,7 @@ if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/vendor/llvm/llvm/CMakeLists.txt")
|
|||||||
message(STATUS "Using vendored LLVM")
|
message(STATUS "Using vendored LLVM")
|
||||||
set(LLVM_ENABLE_PROJECTS "" CACHE STRING "" FORCE)
|
set(LLVM_ENABLE_PROJECTS "" CACHE STRING "" FORCE)
|
||||||
set(LLVM_ENABLE_RUNTIMES "" CACHE STRING "" FORCE)
|
set(LLVM_ENABLE_RUNTIMES "" CACHE STRING "" FORCE)
|
||||||
set(LLVM_BUILD_TOOLS NO CACHE BOOL "" FORCE)
|
set(LLVM_BUILD_TOOLS YES CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
set(LLVM_TARGETS_TO_BUILD "X86;ARM;AArch64" CACHE STRING "" FORCE)
|
set(LLVM_TARGETS_TO_BUILD "X86;ARM;AArch64" CACHE STRING "" FORCE)
|
||||||
set(LLVM_INCLUDE_BENCHMARKS NO CACHE BOOL "" FORCE)
|
set(LLVM_INCLUDE_BENCHMARKS NO CACHE BOOL "" FORCE)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <llvm/Support/Error.h>
|
||||||
#include "bluebell.hpp"
|
#include "bluebell.hpp"
|
||||||
#include "pre-compiler.hpp"
|
#include "pre-compiler.hpp"
|
||||||
#include "compiler.hpp"
|
#include "compiler.hpp"
|
||||||
@@ -47,6 +49,13 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
auto shader = pre_compile_shader(shader_src.str());
|
auto shader = pre_compile_shader(shader_src.str());
|
||||||
Compiler compiler;
|
Compiler compiler;
|
||||||
compiler.compile(*shader);
|
auto module = compiler.compile(*shader);
|
||||||
|
if (!module) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to build module";
|
||||||
|
}
|
||||||
|
Runtime runtime;
|
||||||
|
if(auto err = runtime.set_module(std::move(module.getValue()))) {
|
||||||
|
report_fatal_error(std::move(err), false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "compiler.hpp"
|
#include "compiler.hpp"
|
||||||
|
#include <llvm/Bitcode/BitcodeWriter.h>
|
||||||
#include <llvm/IR/LLVMContext.h>
|
#include <llvm/IR/LLVMContext.h>
|
||||||
#include <llvm/IR/Module.h>
|
#include <llvm/IR/Module.h>
|
||||||
#include <llvm/IR/IRBuilder.h>
|
#include <llvm/IR/IRBuilder.h>
|
||||||
@@ -855,6 +856,7 @@ public:
|
|||||||
finish_tgv();
|
finish_tgv();
|
||||||
auto ftype = types[OP_WORD(3)];
|
auto ftype = types[OP_WORD(3)];
|
||||||
auto ftype_llvm = (llvm::FunctionType*)ftype->get_llvm_type();
|
auto ftype_llvm = (llvm::FunctionType*)ftype->get_llvm_type();
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Vivifying function for OpFunction";
|
||||||
cur_function = vivify_function(ftype_llvm, OP_WORD(1));
|
cur_function = vivify_function(ftype_llvm, OP_WORD(1));
|
||||||
if (!cur_function->function->empty()) {
|
if (!cur_function->function->empty()) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Started assembling into " << cur_function->function->getName().str()
|
BOOST_LOG_TRIVIAL(error) << "Started assembling into " << cur_function->function->getName().str()
|
||||||
@@ -889,7 +891,8 @@ public:
|
|||||||
types[OP_WORD(0)]->get_llvm_type(),
|
types[OP_WORD(0)]->get_llvm_type(),
|
||||||
arg_types,
|
arg_types,
|
||||||
false);
|
false);
|
||||||
auto fn = vivify_function(ftype, OP_WORD(3));
|
BOOST_LOG_TRIVIAL(debug) << "Vivifying function for OpFunctionCall";
|
||||||
|
auto fn = vivify_function(ftype, OP_WORD(2));
|
||||||
put_value(rid, builder->CreateCall(fn->function, arg_values));
|
put_value(rid, builder->CreateCall(fn->function, arg_values));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1317,13 +1320,22 @@ Compiler::Compiler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<llvm::orc::ThreadSafeModule> Compiler::compile(std::vector<uint32_t> &spv_module) {
|
llvm::Optional<llvm::orc::ThreadSafeModule> Compiler::compile(std::vector<uint32_t> &spv_module) {
|
||||||
|
std::error_code err_code;
|
||||||
auto impl = std::make_unique<CompilerImpl>();
|
auto impl = std::make_unique<CompilerImpl>();
|
||||||
auto ret = impl->process_module(spv_module);
|
auto ret = impl->process_module(spv_module);
|
||||||
impl->generate_support();
|
impl->generate_support();
|
||||||
|
|
||||||
llvm::verifyModule(*impl->module);
|
llvm::verifyModule(*impl->module);
|
||||||
|
llvm::raw_fd_ostream bc_stream("shader.bc", err_code);
|
||||||
|
if (err_code) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to write bitcode";
|
||||||
|
} else {
|
||||||
|
llvm::WriteBitcodeToFile(*impl->module, bc_stream);
|
||||||
|
bc_stream.flush();
|
||||||
|
bc_stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
impl->module->print(llvm::outs(), nullptr, false, true);
|
// impl->module->print(llvm::outs(), nullptr, false, true);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Optimizing";
|
BOOST_LOG_TRIVIAL(debug) << "Optimizing";
|
||||||
// start generating machine code
|
// start generating machine code
|
||||||
@@ -1358,10 +1370,17 @@ llvm::Optional<llvm::orc::ThreadSafeModule> Compiler::compile(std::vector<uint32
|
|||||||
// pass.add(llvm::createLICMPass());
|
// pass.add(llvm::createLICMPass());
|
||||||
|
|
||||||
pass_builder.populateModulePassManager(pass);
|
pass_builder.populateModulePassManager(pass);
|
||||||
|
llvm::raw_fd_ostream bc_opt_stream("shader.opt.bc", err_code);
|
||||||
|
if (err_code) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to write optimized bitcode";
|
||||||
|
} else {
|
||||||
|
llvm::WriteBitcodeToFile(*impl->module, bc_opt_stream);
|
||||||
|
bc_opt_stream.flush();
|
||||||
|
bc_opt_stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
// add output to object file
|
// add output to object file
|
||||||
std::error_code err_code;
|
|
||||||
llvm::raw_fd_ostream objfile("shader.o", err_code);
|
llvm::raw_fd_ostream objfile("shader.o", err_code);
|
||||||
llvm::raw_fd_ostream asfile("shader.s", err_code);
|
|
||||||
if (err_code) {
|
if (err_code) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Failed to open object file: " << err_code.message();
|
BOOST_LOG_TRIVIAL(error) << "Failed to open object file: " << err_code.message();
|
||||||
|
|
||||||
@@ -1375,7 +1394,6 @@ llvm::Optional<llvm::orc::ThreadSafeModule> Compiler::compile(std::vector<uint32
|
|||||||
}
|
}
|
||||||
pass.run(*impl->module);
|
pass.run(*impl->module);
|
||||||
objfile.flush();
|
objfile.flush();
|
||||||
asfile.flush();
|
|
||||||
|
|
||||||
// impl->module->print(llvm::outs(), nullptr, false, true);
|
// impl->module->print(llvm::outs(), nullptr, false, true);
|
||||||
return {llvm::orc::ThreadSafeModule(std::move(impl->module),
|
return {llvm::orc::ThreadSafeModule(std::move(impl->module),
|
||||||
@@ -1385,7 +1403,7 @@ llvm::Optional<llvm::orc::ThreadSafeModule> Compiler::compile(std::vector<uint32
|
|||||||
Compiler::~Compiler() = default;
|
Compiler::~Compiler() = default;
|
||||||
|
|
||||||
FunctionContext::FunctionContext(struct CompilerImpl &compiler, llvm::FunctionType *ftype, uint32_t id) {
|
FunctionContext::FunctionContext(struct CompilerImpl &compiler, llvm::FunctionType *ftype, uint32_t id) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Creating function for id " << id;
|
||||||
bool is_ep = false;
|
bool is_ep = false;
|
||||||
std::string name;
|
std::string name;
|
||||||
auto linkage = llvm::Function::ExternalLinkage;
|
auto linkage = llvm::Function::ExternalLinkage;
|
||||||
@@ -1393,13 +1411,16 @@ FunctionContext::FunctionContext(struct CompilerImpl &compiler, llvm::FunctionTy
|
|||||||
if (ep.second->func_id == id) {
|
if (ep.second->func_id == id) {
|
||||||
is_ep = true;
|
is_ep = true;
|
||||||
name = ep.second->name;
|
name = ep.second->name;
|
||||||
linkage = llvm::Function::ExternalLinkage;
|
// The entry point is not *actually* being used as an entry point; we use a wrapper to stuff and unload
|
||||||
|
// the context using details known only at compile-time
|
||||||
|
// linkage = llvm::Function::ExternalLinkage;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
auto it = compiler.value_names.find(id);
|
auto it = compiler.value_names.find(id);
|
||||||
if (it != compiler.value_names.end()) {
|
if (it != compiler.value_names.end()) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Name based on value_names";
|
||||||
name = it->second;
|
name = it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@
|
|||||||
#include <llvm/Transforms/IPO.h>
|
#include <llvm/Transforms/IPO.h>
|
||||||
#include <llvm/Transforms/Utils.h>
|
#include <llvm/Transforms/Utils.h>
|
||||||
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
|
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
// we need libm, so import it
|
||||||
struct RuntimeImpl {
|
struct RuntimeImpl {
|
||||||
|
|
||||||
std::unique_ptr<llvm::legacy::PassManager> passManager;
|
std::unique_ptr<llvm::legacy::PassManager> passManager;
|
||||||
@@ -47,9 +49,13 @@ struct RuntimeImpl {
|
|||||||
if (auto err = jit->addIRModule(std::move(mod))) {
|
if (auto err = jit->addIRModule(std::move(mod))) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
auto sym = jit->lookup("setup");
|
llvm::JITEvaluatedSymbol get_context_size;
|
||||||
|
|
||||||
|
float foo = cosf(0.);
|
||||||
|
|
||||||
|
if (auto err = jit->lookup("get_context_size").moveInto(get_context_size)) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return llvm::Error::success();
|
return llvm::Error::success();
|
||||||
}
|
}
|
||||||
@@ -58,6 +64,7 @@ struct RuntimeImpl {
|
|||||||
Runtime::Runtime(): impl(std::make_unique<RuntimeImpl>()) {
|
Runtime::Runtime(): impl(std::make_unique<RuntimeImpl>()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Runtime::~Runtime() = default;
|
||||||
|
|
||||||
llvm::Error Runtime::set_module(llvm::orc::ThreadSafeModule module) {
|
llvm::Error Runtime::set_module(llvm::orc::ThreadSafeModule module) {
|
||||||
return impl->setModule(std::move(module));
|
return impl->setModule(std::move(module));
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ class Runtime {
|
|||||||
// the compiler will construct this from its internals
|
// the compiler will construct this from its internals
|
||||||
friend class Compiler;
|
friend class Compiler;
|
||||||
std::unique_ptr<struct RuntimeImpl> impl;
|
std::unique_ptr<struct RuntimeImpl> impl;
|
||||||
protected:
|
|
||||||
Runtime();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Runtime();
|
||||||
|
~Runtime();
|
||||||
|
|
||||||
llvm::Error set_module(llvm::orc::ThreadSafeModule module);
|
llvm::Error set_module(llvm::orc::ThreadSafeModule module);
|
||||||
void render_frame(const Uniforms &uniforms, float buf[32][32][3]);
|
void render_frame(const Uniforms &uniforms, float buf[32][32][3]);
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user