authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-02 23:48:48-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-02 23:48:48-04:00
logcd1bd78aa9b4120ee95cd6347b7adce0d460f9d2
treedb1b897859fb6a1be751aa413d77b20ad411dc74
parent633781e31dedaa27d9692d56f6cf073931ca311a

simple add function works with IR


6 files changed, 1011 insertions(+), 129 deletions(-)

src/all_types.hpp+8
......@@ -1420,6 +1420,7 @@ enum IrInstructionId {
14201420 IrInstructionIdBuiltinCall,
14211421 IrInstructionIdConst,
14221422 IrInstructionIdReturn,
1423 IrInstructionIdCast,
14231424};
14241425
14251426struct IrInstruction {
......@@ -1539,5 +1540,12 @@ struct IrInstructionReturn {
15391540 IrInstruction *value;
15401541};
15411542
1543struct IrInstructionCast {
1544 IrInstruction base;
1545
1546 IrInstruction *value;
1547 IrInstruction *dest_type;
1548 bool is_implicit;
1549};
15421550
15431551#endif
src/analyze.cpp+6-17
......@@ -42,10 +42,8 @@ static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, As
4242 TypeTableEntry *expected_type, uint64_t x, bool depends_on_compile_var);
4343static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, bool value,
4444 bool depends_on_compile_var);
45static AstNode *find_decl(BlockContext *context, Buf *name);
4645static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
4746 bool pointer_only, BlockContext *block_context, bool depends_on_compile_var);
48static TopLevelDecl *get_as_top_level_decl(AstNode *node);
4947static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
5048 BlockContext *context, AstNode *source_node,
5149 AstNodeVariableDeclaration *variable_declaration,
......@@ -1757,7 +1755,7 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {
17571755 node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk;
17581756}
17591757
1760static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) {
1758void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) {
17611759 TopLevelDecl *tld = get_as_top_level_decl(node);
17621760 if (tld->resolution != TldResolutionUnresolved) {
17631761 return;
......@@ -1978,7 +1976,7 @@ static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTa
19781976 return false;
19791977}
19801978
1981static bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
1979bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
19821980 if (expected_type == actual_type)
19831981 return true;
19841982
......@@ -2302,7 +2300,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, ImportTableEntry *
23022300 return g->builtin_types.entry_invalid;
23032301}
23042302
2305static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *import,
2303TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *import,
23062304 BlockContext *block_context, AstNode *parent_source_node,
23072305 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count)
23082306{
......@@ -2358,7 +2356,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
23582356 return context;
23592357}
23602358
2361static AstNode *find_decl(BlockContext *context, Buf *name) {
2359AstNode *find_decl(BlockContext *context, Buf *name) {
23622360 while (context) {
23632361 auto entry = context->decl_table.maybe_get(name);
23642362 if (entry) {
......@@ -2369,7 +2367,7 @@ static AstNode *find_decl(BlockContext *context, Buf *name) {
23692367 return nullptr;
23702368}
23712369
2372static VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name) {
2370VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name) {
23732371 BlockContext *context = orig_context;
23742372 while (context) {
23752373 auto entry = context->var_table.maybe_get(name);
......@@ -3248,10 +3246,6 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod
32483246static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
32493247 TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
32503248{
3251 if (node->data.symbol_expr.override_type_entry) {
3252 return resolve_expr_const_val_as_type(g, node, node->data.symbol_expr.override_type_entry, false);
3253 }
3254
32553249 Buf *variable_name = node->data.symbol_expr.symbol;
32563250
32573251 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);
......@@ -4091,11 +4085,6 @@ static TypeTableEntry *analyze_this_literal_expr(CodeGen *g, ImportTableEntry *i
40914085static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import,
40924086 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
40934087{
4094 if (node->data.number_literal.overflow) {
4095 add_node_error(g, node, buf_sprintf("number literal too large to be represented in any type"));
4096 return g->builtin_types.entry_invalid;
4097 }
4098
40994088 return resolve_expr_const_val_as_bignum(g, node, expected_type, node->data.number_literal.bignum, false);
41004089}
41014090
......@@ -7536,7 +7525,7 @@ Expr *get_resolved_expr(AstNode *node) {
75367525 zig_unreachable();
75377526}
75387527
7539static TopLevelDecl *get_as_top_level_decl(AstNode *node) {
7528TopLevelDecl *get_as_top_level_decl(AstNode *node) {
75407529 switch (node->type) {
75417530 case NodeTypeVariableDeclaration:
75427531 return &node->data.variable_declaration.top_level_decl;
src/analyze.hpp+10
......@@ -45,4 +45,14 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
4545
4646AstNode *first_executing_node(AstNode *node);
4747
48TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *import,
49 BlockContext *block_context, AstNode *parent_source_node,
50 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count);
51
52bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);
53VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name);
54AstNode *find_decl(BlockContext *context, Buf *name);
55void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only);
56TopLevelDecl *get_as_top_level_decl(AstNode *node);
57
4858#endif
src/codegen.cpp+105-9
......@@ -65,8 +65,6 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
6565 g->is_test_build = false;
6666 g->want_h_file = true;
6767
68 g->invalid_instruction = allocate<IrInstruction>(1);
69
7068 // the error.Ok value
7169 g->error_decls.append(nullptr);
7270
......@@ -252,10 +250,6 @@ static void set_debug_source_node(CodeGen *g, AstNode *node) {
252250 ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);
253251}
254252
255static void ir_set_debug(CodeGen *g, IrInstruction *instruction) {
256 set_debug_source_node(g, instruction->source_node);
257}
258
259253static void clear_debug_source_node(CodeGen *g) {
260254 ZigLLVMClearCurrentDebugLocation(g->builder);
261255}
......@@ -375,6 +369,10 @@ static bool want_debug_safety(CodeGen *g, AstNode *node) {
375369 return want_debug_safety_recursive(g, node->block_context);
376370}
377371
372static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) {
373 return want_debug_safety(g, instruction->source_node);
374}
375
378376static void gen_debug_safety_crash(CodeGen *g) {
379377 LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
380378 LLVMBuildUnreachable(g->builder);
......@@ -2800,12 +2798,104 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
28002798}
28012799
28022800static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
2803 ir_set_debug(g, &return_instruction->base);
28042801 LLVMBuildRet(g->builder, return_instruction->value->llvm_value);
28052802 return nullptr;
28062803}
28072804
2805static LLVMValueRef ir_render_load_var(CodeGen *g, IrExecutable *executable,
2806 IrInstructionLoadVar *load_var_instruction)
2807{
2808 VariableTableEntry *var = load_var_instruction->var;
2809 if (!type_has_bits(var->type))
2810 return nullptr;
2811
2812 assert(var->value_ref);
2813 return get_handle_value(g, load_var_instruction->base.source_node, var->value_ref, var->type);
2814}
2815
2816static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
2817 IrInstructionBinOp *bin_op_instruction)
2818{
2819 IrBinOp op_id = bin_op_instruction->op_id;
2820 LLVMValueRef op1 = bin_op_instruction->op1->llvm_value;
2821 LLVMValueRef op2 = bin_op_instruction->op2->llvm_value;
2822 if (op_id == IrBinOpBoolOr) {
2823 return LLVMBuildOr(g->builder, op1, op2, "");
2824 } else if (op_id == IrBinOpBoolAnd) {
2825 return LLVMBuildAnd(g->builder, op1, op2, "");
2826 } else {
2827 zig_unreachable();
2828 }
2829}
2830
2831static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable,
2832 IrInstructionBinOp *bin_op_instruction)
2833{
2834 IrBinOp op_id = bin_op_instruction->op_id;
2835 IrInstruction *op1 = bin_op_instruction->op1;
2836 IrInstruction *op2 = bin_op_instruction->op2;
2837
2838 assert(op1->type_entry == op2->type_entry);
2839
2840 if (op1->type_entry->id == TypeTableEntryIdFloat) {
2841 return LLVMBuildFAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
2842 } else if (op1->type_entry->id == TypeTableEntryIdInt) {
2843 bool is_wrapping = (op_id == IrBinOpAddWrap);
2844 if (is_wrapping) {
2845 return LLVMBuildAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
2846 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {
2847 return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1->llvm_value, op2->llvm_value);
2848 } else if (op1->type_entry->data.integral.is_signed) {
2849 return LLVMBuildNSWAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
2850 } else {
2851 return LLVMBuildNUWAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
2852 }
2853 } else {
2854 zig_unreachable();
2855 }
2856}
2857
2858static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2859 IrInstructionBinOp *bin_op_instruction)
2860{
2861 IrBinOp op_id = bin_op_instruction->op_id;
2862 switch (op_id) {
2863 case IrBinOpInvalid:
2864 case IrBinOpArrayCat:
2865 case IrBinOpArrayMult:
2866 zig_unreachable();
2867 case IrBinOpBoolOr:
2868 case IrBinOpBoolAnd:
2869 return ir_render_bin_op_bool(g, executable, bin_op_instruction);
2870 case IrBinOpCmpEq:
2871 case IrBinOpCmpNotEq:
2872 case IrBinOpCmpLessThan:
2873 case IrBinOpCmpGreaterThan:
2874 case IrBinOpCmpLessOrEq:
2875 case IrBinOpCmpGreaterOrEq:
2876 zig_panic("TODO bin op cmp");
2877 case IrBinOpAdd:
2878 case IrBinOpAddWrap:
2879 return ir_render_bin_op_add(g, executable, bin_op_instruction);
2880 case IrBinOpBinOr:
2881 case IrBinOpBinXor:
2882 case IrBinOpBinAnd:
2883 case IrBinOpBitShiftLeft:
2884 case IrBinOpBitShiftLeftWrap:
2885 case IrBinOpBitShiftRight:
2886 case IrBinOpSub:
2887 case IrBinOpSubWrap:
2888 case IrBinOpMult:
2889 case IrBinOpMultWrap:
2890 case IrBinOpDiv:
2891 case IrBinOpMod:
2892 zig_panic("TODO render more bin ops to LLVM");
2893 }
2894 zig_unreachable();
2895}
2896
28082897static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
2898 set_debug_source_node(g, instruction->source_node);
28092899 switch (instruction->id) {
28102900 case IrInstructionIdInvalid:
28112901 zig_unreachable();
......@@ -2813,14 +2903,17 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
28132903 return gen_const_val(g, instruction->type_entry, &instruction->static_value);
28142904 case IrInstructionIdReturn:
28152905 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
2906 case IrInstructionIdLoadVar:
2907 return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction);
2908 case IrInstructionIdBinOp:
2909 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
28162910 case IrInstructionIdCondBr:
28172911 case IrInstructionIdSwitchBr:
28182912 case IrInstructionIdPhi:
2819 case IrInstructionIdBinOp:
2820 case IrInstructionIdLoadVar:
28212913 case IrInstructionIdStoreVar:
28222914 case IrInstructionIdCall:
28232915 case IrInstructionIdBuiltinCall:
2916 case IrInstructionIdCast:
28242917 zig_panic("TODO render more IR instructions to LLVM");
28252918 }
28262919 zig_unreachable();
......@@ -5013,6 +5106,9 @@ static void init(CodeGen *g, Buf *source_path) {
50135106
50145107 define_builtin_types(g);
50155108 define_builtin_fns(g);
5109
5110 g->invalid_instruction = allocate<IrInstruction>(1);
5111 g->invalid_instruction->type_entry = g->builtin_types.entry_invalid;
50165112}
50175113
50185114void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
src/ir.cpp+769-80
......@@ -9,7 +9,13 @@ struct IrGen {
99 IrExecutable *exec;
1010};
1111
12static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_context);
12struct IrAnalyze {
13 CodeGen *codegen;
14 IrExecutable *exec;
15 IrBasicBlock *current_basic_block;
16};
17
18static IrInstruction *ir_gen_node(IrGen *irg, AstNode *node, BlockContext *scope);
1319
1420static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
1521 if (!basic_block->last) {
......@@ -25,9 +31,33 @@ static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *inst
2531 }
2632}
2733
28static size_t exec_next_debug_id(IrGen *ir) {
29 size_t result = ir->exec->next_debug_id;
30 ir->exec->next_debug_id += 1;
34static void ir_instruction_insert(IrBasicBlock *basic_block,
35 IrInstruction *before_instruction, IrInstruction *after_instruction,
36 IrInstruction *new_instruction)
37{
38 assert(before_instruction || after_instruction);
39 assert(!before_instruction || !after_instruction);
40
41 if (before_instruction) {
42 IrInstruction *displaced_instruction = before_instruction->prev;
43 before_instruction->prev = new_instruction;
44 new_instruction->prev = displaced_instruction;
45 new_instruction->next = before_instruction;
46 if (basic_block->first == before_instruction)
47 basic_block->first = new_instruction;
48 } else {
49 IrInstruction *displaced_instruction = after_instruction->next;
50 after_instruction->next = new_instruction;
51 new_instruction->prev = after_instruction;
52 new_instruction->next = displaced_instruction;
53 if (basic_block->last == after_instruction)
54 basic_block->last = new_instruction;
55 }
56}
57
58static size_t exec_next_debug_id(IrExecutable *exec) {
59 size_t result = exec->next_debug_id;
60 exec->next_debug_id += 1;
3161 return result;
3262}
3363
......@@ -71,32 +101,117 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) {
71101 return IrInstructionIdReturn;
72102}
73103
104static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
105 return IrInstructionIdCast;
106}
107
74108template<typename T>
75static T *ir_build_instruction(IrGen *ir, AstNode *source_node) {
109static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
76110 T *special_instruction = allocate<T>(1);
77111 special_instruction->base.id = ir_instruction_id(special_instruction);
78112 special_instruction->base.source_node = source_node;
79 special_instruction->base.type_entry = ir->codegen->builtin_types.entry_unreachable;
80 special_instruction->base.debug_id = exec_next_debug_id(ir);
81 ir_instruction_append(ir->current_basic_block, &special_instruction->base);
113 special_instruction->base.debug_id = exec_next_debug_id(exec);
114 return special_instruction;
115}
116
117template<typename T>
118static T *ir_build_instruction(IrGen *irg, AstNode *source_node) {
119 T *special_instruction = ir_create_instruction<T>(irg->exec, source_node);
120 ir_instruction_append(irg->current_basic_block, &special_instruction->base);
82121 return special_instruction;
83122}
84123
85static IrInstruction *ir_build_return(IrGen *ir, AstNode *source_node, IrInstruction *return_value) {
86 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(ir, source_node);
87 return_instruction->base.type_entry = ir->codegen->builtin_types.entry_unreachable;
124static IrInstruction *ir_insert_const_type(IrAnalyze *ira, IrInstruction *before_instruction,
125 IrInstruction *after_instruction, TypeTableEntry *type_entry)
126{
127 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->exec,
128 before_instruction->source_node);
129 const_instruction->base.type_entry = ira->codegen->builtin_types.entry_type;
130 const_instruction->base.static_value.ok = true;
131 const_instruction->base.static_value.data.x_type = type_entry;
132 ir_instruction_insert(ira->current_basic_block, before_instruction, after_instruction, &const_instruction->base);
133 return &const_instruction->base;
134}
135
136static IrInstruction *ir_insert_cast(IrAnalyze *ira,
137 IrInstruction *before_instruction, IrInstruction *after_instruction,
138 IrInstruction *dest_type, IrInstruction *value, bool is_implicit)
139{
140 IrInstructionCast *cast_instruction = ir_create_instruction<IrInstructionCast>(ira->exec,
141 before_instruction->source_node);
142 cast_instruction->dest_type = dest_type;
143 cast_instruction->value = value;
144 cast_instruction->is_implicit = is_implicit;
145 ir_instruction_insert(ira->current_basic_block, before_instruction, after_instruction, &cast_instruction->base);
146 return &cast_instruction->base;
147}
148
149static IrInstruction *ir_build_return(IrGen *irg, AstNode *source_node, IrInstruction *return_value) {
150 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irg, source_node);
151 return_instruction->base.type_entry = irg->codegen->builtin_types.entry_unreachable;
88152 return_instruction->base.static_value.ok = true;
89153 return_instruction->value = return_value;
90154 return &return_instruction->base;
91155}
92156
93static IrInstruction *ir_build_void(IrGen *ir, AstNode *source_node) {
94 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(ir, source_node);
95 const_instruction->base.type_entry = ir->codegen->builtin_types.entry_void;
157static IrInstruction *ir_build_const_void(IrGen *irg, AstNode *source_node) {
158 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node);
159 const_instruction->base.type_entry = irg->codegen->builtin_types.entry_void;
160 const_instruction->base.static_value.ok = true;
161 return &const_instruction->base;
162}
163
164static IrInstruction *ir_build_const_bignum(IrGen *irg, AstNode *source_node, BigNum *bignum) {
165 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node);
166 const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ?
167 irg->codegen->builtin_types.entry_num_lit_int : irg->codegen->builtin_types.entry_num_lit_float;
96168 const_instruction->base.static_value.ok = true;
169 const_instruction->base.static_value.data.x_bignum = *bignum;
97170 return &const_instruction->base;
98171}
99172
173static IrInstruction *ir_build_const_type(IrGen *irg, AstNode *source_node, TypeTableEntry *type_entry) {
174 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node);
175 const_instruction->base.type_entry = irg->codegen->builtin_types.entry_type;
176 const_instruction->base.static_value.ok = true;
177 const_instruction->base.static_value.data.x_type = type_entry;
178 return &const_instruction->base;
179}
180
181static IrInstruction *ir_build_const_fn(IrGen *irg, AstNode *source_node, FnTableEntry *fn_entry) {
182 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node);
183 const_instruction->base.type_entry = fn_entry->type_entry;
184 const_instruction->base.static_value.ok = true;
185 const_instruction->base.static_value.data.x_fn = fn_entry;
186 return &const_instruction->base;
187}
188
189static IrInstruction *ir_build_const_generic_fn(IrGen *irg, AstNode *source_node, TypeTableEntry *fn_type) {
190 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node);
191 const_instruction->base.type_entry = fn_type;
192 const_instruction->base.static_value.ok = true;
193 const_instruction->base.static_value.data.x_type = fn_type;
194 return &const_instruction->base;
195}
196
197static IrInstruction *ir_build_bin_op(IrGen *irg, AstNode *source_node, IrBinOp op_id,
198 IrInstruction *op1, IrInstruction *op2)
199{
200 IrInstructionBinOp *bin_op_instruction = ir_build_instruction<IrInstructionBinOp>(irg, source_node);
201 bin_op_instruction->op_id = op_id;
202 bin_op_instruction->op1 = op1;
203 bin_op_instruction->op2 = op2;
204 return &bin_op_instruction->base;
205}
206
207static IrInstruction *ir_build_load_var(IrGen *irg, AstNode *source_node, VariableTableEntry *var) {
208 IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irg, source_node);
209 load_var_instruction->base.type_entry = var->type;
210 load_var_instruction->var = var;
211 return &load_var_instruction->base;
212}
213
214
100215//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
101216// size_t result = 0;
102217// while (inner_block != outer_block) {
......@@ -111,7 +226,7 @@ static IrInstruction *ir_build_void(IrGen *ir, AstNode *source_node) {
111226// return result;
112227//}
113228
114static void ir_gen_defers_for_block(IrGen *ir, BlockContext *inner_block, BlockContext *outer_block,
229static void ir_gen_defers_for_block(IrGen *irg, BlockContext *inner_block, BlockContext *outer_block,
115230 bool gen_error_defers, bool gen_maybe_defers)
116231{
117232 while (inner_block != outer_block) {
......@@ -121,15 +236,15 @@ static void ir_gen_defers_for_block(IrGen *ir, BlockContext *inner_block, BlockC
121236 (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe)))
122237 {
123238 AstNode *defer_expr_node = inner_block->node->data.defer.expr;
124 ir_gen_node(ir, defer_expr_node, defer_expr_node->block_context);
239 ir_gen_node(irg, defer_expr_node, defer_expr_node->block_context);
125240 }
126241 inner_block = inner_block->parent;
127242 }
128243}
129244
130//static IrInstruction *ir_gen_return(IrGen *ir, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) {
245//static IrInstruction *ir_gen_return(IrGen *irg, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) {
131246// BlockContext *defer_inner_block = source_node->block_context;
132// BlockContext *defer_outer_block = ir->node->block_context;
247// BlockContext *defer_outer_block = irg->node->block_context;
133248// if (rk == ReturnKnowledgeUnknown) {
134249// if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) {
135250// // generate branching code that checks the return value and generates defers
......@@ -137,14 +252,14 @@ static void ir_gen_defers_for_block(IrGen *ir, BlockContext *inner_block, BlockC
137252// zig_panic("TODO");
138253// }
139254// } else if (rk != ReturnKnowledgeSkipDefers) {
140// ir_gen_defers_for_block(ir, defer_inner_block, defer_outer_block,
255// ir_gen_defers_for_block(irg, defer_inner_block, defer_outer_block,
141256// rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull);
142257// }
143258//
144// return ir_build_return(ir, source_node, value);
259// return ir_build_return(irg, source_node, value);
145260//}
146261
147static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node) {
262static IrInstruction *ir_gen_block(IrGen *irg, AstNode *block_node) {
148263 assert(block_node->type == NodeTypeBlock);
149264
150265 BlockContext *parent_context = block_node->block_context;
......@@ -154,8 +269,8 @@ static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node) {
154269 IrInstruction *return_value = nullptr;
155270 for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) {
156271 AstNode *statement_node = block_node->data.block.statements.at(i);
157 return_value = ir_gen_node(ir, statement_node, child_context);
158 if (statement_node->type == NodeTypeDefer && return_value != ir->codegen->invalid_instruction) {
272 return_value = ir_gen_node(irg, statement_node, child_context);
273 if (statement_node->type == NodeTypeDefer && return_value != irg->codegen->invalid_instruction) {
159274 // defer starts a new block context
160275 child_context = statement_node->data.defer.child_block;
161276 assert(child_context);
......@@ -163,20 +278,188 @@ static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node) {
163278 }
164279
165280 if (!return_value)
166 return_value = ir_build_void(ir, block_node);
281 return_value = ir_build_const_void(irg, block_node);
167282
168 ir_gen_defers_for_block(ir, child_context, outer_block_context, false, false);
283 ir_gen_defers_for_block(irg, child_context, outer_block_context, false, false);
169284
170285 return return_value;
171286}
172287
173static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_context) {
288static IrInstruction *ir_gen_bin_op_id(IrGen *irg, AstNode *node, IrBinOp op_id) {
289 IrInstruction *op1 = ir_gen_node(irg, node->data.bin_op_expr.op1, node->block_context);
290 IrInstruction *op2 = ir_gen_node(irg, node->data.bin_op_expr.op2, node->block_context);
291 return ir_build_bin_op(irg, node, op_id, op1, op2);
292}
293
294static IrInstruction *ir_gen_bin_op(IrGen *irg, AstNode *node) {
295 assert(node->type == NodeTypeBinOpExpr);
296
297 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
298 switch (bin_op_type) {
299 case BinOpTypeInvalid:
300 zig_unreachable();
301 case BinOpTypeAssign:
302 case BinOpTypeAssignTimes:
303 case BinOpTypeAssignTimesWrap:
304 case BinOpTypeAssignDiv:
305 case BinOpTypeAssignMod:
306 case BinOpTypeAssignPlus:
307 case BinOpTypeAssignPlusWrap:
308 case BinOpTypeAssignMinus:
309 case BinOpTypeAssignMinusWrap:
310 case BinOpTypeAssignBitShiftLeft:
311 case BinOpTypeAssignBitShiftLeftWrap:
312 case BinOpTypeAssignBitShiftRight:
313 case BinOpTypeAssignBitAnd:
314 case BinOpTypeAssignBitXor:
315 case BinOpTypeAssignBitOr:
316 case BinOpTypeAssignBoolAnd:
317 case BinOpTypeAssignBoolOr:
318 zig_panic("TODO gen IR for assignment");
319 case BinOpTypeBoolOr:
320 case BinOpTypeBoolAnd:
321 // note: this is not a direct mapping to IrBinOpBoolOr/And
322 // because of the control flow
323 zig_panic("TODO gen IR for bool or/and");
324 case BinOpTypeCmpEq:
325 return ir_gen_bin_op_id(irg, node, IrBinOpCmpEq);
326 case BinOpTypeCmpNotEq:
327 return ir_gen_bin_op_id(irg, node, IrBinOpCmpNotEq);
328 case BinOpTypeCmpLessThan:
329 return ir_gen_bin_op_id(irg, node, IrBinOpCmpLessThan);
330 case BinOpTypeCmpGreaterThan:
331 return ir_gen_bin_op_id(irg, node, IrBinOpCmpGreaterThan);
332 case BinOpTypeCmpLessOrEq:
333 return ir_gen_bin_op_id(irg, node, IrBinOpCmpLessOrEq);
334 case BinOpTypeCmpGreaterOrEq:
335 return ir_gen_bin_op_id(irg, node, IrBinOpCmpGreaterOrEq);
336 case BinOpTypeBinOr:
337 return ir_gen_bin_op_id(irg, node, IrBinOpBinOr);
338 case BinOpTypeBinXor:
339 return ir_gen_bin_op_id(irg, node, IrBinOpBinXor);
340 case BinOpTypeBinAnd:
341 return ir_gen_bin_op_id(irg, node, IrBinOpBinAnd);
342 case BinOpTypeBitShiftLeft:
343 return ir_gen_bin_op_id(irg, node, IrBinOpBitShiftLeft);
344 case BinOpTypeBitShiftLeftWrap:
345 return ir_gen_bin_op_id(irg, node, IrBinOpBitShiftLeftWrap);
346 case BinOpTypeBitShiftRight:
347 return ir_gen_bin_op_id(irg, node, IrBinOpBitShiftRight);
348 case BinOpTypeAdd:
349 return ir_gen_bin_op_id(irg, node, IrBinOpAdd);
350 case BinOpTypeAddWrap:
351 return ir_gen_bin_op_id(irg, node, IrBinOpAddWrap);
352 case BinOpTypeSub:
353 return ir_gen_bin_op_id(irg, node, IrBinOpSub);
354 case BinOpTypeSubWrap:
355 return ir_gen_bin_op_id(irg, node, IrBinOpSubWrap);
356 case BinOpTypeMult:
357 return ir_gen_bin_op_id(irg, node, IrBinOpMult);
358 case BinOpTypeMultWrap:
359 return ir_gen_bin_op_id(irg, node, IrBinOpMultWrap);
360 case BinOpTypeDiv:
361 return ir_gen_bin_op_id(irg, node, IrBinOpDiv);
362 case BinOpTypeMod:
363 return ir_gen_bin_op_id(irg, node, IrBinOpMod);
364 case BinOpTypeArrayCat:
365 return ir_gen_bin_op_id(irg, node, IrBinOpArrayCat);
366 case BinOpTypeArrayMult:
367 return ir_gen_bin_op_id(irg, node, IrBinOpArrayMult);
368 case BinOpTypeUnwrapMaybe:
369 zig_panic("TODO gen IR for unwrap maybe");
370 }
371 zig_unreachable();
372}
373
374static IrInstruction *ir_gen_num_lit(IrGen *irg, AstNode *node) {
375 assert(node->type == NodeTypeNumberLiteral);
376
377 if (node->data.number_literal.overflow) {
378 add_node_error(irg->codegen, node, buf_sprintf("number literal too large to be represented in any type"));
379 return irg->codegen->invalid_instruction;
380 }
381
382 return ir_build_const_bignum(irg, node, node->data.number_literal.bignum);
383}
384
385static IrInstruction *ir_gen_decl_ref(IrGen *irg, AstNode *source_node, AstNode *decl_node,
386 bool pointer_only, BlockContext *scope)
387{
388 resolve_top_level_decl(irg->codegen, decl_node, pointer_only);
389 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
390 if (tld->resolution == TldResolutionInvalid)
391 return irg->codegen->invalid_instruction;
392
393 if (decl_node->type == NodeTypeVariableDeclaration) {
394 VariableTableEntry *var = decl_node->data.variable_declaration.variable;
395 return ir_build_load_var(irg, source_node, var);
396 } else if (decl_node->type == NodeTypeFnProto) {
397 FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
398 assert(fn_entry->type_entry);
399 if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) {
400 return ir_build_const_generic_fn(irg, source_node, fn_entry->type_entry);
401 } else {
402 return ir_build_const_fn(irg, source_node, fn_entry);
403 }
404 } else if (decl_node->type == NodeTypeContainerDecl) {
405 if (decl_node->data.struct_decl.generic_params.length > 0) {
406 TypeTableEntry *type_entry = decl_node->data.struct_decl.generic_fn_type;
407 assert(type_entry);
408 return ir_build_const_generic_fn(irg, source_node, type_entry);
409 } else {
410 return ir_build_const_type(irg, source_node, decl_node->data.struct_decl.type_entry);
411 }
412 } else if (decl_node->type == NodeTypeTypeDecl) {
413 return ir_build_const_type(irg, source_node, decl_node->data.type_decl.child_type_entry);
414 } else {
415 zig_unreachable();
416 }
417}
418
419static IrInstruction *ir_gen_symbol(IrGen *irg, AstNode *node, bool pointer_only) {
420 assert(node->type == NodeTypeSymbol);
421
422 if (node->data.symbol_expr.override_type_entry)
423 return ir_build_const_type(irg, node, node->data.symbol_expr.override_type_entry);
424
425 Buf *variable_name = node->data.symbol_expr.symbol;
426
427 auto primitive_table_entry = irg->codegen->primitive_type_table.maybe_get(variable_name);
428 if (primitive_table_entry)
429 return ir_build_const_type(irg, node, primitive_table_entry->value);
430
431 VariableTableEntry *var = find_variable(irg->codegen, node->block_context, variable_name);
432 if (var)
433 return ir_build_load_var(irg, node, var);
434
435 AstNode *decl_node = find_decl(node->block_context, variable_name);
436 if (decl_node)
437 return ir_gen_decl_ref(irg, node, decl_node, pointer_only, node->block_context);
438
439 if (node->owner->any_imports_failed) {
440 // skip the error message since we had a failing import in this file
441 // if an import breaks we don't need redundant undeclared identifier errors
442 return irg->codegen->invalid_instruction;
443 }
444
445 add_node_error(irg->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
446 return irg->codegen->invalid_instruction;
447}
448
449static IrInstruction *ir_gen_node_extra(IrGen *irg, AstNode *node, BlockContext *block_context,
450 bool pointer_only)
451{
174452 node->block_context = block_context;
175453
176454 switch (node->type) {
177455 case NodeTypeBlock:
178 return ir_gen_block(ir, node);
456 return ir_gen_block(irg, node);
179457 case NodeTypeBinOpExpr:
458 return ir_gen_bin_op(irg, node);
459 case NodeTypeNumberLiteral:
460 return ir_gen_num_lit(irg, node);
461 case NodeTypeSymbol:
462 return ir_gen_symbol(irg, node, pointer_only);
180463 case NodeTypeUnwrapErrorExpr:
181464 case NodeTypeReturnExpr:
182465 case NodeTypeDefer:
......@@ -191,14 +474,12 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_
191474 case NodeTypeWhileExpr:
192475 case NodeTypeForExpr:
193476 case NodeTypeAsmExpr:
194 case NodeTypeSymbol:
195477 case NodeTypeGoto:
196478 case NodeTypeBreak:
197479 case NodeTypeContinue:
198480 case NodeTypeLabel:
199481 case NodeTypeContainerInitExpr:
200482 case NodeTypeSwitchExpr:
201 case NodeTypeNumberLiteral:
202483 case NodeTypeBoolLiteral:
203484 case NodeTypeStringLiteral:
204485 case NodeTypeCharLiteral:
......@@ -228,42 +509,49 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_
228509 zig_unreachable();
229510}
230511
512static IrInstruction *ir_gen_node(IrGen *irg, AstNode *node, BlockContext *scope) {
513 bool pointer_only_no = false;
514 return ir_gen_node_extra(irg, node, scope, pointer_only_no);
515}
516
231517static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope,
232 IrExecutable *ir_executable, bool add_return)
518 IrExecutable *ir_executable, bool add_return, bool pointer_only)
233519{
234520 assert(node->owner);
235521
236522 IrGen ir_gen = {0};
237 IrGen *ir = &ir_gen;
523 IrGen *irg = &ir_gen;
238524
239 ir->codegen = g;
240 ir->node = node;
241 ir->exec = ir_executable;
525 irg->codegen = g;
526 irg->node = node;
527 irg->exec = ir_executable;
242528
243 ir->exec->basic_block_list = allocate<IrBasicBlock*>(1);
244 ir->exec->basic_block_count = 1;
529 irg->exec->basic_block_list = allocate<IrBasicBlock*>(1);
530 irg->exec->basic_block_count = 1;
245531
246532 IrBasicBlock *entry_basic_block = allocate<IrBasicBlock>(1);
247 ir->current_basic_block = entry_basic_block;
248 ir->exec->basic_block_list[0] = entry_basic_block;
533 irg->current_basic_block = entry_basic_block;
534 irg->exec->basic_block_list[0] = entry_basic_block;
249535
250 IrInstruction *result = ir_gen_node(ir, node, scope);
536 IrInstruction *result = ir_gen_node_extra(irg, node, scope, pointer_only);
251537 assert(result);
252538
253539 if (result == g->invalid_instruction)
254540 return result;
255541
256542 if (add_return)
257 return ir_build_return(ir, result->source_node, result);
543 return ir_build_return(irg, result->source_node, result);
258544
259545 return result;
260546}
261547
262IrInstruction *ir_gen(CodeGen *g, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {
263 return ir_gen_add_return(g, node, scope, ir_executable, false);
548IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {
549 bool add_return_no = false;
550 bool pointer_only_no = false;
551 return ir_gen_add_return(codegen, node, scope, ir_executable, add_return_no, pointer_only_no);
264552}
265553
266IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry) {
554IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
267555 assert(fn_entry);
268556
269557 IrExecutable *ir_executable = &fn_entry->ir_executable;
......@@ -274,7 +562,8 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry) {
274562 BlockContext *scope = fn_def_node->data.fn_def.block_context;
275563
276564 bool add_return_yes = true;
277 return ir_gen_add_return(g, body_node, scope, ir_executable, add_return_yes);
565 bool pointer_only_no = false;
566 return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, pointer_only_no);
278567}
279568
280569/*
......@@ -322,96 +611,496 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
322611// return nullptr;
323612//}
324613
325static IrInstruction *ir_get_casted_instruction(CodeGen *g, IrInstruction *instruction,
326 TypeTableEntry *expected_type)
614static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {
615 TypeTableEntry *other_type_underlying = get_underlying_type(other_type);
616
617 if (other_type_underlying->id == TypeTableEntryIdInvalid) {
618 return false;
619 }
620
621 ConstExprValue *const_val = &instruction->static_value;
622 assert(const_val->ok);
623 if (other_type_underlying->id == TypeTableEntryIdFloat) {
624 return true;
625 } else if (other_type_underlying->id == TypeTableEntryIdInt &&
626 const_val->data.x_bignum.kind == BigNumKindInt)
627 {
628 if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type_underlying->data.integral.bit_count,
629 other_type_underlying->data.integral.is_signed))
630 {
631 return true;
632 }
633 } else if ((other_type_underlying->id == TypeTableEntryIdNumLitFloat &&
634 const_val->data.x_bignum.kind == BigNumKindFloat) ||
635 (other_type_underlying->id == TypeTableEntryIdNumLitInt &&
636 const_val->data.x_bignum.kind == BigNumKindInt))
637 {
638 return true;
639 }
640
641 const char *num_lit_str = (const_val->data.x_bignum.kind == BigNumKindFloat) ? "float" : "integer";
642
643 add_node_error(ira->codegen, instruction->source_node,
644 buf_sprintf("%s value %s cannot be implicitly casted to type '%s'",
645 num_lit_str,
646 buf_ptr(bignum_to_buf(&const_val->data.x_bignum)),
647 buf_ptr(&other_type->name)));
648 return false;
649}
650
651static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *parent_instruction,
652 IrInstruction **instructions, size_t instruction_count)
653{
654 assert(instruction_count >= 1);
655 IrInstruction *prev_inst = instructions[0];
656 if (prev_inst->type_entry->id == TypeTableEntryIdInvalid) {
657 return ira->codegen->builtin_types.entry_invalid;
658 }
659 for (size_t i = 1; i < instruction_count; i += 1) {
660 IrInstruction *cur_inst = instructions[i];
661 TypeTableEntry *cur_type = cur_inst->type_entry;
662 TypeTableEntry *prev_type = prev_inst->type_entry;
663 if (cur_type->id == TypeTableEntryIdInvalid) {
664 return cur_type;
665 } else if (types_match_const_cast_only(prev_type, cur_type)) {
666 continue;
667 } else if (types_match_const_cast_only(cur_type, prev_type)) {
668 prev_inst = cur_inst;
669 continue;
670 } else if (prev_type->id == TypeTableEntryIdUnreachable) {
671 prev_inst = cur_inst;
672 } else if (cur_type->id == TypeTableEntryIdUnreachable) {
673 continue;
674 } else if (prev_type->id == TypeTableEntryIdInt &&
675 cur_type->id == TypeTableEntryIdInt &&
676 prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)
677 {
678 if (cur_type->data.integral.bit_count > prev_type->data.integral.bit_count) {
679 prev_inst = cur_inst;
680 }
681 continue;
682 } else if (prev_type->id == TypeTableEntryIdFloat &&
683 cur_type->id == TypeTableEntryIdFloat)
684 {
685 if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {
686 prev_inst = cur_inst;
687 }
688 } else if (prev_type->id == TypeTableEntryIdErrorUnion &&
689 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))
690 {
691 continue;
692 } else if (cur_type->id == TypeTableEntryIdErrorUnion &&
693 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))
694 {
695 prev_inst = cur_inst;
696 continue;
697 } else if (prev_type->id == TypeTableEntryIdNumLitInt ||
698 prev_type->id == TypeTableEntryIdNumLitFloat)
699 {
700 if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type)) {
701 prev_inst = cur_inst;
702 continue;
703 } else {
704 return ira->codegen->builtin_types.entry_invalid;
705 }
706 } else if (cur_type->id == TypeTableEntryIdNumLitInt ||
707 cur_type->id == TypeTableEntryIdNumLitFloat)
708 {
709 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type)) {
710 continue;
711 } else {
712 return ira->codegen->builtin_types.entry_invalid;
713 }
714 } else {
715 add_node_error(ira->codegen, parent_instruction->source_node,
716 buf_sprintf("incompatible types: '%s' and '%s'",
717 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
718
719 return ira->codegen->builtin_types.entry_invalid;
720 }
721 }
722 return prev_inst->type_entry;
723}
724
725enum ImplicitCastMatchResult {
726 ImplicitCastMatchResultNo,
727 ImplicitCastMatchResultYes,
728 ImplicitCastMatchResultReportedError,
729};
730
731static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, TypeTableEntry *expected_type,
732 TypeTableEntry *actual_type, IrInstruction *value)
733{
734 if (types_match_const_cast_only(expected_type, actual_type)) {
735 return ImplicitCastMatchResultYes;
736 }
737
738 // implicit conversion from non maybe type to maybe type
739 if (expected_type->id == TypeTableEntryIdMaybe &&
740 ir_types_match_with_implicit_cast(ira, expected_type->data.maybe.child_type, actual_type, value))
741 {
742 return ImplicitCastMatchResultYes;
743 }
744
745 // implicit conversion from null literal to maybe type
746 if (expected_type->id == TypeTableEntryIdMaybe &&
747 actual_type->id == TypeTableEntryIdNullLit)
748 {
749 return ImplicitCastMatchResultYes;
750 }
751
752 // implicit conversion from error child type to error type
753 if (expected_type->id == TypeTableEntryIdErrorUnion &&
754 ir_types_match_with_implicit_cast(ira, expected_type->data.error.child_type, actual_type, value))
755 {
756 return ImplicitCastMatchResultYes;
757 }
758
759 // implicit conversion from pure error to error union type
760 if (expected_type->id == TypeTableEntryIdErrorUnion &&
761 actual_type->id == TypeTableEntryIdPureError)
762 {
763 return ImplicitCastMatchResultYes;
764 }
765
766 // implicit widening conversion
767 if (expected_type->id == TypeTableEntryIdInt &&
768 actual_type->id == TypeTableEntryIdInt &&
769 expected_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
770 expected_type->data.integral.bit_count >= actual_type->data.integral.bit_count)
771 {
772 return ImplicitCastMatchResultYes;
773 }
774
775 // small enough unsigned ints can get casted to large enough signed ints
776 if (expected_type->id == TypeTableEntryIdInt && expected_type->data.integral.is_signed &&
777 actual_type->id == TypeTableEntryIdInt && !actual_type->data.integral.is_signed &&
778 expected_type->data.integral.bit_count > actual_type->data.integral.bit_count)
779 {
780 return ImplicitCastMatchResultYes;
781 }
782
783 // implicit float widening conversion
784 if (expected_type->id == TypeTableEntryIdFloat &&
785 actual_type->id == TypeTableEntryIdFloat &&
786 expected_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
787 {
788 return ImplicitCastMatchResultYes;
789 }
790
791 // implicit array to slice conversion
792 if (expected_type->id == TypeTableEntryIdStruct &&
793 expected_type->data.structure.is_slice &&
794 actual_type->id == TypeTableEntryIdArray &&
795 types_match_const_cast_only(
796 expected_type->data.structure.fields[0].type_entry->data.pointer.child_type,
797 actual_type->data.array.child_type))
798 {
799 return ImplicitCastMatchResultYes;
800 }
801
802 // implicit number literal to typed number
803 if ((actual_type->id == TypeTableEntryIdNumLitFloat ||
804 actual_type->id == TypeTableEntryIdNumLitInt))
805 {
806 if (ir_num_lit_fits_in_other_type(ira, value, expected_type)) {
807 return ImplicitCastMatchResultYes;
808 } else {
809 return ImplicitCastMatchResultReportedError;
810 }
811 }
812
813 return ImplicitCastMatchResultNo;
814}
815
816static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, IrInstruction *parent_instruction,
817 IrInstruction **instructions, size_t instruction_count)
818{
819 return ir_determine_peer_types(ira, parent_instruction, instructions, instruction_count);
820}
821
822static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,
823 TypeTableEntry *expected_type,
824 IrInstruction *before_instruction, IrInstruction *after_instruction)
327825{
328 assert(instruction);
329 assert(instruction != g->invalid_instruction);
826 assert(value);
827 assert(before_instruction || after_instruction);
828 assert(!before_instruction || !after_instruction);
829 assert(value != ira->codegen->invalid_instruction);
330830 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);
331 assert(instruction->type_entry);
332 assert(instruction->type_entry->id != TypeTableEntryIdInvalid);
831 assert(value->type_entry);
832 assert(value->type_entry->id != TypeTableEntryIdInvalid);
333833 if (expected_type == nullptr)
334 return instruction; // anything will do
335 if (expected_type == instruction->type_entry)
336 return instruction; // match
337 if (instruction->type_entry->id == TypeTableEntryIdUnreachable)
338 return instruction;
834 return value; // anything will do
835 if (expected_type == value->type_entry)
836 return value; // match
837 if (value->type_entry->id == TypeTableEntryIdUnreachable)
838 return value;
839
840 ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->type_entry, value);
841 switch (result) {
842 case ImplicitCastMatchResultNo:
843 add_node_error(ira->codegen, first_executing_node(value->source_node),
844 buf_sprintf("expected type '%s', got '%s'",
845 buf_ptr(&expected_type->name),
846 buf_ptr(&value->type_entry->name)));
847 return ira->codegen->invalid_instruction;
848
849 case ImplicitCastMatchResultYes:
850 {
851 IrInstruction *dest_type = ir_insert_const_type(ira, before_instruction,
852 after_instruction, expected_type);
853 bool is_implicit = true;
854 IrInstruction *cast_instruction = ir_insert_cast(ira, nullptr, dest_type,
855 dest_type, value, is_implicit);
856 return cast_instruction;
857 }
858 case ImplicitCastMatchResultReportedError:
859 return ira->codegen->invalid_instruction;
860 }
339861
340 zig_panic("TODO implicit cast instruction");
862 zig_unreachable();
341863}
342864
343static TypeTableEntry *ir_analyze_instruction_return(CodeGen *g, IrInstructionReturn *return_instruction) {
865static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *return_instruction) {
344866 AstNode *source_node = return_instruction->base.source_node;
345867 BlockContext *scope = source_node->block_context;
346868 if (!scope->fn_entry) {
347 add_node_error(g, source_node, buf_sprintf("return expression outside function definition"));
348 return g->builtin_types.entry_invalid;
869 add_node_error(ira->codegen, source_node, buf_sprintf("return expression outside function definition"));
870 return ira->codegen->builtin_types.entry_invalid;
349871 }
350872
351873 TypeTableEntry *expected_return_type = scope->fn_entry->type_entry->data.fn.fn_type_id.return_type;
352874 if (expected_return_type->id == TypeTableEntryIdVoid && !return_instruction->value) {
353 return g->builtin_types.entry_unreachable;
875 return ira->codegen->builtin_types.entry_unreachable;
354876 }
355877
356 return_instruction->value = ir_get_casted_instruction(g, return_instruction->value, expected_return_type);
357 if (return_instruction->value == g->invalid_instruction) {
358 return g->builtin_types.entry_invalid;
878 return_instruction->value = ir_get_casted_value(ira,
879 return_instruction->value, expected_return_type, &return_instruction->base, nullptr);
880 if (return_instruction->value == ira->codegen->invalid_instruction) {
881 return ira->codegen->builtin_types.entry_invalid;
359882 }
360 return g->builtin_types.entry_unreachable;
883 return ira->codegen->builtin_types.entry_unreachable;
361884}
362885
363static TypeTableEntry *ir_analyze_instruction_const(CodeGen *g, IrInstructionConst *const_instruction) {
886static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {
364887 return const_instruction->base.type_entry;
365888}
366889
367static TypeTableEntry *ir_analyze_instruction_nocast(CodeGen *g, IrInstruction *instruction) {
890static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
891 IrInstruction *op1 = bin_op_instruction->op1;
892 IrInstruction *op2 = bin_op_instruction->op2;
893
894 IrInstruction *casted_op1 = ir_get_casted_value(ira, op1, ira->codegen->builtin_types.entry_bool,
895 &bin_op_instruction->base, nullptr);
896 if (casted_op1 == ira->codegen->invalid_instruction)
897 return ira->codegen->builtin_types.entry_invalid;
898
899 IrInstruction *casted_op2 = ir_get_casted_value(ira, op2, ira->codegen->builtin_types.entry_bool,
900 &bin_op_instruction->base, nullptr);
901 if (casted_op2 == ira->codegen->invalid_instruction)
902 return ira->codegen->builtin_types.entry_invalid;
903
904 return ira->codegen->builtin_types.entry_bool;
905}
906
907static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
908 IrInstruction *op1 = bin_op_instruction->op1;
909 IrInstruction *op2 = bin_op_instruction->op2;
910 IrInstruction *instructions[] = {op1, op2};
911 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &bin_op_instruction->base, instructions, 2);
912 if (resolved_type->id == TypeTableEntryIdInvalid)
913 return resolved_type;
914 IrBinOp op_id = bin_op_instruction->op_id;
915
916 bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
917 AstNode *source_node = bin_op_instruction->base.source_node;
918 switch (resolved_type->id) {
919 case TypeTableEntryIdInvalid:
920 return ira->codegen->builtin_types.entry_invalid;
921
922 case TypeTableEntryIdNumLitFloat:
923 case TypeTableEntryIdNumLitInt:
924 case TypeTableEntryIdInt:
925 case TypeTableEntryIdFloat:
926 break;
927
928 case TypeTableEntryIdBool:
929 case TypeTableEntryIdMetaType:
930 case TypeTableEntryIdVoid:
931 case TypeTableEntryIdPointer:
932 case TypeTableEntryIdPureError:
933 case TypeTableEntryIdFn:
934 case TypeTableEntryIdTypeDecl:
935 case TypeTableEntryIdNamespace:
936 case TypeTableEntryIdBlock:
937 case TypeTableEntryIdGenericFn:
938 if (!is_equality_cmp) {
939 add_node_error(ira->codegen, source_node,
940 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
941 return ira->codegen->builtin_types.entry_invalid;
942 }
943 break;
944
945 case TypeTableEntryIdEnum:
946 if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) {
947 add_node_error(ira->codegen, source_node,
948 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
949 return ira->codegen->builtin_types.entry_invalid;
950 }
951 break;
952
953 case TypeTableEntryIdUnreachable:
954 case TypeTableEntryIdArray:
955 case TypeTableEntryIdStruct:
956 case TypeTableEntryIdUndefLit:
957 case TypeTableEntryIdNullLit:
958 case TypeTableEntryIdMaybe:
959 case TypeTableEntryIdErrorUnion:
960 case TypeTableEntryIdUnion:
961 add_node_error(ira->codegen, source_node,
962 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
963 return ira->codegen->builtin_types.entry_invalid;
964
965 case TypeTableEntryIdVar:
966 zig_unreachable();
967 }
968
969 return ira->codegen->builtin_types.entry_bool;
970}
971
972static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
973 IrInstruction *op1 = bin_op_instruction->op1;
974 IrInstruction *op2 = bin_op_instruction->op2;
975 IrInstruction *instructions[] = {op1, op2};
976 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &bin_op_instruction->base, instructions, 2);
977 if (resolved_type->id == TypeTableEntryIdInvalid)
978 return resolved_type;
979 IrBinOp op_id = bin_op_instruction->op_id;
980
981 if (resolved_type->id == TypeTableEntryIdInt ||
982 resolved_type->id == TypeTableEntryIdNumLitInt)
983 {
984 // int
985 } else if ((resolved_type->id == TypeTableEntryIdFloat ||
986 resolved_type->id == TypeTableEntryIdNumLitFloat) &&
987 (op_id == IrBinOpAdd ||
988 op_id == IrBinOpSub ||
989 op_id == IrBinOpMult ||
990 op_id == IrBinOpDiv ||
991 op_id == IrBinOpMod))
992 {
993 // float
994 } else {
995 AstNode *source_node = bin_op_instruction->base.source_node;
996 add_node_error(ira->codegen, source_node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
997 buf_ptr(&op1->type_entry->name),
998 buf_ptr(&op2->type_entry->name)));
999 return ira->codegen->builtin_types.entry_invalid;
1000 }
1001
1002 return resolved_type;
1003}
1004
1005
1006static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
1007 IrBinOp op_id = bin_op_instruction->op_id;
1008 switch (op_id) {
1009 case IrBinOpInvalid:
1010 zig_unreachable();
1011 case IrBinOpBoolOr:
1012 case IrBinOpBoolAnd:
1013 return ir_analyze_bin_op_bool(ira, bin_op_instruction);
1014 case IrBinOpCmpEq:
1015 case IrBinOpCmpNotEq:
1016 case IrBinOpCmpLessThan:
1017 case IrBinOpCmpGreaterThan:
1018 case IrBinOpCmpLessOrEq:
1019 case IrBinOpCmpGreaterOrEq:
1020 return ir_analyze_bin_op_cmp(ira, bin_op_instruction);
1021 case IrBinOpBinOr:
1022 case IrBinOpBinXor:
1023 case IrBinOpBinAnd:
1024 case IrBinOpBitShiftLeft:
1025 case IrBinOpBitShiftLeftWrap:
1026 case IrBinOpBitShiftRight:
1027 case IrBinOpAdd:
1028 case IrBinOpAddWrap:
1029 case IrBinOpSub:
1030 case IrBinOpSubWrap:
1031 case IrBinOpMult:
1032 case IrBinOpMultWrap:
1033 case IrBinOpDiv:
1034 case IrBinOpMod:
1035 return ir_analyze_bin_op_math(ira, bin_op_instruction);
1036 case IrBinOpArrayCat:
1037 case IrBinOpArrayMult:
1038 zig_panic("TODO analyze more binary operations");
1039 }
1040 zig_unreachable();
1041}
1042
1043static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstructionLoadVar *load_var_instruction) {
1044 return load_var_instruction->var->type;
1045}
1046
1047static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
3681048 switch (instruction->id) {
3691049 case IrInstructionIdInvalid:
3701050 zig_unreachable();
3711051 case IrInstructionIdReturn:
372 return ir_analyze_instruction_return(g, (IrInstructionReturn *)instruction);
1052 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);
3731053 case IrInstructionIdConst:
374 return ir_analyze_instruction_const(g, (IrInstructionConst *)instruction);
1054 return ir_analyze_instruction_const(ira, (IrInstructionConst *)instruction);
1055 case IrInstructionIdBinOp:
1056 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
1057 case IrInstructionIdLoadVar:
1058 return ir_analyze_instruction_load_var(ira, (IrInstructionLoadVar *)instruction);
3751059 case IrInstructionIdCondBr:
3761060 case IrInstructionIdSwitchBr:
3771061 case IrInstructionIdPhi:
378 case IrInstructionIdBinOp:
379 case IrInstructionIdLoadVar:
3801062 case IrInstructionIdStoreVar:
3811063 case IrInstructionIdCall:
3821064 case IrInstructionIdBuiltinCall:
1065 case IrInstructionIdCast:
3831066 zig_panic("TODO analyze more instructions");
3841067 }
3851068 zig_unreachable();
3861069}
3871070
388static TypeTableEntry *ir_analyze_instruction(CodeGen *g, IrInstruction *instruction,
1071static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction,
3891072 TypeTableEntry *expected_type)
3901073{
391 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(g, instruction);
1074 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);
3921075 instruction->type_entry = instruction_type;
3931076
394 IrInstruction *casted_instruction = ir_get_casted_instruction(g, instruction, expected_type);
1077 IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type,
1078 nullptr, instruction);
3951079 return casted_instruction->type_entry;
3961080}
3971081
398TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *executable, TypeTableEntry *expected_type) {
399 TypeTableEntry *return_type = g->builtin_types.entry_void;
1082TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *executable, TypeTableEntry *expected_type) {
1083 IrAnalyze ir_analyze_data = {};
1084 IrAnalyze *ira = &ir_analyze_data;
1085 ira->codegen = codegen;
1086 ira->exec = executable;
1087
1088 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;
4001089
4011090 for (size_t i = 0; i < executable->basic_block_count; i += 1) {
402 IrBasicBlock *current_block = executable->basic_block_list[i];
1091 ira->current_basic_block = executable->basic_block_list[i];
4031092
404 for (IrInstruction *instruction = current_block->first; instruction != nullptr;
1093 for (IrInstruction *instruction = ira->current_basic_block->first; instruction != nullptr;
4051094 instruction = instruction->next)
4061095 {
4071096 if (return_type->id == TypeTableEntryIdUnreachable) {
408 add_node_error(g, first_executing_node(instruction->source_node),
1097 add_node_error(ira->codegen, first_executing_node(instruction->source_node),
4091098 buf_sprintf("unreachable code"));
4101099 break;
4111100 }
412 bool is_last = (instruction == current_block->last);
1101 bool is_last = (instruction == ira->current_basic_block->last);
4131102 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
414 return_type = ir_analyze_instruction(g, instruction, passed_expected_type);
1103 return_type = ir_analyze_instruction(ira, instruction, passed_expected_type);
4151104 }
4161105 }
4171106
src/ir_print.cpp+113-23
......@@ -25,12 +25,24 @@ static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instructio
2525
2626static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
2727 ir_print_prefix(irp, &const_instruction->base);
28 switch (const_instruction->base.type_entry->id) {
28 TypeTableEntry *type_entry = const_instruction->base.type_entry;
29 fprintf(irp->f, "%s ", buf_ptr(&type_entry->name));
30 switch (type_entry->id) {
2931 case TypeTableEntryIdInvalid:
3032 zig_unreachable();
3133 case TypeTableEntryIdVoid:
32 fprintf(irp->f, "void\n");
34 fprintf(irp->f, "%s\n", "void");
3335 break;
36 case TypeTableEntryIdNumLitFloat:
37 fprintf(irp->f, "%f\n", const_instruction->base.static_value.data.x_bignum.data.x_float);
38 break;
39 case TypeTableEntryIdNumLitInt:
40 {
41 BigNum *bignum = &const_instruction->base.static_value.data.x_bignum;
42 const char *negative_str = bignum->is_negative ? "-" : "";
43 fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);
44 break;
45 }
3446 case TypeTableEntryIdVar:
3547 case TypeTableEntryIdMetaType:
3648 case TypeTableEntryIdBool:
......@@ -40,8 +52,6 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)
4052 case TypeTableEntryIdPointer:
4153 case TypeTableEntryIdArray:
4254 case TypeTableEntryIdStruct:
43 case TypeTableEntryIdNumLitFloat:
44 case TypeTableEntryIdNumLitInt:
4555 case TypeTableEntryIdUndefLit:
4656 case TypeTableEntryIdNullLit:
4757 case TypeTableEntryIdMaybe:
......@@ -58,6 +68,104 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)
5868 }
5969}
6070
71
72static const char *ir_bin_op_id_str(IrBinOp op_id) {
73 switch (op_id) {
74 case IrBinOpInvalid:
75 zig_unreachable();
76 case IrBinOpBoolOr:
77 return "BoolOr";
78 case IrBinOpBoolAnd:
79 return "BoolAnd";
80 case IrBinOpCmpEq:
81 return "==";
82 case IrBinOpCmpNotEq:
83 return "!=";
84 case IrBinOpCmpLessThan:
85 return "<";
86 case IrBinOpCmpGreaterThan:
87 return ">";
88 case IrBinOpCmpLessOrEq:
89 return "<=";
90 case IrBinOpCmpGreaterOrEq:
91 return ">=";
92 case IrBinOpBinOr:
93 return "|";
94 case IrBinOpBinXor:
95 return "^";
96 case IrBinOpBinAnd:
97 return "&";
98 case IrBinOpBitShiftLeft:
99 return "<<";
100 case IrBinOpBitShiftLeftWrap:
101 return "<<%";
102 case IrBinOpBitShiftRight:
103 return ">>";
104 case IrBinOpAdd:
105 return "+";
106 case IrBinOpAddWrap:
107 return "+%";
108 case IrBinOpSub:
109 return "-";
110 case IrBinOpSubWrap:
111 return "-%";
112 case IrBinOpMult:
113 return "*";
114 case IrBinOpMultWrap:
115 return "*%";
116 case IrBinOpDiv:
117 return "/";
118 case IrBinOpMod:
119 return "%";
120 case IrBinOpArrayCat:
121 return "++";
122 case IrBinOpArrayMult:
123 return "**";
124 }
125 zig_unreachable();
126}
127
128static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) {
129 ir_print_prefix(irp, &bin_op_instruction->base);
130 fprintf(irp->f, "#%zu %s #%zu\n",
131 bin_op_instruction->op1->debug_id,
132 ir_bin_op_id_str(bin_op_instruction->op_id),
133 bin_op_instruction->op2->debug_id);
134}
135
136static void ir_print_load_var(IrPrint *irp, IrInstructionLoadVar *load_var_instruction) {
137 ir_print_prefix(irp, &load_var_instruction->base);
138 fprintf(irp->f, "%s\n",
139 buf_ptr(&load_var_instruction->var->name));
140}
141
142static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
143 switch (instruction->id) {
144 case IrInstructionIdInvalid:
145 zig_unreachable();
146 case IrInstructionIdReturn:
147 ir_print_return(irp, (IrInstructionReturn *)instruction);
148 break;
149 case IrInstructionIdConst:
150 ir_print_const(irp, (IrInstructionConst *)instruction);
151 break;
152 case IrInstructionIdBinOp:
153 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
154 break;
155 case IrInstructionIdLoadVar:
156 ir_print_load_var(irp, (IrInstructionLoadVar *)instruction);
157 break;
158 case IrInstructionIdCondBr:
159 case IrInstructionIdSwitchBr:
160 case IrInstructionIdPhi:
161 case IrInstructionIdStoreVar:
162 case IrInstructionIdCall:
163 case IrInstructionIdBuiltinCall:
164 case IrInstructionIdCast:
165 zig_panic("TODO print more IR instructions");
166 }
167}
168
61169void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
62170 IrPrint ir_print = {};
63171 IrPrint *irp = &ir_print;
......@@ -70,25 +178,7 @@ void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
70178 for (IrInstruction *instruction = current_block->first; instruction != nullptr;
71179 instruction = instruction->next)
72180 {
73 switch (instruction->id) {
74 case IrInstructionIdInvalid:
75 zig_unreachable();
76 case IrInstructionIdReturn:
77 ir_print_return(irp, (IrInstructionReturn *)instruction);
78 break;
79 case IrInstructionIdConst:
80 ir_print_const(irp, (IrInstructionConst *)instruction);
81 break;
82 case IrInstructionIdCondBr:
83 case IrInstructionIdSwitchBr:
84 case IrInstructionIdPhi:
85 case IrInstructionIdBinOp:
86 case IrInstructionIdLoadVar:
87 case IrInstructionIdStoreVar:
88 case IrInstructionIdCall:
89 case IrInstructionIdBuiltinCall:
90 zig_panic("TODO print more IR instructions");
91 }
181 ir_print_instruction(irp, instruction);
92182 }
93183 }
94184}