| ... | ... | @@ -21,6 +21,11 @@ struct IrAnalyze { |
| 21 | 21 | IrBuilder old_irb; |
| 22 | 22 | IrBuilder new_irb; |
| 23 | 23 | IrExecContext exec_context; |
| 24 | ZigList<IrBasicBlock *> block_queue; |
| 25 | size_t block_queue_index; |
| 26 | size_t instruction_index; |
| 27 | TypeTableEntry *explicit_return_type; |
| 28 | ZigList<IrInstruction *> implicit_return_type_list; |
| 24 | 29 | }; |
| 25 | 30 | |
| 26 | 31 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope); |
| ... | ... | @@ -58,11 +63,6 @@ static void ir_ref_bb(IrBasicBlock *bb) { |
| 58 | 63 | bb->ref_count += 1; |
| 59 | 64 | } |
| 60 | 65 | |
| 61 | | static void ir_unref_bb(IrBasicBlock *bb) { |
| 62 | | bb->ref_count -= 1; |
| 63 | | assert(bb->ref_count != SIZE_MAX); |
| 64 | | } |
| 65 | | |
| 66 | 66 | static void ir_ref_instruction(IrInstruction *instruction) { |
| 67 | 67 | instruction->ref_count += 1; |
| 68 | 68 | } |
| ... | ... | @@ -349,6 +349,14 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node, |
| 349 | 349 | return &call_instruction->base; |
| 350 | 350 | } |
| 351 | 351 | |
| 352 | static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 353 | IrInstruction *fn, size_t arg_count, IrInstruction **args) |
| 354 | { |
| 355 | IrInstruction *new_instruction = ir_build_call(irb, old_instruction->source_node, fn, arg_count, args); |
| 356 | ir_link_new_instruction(new_instruction, old_instruction); |
| 357 | return new_instruction; |
| 358 | } |
| 359 | |
| 352 | 360 | static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node, |
| 353 | 361 | BuiltinFnEntry *fn, IrInstruction **args) |
| 354 | 362 | { |
| ... | ... | @@ -396,11 +404,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicB |
| 396 | 404 | return &br_instruction->base; |
| 397 | 405 | } |
| 398 | 406 | |
| 399 | | static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) { |
| 400 | | IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block); |
| 401 | | ir_link_new_instruction(new_instruction, old_instruction); |
| 402 | | return new_instruction; |
| 403 | | } |
| 407 | //static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) { |
| 408 | // IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block); |
| 409 | // ir_link_new_instruction(new_instruction, old_instruction); |
| 410 | // return new_instruction; |
| 411 | //} |
| 404 | 412 | |
| 405 | 413 | static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) { |
| 406 | 414 | IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node); |
| ... | ... | @@ -1273,36 +1281,26 @@ static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext |
| 1273 | 1281 | zig_unreachable(); |
| 1274 | 1282 | } |
| 1275 | 1283 | |
| 1276 | | static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope, |
| 1277 | | IrExecutable *ir_executable, bool add_return, LValPurpose lval) |
| 1278 | | { |
| 1284 | IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) { |
| 1279 | 1285 | assert(node->owner); |
| 1280 | 1286 | |
| 1281 | 1287 | IrBuilder ir_gen = {0}; |
| 1282 | 1288 | IrBuilder *irb = &ir_gen; |
| 1283 | 1289 | |
| 1284 | | irb->codegen = g; |
| 1290 | irb->codegen = codegen; |
| 1285 | 1291 | irb->exec = ir_executable; |
| 1286 | 1292 | |
| 1287 | 1293 | irb->current_basic_block = ir_build_basic_block(irb, "Entry"); |
| 1288 | 1294 | // Entry block gets a reference because we enter it to begin. |
| 1289 | 1295 | ir_ref_bb(irb->current_basic_block); |
| 1290 | 1296 | |
| 1291 | | IrInstruction *result = ir_gen_node_extra(irb, node, scope, lval); |
| 1297 | IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValPurposeNone); |
| 1292 | 1298 | assert(result); |
| 1293 | 1299 | |
| 1294 | | if (result == g->invalid_instruction) |
| 1300 | if (result == codegen->invalid_instruction) |
| 1295 | 1301 | return result; |
| 1296 | 1302 | |
| 1297 | | if (add_return) |
| 1298 | | return ir_build_return(irb, result->source_node, result); |
| 1299 | | |
| 1300 | | return result; |
| 1301 | | } |
| 1302 | | |
| 1303 | | IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) { |
| 1304 | | bool add_return_no = false; |
| 1305 | | return ir_gen_add_return(codegen, node, scope, ir_executable, add_return_no, LValPurposeNone); |
| 1303 | return ir_build_return(irb, result->source_node, result); |
| 1306 | 1304 | } |
| 1307 | 1305 | |
| 1308 | 1306 | IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| ... | ... | @@ -1315,8 +1313,7 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| 1315 | 1313 | AstNode *body_node = fn_def_node->data.fn_def.body; |
| 1316 | 1314 | BlockContext *scope = fn_def_node->data.fn_def.block_context; |
| 1317 | 1315 | |
| 1318 | | bool add_return_yes = true; |
| 1319 | | return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, LValPurposeNone); |
| 1316 | return ir_gen(codegn, body_node, scope, ir_executable); |
| 1320 | 1317 | } |
| 1321 | 1318 | |
| 1322 | 1319 | /* |
| ... | ... | @@ -1401,7 +1398,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc |
| 1401 | 1398 | return false; |
| 1402 | 1399 | } |
| 1403 | 1400 | |
| 1404 | | static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *parent_instruction, |
| 1401 | static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, AstNode *source_node, |
| 1405 | 1402 | IrInstruction **instructions, size_t instruction_count) |
| 1406 | 1403 | { |
| 1407 | 1404 | assert(instruction_count >= 1); |
| ... | ... | @@ -1465,7 +1462,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa |
| 1465 | 1462 | return ira->codegen->builtin_types.entry_invalid; |
| 1466 | 1463 | } |
| 1467 | 1464 | } else { |
| 1468 | | add_node_error(ira->codegen, parent_instruction->source_node, |
| 1465 | add_node_error(ira->codegen, source_node, |
| 1469 | 1466 | buf_sprintf("incompatible types: '%s' and '%s'", |
| 1470 | 1467 | buf_ptr(&prev_type->name), buf_ptr(&cur_type->name))); |
| 1471 | 1468 | |
| ... | ... | @@ -1566,10 +1563,10 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 1566 | 1563 | return ImplicitCastMatchResultNo; |
| 1567 | 1564 | } |
| 1568 | 1565 | |
| 1569 | | static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, IrInstruction *parent_instruction, |
| 1566 | static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, |
| 1570 | 1567 | IrInstruction **instructions, size_t instruction_count) |
| 1571 | 1568 | { |
| 1572 | | return ir_determine_peer_types(ira, parent_instruction, instructions, instruction_count); |
| 1569 | return ir_determine_peer_types(ira, source_node, instructions, instruction_count); |
| 1573 | 1570 | } |
| 1574 | 1571 | |
| 1575 | 1572 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| ... | ... | @@ -1608,9 +1605,29 @@ static bool is_u8(TypeTableEntry *type) { |
| 1608 | 1605 | static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { |
| 1609 | 1606 | if (old_bb->other) |
| 1610 | 1607 | return old_bb->other; |
| 1611 | | return ir_build_bb_from(&ira->new_irb, old_bb); |
| 1608 | IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb); |
| 1609 | ira->block_queue.append(new_bb); |
| 1610 | return new_bb; |
| 1612 | 1611 | } |
| 1613 | 1612 | |
| 1613 | static void ir_finish_bb(IrAnalyze *ira) { |
| 1614 | ira->block_queue_index += 1; |
| 1615 | |
| 1616 | if (ira->block_queue_index < ira->block_queue.length) { |
| 1617 | IrBasicBlock *old_bb = ira->block_queue.at(ira->block_queue_index); |
| 1618 | ira->instruction_index = 0; |
| 1619 | ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb); |
| 1620 | ira->old_irb.current_basic_block = old_bb; |
| 1621 | } |
| 1622 | } |
| 1623 | |
| 1624 | static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { |
| 1625 | ira->instruction_index = 0; |
| 1626 | |
| 1627 | ira->old_irb.current_basic_block = old_bb; |
| 1628 | } |
| 1629 | |
| 1630 | |
| 1614 | 1631 | static ConstExprValue *ir_get_out_val(IrInstruction *instruction) { |
| 1615 | 1632 | instruction->other = instruction; |
| 1616 | 1633 | return &instruction->static_value; |
| ... | ... | @@ -1942,8 +1959,11 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi |
| 1942 | 1959 | if (value == ira->codegen->invalid_instruction) { |
| 1943 | 1960 | return ira->codegen->builtin_types.entry_invalid; |
| 1944 | 1961 | } |
| 1962 | ira->implicit_return_type_list.append(value); |
| 1945 | 1963 | |
| 1946 | | return ir_build_return_from(&ira->new_irb, &return_instruction->base, value)->type_entry; |
| 1964 | IrInstruction *new_instruction = ir_build_return_from(&ira->new_irb, &return_instruction->base, value); |
| 1965 | ir_finish_bb(ira); |
| 1966 | return new_instruction->type_entry; |
| 1947 | 1967 | } |
| 1948 | 1968 | |
| 1949 | 1969 | static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) { |
| ... | ... | @@ -1991,10 +2011,10 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 1991 | 2011 | } |
| 1992 | 2012 | |
| 1993 | 2013 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 1994 | | IrInstruction *op1 = bin_op_instruction->op1; |
| 1995 | | IrInstruction *op2 = bin_op_instruction->op2; |
| 2014 | IrInstruction *op1 = bin_op_instruction->op1->other; |
| 2015 | IrInstruction *op2 = bin_op_instruction->op2->other; |
| 1996 | 2016 | IrInstruction *instructions[] = {op1, op2}; |
| 1997 | | TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &bin_op_instruction->base, instructions, 2); |
| 2017 | TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2); |
| 1998 | 2018 | if (resolved_type->id == TypeTableEntryIdInvalid) |
| 1999 | 2019 | return resolved_type; |
| 2000 | 2020 | IrBinOp op_id = bin_op_instruction->op_id; |
| ... | ... | @@ -2052,9 +2072,60 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 2052 | 2072 | zig_unreachable(); |
| 2053 | 2073 | } |
| 2054 | 2074 | |
| 2055 | | zig_panic("TODO interpret bin_op_cmp"); |
| 2075 | IrInstruction *casted_op1 = ir_get_casted_value(ira, op1, resolved_type); |
| 2076 | if (casted_op1 == ira->codegen->invalid_instruction) |
| 2077 | return ira->codegen->builtin_types.entry_invalid; |
| 2078 | |
| 2079 | IrInstruction *casted_op2 = ir_get_casted_value(ira, op2, resolved_type); |
| 2080 | if (casted_op2 == ira->codegen->invalid_instruction) |
| 2081 | return ira->codegen->builtin_types.entry_invalid; |
| 2082 | |
| 2083 | ConstExprValue *op1_val = &casted_op1->static_value; |
| 2084 | ConstExprValue *op2_val = &casted_op2->static_value; |
| 2085 | if (op1_val->ok && op2_val->ok) { |
| 2086 | bool type_can_gt_lt_cmp = (resolved_type->id == TypeTableEntryIdNumLitFloat || |
| 2087 | resolved_type->id == TypeTableEntryIdNumLitInt || |
| 2088 | resolved_type->id == TypeTableEntryIdFloat || |
| 2089 | resolved_type->id == TypeTableEntryIdInt); |
| 2090 | bool answer; |
| 2091 | if (type_can_gt_lt_cmp) { |
| 2092 | bool (*bignum_cmp)(BigNum *, BigNum *); |
| 2093 | if (op_id == IrBinOpCmpEq) { |
| 2094 | bignum_cmp = bignum_cmp_eq; |
| 2095 | } else if (op_id == IrBinOpCmpNotEq) { |
| 2096 | bignum_cmp = bignum_cmp_neq; |
| 2097 | } else if (op_id == IrBinOpCmpLessThan) { |
| 2098 | bignum_cmp = bignum_cmp_lt; |
| 2099 | } else if (op_id == IrBinOpCmpGreaterThan) { |
| 2100 | bignum_cmp = bignum_cmp_gt; |
| 2101 | } else if (op_id == IrBinOpCmpLessOrEq) { |
| 2102 | bignum_cmp = bignum_cmp_lte; |
| 2103 | } else if (op_id == IrBinOpCmpGreaterOrEq) { |
| 2104 | bignum_cmp = bignum_cmp_gte; |
| 2105 | } else { |
| 2106 | zig_unreachable(); |
| 2107 | } |
| 2056 | 2108 | |
| 2057 | | ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1->other, op2->other); |
| 2109 | answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum); |
| 2110 | } else { |
| 2111 | bool are_equal = const_values_equal(op1_val, op2_val, resolved_type); |
| 2112 | if (op_id == IrBinOpCmpEq) { |
| 2113 | answer = are_equal; |
| 2114 | } else if (op_id == IrBinOpCmpNotEq) { |
| 2115 | answer = !are_equal; |
| 2116 | } else { |
| 2117 | zig_unreachable(); |
| 2118 | } |
| 2119 | } |
| 2120 | |
| 2121 | ConstExprValue *out_val = ir_get_out_val(&bin_op_instruction->base); |
| 2122 | out_val->ok = true; |
| 2123 | out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; |
| 2124 | out_val->data.x_bool = answer; |
| 2125 | return ira->codegen->builtin_types.entry_bool; |
| 2126 | } |
| 2127 | |
| 2128 | ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, casted_op1, casted_op2); |
| 2058 | 2129 | |
| 2059 | 2130 | return ira->codegen->builtin_types.entry_bool; |
| 2060 | 2131 | } |
| ... | ... | @@ -2158,7 +2229,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 2158 | 2229 | IrInstruction *op1 = bin_op_instruction->op1->other; |
| 2159 | 2230 | IrInstruction *op2 = bin_op_instruction->op2->other; |
| 2160 | 2231 | IrInstruction *instructions[] = {op1, op2}; |
| 2161 | | TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &bin_op_instruction->base, instructions, 2); |
| 2232 | TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2); |
| 2162 | 2233 | if (resolved_type->id == TypeTableEntryIdInvalid) |
| 2163 | 2234 | return resolved_type; |
| 2164 | 2235 | IrBinOp op_id = bin_op_instruction->op_id; |
| ... | ... | @@ -2393,6 +2464,13 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction |
| 2393 | 2464 | |
| 2394 | 2465 | ir_link_new_instruction(cast_instruction, &call_instruction->base); |
| 2395 | 2466 | return cast_instruction->type_entry; |
| 2467 | } else if (fn_ref->type_entry->id == TypeTableEntryIdFn) { |
| 2468 | // TODO fully port over the fn call analyze code to IR |
| 2469 | FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_fn; |
| 2470 | |
| 2471 | ir_build_call_from(&ira->new_irb, &call_instruction->base, |
| 2472 | call_instruction->fn, call_instruction->arg_count, call_instruction->args); |
| 2473 | return fn_table_entry->type_entry; |
| 2396 | 2474 | } else { |
| 2397 | 2475 | zig_panic("TODO analyze more fn call types"); |
| 2398 | 2476 | } |
| ... | ... | @@ -3777,9 +3855,15 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 3777 | 3855 | |
| 3778 | 3856 | static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) { |
| 3779 | 3857 | IrBasicBlock *old_dest_block = br_instruction->dest_block; |
| 3780 | | IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block); |
| 3781 | | ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb); |
| 3858 | |
| 3859 | // TODO detect backward jumps |
| 3860 | |
| 3861 | ir_inline_bb(ira, old_dest_block); |
| 3782 | 3862 | return ira->codegen->builtin_types.entry_unreachable; |
| 3863 | |
| 3864 | //IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block); |
| 3865 | //ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb); |
| 3866 | //return ira->codegen->builtin_types.entry_unreachable; |
| 3783 | 3867 | } |
| 3784 | 3868 | |
| 3785 | 3869 | static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { |
| ... | ... | @@ -3787,26 +3871,20 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct |
| 3787 | 3871 | IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type); |
| 3788 | 3872 | if (condition == ira->codegen->invalid_instruction) |
| 3789 | 3873 | return ira->codegen->builtin_types.entry_invalid; |
| 3790 | | |
| 3874 | |
| 3875 | // TODO detect backward jumps |
| 3791 | 3876 | if (condition->static_value.ok) { |
| 3792 | | IrBasicBlock *old_dest_block; |
| 3793 | | IrBasicBlock *old_ignored_block; |
| 3794 | | if (condition->static_value.data.x_bool) { |
| 3795 | | old_dest_block = cond_br_instruction->then_block; |
| 3796 | | old_ignored_block = cond_br_instruction->else_block; |
| 3797 | | } else { |
| 3798 | | old_dest_block = cond_br_instruction->else_block; |
| 3799 | | old_ignored_block = cond_br_instruction->then_block; |
| 3800 | | } |
| 3801 | | ir_unref_bb(old_ignored_block); |
| 3802 | | IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block); |
| 3803 | | ir_build_br_from(&ira->new_irb, &cond_br_instruction->base, new_bb); |
| 3877 | IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ? |
| 3878 | cond_br_instruction->then_block : cond_br_instruction->else_block; |
| 3879 | |
| 3880 | ir_inline_bb(ira, old_dest_block); |
| 3804 | 3881 | return ira->codegen->builtin_types.entry_unreachable; |
| 3805 | 3882 | } |
| 3806 | 3883 | |
| 3807 | 3884 | IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block); |
| 3808 | 3885 | IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block); |
| 3809 | 3886 | ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block); |
| 3887 | ir_finish_bb(ira); |
| 3810 | 3888 | return ira->codegen->builtin_types.entry_unreachable; |
| 3811 | 3889 | } |
| 3812 | 3890 | |
| ... | ... | @@ -3862,7 +3940,9 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira, |
| 3862 | 3940 | static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira, |
| 3863 | 3941 | IrInstructionUnreachable *unreachable_instruction) |
| 3864 | 3942 | { |
| 3865 | | return ir_build_unreachable_from(&ira->new_irb, &unreachable_instruction->base)->type_entry; |
| 3943 | IrInstruction *new_instruction = ir_build_unreachable_from(&ira->new_irb, &unreachable_instruction->base); |
| 3944 | ir_finish_bb(ira); |
| 3945 | return new_instruction->type_entry; |
| 3866 | 3946 | } |
| 3867 | 3947 | |
| 3868 | 3948 | static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) { |
| ... | ... | @@ -3889,7 +3969,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 3889 | 3969 | return first_value->type_entry; |
| 3890 | 3970 | } |
| 3891 | 3971 | |
| 3892 | | TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &phi_instruction->base, |
| 3972 | TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node, |
| 3893 | 3973 | new_incoming_values.items, new_incoming_values.length); |
| 3894 | 3974 | if (resolved_type->id == TypeTableEntryIdInvalid) |
| 3895 | 3975 | return resolved_type; |
| ... | ... | @@ -4014,8 +4094,6 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins |
| 4014 | 4094 | { |
| 4015 | 4095 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); |
| 4016 | 4096 | instruction->type_entry = instruction_type; |
| 4017 | | if (instruction->other) |
| 4018 | | instruction->other->type_entry = instruction_type; |
| 4019 | 4097 | |
| 4020 | 4098 | IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type); |
| 4021 | 4099 | return casted_instruction->type_entry; |
| ... | ... | @@ -4024,11 +4102,12 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins |
| 4024 | 4102 | // This function attempts to evaluate IR code while doing type checking and other analysis. |
| 4025 | 4103 | // It emits a new IrExecutable which is partially evaluated IR code. |
| 4026 | 4104 | TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec, |
| 4027 | | TypeTableEntry *expected_type) |
| 4105 | TypeTableEntry *expected_type, AstNode *expected_type_source_node) |
| 4028 | 4106 | { |
| 4029 | 4107 | IrAnalyze ir_analyze_data = {}; |
| 4030 | 4108 | IrAnalyze *ira = &ir_analyze_data; |
| 4031 | 4109 | ira->codegen = codegen; |
| 4110 | ira->explicit_return_type = expected_type; |
| 4032 | 4111 | |
| 4033 | 4112 | ira->old_irb.codegen = codegen; |
| 4034 | 4113 | ira->old_irb.exec = old_exec; |
| ... | ... | @@ -4039,34 +4118,27 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl |
| 4039 | 4118 | ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count; |
| 4040 | 4119 | ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count); |
| 4041 | 4120 | |
| 4042 | | TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void; |
| 4043 | | for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) { |
| 4044 | | ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(bb_i); |
| 4045 | | if (ira->old_irb.current_basic_block->ref_count == 0) |
| 4046 | | continue; |
| 4121 | IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0); |
| 4122 | IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb); |
| 4123 | ir_ref_bb(new_entry_bb); |
| 4124 | ira->old_irb.current_basic_block = old_entry_bb; |
| 4125 | ira->new_irb.current_basic_block = new_entry_bb; |
| 4126 | ira->block_queue_index = 0; |
| 4127 | ira->instruction_index = 0; |
| 4047 | 4128 | |
| 4048 | | ira->new_irb.current_basic_block = ir_get_new_bb(ira, ira->old_irb.current_basic_block); |
| 4129 | while (ira->block_queue_index < ira->block_queue.length) { |
| 4130 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); |
| 4131 | TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction, nullptr); |
| 4049 | 4132 | |
| 4050 | | return_type = ira->codegen->builtin_types.entry_void; |
| 4133 | // unreachable instructions do their own control flow. |
| 4134 | if (return_type->id == TypeTableEntryIdUnreachable) |
| 4135 | continue; |
| 4051 | 4136 | |
| 4052 | | for (size_t instr_i = 0; instr_i < ira->old_irb.current_basic_block->instruction_list.length; instr_i += 1) { |
| 4053 | | IrInstruction *instruction = ira->old_irb.current_basic_block->instruction_list.at(instr_i); |
| 4054 | | if (return_type->id == TypeTableEntryIdUnreachable) { |
| 4055 | | // TODO |
| 4056 | | //add_node_error(ira->codegen, first_executing_node(instruction->source_node), |
| 4057 | | // buf_sprintf("unreachable code")); |
| 4058 | | break; |
| 4059 | | } |
| 4060 | | bool is_last = (instr_i == ira->old_irb.current_basic_block->instruction_list.length - 1); |
| 4061 | | TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr; |
| 4062 | | return_type = ir_analyze_instruction(ira, instruction, passed_expected_type); |
| 4063 | | } |
| 4137 | ira->instruction_index += 1; |
| 4064 | 4138 | } |
| 4065 | 4139 | |
| 4066 | | // Give entry block a ref |
| 4067 | | ir_ref_bb(ira->new_irb.exec->basic_block_list.at(0)); |
| 4068 | | |
| 4069 | | return return_type; |
| 4140 | return ir_resolve_peer_types(ira, expected_type_source_node, ira->implicit_return_type_list.items, |
| 4141 | ira->implicit_return_type_list.length); |
| 4070 | 4142 | } |
| 4071 | 4143 | |
| 4072 | 4144 | static bool ir_builtin_call_has_side_effects(IrInstructionBuiltinCall *call_instruction) { |