unlogic
Loading...
Searching...
No Matches
Compiler.cpp
Go to the documentation of this file.
1//
2// Created by nathan on 6/8/24.
3//
4
5#include "Compiler.h"
6#include <llvm/ExecutionEngine/Orc/Core.h>
7#include <llvm/ExecutionEngine/Orc/ThreadSafeModule.h>
8#include <llvm/Support/TargetSelect.h>
9#include "parser/Node.h"
11
12using namespace unlogic;
13
15{
16 auto function_ea = this->jit_->lookup("__entry");
17 if (auto e = function_ea.takeError())
18 {
19 throw std::runtime_error(llvm::toString(std::move(e)));
20 }
21
22 auto program = function_ea->toPtr<void(Scene *)>();
23
24 return program(scene);
25}
26
28{
29 llvm::InitializeNativeTarget();
30 llvm::InitializeNativeTargetAsmPrinter();
31 llvm::InitializeNativeTargetAsmParser();
32}
33
34std::expected<Program, CompilationError> Compiler::Compile(std::string_view program_text, std::vector<bf::Token<ParserGrammarType>> *tokens)
35{
36 // Parse program
37 auto ast = this->parser_.Parse(program_text, tokens);
38 if (!ast.has_value())
39 {
40 return std::unexpected(ast.error());
41 }
42
43 auto ast_body = std::get<std::unique_ptr<Node>>(std::move(*ast));
44
45 // Establish context for build
46 auto ctx = std::make_unique<llvm::LLVMContext>();
47
48 auto jit = std::move(*llvm::orc::LLJITBuilder().create());
49
50 // Create and link libraries to main dylib
51 llvm::orc::JITDylib &main = jit->getMainJITDylib();
52
53 // Create module
54 auto module = std::make_unique<llvm::Module>("unlogic", *ctx.get());
55
56 // Create program scope
57 Scope program_scope;
58 program_scope.PushLayer();
59
60 for (auto library: this->default_libraries_)
61 {
62 // Generate symbol map
63 llvm::orc::SymbolMap library_symbols;
64 for (auto symbol: library->symbols)
65 {
66 library_symbols.insert({
67 jit->mangleAndIntern(symbol->name),
68 symbol->symbol,
69 });
70
71 symbol->Define(*ctx.get(), *module);
72 }
73
74 // Add symbol map
75 auto std_sym_def = main.define(llvm::orc::absoluteSymbols(library_symbols));
76 if (std_sym_def)
77 {
78 return std::unexpected(std::move(std_sym_def));
79 }
80 }
81
82 // Create IR generation context
83 IRGenerationContext ir_ctx = {
84 .llvm_ctx = *ctx.get(),
85 .module = std::move(module),
86 .scope = program_scope,
87 };
88
89 // IR Generator
90 IRGenerator generator(ir_ctx);
91
92 // Build program
93 try
94 {
95 std::visit(generator, *ast_body);
96 }
97 catch (std::runtime_error &e)
98 {
99 return std::unexpected(Error{e.what()});
100 }
101
102 llvm::orc::ThreadSafeModule tsm(std::move(ir_ctx.module), std::move(ctx));
103 auto e = jit->addIRModule(std::move(tsm));
104
105 return Program(std::move(jit));
106}
107
108Compiler::Compiler(std::vector<Library *> default_libraries) :
109 default_libraries_(std::move(default_libraries)), parser_(*bf::SLRParser<ParserGrammarType>::Build(unlogic::unlogic_program))
110{
111}
bf::DefineNonTerminal< G, std::unique_ptr< Node > > program
Definition Parser.cpp:191
static void InitializeGlobalCompilerRuntime()
Definition Compiler.cpp:27
std::expected< Program, CompilationError > Compile(std::string_view program_text, std::vector< bf::Token< ParserGrammarType > > *tokens=nullptr)
Definition Compiler.cpp:34
void operator()(Scene *scene)
Definition Compiler.cpp:14
bf::GrammarDefinition< ParserValueType, SyntaxHighlightingGroup > ParserGrammarType
Definition Parser.h:20
bf::NonTerminal< ParserGrammarType > & unlogic_program
Definition Parser.cpp:200