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 {...@@ -1420,6 +1420,7 @@ enum IrInstructionId {
1420 IrInstructionIdBuiltinCall,1420 IrInstructionIdBuiltinCall,
1421 IrInstructionIdConst,1421 IrInstructionIdConst,
1422 IrInstructionIdReturn,1422 IrInstructionIdReturn,
1423 IrInstructionIdCast,
1423};1424};
14241425
1425struct IrInstruction {1426struct IrInstruction {
...@@ -1539,5 +1540,12 @@ struct IrInstructionReturn {...@@ -1539,5 +1540,12 @@ struct IrInstructionReturn {
1539 IrInstruction *value;1540 IrInstruction *value;
1540};1541};
15411542
1543struct IrInstructionCast {
1544 IrInstruction base;
1545
1546 IrInstruction *value;
1547 IrInstruction *dest_type;
1548 bool is_implicit;
1549};
15421550
1543#endif1551#endif
src/analyze.cpp+6-17
...@@ -42,10 +42,8 @@ static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, As...@@ -42,10 +42,8 @@ static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, As
42 TypeTableEntry *expected_type, uint64_t x, bool depends_on_compile_var);42 TypeTableEntry *expected_type, uint64_t x, bool depends_on_compile_var);
43static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, bool value,43static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, bool value,
44 bool depends_on_compile_var);44 bool depends_on_compile_var);
45static AstNode *find_decl(BlockContext *context, Buf *name);
46static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,45static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
47 bool pointer_only, BlockContext *block_context, bool depends_on_compile_var);46 bool pointer_only, BlockContext *block_context, bool depends_on_compile_var);
48static TopLevelDecl *get_as_top_level_decl(AstNode *node);
49static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,47static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
50 BlockContext *context, AstNode *source_node,48 BlockContext *context, AstNode *source_node,
51 AstNodeVariableDeclaration *variable_declaration,49 AstNodeVariableDeclaration *variable_declaration,
...@@ -1757,7 +1755,7 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {...@@ -1757,7 +1755,7 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {
1757 node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk;1755 node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk;
1758}1756}
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) {
1761 TopLevelDecl *tld = get_as_top_level_decl(node);1759 TopLevelDecl *tld = get_as_top_level_decl(node);
1762 if (tld->resolution != TldResolutionUnresolved) {1760 if (tld->resolution != TldResolutionUnresolved) {
1763 return;1761 return;
...@@ -1978,7 +1976,7 @@ static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTa...@@ -1978,7 +1976,7 @@ static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTa
1978 return false;1976 return false;
1979}1977}
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) {
1982 if (expected_type == actual_type)1980 if (expected_type == actual_type)
1983 return true;1981 return true;
19841982
...@@ -2302,7 +2300,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, ImportTableEntry *...@@ -2302,7 +2300,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, ImportTableEntry *
2302 return g->builtin_types.entry_invalid;2300 return g->builtin_types.entry_invalid;
2303}2301}
23042302
2305static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *import,2303TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *import,
2306 BlockContext *block_context, AstNode *parent_source_node,2304 BlockContext *block_context, AstNode *parent_source_node,
2307 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count)2305 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count)
2308{2306{
...@@ -2358,7 +2356,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {...@@ -2358,7 +2356,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
2358 return context;2356 return context;
2359}2357}
23602358
2361static AstNode *find_decl(BlockContext *context, Buf *name) {2359AstNode *find_decl(BlockContext *context, Buf *name) {
2362 while (context) {2360 while (context) {
2363 auto entry = context->decl_table.maybe_get(name);2361 auto entry = context->decl_table.maybe_get(name);
2364 if (entry) {2362 if (entry) {
...@@ -2369,7 +2367,7 @@ static AstNode *find_decl(BlockContext *context, Buf *name) {...@@ -2369,7 +2367,7 @@ static AstNode *find_decl(BlockContext *context, Buf *name) {
2369 return nullptr;2367 return nullptr;
2370}2368}
23712369
2372static VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name) {2370VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name) {
2373 BlockContext *context = orig_context;2371 BlockContext *context = orig_context;
2374 while (context) {2372 while (context) {
2375 auto entry = context->var_table.maybe_get(name);2373 auto entry = context->var_table.maybe_get(name);
...@@ -3248,10 +3246,6 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod...@@ -3248,10 +3246,6 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod
3248static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,3246static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3249 TypeTableEntry *expected_type, AstNode *node, bool pointer_only)3247 TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
3250{3248{
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
3255 Buf *variable_name = node->data.symbol_expr.symbol;3249 Buf *variable_name = node->data.symbol_expr.symbol;
32563250
3257 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);3251 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...@@ -4091,11 +4085,6 @@ static TypeTableEntry *analyze_this_literal_expr(CodeGen *g, ImportTableEntry *i
4091static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import,4085static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import,
4092 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)4086 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
4093{4087{
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
4099 return resolve_expr_const_val_as_bignum(g, node, expected_type, node->data.number_literal.bignum, false);4088 return resolve_expr_const_val_as_bignum(g, node, expected_type, node->data.number_literal.bignum, false);
4100}4089}
41014090
...@@ -7536,7 +7525,7 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -7536,7 +7525,7 @@ Expr *get_resolved_expr(AstNode *node) {
7536 zig_unreachable();7525 zig_unreachable();
7537}7526}
75387527
7539static TopLevelDecl *get_as_top_level_decl(AstNode *node) {7528TopLevelDecl *get_as_top_level_decl(AstNode *node) {
7540 switch (node->type) {7529 switch (node->type) {
7541 case NodeTypeVariableDeclaration:7530 case NodeTypeVariableDeclaration:
7542 return &node->data.variable_declaration.top_level_decl;7531 return &node->data.variable_declaration.top_level_decl;
src/analyze.hpp+10
...@@ -45,4 +45,14 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,...@@ -45,4 +45,14 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
4545
46AstNode *first_executing_node(AstNode *node);46AstNode *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
48#endif58#endif
src/codegen.cpp+105-9
...@@ -65,8 +65,6 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {...@@ -65,8 +65,6 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
65 g->is_test_build = false;65 g->is_test_build = false;
66 g->want_h_file = true;66 g->want_h_file = true;
6767
68 g->invalid_instruction = allocate<IrInstruction>(1);
69
70 // the error.Ok value68 // the error.Ok value
71 g->error_decls.append(nullptr);69 g->error_decls.append(nullptr);
7270
...@@ -252,10 +250,6 @@ static void set_debug_source_node(CodeGen *g, AstNode *node) {...@@ -252,10 +250,6 @@ static void set_debug_source_node(CodeGen *g, AstNode *node) {
252 ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);250 ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);
253}251}
254252
255static void ir_set_debug(CodeGen *g, IrInstruction *instruction) {
256 set_debug_source_node(g, instruction->source_node);
257}
258
259static void clear_debug_source_node(CodeGen *g) {253static void clear_debug_source_node(CodeGen *g) {
260 ZigLLVMClearCurrentDebugLocation(g->builder);254 ZigLLVMClearCurrentDebugLocation(g->builder);
261}255}
...@@ -375,6 +369,10 @@ static bool want_debug_safety(CodeGen *g, AstNode *node) {...@@ -375,6 +369,10 @@ static bool want_debug_safety(CodeGen *g, AstNode *node) {
375 return want_debug_safety_recursive(g, node->block_context);369 return want_debug_safety_recursive(g, node->block_context);
376}370}
377371
372static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) {
373 return want_debug_safety(g, instruction->source_node);
374}
375
378static void gen_debug_safety_crash(CodeGen *g) {376static void gen_debug_safety_crash(CodeGen *g) {
379 LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");377 LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
380 LLVMBuildUnreachable(g->builder);378 LLVMBuildUnreachable(g->builder);
...@@ -2800,12 +2798,104 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {...@@ -2800,12 +2798,104 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
2800}2798}
28012799
2802static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {2800static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
2803 ir_set_debug(g, &return_instruction->base);
2804 LLVMBuildRet(g->builder, return_instruction->value->llvm_value);2801 LLVMBuildRet(g->builder, return_instruction->value->llvm_value);
2805 return nullptr;2802 return nullptr;
2806}2803}
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
2808static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {2897static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
2898 set_debug_source_node(g, instruction->source_node);
2809 switch (instruction->id) {2899 switch (instruction->id) {
2810 case IrInstructionIdInvalid:2900 case IrInstructionIdInvalid:
2811 zig_unreachable();2901 zig_unreachable();
...@@ -2813,14 +2903,17 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2813,14 +2903,17 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2813 return gen_const_val(g, instruction->type_entry, &instruction->static_value);2903 return gen_const_val(g, instruction->type_entry, &instruction->static_value);
2814 case IrInstructionIdReturn:2904 case IrInstructionIdReturn:
2815 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);2905 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);
2816 case IrInstructionIdCondBr:2910 case IrInstructionIdCondBr:
2817 case IrInstructionIdSwitchBr:2911 case IrInstructionIdSwitchBr:
2818 case IrInstructionIdPhi:2912 case IrInstructionIdPhi:
2819 case IrInstructionIdBinOp:
2820 case IrInstructionIdLoadVar:
2821 case IrInstructionIdStoreVar:2913 case IrInstructionIdStoreVar:
2822 case IrInstructionIdCall:2914 case IrInstructionIdCall:
2823 case IrInstructionIdBuiltinCall:2915 case IrInstructionIdBuiltinCall:
2916 case IrInstructionIdCast:
2824 zig_panic("TODO render more IR instructions to LLVM");2917 zig_panic("TODO render more IR instructions to LLVM");
2825 }2918 }
2826 zig_unreachable();2919 zig_unreachable();
...@@ -5013,6 +5106,9 @@ static void init(CodeGen *g, Buf *source_path) {...@@ -5013,6 +5106,9 @@ static void init(CodeGen *g, Buf *source_path) {
50135106
5014 define_builtin_types(g);5107 define_builtin_types(g);
5015 define_builtin_fns(g);5108 define_builtin_fns(g);
5109
5110 g->invalid_instruction = allocate<IrInstruction>(1);
5111 g->invalid_instruction->type_entry = g->builtin_types.entry_invalid;
5016}5112}
50175113
5018void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {5114void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
src/ir.cpp+769-80
...@@ -9,7 +9,13 @@ struct IrGen {...@@ -9,7 +9,13 @@ struct IrGen {
9 IrExecutable *exec;9 IrExecutable *exec;
10};10};
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
14static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {20static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
15 if (!basic_block->last) {21 if (!basic_block->last) {
...@@ -25,9 +31,33 @@ static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *inst...@@ -25,9 +31,33 @@ static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *inst
25 }31 }
26}32}
2733
28static size_t exec_next_debug_id(IrGen *ir) {34static void ir_instruction_insert(IrBasicBlock *basic_block,
29 size_t result = ir->exec->next_debug_id;35 IrInstruction *before_instruction, IrInstruction *after_instruction,
30 ir->exec->next_debug_id += 1;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;
31 return result;61 return result;
32}62}
3363
...@@ -71,32 +101,117 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) {...@@ -71,32 +101,117 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) {
71 return IrInstructionIdReturn;101 return IrInstructionIdReturn;
72}102}
73103
104static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
105 return IrInstructionIdCast;
106}
107
74template<typename T>108template<typename T>
75static T *ir_build_instruction(IrGen *ir, AstNode *source_node) {109static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
76 T *special_instruction = allocate<T>(1);110 T *special_instruction = allocate<T>(1);
77 special_instruction->base.id = ir_instruction_id(special_instruction);111 special_instruction->base.id = ir_instruction_id(special_instruction);
78 special_instruction->base.source_node = source_node;112 special_instruction->base.source_node = source_node;
79 special_instruction->base.type_entry = ir->codegen->builtin_types.entry_unreachable;113 special_instruction->base.debug_id = exec_next_debug_id(exec);
80 special_instruction->base.debug_id = exec_next_debug_id(ir);114 return special_instruction;
81 ir_instruction_append(ir->current_basic_block, &special_instruction->base);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);
82 return special_instruction;121 return special_instruction;
83}122}
84123
85static IrInstruction *ir_build_return(IrGen *ir, AstNode *source_node, IrInstruction *return_value) {124static IrInstruction *ir_insert_const_type(IrAnalyze *ira, IrInstruction *before_instruction,
86 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(ir, source_node);125 IrInstruction *after_instruction, TypeTableEntry *type_entry)
87 return_instruction->base.type_entry = ir->codegen->builtin_types.entry_unreachable;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;
88 return_instruction->base.static_value.ok = true;152 return_instruction->base.static_value.ok = true;
89 return_instruction->value = return_value;153 return_instruction->value = return_value;
90 return &return_instruction->base;154 return &return_instruction->base;
91}155}
92156
93static IrInstruction *ir_build_void(IrGen *ir, AstNode *source_node) {157static IrInstruction *ir_build_const_void(IrGen *irg, AstNode *source_node) {
94 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(ir, source_node);158 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node);
95 const_instruction->base.type_entry = ir->codegen->builtin_types.entry_void;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;
96 const_instruction->base.static_value.ok = true;168 const_instruction->base.static_value.ok = true;
169 const_instruction->base.static_value.data.x_bignum = *bignum;
97 return &const_instruction->base;170 return &const_instruction->base;
98}171}
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
100//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {215//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
101// size_t result = 0;216// size_t result = 0;
102// while (inner_block != outer_block) {217// while (inner_block != outer_block) {
...@@ -111,7 +226,7 @@ static IrInstruction *ir_build_void(IrGen *ir, AstNode *source_node) {...@@ -111,7 +226,7 @@ static IrInstruction *ir_build_void(IrGen *ir, AstNode *source_node) {
111// return result;226// return result;
112//}227//}
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,
115 bool gen_error_defers, bool gen_maybe_defers)230 bool gen_error_defers, bool gen_maybe_defers)
116{231{
117 while (inner_block != outer_block) {232 while (inner_block != outer_block) {
...@@ -121,15 +236,15 @@ static void ir_gen_defers_for_block(IrGen *ir, BlockContext *inner_block, BlockC...@@ -121,15 +236,15 @@ static void ir_gen_defers_for_block(IrGen *ir, BlockContext *inner_block, BlockC
121 (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe)))236 (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe)))
122 {237 {
123 AstNode *defer_expr_node = inner_block->node->data.defer.expr;238 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);
125 }240 }
126 inner_block = inner_block->parent;241 inner_block = inner_block->parent;
127 }242 }
128}243}
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) {
131// BlockContext *defer_inner_block = source_node->block_context;246// 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;
133// if (rk == ReturnKnowledgeUnknown) {248// if (rk == ReturnKnowledgeUnknown) {
134// if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) {249// if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) {
135// // generate branching code that checks the return value and generates defers250// // 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...@@ -137,14 +252,14 @@ static void ir_gen_defers_for_block(IrGen *ir, BlockContext *inner_block, BlockC
137// zig_panic("TODO");252// zig_panic("TODO");
138// }253// }
139// } else if (rk != ReturnKnowledgeSkipDefers) {254// } 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,
141// rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull);256// rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull);
142// }257// }
143//258//
144// return ir_build_return(ir, source_node, value);259// return ir_build_return(irg, source_node, value);
145//}260//}
146261
147static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node) {262static IrInstruction *ir_gen_block(IrGen *irg, AstNode *block_node) {
148 assert(block_node->type == NodeTypeBlock);263 assert(block_node->type == NodeTypeBlock);
149264
150 BlockContext *parent_context = block_node->block_context;265 BlockContext *parent_context = block_node->block_context;
...@@ -154,8 +269,8 @@ static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node) {...@@ -154,8 +269,8 @@ static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node) {
154 IrInstruction *return_value = nullptr;269 IrInstruction *return_value = nullptr;
155 for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) {270 for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) {
156 AstNode *statement_node = block_node->data.block.statements.at(i);271 AstNode *statement_node = block_node->data.block.statements.at(i);
157 return_value = ir_gen_node(ir, statement_node, child_context);272 return_value = ir_gen_node(irg, statement_node, child_context);
158 if (statement_node->type == NodeTypeDefer && return_value != ir->codegen->invalid_instruction) {273 if (statement_node->type == NodeTypeDefer && return_value != irg->codegen->invalid_instruction) {
159 // defer starts a new block context274 // defer starts a new block context
160 child_context = statement_node->data.defer.child_block;275 child_context = statement_node->data.defer.child_block;
161 assert(child_context);276 assert(child_context);
...@@ -163,20 +278,188 @@ static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node) {...@@ -163,20 +278,188 @@ static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node) {
163 }278 }
164279
165 if (!return_value)280 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
170 return return_value;285 return return_value;
171}286}
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{
174 node->block_context = block_context;452 node->block_context = block_context;
175453
176 switch (node->type) {454 switch (node->type) {
177 case NodeTypeBlock:455 case NodeTypeBlock:
178 return ir_gen_block(ir, node);456 return ir_gen_block(irg, node);
179 case NodeTypeBinOpExpr:457 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);
180 case NodeTypeUnwrapErrorExpr:463 case NodeTypeUnwrapErrorExpr:
181 case NodeTypeReturnExpr:464 case NodeTypeReturnExpr:
182 case NodeTypeDefer:465 case NodeTypeDefer:
...@@ -191,14 +474,12 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_...@@ -191,14 +474,12 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_
191 case NodeTypeWhileExpr:474 case NodeTypeWhileExpr:
192 case NodeTypeForExpr:475 case NodeTypeForExpr:
193 case NodeTypeAsmExpr:476 case NodeTypeAsmExpr:
194 case NodeTypeSymbol:
195 case NodeTypeGoto:477 case NodeTypeGoto:
196 case NodeTypeBreak:478 case NodeTypeBreak:
197 case NodeTypeContinue:479 case NodeTypeContinue:
198 case NodeTypeLabel:480 case NodeTypeLabel:
199 case NodeTypeContainerInitExpr:481 case NodeTypeContainerInitExpr:
200 case NodeTypeSwitchExpr:482 case NodeTypeSwitchExpr:
201 case NodeTypeNumberLiteral:
202 case NodeTypeBoolLiteral:483 case NodeTypeBoolLiteral:
203 case NodeTypeStringLiteral:484 case NodeTypeStringLiteral:
204 case NodeTypeCharLiteral:485 case NodeTypeCharLiteral:
...@@ -228,42 +509,49 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_...@@ -228,42 +509,49 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_
228 zig_unreachable();509 zig_unreachable();
229}510}
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
231static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope,517static 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)
233{519{
234 assert(node->owner);520 assert(node->owner);
235521
236 IrGen ir_gen = {0};522 IrGen ir_gen = {0};
237 IrGen *ir = &ir_gen;523 IrGen *irg = &ir_gen;
238524
239 ir->codegen = g;525 irg->codegen = g;
240 ir->node = node;526 irg->node = node;
241 ir->exec = ir_executable;527 irg->exec = ir_executable;
242528
243 ir->exec->basic_block_list = allocate<IrBasicBlock*>(1);529 irg->exec->basic_block_list = allocate<IrBasicBlock*>(1);
244 ir->exec->basic_block_count = 1;530 irg->exec->basic_block_count = 1;
245531
246 IrBasicBlock *entry_basic_block = allocate<IrBasicBlock>(1);532 IrBasicBlock *entry_basic_block = allocate<IrBasicBlock>(1);
247 ir->current_basic_block = entry_basic_block;533 irg->current_basic_block = entry_basic_block;
248 ir->exec->basic_block_list[0] = 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);
251 assert(result);537 assert(result);
252538
253 if (result == g->invalid_instruction)539 if (result == g->invalid_instruction)
254 return result;540 return result;
255541
256 if (add_return)542 if (add_return)
257 return ir_build_return(ir, result->source_node, result);543 return ir_build_return(irg, result->source_node, result);
258544
259 return result;545 return result;
260}546}
261547
262IrInstruction *ir_gen(CodeGen *g, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {548IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {
263 return ir_gen_add_return(g, node, scope, ir_executable, false);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);
264}552}
265553
266IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry) {554IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
267 assert(fn_entry);555 assert(fn_entry);
268556
269 IrExecutable *ir_executable = &fn_entry->ir_executable;557 IrExecutable *ir_executable = &fn_entry->ir_executable;
...@@ -274,7 +562,8 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry) {...@@ -274,7 +562,8 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry) {
274 BlockContext *scope = fn_def_node->data.fn_def.block_context;562 BlockContext *scope = fn_def_node->data.fn_def.block_context;
275563
276 bool add_return_yes = true;564 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);
278}567}
279568
280/*569/*
...@@ -322,96 +611,496 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no...@@ -322,96 +611,496 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
322// return nullptr;611// return nullptr;
323//}612//}
324613
325static IrInstruction *ir_get_casted_instruction(CodeGen *g, IrInstruction *instruction,614static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {
326 TypeTableEntry *expected_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)
327{825{
328 assert(instruction);826 assert(value);
329 assert(instruction != g->invalid_instruction);827 assert(before_instruction || after_instruction);
828 assert(!before_instruction || !after_instruction);
829 assert(value != ira->codegen->invalid_instruction);
330 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);830 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);
331 assert(instruction->type_entry);831 assert(value->type_entry);
332 assert(instruction->type_entry->id != TypeTableEntryIdInvalid);832 assert(value->type_entry->id != TypeTableEntryIdInvalid);
333 if (expected_type == nullptr)833 if (expected_type == nullptr)
334 return instruction; // anything will do834 return value; // anything will do
335 if (expected_type == instruction->type_entry)835 if (expected_type == value->type_entry)
336 return instruction; // match836 return value; // match
337 if (instruction->type_entry->id == TypeTableEntryIdUnreachable)837 if (value->type_entry->id == TypeTableEntryIdUnreachable)
338 return instruction;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();
341}863}
342864
343static TypeTableEntry *ir_analyze_instruction_return(CodeGen *g, IrInstructionReturn *return_instruction) {865static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *return_instruction) {
344 AstNode *source_node = return_instruction->base.source_node;866 AstNode *source_node = return_instruction->base.source_node;
345 BlockContext *scope = source_node->block_context;867 BlockContext *scope = source_node->block_context;
346 if (!scope->fn_entry) {868 if (!scope->fn_entry) {
347 add_node_error(g, source_node, buf_sprintf("return expression outside function definition"));869 add_node_error(ira->codegen, source_node, buf_sprintf("return expression outside function definition"));
348 return g->builtin_types.entry_invalid;870 return ira->codegen->builtin_types.entry_invalid;
349 }871 }
350872
351 TypeTableEntry *expected_return_type = scope->fn_entry->type_entry->data.fn.fn_type_id.return_type;873 TypeTableEntry *expected_return_type = scope->fn_entry->type_entry->data.fn.fn_type_id.return_type;
352 if (expected_return_type->id == TypeTableEntryIdVoid && !return_instruction->value) {874 if (expected_return_type->id == TypeTableEntryIdVoid && !return_instruction->value) {
353 return g->builtin_types.entry_unreachable;875 return ira->codegen->builtin_types.entry_unreachable;
354 }876 }
355877
356 return_instruction->value = ir_get_casted_instruction(g, return_instruction->value, expected_return_type);878 return_instruction->value = ir_get_casted_value(ira,
357 if (return_instruction->value == g->invalid_instruction) {879 return_instruction->value, expected_return_type, &return_instruction->base, nullptr);
358 return g->builtin_types.entry_invalid;880 if (return_instruction->value == ira->codegen->invalid_instruction) {
881 return ira->codegen->builtin_types.entry_invalid;
359 }882 }
360 return g->builtin_types.entry_unreachable;883 return ira->codegen->builtin_types.entry_unreachable;
361}884}
362885
363static TypeTableEntry *ir_analyze_instruction_const(CodeGen *g, IrInstructionConst *const_instruction) {886static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {
364 return const_instruction->base.type_entry;887 return const_instruction->base.type_entry;
365}888}
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) {
368 switch (instruction->id) {1048 switch (instruction->id) {
369 case IrInstructionIdInvalid:1049 case IrInstructionIdInvalid:
370 zig_unreachable();1050 zig_unreachable();
371 case IrInstructionIdReturn:1051 case IrInstructionIdReturn:
372 return ir_analyze_instruction_return(g, (IrInstructionReturn *)instruction);1052 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);
373 case IrInstructionIdConst:1053 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);
375 case IrInstructionIdCondBr:1059 case IrInstructionIdCondBr:
376 case IrInstructionIdSwitchBr:1060 case IrInstructionIdSwitchBr:
377 case IrInstructionIdPhi:1061 case IrInstructionIdPhi:
378 case IrInstructionIdBinOp:
379 case IrInstructionIdLoadVar:
380 case IrInstructionIdStoreVar:1062 case IrInstructionIdStoreVar:
381 case IrInstructionIdCall:1063 case IrInstructionIdCall:
382 case IrInstructionIdBuiltinCall:1064 case IrInstructionIdBuiltinCall:
1065 case IrInstructionIdCast:
383 zig_panic("TODO analyze more instructions");1066 zig_panic("TODO analyze more instructions");
384 }1067 }
385 zig_unreachable();1068 zig_unreachable();
386}1069}
3871070
388static TypeTableEntry *ir_analyze_instruction(CodeGen *g, IrInstruction *instruction,1071static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction,
389 TypeTableEntry *expected_type)1072 TypeTableEntry *expected_type)
390{1073{
391 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(g, instruction);1074 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);
392 instruction->type_entry = instruction_type;1075 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);
395 return casted_instruction->type_entry;1079 return casted_instruction->type_entry;
396}1080}
3971081
398TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *executable, TypeTableEntry *expected_type) {1082TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *executable, TypeTableEntry *expected_type) {
399 TypeTableEntry *return_type = g->builtin_types.entry_void;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
401 for (size_t i = 0; i < executable->basic_block_count; i += 1) {1090 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;
405 instruction = instruction->next)1094 instruction = instruction->next)
406 {1095 {
407 if (return_type->id == TypeTableEntryIdUnreachable) {1096 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),
409 buf_sprintf("unreachable code"));1098 buf_sprintf("unreachable code"));
410 break;1099 break;
411 }1100 }
412 bool is_last = (instruction == current_block->last);1101 bool is_last = (instruction == ira->current_basic_block->last);
413 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;1102 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);
415 }1104 }
416 }1105 }
4171106
src/ir_print.cpp+113-23
...@@ -25,12 +25,24 @@ static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instructio...@@ -25,12 +25,24 @@ static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instructio
2525
26static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {26static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
27 ir_print_prefix(irp, &const_instruction->base);27 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) {
29 case TypeTableEntryIdInvalid:31 case TypeTableEntryIdInvalid:
30 zig_unreachable();32 zig_unreachable();
31 case TypeTableEntryIdVoid:33 case TypeTableEntryIdVoid:
32 fprintf(irp->f, "void\n");34 fprintf(irp->f, "%s\n", "void");
33 break;35 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 }
34 case TypeTableEntryIdVar:46 case TypeTableEntryIdVar:
35 case TypeTableEntryIdMetaType:47 case TypeTableEntryIdMetaType:
36 case TypeTableEntryIdBool:48 case TypeTableEntryIdBool:
...@@ -40,8 +52,6 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)...@@ -40,8 +52,6 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)
40 case TypeTableEntryIdPointer:52 case TypeTableEntryIdPointer:
41 case TypeTableEntryIdArray:53 case TypeTableEntryIdArray:
42 case TypeTableEntryIdStruct:54 case TypeTableEntryIdStruct:
43 case TypeTableEntryIdNumLitFloat:
44 case TypeTableEntryIdNumLitInt:
45 case TypeTableEntryIdUndefLit:55 case TypeTableEntryIdUndefLit:
46 case TypeTableEntryIdNullLit:56 case TypeTableEntryIdNullLit:
47 case TypeTableEntryIdMaybe:57 case TypeTableEntryIdMaybe:
...@@ -58,6 +68,104 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)...@@ -58,6 +68,104 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)
58 }68 }
59}69}
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
61void ir_print(FILE *f, IrExecutable *executable, int indent_size) {169void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
62 IrPrint ir_print = {};170 IrPrint ir_print = {};
63 IrPrint *irp = &ir_print;171 IrPrint *irp = &ir_print;
...@@ -70,25 +178,7 @@ void ir_print(FILE *f, IrExecutable *executable, int indent_size) {...@@ -70,25 +178,7 @@ void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
70 for (IrInstruction *instruction = current_block->first; instruction != nullptr;178 for (IrInstruction *instruction = current_block->first; instruction != nullptr;
71 instruction = instruction->next)179 instruction = instruction->next)
72 {180 {
73 switch (instruction->id) {181 ir_print_instruction(irp, instruction);
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 }
92 }182 }
93 }183 }
94}184}