Yume
compiler.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "ast/crtp_walker.hpp"
6#include "type_holder.hpp"
7#include "util.hpp"
8#include "vals.hpp"
9#include <deque>
10#include <llvm/IR/DIBuilder.h>
11#include <llvm/IR/GlobalVariable.h>
12#include <llvm/IR/IRBuilder.h>
13#include <llvm/IR/LLVMContext.h>
14#include <llvm/IR/Module.h>
15#include <llvm/Target/TargetMachine.h>
16#include <map>
17#include <memory>
18#include <optional>
19#include <queue>
20#include <stdexcept>
21#include <string>
22#include <vector>
23
24namespace llvm {
25class Function;
26class Type;
27class Value;
28} // namespace llvm
29
30namespace yume {
31namespace ast {
32class AST;
33class Expr;
34struct Program;
35struct StructDecl;
36class Stmt;
37} // namespace ast
38namespace ty {
39class Struct;
40class BaseType;
41} // namespace ty
42
43/// The `Compiler` the the primary top-level type during compilation. A single instance is created during the
44/// compilation process.
45class Compiler : public CRTPWalker<Compiler> {
46 vector<SourceFile> m_sources;
47 TypeHolder m_types;
48 std::deque<Fn> m_fns{};
49 std::deque<Struct> m_structs{};
50 std::deque<Fn> m_ctors{};
51 std::deque<Const> m_consts{};
52 std::queue<DeclLike> m_decl_queue{};
53 unique_ptr<semantic::TypeWalker> m_walker;
54
55 Fn* m_current_fn{};
56 /// Local variables currently in function scope. Used for destructors
58 /// In a constructor, the object being constructed, implicitly created by the compiler.
59 optional<InScope> m_scope_ctor{};
60
61 Struct* m_slice_struct{};
62
63 llvm::Function* m_global_ctor_fn;
64 llvm::Function* m_global_dtor_fn;
65
66 ast::AST* m_return_value{};
67
68 std::map<ast::Program*, llvm::DICompileUnit*> m_source_mapping{};
69
70 unique_ptr<llvm::LLVMContext> m_context;
71 unique_ptr<llvm::IRBuilder<>> m_builder;
72 unique_ptr<llvm::Module> m_module;
73 unique_ptr<llvm::TargetMachine> m_target_machine;
74 unique_ptr<llvm::DIBuilder> m_debug;
75
77 friend CRTPWalker;
78
79public:
80 [[nodiscard]] auto module() const -> const auto& { return m_module; }
81 [[nodiscard]] auto context() const -> const auto& { return m_context; }
82 [[nodiscard]] auto builder() const -> const auto& { return m_builder; }
83
84 Compiler(const optional<string>& target_triple, vector<SourceFile> source_files);
85 /// Begin compilation!
86 void run();
87
88 /// Declare a function/constructor in bytecode, or get an existing declaration.
89 auto declare(Fn&) -> llvm::Function*;
90
91 auto create_struct(Struct&) -> bool;
92
93 /// Compile the body of a function or constructor.
94 void define(Fn&);
95 void define(Const&);
96
98 auto decl_statement(ast::Stmt&, optional<ty::Type> parent = std::nullopt, ast::Program* member = nullptr,
99 nullable<Substitutions*> parent_subs = nullptr) -> DeclLike;
100 auto body_expression(ast::Expr& expr) -> Val;
102
103 void write_object(const char* filename, bool binary);
104
105 /// Convert a type into its corresponding LLVM type
106 auto llvm_type(ty::Type type, bool erase_opaque = false) -> llvm::Type*;
107
108 auto ptr_bitsize() -> unsigned int;
109
110 /// Default-constructs an object of specified type \p type
111 auto default_init(ty::Type type) -> Val;
112 /// Destructs an object \p val of specified type \p type
113 void destruct(Val val, ty::Type type);
114
115 [[nodiscard]] auto source_files() -> const auto& { return m_sources; }
116
117private:
118 template <typename T>
119 requires (!std::is_const_v<T>)
120 void statement(T& stat) {
121 throw std::runtime_error("Unknown statement "s + stat.kind_name());
122 }
123
124 template <typename T>
125 requires (!std::is_const_v<T>)
126 auto expression(T& expr) -> Val {
127 throw std::runtime_error("Unknown expression "s + expr.kind_name());
128 }
129
130 /// Create a temporary `IRBuilder` which points to the entrypoint of the current function being compiled. This is used
131 /// for variable declarations, which are always at the entrypoint, as to not cause a stack overflow with locals.
132 auto entrypoint_builder() -> llvm::IRBuilder<>;
133 auto entrypoint_dtor_builder() -> llvm::IRBuilder<>;
134
135 /// Common code between defining functions and constructors. \see define .
136 void setup_fn_base(Fn&);
137
138 /// Run the destructors for every owned local variable in the current scope. Should be run when exiting a scope.
139 void destruct_last_scope();
140 /// Run the destructors for every owned local variable in all scopes of the current function. Should be run when
141 /// returning from a function in any way.
142 void destruct_all_scopes();
143 /// Create a new temporary variable in the current scope, that will automatically be destructed at the end of the
144 /// scope.
145 void make_temporary_in_scope(Val& val, const ast::AST& ast, const string& name = "tmp"s);
146
147 void expose_parameter_as_local(ty::Type type, const string& name, const ast::AST& ast, Val val);
148
149 auto create_malloc(llvm::Type* base_type, Val slice_size, string_view name = ""sv) -> Val;
150 auto create_malloc(llvm::Type* base_type, uint64_t slice_size, string_view name = ""sv) -> Val;
151 auto create_free(Val ptr) -> Val;
152
153 /// Handle all primitive, built-in functions
154 auto primitive(Fn* fn, const vector<Val>& args, const vector<ty::Type>& types, vector<ast::AnyExpr*>& ast_args)
155 -> optional<Val>;
156 /// Handle primitive functions taking two integral values, such as most arithmetic operations (add, multiply, etc).
157 auto int_bin_primitive(const string& primitive, const vector<Val>& args) -> Val;
158
159 /// Instruct the `TypeWalker` to perform semantic analysis and infer types for the given declaration.
160 void walk_types(DeclLike);
161
162 void make_dup(Val& value, ast::AnyExpr& ast);
163
164 auto get_vtable(Struct& st, const Struct& iface) noexcept(false) -> nonnull<llvm::GlobalVariable*>;
165
166 void declare_default_ctor(Struct&);
167};
168} // namespace yume
The Compiler the the primary top-level type during compilation. A single instance is created during t...
Definition: compiler.hpp:45
auto source_files() -> const auto &
Definition: compiler.hpp:115
auto builder() const -> const auto &
Definition: compiler.hpp:82
auto body_expression(ast::Expr &expr) -> Val
Definition: compiler.cpp:1632
void body_statement(ast::Stmt &)
Definition: compiler.cpp:1626
auto ptr_bitsize() -> unsigned int
Definition: compiler.cpp:1369
auto llvm_type(ty::Type type, bool erase_opaque=false) -> llvm::Type *
Convert a type into its corresponding LLVM type.
Definition: compiler.cpp:429
auto direct_call_operator(ast::CallExpr &expr) -> Val
Definition: compiler.cpp:1259
void run()
Begin compilation!
Definition: compiler.cpp:180
void define(Fn &)
Compile the body of a function or constructor.
Definition: compiler.cpp:683
void write_object(const char *filename, bool binary)
Definition: compiler.cpp:1611
auto declare(Fn &) -> llvm::Function *
Declare a function/constructor in bytecode, or get an existing declaration.
Definition: compiler.cpp:544
Compiler(const optional< string > &target_triple, vector< SourceFile > source_files)
Definition: compiler.cpp:88
auto module() const -> const auto &
Definition: compiler.hpp:80
auto decl_statement(ast::Stmt &, optional< ty::Type > parent=std::nullopt, ast::Program *member=nullptr, nullable< Substitutions * > parent_subs=nullptr) -> DeclLike
Definition: compiler.cpp:305
void destruct(Val val, ty::Type type)
Destructs an object val of specified type type.
Definition: compiler.cpp:472
auto context() const -> const auto &
Definition: compiler.hpp:81
auto default_init(ty::Type type) -> Val
Default-constructs an object of specified type type.
Definition: compiler.cpp:518
auto create_struct(Struct &) -> bool
Definition: compiler.cpp:277
All nodes in the AST tree of the program inherit from this class.
Definition: ast.hpp:224
Expressions have an associated value and type.
Definition: ast.hpp:438
Statements make up most things in source code.
Definition: ast.hpp:297
Represents a type in the type system. NOTE: that this isn't the class to use for type introspection,...
Definition: type_base.hpp:42
An user-defined struct type with associated fields.
Definition: type.hpp:78
A "qualified" type, with a non-stackable qualifier, i.e. mut.
Definition: type_base.hpp:66
Definition: ast.hpp:20
AnyBase< Expr > AnyExpr
Definition: ast.hpp:448
Definition: ast.cpp:8
T nullable
Definition: util.hpp:72
A helper template to walk the Abstract Syntax Tree (AST), utilizing the Curiously Recurring Template ...
Definition: crtp_walker.hpp:23
A constant declaration in the compiler.
Definition: vals.hpp:174
A common base between declarations in the compiler: Fn, Struct and Const. Its value may also be absen...
Definition: vals.hpp:208
A function declaration in the compiler.
Definition: vals.hpp:52
A struct declaration in the compiler.
Definition: vals.hpp:136
A value of a complied expression.
Definition: vals.hpp:262
A function call or operator.
Definition: ast.hpp:562
The top level structure of a file of source code.
Definition: ast.hpp:957
Determine the type information of AST nodes. This makes up most of the "semantic" phase of the compil...
Definition: type_walker.hpp:33