tan  0.0.1
code_generator.h
1 #ifndef __TAN_SRC_CODEGEN_CODE_GENERATOR_H__
2 #define __TAN_SRC_CODEGEN_CODE_GENERATOR_H__
3 #include "base.h"
4 #include "ast/fwd.h"
5 #include "common/compiler_action.h"
6 
7 #include <llvm/Target/TargetMachine.h>
8 #include <llvm/IR/IRBuilder.h>
9 #include <llvm/IR/Value.h>
10 #include <llvm/IR/DIBuilder.h>
11 #include <llvm/IR/Instructions.h>
12 #include <llvm/IR/BasicBlock.h>
13 using llvm::AllocaInst;
14 using llvm::BasicBlock;
15 using llvm::DIBuilder;
16 using llvm::IRBuilder;
17 using llvm::TargetMachine;
18 using llvm::Value;
19 
20 namespace tanlang {
21 
22 class ASTBase;
23 class StructType;
24 class Package;
25 
26 class CodeGenerator final : public CompilerAction<CodeGenerator, Package *, void> {
27 public:
28  CodeGenerator() = delete;
29  explicit CodeGenerator(TargetMachine *target_machine);
30  ~CodeGenerator();
31 
32  void init(Package *package) override;
33  void run_impl(Package *package);
34  llvm::Value *cached_visit(ASTBase *p);
35  void default_visit(ASTBase *) override;
36 
37  void emit_to_file(const str &filename);
38  void run_passes();
39  void dump_ir() const;
40 
41 private:
42  [[noreturn]] void error(ErrorType type, ASTBase *p, const str &message);
43 
44 private:
45  /**
46  * \brief Convert a value to from orig type to dest type.
47  * \details Returns nullptr if failed to convert.
48  * \param dest Destination type.
49  * \param expr Original expression.
50  * \return Converted value if convertible, otherwise `nullptr`. Note that the returned value is always rvalue. To
51  * get an lvalue, create a temporary variable and store the value to it.
52  */
53  llvm::Value *convert_llvm_type_to(Expr *expr, Type *dest);
54 
55  /// Create a load instruction if the type is lvalue. Otherwise return the original value.
56  llvm::Value *load_if_is_lvalue(Expr *expr);
57 
58  llvm::Type *to_llvm_type(Type *p);
59  llvm::Metadata *to_llvm_metadata(Type *p, llvm::DIFile *di_file, uint32_t lineno);
60  llvm::DISubroutineType *create_function_debug_info_type(llvm::Metadata *ret, vector<llvm::Metadata *> args);
61 
62 private:
63  umap<Type *, llvm::Type *> _llvm_type_cache{};
64  umap<Type *, llvm::Metadata *> _llvm_meta_cache{};
65  umap<ASTBase *, llvm::Value *> _llvm_value_cache{};
66 
67  // Map source files to their DIFile instances
68  umap<TokenizedSourceFile *, llvm::DIFile *> _di_files{};
69 
70  /// LLVM things
71  llvm::IRBuilder<> *_builder = nullptr;
72  llvm::DIBuilder *_di_builder = nullptr;
73  llvm::LLVMContext *_llvm_ctx = nullptr;
74  llvm::Module *_module = nullptr;
75  vector<llvm::DIScope *> _di_scope{};
76  llvm::TargetMachine *_target_machine = nullptr;
77 
78 private:
79  llvm::DIScope *get_current_di_scope() const;
80  void push_di_scope(llvm::DIScope *scope);
81  void pop_di_scope();
82  void set_current_debug_location(ASTBase *p);
83  llvm::DebugLoc debug_loc_of_node(ASTBase *p, llvm::MDNode *scope = nullptr);
84 
85  /**
86  * \brief create_ty an `alloca` instruction in the beginning of a block.
87  * \param block BasicBlock to insert to.
88  * \param type Intended type to store.
89  * \param name Name of the `alloca` instruction.
90  * \param size size of the array if greater than 1
91  */
92  AllocaInst *create_block_alloca(BasicBlock *block, llvm::Type *type, size_t size = 1, const str &name = "");
93 
94 private:
95  Value *codegen_var_arg_decl(Decl *p);
96  Value *codegen_struct_default_value(StructType *ty);
97  Value *codegen_type_default_value(Type *p);
98  Value *codegen_literals(Literal *p);
99  Value *codegen_func_prototype(FunctionDecl *p, bool import_ = false);
100  Value *codegen_ptr_deref(UnaryOperator *p);
101  Value *codegen_relop(BinaryOperator *p);
102  Value *codegen_bnot(UnaryOperator *p);
103  Value *codegen_lnot(UnaryOperator *p);
104  Value *codegen_address_of(UnaryOperator *p);
105  Value *codegen_arithmetic(BinaryOperator *p);
106  Value *codegen_comparison(BinaryOperator *p);
107  Value *codegen_member_access(BinaryOperator *p);
108 
109  /**
110  * \brief Get or create a DIFile instance for the source file that contains node p
111  */
112  llvm::DIFile *get_or_create_di_file(ASTBase *p);
113 
114 public:
115  DECLARE_AST_VISITOR_IMPL(Package);
116  DECLARE_AST_VISITOR_IMPL(Identifier);
117  DECLARE_AST_VISITOR_IMPL(Parenthesis);
118  DECLARE_AST_VISITOR_IMPL(If);
119  DECLARE_AST_VISITOR_IMPL(VarDecl);
120  DECLARE_AST_VISITOR_IMPL(ArgDecl);
121  DECLARE_AST_VISITOR_IMPL(Return);
122  DECLARE_AST_VISITOR_IMPL(CompoundStmt);
123  DECLARE_AST_VISITOR_IMPL(BinaryOrUnary);
124  DECLARE_AST_VISITOR_IMPL(BinaryOperator);
125  DECLARE_AST_VISITOR_IMPL(UnaryOperator);
126  DECLARE_AST_VISITOR_IMPL(Cast);
127  DECLARE_AST_VISITOR_IMPL(Assignment);
128  DECLARE_AST_VISITOR_IMPL(FunctionCall);
129  DECLARE_AST_VISITOR_IMPL(FunctionDecl);
130  DECLARE_AST_VISITOR_IMPL(Import);
131  DECLARE_AST_VISITOR_IMPL(Intrinsic);
132  DECLARE_AST_VISITOR_IMPL(ArrayLiteral);
133  DECLARE_AST_VISITOR_IMPL(CharLiteral);
134  DECLARE_AST_VISITOR_IMPL(BoolLiteral);
135  DECLARE_AST_VISITOR_IMPL(IntegerLiteral);
136  DECLARE_AST_VISITOR_IMPL(FloatLiteral);
137  DECLARE_AST_VISITOR_IMPL(StringLiteral);
138  DECLARE_AST_VISITOR_IMPL(NullPointerLiteral);
139  // DECLARE_AST_VISITOR_IMPL(MemberAccess);
140  DECLARE_AST_VISITOR_IMPL(StructDecl);
141  DECLARE_AST_VISITOR_IMPL(Loop);
142  DECLARE_AST_VISITOR_IMPL(BreakContinue);
143  DECLARE_AST_VISITOR_IMPL(VarRef);
144  DECLARE_AST_VISITOR_IMPL(PackageDecl);
145 };
146 
147 } // namespace tanlang
148 
149 #endif //__TAN_SRC_CODEGEN_CODE_GENERATOR_H__
Represent if-[else] or if-elif-[else] statements.
Definition: stmt.h:144
A generic representation of Intrinsic variables/functions.
Definition: intrinsic.h:55
Type is immutable once created. The exception is StructType. Its information is updated in multiple s...
Definition: type.h:22