| ... | @@ -21,6 +21,11 @@ struct IrAnalyze { | ... | @@ -21,6 +21,11 @@ struct IrAnalyze { |
| 21 | IrBuilder old_irb; | 21 | IrBuilder old_irb; |
| 22 | IrBuilder new_irb; | 22 | IrBuilder new_irb; |
| 23 | IrExecContext exec_context; | 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 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope); | 31 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope); |
| ... | @@ -58,11 +63,6 @@ static void ir_ref_bb(IrBasicBlock *bb) { | ... | @@ -58,11 +63,6 @@ static void ir_ref_bb(IrBasicBlock *bb) { |
| 58 | bb->ref_count += 1; | 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 | static void ir_ref_instruction(IrInstruction *instruction) { | 66 | static void ir_ref_instruction(IrInstruction *instruction) { |
| 67 | instruction->ref_count += 1; | 67 | instruction->ref_count += 1; |
| 68 | } | 68 | } |
| ... | @@ -349,6 +349,14 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node, | ... | @@ -349,6 +349,14 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node, |
| 349 | return &call_instruction->base; | 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 | static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node, | 360 | static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node, |
| 353 | BuiltinFnEntry *fn, IrInstruction **args) | 361 | BuiltinFnEntry *fn, IrInstruction **args) |
| 354 | { | 362 | { |
| ... | @@ -396,11 +404,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicB | ... | @@ -396,11 +404,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicB |
| 396 | return &br_instruction->base; | 404 | return &br_instruction->base; |
| 397 | } | 405 | } |
| 398 | | 406 | |
| 399 | static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) { | 407 | //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); | 408 | // IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block); |
| 401 | ir_link_new_instruction(new_instruction, old_instruction); | 409 | // ir_link_new_instruction(new_instruction, old_instruction); |
| 402 | return new_instruction; | 410 | // return new_instruction; |
| 403 | } | 411 | //} |
| 404 | | 412 | |
| 405 | static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) { | 413 | static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) { |
| 406 | IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node); | 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,36 +1281,26 @@ static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext |
| 1273 | zig_unreachable(); | 1281 | zig_unreachable(); |
| 1274 | } | 1282 | } |
| 1275 | | 1283 | |
| 1276 | static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope, | 1284 | IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) { |
| 1277 | IrExecutable *ir_executable, bool add_return, LValPurpose lval) | | |
| 1278 | { | | |
| 1279 | assert(node->owner); | 1285 | assert(node->owner); |
| 1280 | | 1286 | |
| 1281 | IrBuilder ir_gen = {0}; | 1287 | IrBuilder ir_gen = {0}; |
| 1282 | IrBuilder *irb = &ir_gen; | 1288 | IrBuilder *irb = &ir_gen; |
| 1283 | | 1289 | |
| 1284 | irb->codegen = g; | 1290 | irb->codegen = codegen; |
| 1285 | irb->exec = ir_executable; | 1291 | irb->exec = ir_executable; |
| 1286 | | 1292 | |
| 1287 | irb->current_basic_block = ir_build_basic_block(irb, "Entry"); | 1293 | irb->current_basic_block = ir_build_basic_block(irb, "Entry"); |
| 1288 | // Entry block gets a reference because we enter it to begin. | 1294 | // Entry block gets a reference because we enter it to begin. |
| 1289 | ir_ref_bb(irb->current_basic_block); | 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 | assert(result); | 1298 | assert(result); |
| 1293 | | 1299 | |
| 1294 | if (result == g->invalid_instruction) | 1300 | if (result == codegen->invalid_instruction) |
| 1295 | return result; | 1301 | return result; |
| 1296 | | 1302 | |
| 1297 | if (add_return) | 1303 | return ir_build_return(irb, result->source_node, result); |
| 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); | | |
| 1306 | } | 1304 | } |
| 1307 | | 1305 | |
| 1308 | IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { | 1306 | IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| ... | @@ -1315,8 +1313,7 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { | ... | @@ -1315,8 +1313,7 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| 1315 | AstNode *body_node = fn_def_node->data.fn_def.body; | 1313 | AstNode *body_node = fn_def_node->data.fn_def.body; |
| 1316 | BlockContext *scope = fn_def_node->data.fn_def.block_context; | 1314 | BlockContext *scope = fn_def_node->data.fn_def.block_context; |
| 1317 | | 1315 | |
| 1318 | bool add_return_yes = true; | 1316 | return ir_gen(codegn, body_node, scope, ir_executable); |
| 1319 | return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, LValPurposeNone); | | |
| 1320 | } | 1317 | } |
| 1321 | | 1318 | |
| 1322 | /* | 1319 | /* |
| ... | @@ -1401,7 +1398,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -1401,7 +1398,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc |
| 1401 | return false; | 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 | IrInstruction **instructions, size_t instruction_count) | 1402 | IrInstruction **instructions, size_t instruction_count) |
| 1406 | { | 1403 | { |
| 1407 | assert(instruction_count >= 1); | 1404 | assert(instruction_count >= 1); |
| ... | @@ -1465,7 +1462,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa | ... | @@ -1465,7 +1462,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa |
| 1465 | return ira->codegen->builtin_types.entry_invalid; | 1462 | return ira->codegen->builtin_types.entry_invalid; |
| 1466 | } | 1463 | } |
| 1467 | } else { | 1464 | } else { |
| 1468 | add_node_error(ira->codegen, parent_instruction->source_node, | 1465 | add_node_error(ira->codegen, source_node, |
| 1469 | buf_sprintf("incompatible types: '%s' and '%s'", | 1466 | buf_sprintf("incompatible types: '%s' and '%s'", |
| 1470 | buf_ptr(&prev_type->name), buf_ptr(&cur_type->name))); | 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,10 +1563,10 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 1566 | return ImplicitCastMatchResultNo; | 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 | IrInstruction **instructions, size_t instruction_count) | 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 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | 1572 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| ... | @@ -1608,9 +1605,29 @@ static bool is_u8(TypeTableEntry *type) { | ... | @@ -1608,9 +1605,29 @@ static bool is_u8(TypeTableEntry *type) { |
| 1608 | static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { | 1605 | static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { |
| 1609 | if (old_bb->other) | 1606 | if (old_bb->other) |
| 1610 | return old_bb->other; | 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 | static ConstExprValue *ir_get_out_val(IrInstruction *instruction) { | 1631 | static ConstExprValue *ir_get_out_val(IrInstruction *instruction) { |
| 1615 | instruction->other = instruction; | 1632 | instruction->other = instruction; |
| 1616 | return &instruction->static_value; | 1633 | return &instruction->static_value; |
| ... | @@ -1942,8 +1959,11 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi | ... | @@ -1942,8 +1959,11 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi |
| 1942 | if (value == ira->codegen->invalid_instruction) { | 1959 | if (value == ira->codegen->invalid_instruction) { |
| 1943 | return ira->codegen->builtin_types.entry_invalid; | 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 | static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) { | 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,10 +2011,10 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 1991 | } | 2011 | } |
| 1992 | | 2012 | |
| 1993 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { | 2013 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 1994 | IrInstruction *op1 = bin_op_instruction->op1; | 2014 | IrInstruction *op1 = bin_op_instruction->op1->other; |
| 1995 | IrInstruction *op2 = bin_op_instruction->op2; | 2015 | IrInstruction *op2 = bin_op_instruction->op2->other; |
| 1996 | IrInstruction *instructions[] = {op1, op2}; | 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 | if (resolved_type->id == TypeTableEntryIdInvalid) | 2018 | if (resolved_type->id == TypeTableEntryIdInvalid) |
| 1999 | return resolved_type; | 2019 | return resolved_type; |
| 2000 | IrBinOp op_id = bin_op_instruction->op_id; | 2020 | IrBinOp op_id = bin_op_instruction->op_id; |
| ... | @@ -2052,9 +2072,60 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -2052,9 +2072,60 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 2052 | zig_unreachable(); | 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 | return ira->codegen->builtin_types.entry_bool; | 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,7 +2229,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 2158 | IrInstruction *op1 = bin_op_instruction->op1->other; | 2229 | IrInstruction *op1 = bin_op_instruction->op1->other; |
| 2159 | IrInstruction *op2 = bin_op_instruction->op2->other; | 2230 | IrInstruction *op2 = bin_op_instruction->op2->other; |
| 2160 | IrInstruction *instructions[] = {op1, op2}; | 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 | if (resolved_type->id == TypeTableEntryIdInvalid) | 2233 | if (resolved_type->id == TypeTableEntryIdInvalid) |
| 2163 | return resolved_type; | 2234 | return resolved_type; |
| 2164 | IrBinOp op_id = bin_op_instruction->op_id; | 2235 | IrBinOp op_id = bin_op_instruction->op_id; |
| ... | @@ -2393,6 +2464,13 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction | ... | @@ -2393,6 +2464,13 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction |
| 2393 | | 2464 | |
| 2394 | ir_link_new_instruction(cast_instruction, &call_instruction->base); | 2465 | ir_link_new_instruction(cast_instruction, &call_instruction->base); |
| 2395 | return cast_instruction->type_entry; | 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 | } else { | 2474 | } else { |
| 2397 | zig_panic("TODO analyze more fn call types"); | 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,9 +3855,15 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 3777 | | 3855 | |
| 3778 | static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) { | 3856 | static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) { |
| 3779 | IrBasicBlock *old_dest_block = br_instruction->dest_block; | 3857 | IrBasicBlock *old_dest_block = br_instruction->dest_block; |
| 3780 | IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block); | 3858 | |
| 3781 | ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb); | 3859 | // TODO detect backward jumps |
| | 3860 | |
| | 3861 | ir_inline_bb(ira, old_dest_block); |
| 3782 | return ira->codegen->builtin_types.entry_unreachable; | 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 | static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { | 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,26 +3871,20 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct |
| 3787 | IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type); | 3871 | IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type); |
| 3788 | if (condition == ira->codegen->invalid_instruction) | 3872 | if (condition == ira->codegen->invalid_instruction) |
| 3789 | return ira->codegen->builtin_types.entry_invalid; | 3873 | return ira->codegen->builtin_types.entry_invalid; |
| 3790 | | 3874 | |
| | 3875 | // TODO detect backward jumps |
| 3791 | if (condition->static_value.ok) { | 3876 | if (condition->static_value.ok) { |
| 3792 | IrBasicBlock *old_dest_block; | 3877 | IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ? |
| 3793 | IrBasicBlock *old_ignored_block; | 3878 | cond_br_instruction->then_block : cond_br_instruction->else_block; |
| 3794 | if (condition->static_value.data.x_bool) { | 3879 | |
| 3795 | old_dest_block = cond_br_instruction->then_block; | 3880 | ir_inline_bb(ira, old_dest_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); | | |
| 3804 | return ira->codegen->builtin_types.entry_unreachable; | 3881 | return ira->codegen->builtin_types.entry_unreachable; |
| 3805 | } | 3882 | } |
| 3806 | | 3883 | |
| 3807 | IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block); | 3884 | IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block); |
| 3808 | IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block); | 3885 | IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block); |
| 3809 | ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block); | 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 | return ira->codegen->builtin_types.entry_unreachable; | 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,7 +3940,9 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira, |
| 3862 | static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira, | 3940 | static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira, |
| 3863 | IrInstructionUnreachable *unreachable_instruction) | 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 | static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) { | 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,7 +3969,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 3889 | return first_value->type_entry; | 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 | new_incoming_values.items, new_incoming_values.length); | 3973 | new_incoming_values.items, new_incoming_values.length); |
| 3894 | if (resolved_type->id == TypeTableEntryIdInvalid) | 3974 | if (resolved_type->id == TypeTableEntryIdInvalid) |
| 3895 | return resolved_type; | 3975 | return resolved_type; |
| ... | @@ -4014,8 +4094,6 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins | ... | @@ -4014,8 +4094,6 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins |
| 4014 | { | 4094 | { |
| 4015 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); | 4095 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); |
| 4016 | instruction->type_entry = instruction_type; | 4096 | instruction->type_entry = instruction_type; |
| 4017 | if (instruction->other) | | |
| 4018 | instruction->other->type_entry = instruction_type; | | |
| 4019 | | 4097 | |
| 4020 | IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type); | 4098 | IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type); |
| 4021 | return casted_instruction->type_entry; | 4099 | return casted_instruction->type_entry; |
| ... | @@ -4024,11 +4102,12 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins | ... | @@ -4024,11 +4102,12 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins |
| 4024 | // This function attempts to evaluate IR code while doing type checking and other analysis. | 4102 | // This function attempts to evaluate IR code while doing type checking and other analysis. |
| 4025 | // It emits a new IrExecutable which is partially evaluated IR code. | 4103 | // It emits a new IrExecutable which is partially evaluated IR code. |
| 4026 | TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec, | 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 | IrAnalyze ir_analyze_data = {}; | 4107 | IrAnalyze ir_analyze_data = {}; |
| 4030 | IrAnalyze *ira = &ir_analyze_data; | 4108 | IrAnalyze *ira = &ir_analyze_data; |
| 4031 | ira->codegen = codegen; | 4109 | ira->codegen = codegen; |
| | 4110 | ira->explicit_return_type = expected_type; |
| 4032 | | 4111 | |
| 4033 | ira->old_irb.codegen = codegen; | 4112 | ira->old_irb.codegen = codegen; |
| 4034 | ira->old_irb.exec = old_exec; | 4113 | ira->old_irb.exec = old_exec; |
| ... | @@ -4039,34 +4118,27 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl | ... | @@ -4039,34 +4118,27 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl |
| 4039 | ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count; | 4118 | ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count; |
| 4040 | ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count); | 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; | 4121 | IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0); |
| 4043 | for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) { | 4122 | IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb); |
| 4044 | ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(bb_i); | 4123 | ir_ref_bb(new_entry_bb); |
| 4045 | if (ira->old_irb.current_basic_block->ref_count == 0) | 4124 | ira->old_irb.current_basic_block = old_entry_bb; |
| 4046 | continue; | 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) { | 4137 | ira->instruction_index += 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 | } | | |
| 4064 | } | 4138 | } |
| 4065 | | 4139 | |
| 4066 | // Give entry block a ref | 4140 | return ir_resolve_peer_types(ira, expected_type_source_node, ira->implicit_return_type_list.items, |
| 4067 | ir_ref_bb(ira->new_irb.exec->basic_block_list.at(0)); | 4141 | ira->implicit_return_type_list.length); |
| 4068 | | | |
| 4069 | return return_type; | | |
| 4070 | } | 4142 | } |
| 4071 | | 4143 | |
| 4072 | static bool ir_builtin_call_has_side_effects(IrInstructionBuiltinCall *call_instruction) { | 4144 | static bool ir_builtin_call_has_side_effects(IrInstructionBuiltinCall *call_instruction) { |