| ... | ... | @@ -200,6 +200,7 @@ static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 200 | 200 | |
| 201 | 201 | template<typename T> |
| 202 | 202 | static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) { |
| 203 | assert(source_node); |
| 203 | 204 | T *special_instruction = ir_create_instruction<T>(irb->exec, source_node); |
| 204 | 205 | ir_instruction_append(irb->current_basic_block, &special_instruction->base); |
| 205 | 206 | return special_instruction; |
| ... | ... | @@ -220,7 +221,7 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInst |
| 220 | 221 | } |
| 221 | 222 | |
| 222 | 223 | static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrInstruction *condition, |
| 223 | | IrBasicBlock *then_block, IrBasicBlock *else_block) |
| 224 | IrBasicBlock *then_block, IrBasicBlock *else_block, bool is_inline) |
| 224 | 225 | { |
| 225 | 226 | IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, source_node); |
| 226 | 227 | cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable; |
| ... | ... | @@ -228,6 +229,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI |
| 228 | 229 | cond_br_instruction->condition = condition; |
| 229 | 230 | cond_br_instruction->then_block = then_block; |
| 230 | 231 | cond_br_instruction->else_block = else_block; |
| 232 | cond_br_instruction->is_inline = is_inline; |
| 231 | 233 | |
| 232 | 234 | ir_ref_instruction(condition); |
| 233 | 235 | ir_ref_bb(then_block); |
| ... | ... | @@ -237,10 +239,10 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI |
| 237 | 239 | } |
| 238 | 240 | |
| 239 | 241 | static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 240 | | IrInstruction *condition, IrBasicBlock *then_block, IrBasicBlock *else_block) |
| 242 | IrInstruction *condition, IrBasicBlock *then_block, IrBasicBlock *else_block, bool is_inline) |
| 241 | 243 | { |
| 242 | 244 | IrInstruction *new_instruction = ir_build_cond_br(irb, old_instruction->source_node, |
| 243 | | condition, then_block, else_block); |
| 245 | condition, then_block, else_block, is_inline); |
| 244 | 246 | ir_link_new_instruction(new_instruction, old_instruction); |
| 245 | 247 | return new_instruction; |
| 246 | 248 | } |
| ... | ... | @@ -517,22 +519,23 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr |
| 517 | 519 | return new_instruction; |
| 518 | 520 | } |
| 519 | 521 | |
| 520 | | static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block) { |
| 522 | static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block, bool is_inline) { |
| 521 | 523 | IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node); |
| 522 | 524 | br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable; |
| 523 | 525 | br_instruction->base.static_value.ok = true; |
| 524 | 526 | br_instruction->dest_block = dest_block; |
| 527 | br_instruction->is_inline = is_inline; |
| 525 | 528 | |
| 526 | 529 | ir_ref_bb(dest_block); |
| 527 | 530 | |
| 528 | 531 | return &br_instruction->base; |
| 529 | 532 | } |
| 530 | 533 | |
| 531 | | //static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) { |
| 532 | | // IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block); |
| 533 | | // ir_link_new_instruction(new_instruction, old_instruction); |
| 534 | | // return new_instruction; |
| 535 | | //} |
| 534 | static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) { |
| 535 | IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block, false); |
| 536 | ir_link_new_instruction(new_instruction, old_instruction); |
| 537 | return new_instruction; |
| 538 | } |
| 536 | 539 | |
| 537 | 540 | static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) { |
| 538 | 541 | IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node); |
| ... | ... | @@ -634,7 +637,7 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node, |
| 634 | 637 | decl_var_instruction->var_type = var_type; |
| 635 | 638 | decl_var_instruction->init_value = init_value; |
| 636 | 639 | |
| 637 | | ir_ref_instruction(var_type); |
| 640 | if (var_type) ir_ref_instruction(var_type); |
| 638 | 641 | ir_ref_instruction(init_value); |
| 639 | 642 | |
| 640 | 643 | return &decl_var_instruction->base; |
| ... | ... | @@ -775,13 +778,14 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) { |
| 775 | 778 | } |
| 776 | 779 | |
| 777 | 780 | static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockContext *scope, |
| 778 | | Buf *name, bool is_const, bool is_shadowable) |
| 781 | Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline) |
| 779 | 782 | { |
| 780 | 783 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); |
| 781 | 784 | variable_entry->block_context = scope; |
| 782 | 785 | variable_entry->import = node->owner; |
| 783 | 786 | variable_entry->shadowable = is_shadowable; |
| 784 | 787 | variable_entry->mem_slot_index = SIZE_MAX; |
| 788 | variable_entry->is_inline = is_inline; |
| 785 | 789 | |
| 786 | 790 | if (name) { |
| 787 | 791 | buf_init_from_buf(&variable_entry->name, name); |
| ... | ... | @@ -817,7 +821,8 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockC |
| 817 | 821 | buf_init_from_str(&variable_entry->name, "_anon"); |
| 818 | 822 | } |
| 819 | 823 | |
| 820 | | variable_entry->is_const = is_const; |
| 824 | variable_entry->src_is_const = src_is_const; |
| 825 | variable_entry->gen_is_const = gen_is_const; |
| 821 | 826 | variable_entry->decl_node = node; |
| 822 | 827 | |
| 823 | 828 | return variable_entry; |
| ... | ... | @@ -825,10 +830,12 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockC |
| 825 | 830 | |
| 826 | 831 | // Set name to nullptr to make the variable anonymous (not visible to programmer). |
| 827 | 832 | static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, BlockContext *scope, Buf *name, |
| 828 | | bool is_const, bool is_shadowable) |
| 833 | bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline) |
| 829 | 834 | { |
| 830 | | VariableTableEntry *var = add_local_var(irb->codegen, node, scope, name, is_const, is_shadowable); |
| 831 | | var->mem_slot_index = exec_next_mem_slot(irb->exec); |
| 835 | VariableTableEntry *var = add_local_var(irb->codegen, node, scope, name, |
| 836 | src_is_const, gen_is_const, is_shadowable, is_inline); |
| 837 | if (is_inline || gen_is_const) |
| 838 | var->mem_slot_index = exec_next_mem_slot(irb->exec); |
| 832 | 839 | return var; |
| 833 | 840 | } |
| 834 | 841 | |
| ... | ... | @@ -1189,14 +1196,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { |
| 1189 | 1196 | IrBasicBlock *else_block = ir_build_basic_block(irb, "Else"); |
| 1190 | 1197 | IrBasicBlock *endif_block = ir_build_basic_block(irb, "EndIf"); |
| 1191 | 1198 | |
| 1192 | | ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block); |
| 1199 | ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block, false); |
| 1193 | 1200 | |
| 1194 | 1201 | ir_set_cursor_at_end(irb, then_block); |
| 1195 | 1202 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, node->block_context); |
| 1196 | 1203 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 1197 | 1204 | return then_expr_result; |
| 1198 | 1205 | IrBasicBlock *after_then_block = irb->current_basic_block; |
| 1199 | | ir_build_br(irb, node, endif_block); |
| 1206 | ir_build_br(irb, node, endif_block, false); |
| 1200 | 1207 | |
| 1201 | 1208 | ir_set_cursor_at_end(irb, else_block); |
| 1202 | 1209 | IrInstruction *else_expr_result; |
| ... | ... | @@ -1208,7 +1215,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { |
| 1208 | 1215 | else_expr_result = ir_build_const_void(irb, node); |
| 1209 | 1216 | } |
| 1210 | 1217 | IrBasicBlock *after_else_block = irb->current_basic_block; |
| 1211 | | ir_build_br(irb, node, endif_block); |
| 1218 | ir_build_br(irb, node, endif_block, false); |
| 1212 | 1219 | |
| 1213 | 1220 | ir_set_cursor_at_end(irb, endif_block); |
| 1214 | 1221 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); |
| ... | ... | @@ -1333,8 +1340,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) { |
| 1333 | 1340 | bool is_shadowable = false; |
| 1334 | 1341 | bool is_const = variable_declaration->is_const; |
| 1335 | 1342 | bool is_extern = variable_declaration->is_extern; |
| 1343 | bool is_inline = variable_declaration->is_inline; |
| 1336 | 1344 | VariableTableEntry *var = ir_add_local_var(irb, node, node->block_context, |
| 1337 | | variable_declaration->symbol, is_const, is_shadowable); |
| 1345 | variable_declaration->symbol, is_const, is_const, is_shadowable, is_inline); |
| 1338 | 1346 | |
| 1339 | 1347 | if (!is_extern && !variable_declaration->expr) { |
| 1340 | 1348 | var->type = irb->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -1356,18 +1364,18 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) { |
| 1356 | 1364 | ir_build_basic_block(irb, "WhileContinue") : cond_block; |
| 1357 | 1365 | IrBasicBlock *end_block = ir_build_basic_block(irb, "WhileEnd"); |
| 1358 | 1366 | |
| 1359 | | ir_build_br(irb, node, cond_block); |
| 1367 | bool is_inline = node->data.while_expr.is_inline; |
| 1368 | ir_build_br(irb, node, cond_block, is_inline); |
| 1360 | 1369 | |
| 1361 | 1370 | if (continue_expr_node) { |
| 1362 | 1371 | ir_set_cursor_at_end(irb, continue_block); |
| 1363 | 1372 | ir_gen_node(irb, continue_expr_node, node->block_context); |
| 1364 | | ir_build_br(irb, node, cond_block); |
| 1365 | | |
| 1373 | ir_build_br(irb, node, cond_block, is_inline); |
| 1366 | 1374 | } |
| 1367 | 1375 | |
| 1368 | 1376 | ir_set_cursor_at_end(irb, cond_block); |
| 1369 | 1377 | IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, node->block_context); |
| 1370 | | ir_build_cond_br(irb, node->data.while_expr.condition, cond_val, body_block, end_block); |
| 1378 | ir_build_cond_br(irb, node->data.while_expr.condition, cond_val, body_block, end_block, is_inline); |
| 1371 | 1379 | |
| 1372 | 1380 | ir_set_cursor_at_end(irb, body_block); |
| 1373 | 1381 | |
| ... | ... | @@ -1377,7 +1385,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) { |
| 1377 | 1385 | irb->break_block_stack.pop(); |
| 1378 | 1386 | irb->continue_block_stack.pop(); |
| 1379 | 1387 | |
| 1380 | | ir_build_br(irb, node, continue_block); |
| 1388 | ir_build_br(irb, node, continue_block, is_inline); |
| 1381 | 1389 | ir_set_cursor_at_end(irb, end_block); |
| 1382 | 1390 | |
| 1383 | 1391 | return ir_build_const_void(irb, node); |
| ... | ... | @@ -1411,30 +1419,36 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { |
| 1411 | 1419 | } else { |
| 1412 | 1420 | elem_var_type = ir_build_ptr_type_child(irb, elem_node, pointer_type); |
| 1413 | 1421 | } |
| 1422 | bool is_inline = node->data.for_expr.is_inline; |
| 1414 | 1423 | |
| 1415 | 1424 | BlockContext *child_scope = new_block_context(node, parent_scope); |
| 1416 | 1425 | child_scope->parent_loop_node = node; |
| 1417 | 1426 | elem_node->block_context = child_scope; |
| 1418 | 1427 | |
| 1419 | 1428 | // TODO make it an error to write to element variable or i variable. |
| 1420 | | |
| 1421 | 1429 | Buf *elem_var_name = elem_node->data.symbol_expr.symbol; |
| 1422 | | node->data.for_expr.elem_var = ir_add_local_var(irb, elem_node, child_scope, elem_var_name, false, false); |
| 1430 | node->data.for_expr.elem_var = ir_add_local_var(irb, elem_node, child_scope, elem_var_name, |
| 1431 | true, false, false, is_inline); |
| 1423 | 1432 | IrInstruction *undefined_value = ir_build_const_undefined(irb, elem_node); |
| 1424 | 1433 | ir_build_var_decl(irb, elem_node, node->data.for_expr.elem_var, elem_var_type, undefined_value); |
| 1425 | 1434 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.elem_var); |
| 1426 | 1435 | |
| 1436 | AstNode *index_var_source_node; |
| 1427 | 1437 | if (index_node) { |
| 1438 | index_var_source_node = index_node; |
| 1428 | 1439 | Buf *index_var_name = index_node->data.symbol_expr.symbol; |
| 1429 | 1440 | index_node->block_context = child_scope; |
| 1430 | | node->data.for_expr.index_var = ir_add_local_var(irb, index_node, child_scope, index_var_name, false, false); |
| 1441 | node->data.for_expr.index_var = ir_add_local_var(irb, index_node, child_scope, index_var_name, |
| 1442 | true, false, false, is_inline); |
| 1431 | 1443 | } else { |
| 1432 | | node->data.for_expr.index_var = ir_add_local_var(irb, node, child_scope, nullptr, false, true); |
| 1444 | index_var_source_node = node; |
| 1445 | node->data.for_expr.index_var = ir_add_local_var(irb, node, child_scope, nullptr, |
| 1446 | true, false, true, is_inline); |
| 1433 | 1447 | } |
| 1434 | 1448 | IrInstruction *usize = ir_build_const_type(irb, node, irb->codegen->builtin_types.entry_usize); |
| 1435 | 1449 | IrInstruction *zero = ir_build_const_usize(irb, node, 0); |
| 1436 | 1450 | IrInstruction *one = ir_build_const_usize(irb, node, 1); |
| 1437 | | ir_build_var_decl(irb, index_node, node->data.for_expr.index_var, usize, zero); |
| 1451 | ir_build_var_decl(irb, index_var_source_node, node->data.for_expr.index_var, usize, zero); |
| 1438 | 1452 | IrInstruction *index_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.index_var); |
| 1439 | 1453 | |
| 1440 | 1454 | |
| ... | ... | @@ -1444,12 +1458,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { |
| 1444 | 1458 | IrBasicBlock *continue_block = ir_build_basic_block(irb, "ForContinue"); |
| 1445 | 1459 | |
| 1446 | 1460 | IrInstruction *len_val = ir_build_read_field(irb, node, array_val, irb->codegen->len_buf); |
| 1447 | | ir_build_br(irb, node, cond_block); |
| 1461 | ir_build_br(irb, node, cond_block, is_inline); |
| 1448 | 1462 | |
| 1449 | 1463 | ir_set_cursor_at_end(irb, cond_block); |
| 1450 | 1464 | IrInstruction *index_val = ir_build_load_ptr(irb, node, index_ptr); |
| 1451 | 1465 | IrInstruction *cond = ir_build_bin_op(irb, node, IrBinOpCmpLessThan, index_val, len_val); |
| 1452 | | ir_build_cond_br(irb, node, cond, body_block, end_block); |
| 1466 | ir_build_cond_br(irb, node, cond, body_block, end_block, is_inline); |
| 1453 | 1467 | |
| 1454 | 1468 | ir_set_cursor_at_end(irb, body_block); |
| 1455 | 1469 | IrInstruction *elem_ptr = ir_build_elem_ptr(irb, node, array_val, index_val); |
| ... | ... | @@ -1467,12 +1481,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { |
| 1467 | 1481 | irb->break_block_stack.pop(); |
| 1468 | 1482 | irb->continue_block_stack.pop(); |
| 1469 | 1483 | |
| 1470 | | ir_build_br(irb, node, continue_block); |
| 1484 | ir_build_br(irb, node, continue_block, is_inline); |
| 1471 | 1485 | |
| 1472 | 1486 | ir_set_cursor_at_end(irb, continue_block); |
| 1473 | 1487 | IrInstruction *new_index_val = ir_build_bin_op(irb, node, IrBinOpAdd, index_val, one); |
| 1474 | 1488 | ir_build_store_ptr(irb, node, index_ptr, new_index_val); |
| 1475 | | ir_build_br(irb, node, cond_block); |
| 1489 | ir_build_br(irb, node, cond_block, is_inline); |
| 1476 | 1490 | |
| 1477 | 1491 | ir_set_cursor_at_end(irb, end_block); |
| 1478 | 1492 | return ir_build_const_void(irb, node); |
| ... | ... | @@ -1911,23 +1925,41 @@ static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { |
| 1911 | 1925 | } |
| 1912 | 1926 | |
| 1913 | 1927 | |
| 1914 | | static ConstExprValue *ir_get_out_val(IrInstruction *instruction) { |
| 1915 | | instruction->other = instruction; |
| 1916 | | return &instruction->static_value; |
| 1928 | static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_instruction, |
| 1929 | bool depends_on_compile_var) |
| 1930 | { |
| 1931 | IrInstruction *new_instruction; |
| 1932 | if (old_instruction->id == IrInstructionIdVarPtr) { |
| 1933 | IrInstructionVarPtr *old_var_ptr_instruction = (IrInstructionVarPtr *)old_instruction; |
| 1934 | IrInstructionVarPtr *var_ptr_instruction = ir_create_instruction<IrInstructionVarPtr>(ira->new_irb.exec, |
| 1935 | old_instruction->source_node); |
| 1936 | var_ptr_instruction->var = old_var_ptr_instruction->var; |
| 1937 | new_instruction = &var_ptr_instruction->base; |
| 1938 | } else if (old_instruction->id == IrInstructionIdFieldPtr) { |
| 1939 | zig_panic("TODO"); |
| 1940 | } else if (old_instruction->id == IrInstructionIdElemPtr) { |
| 1941 | zig_panic("TODO"); |
| 1942 | } else { |
| 1943 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec, |
| 1944 | old_instruction->source_node); |
| 1945 | new_instruction = &const_instruction->base; |
| 1946 | } |
| 1947 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1948 | ConstExprValue *const_val = &new_instruction->static_value; |
| 1949 | const_val->ok = true; |
| 1950 | const_val->depends_on_compile_var = depends_on_compile_var; |
| 1951 | return const_val; |
| 1917 | 1952 | } |
| 1918 | 1953 | |
| 1919 | 1954 | static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instruction) { |
| 1920 | | ConstExprValue *const_val = ir_get_out_val(instruction); |
| 1921 | | const_val->ok = true; |
| 1955 | ir_build_const_from(ira, instruction, false); |
| 1922 | 1956 | return ira->codegen->builtin_types.entry_void; |
| 1923 | 1957 | } |
| 1924 | 1958 | |
| 1925 | 1959 | static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value, |
| 1926 | 1960 | bool depends_on_compile_var) |
| 1927 | 1961 | { |
| 1928 | | ConstExprValue *const_val = ir_get_out_val(instruction); |
| 1929 | | const_val->ok = true; |
| 1930 | | const_val->depends_on_compile_var = depends_on_compile_var; |
| 1962 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, depends_on_compile_var); |
| 1931 | 1963 | bignum_init_unsigned(&const_val->data.x_bignum, value); |
| 1932 | 1964 | return ira->codegen->builtin_types.entry_usize; |
| 1933 | 1965 | } |
| ... | ... | @@ -2295,7 +2327,8 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 2295 | 2327 | ConstExprValue *op1_val = &casted_op1->static_value; |
| 2296 | 2328 | ConstExprValue *op2_val = &casted_op2->static_value; |
| 2297 | 2329 | if (op1_val->ok && op2_val->ok) { |
| 2298 | | ConstExprValue *out_val = ir_get_out_val(&bin_op_instruction->base); |
| 2330 | bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; |
| 2331 | ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var); |
| 2299 | 2332 | |
| 2300 | 2333 | assert(op1->type_entry->id == TypeTableEntryIdBool); |
| 2301 | 2334 | assert(op2->type_entry->id == TypeTableEntryIdBool); |
| ... | ... | @@ -2306,14 +2339,10 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 2306 | 2339 | } else { |
| 2307 | 2340 | zig_unreachable(); |
| 2308 | 2341 | } |
| 2309 | | out_val->ok = true; |
| 2310 | | out_val->depends_on_compile_var = op1_val->depends_on_compile_var || |
| 2311 | | op2_val->depends_on_compile_var; |
| 2312 | 2342 | return bool_type; |
| 2313 | 2343 | } |
| 2314 | 2344 | |
| 2315 | 2345 | ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id, op1->other, op2->other); |
| 2316 | | |
| 2317 | 2346 | return bool_type; |
| 2318 | 2347 | } |
| 2319 | 2348 | |
| ... | ... | @@ -2425,9 +2454,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 2425 | 2454 | } |
| 2426 | 2455 | } |
| 2427 | 2456 | |
| 2428 | | ConstExprValue *out_val = ir_get_out_val(&bin_op_instruction->base); |
| 2429 | | out_val->ok = true; |
| 2430 | | out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; |
| 2457 | bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; |
| 2458 | ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var); |
| 2431 | 2459 | out_val->data.x_bool = answer; |
| 2432 | 2460 | return ira->codegen->builtin_types.entry_bool; |
| 2433 | 2461 | } |
| ... | ... | @@ -4108,12 +4136,15 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr |
| 4108 | 4136 | |
| 4109 | 4137 | // TODO detect backward jumps |
| 4110 | 4138 | |
| 4111 | | ir_inline_bb(ira, old_dest_block); |
| 4112 | | return ira->codegen->builtin_types.entry_unreachable; |
| 4139 | if (br_instruction->is_inline || old_dest_block->ref_count == 1) { |
| 4140 | ir_inline_bb(ira, old_dest_block); |
| 4141 | return ira->codegen->builtin_types.entry_unreachable; |
| 4142 | } |
| 4113 | 4143 | |
| 4114 | | //IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block); |
| 4115 | | //ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb); |
| 4116 | | //return ira->codegen->builtin_types.entry_unreachable; |
| 4144 | IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block); |
| 4145 | ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb); |
| 4146 | ir_finish_bb(ira); |
| 4147 | return ira->codegen->builtin_types.entry_unreachable; |
| 4117 | 4148 | } |
| 4118 | 4149 | |
| 4119 | 4150 | static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { |
| ... | ... | @@ -4129,13 +4160,20 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct |
| 4129 | 4160 | IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ? |
| 4130 | 4161 | cond_br_instruction->then_block : cond_br_instruction->else_block; |
| 4131 | 4162 | |
| 4132 | | ir_inline_bb(ira, old_dest_block); |
| 4163 | if (cond_br_instruction->is_inline || old_dest_block->ref_count == 1) { |
| 4164 | ir_inline_bb(ira, old_dest_block); |
| 4165 | return ira->codegen->builtin_types.entry_unreachable; |
| 4166 | } |
| 4167 | } else if (cond_br_instruction->is_inline) { |
| 4168 | add_node_error(ira->codegen, condition->source_node, |
| 4169 | buf_sprintf("unable to evaluate constant expression")); |
| 4170 | ir_finish_bb(ira); |
| 4133 | 4171 | return ira->codegen->builtin_types.entry_unreachable; |
| 4134 | 4172 | } |
| 4135 | 4173 | |
| 4136 | 4174 | IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block); |
| 4137 | 4175 | IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block); |
| 4138 | | ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block); |
| 4176 | ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block, false); |
| 4139 | 4177 | ir_finish_bb(ira); |
| 4140 | 4178 | return ira->codegen->builtin_types.entry_unreachable; |
| 4141 | 4179 | } |
| ... | ... | @@ -4206,7 +4244,8 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 4206 | 4244 | IrInstruction *value = phi_instruction->incoming_values[i]->other; |
| 4207 | 4245 | assert(value->type_entry); |
| 4208 | 4246 | if (value->static_value.ok) { |
| 4209 | | ConstExprValue *out_val = ir_get_out_val(&phi_instruction->base); |
| 4247 | ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base, |
| 4248 | value->static_value.depends_on_compile_var); |
| 4210 | 4249 | *out_val = value->static_value; |
| 4211 | 4250 | } else { |
| 4212 | 4251 | phi_instruction->base.other = value; |
| ... | ... | @@ -4259,9 +4298,9 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct |
| 4259 | 4298 | if (var->mem_slot_index != SIZE_MAX) { |
| 4260 | 4299 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| 4261 | 4300 | if (mem_slot->ok) { |
| 4262 | | ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base); |
| 4301 | ConstExprValue *out_val = ir_build_const_from(ira, &var_ptr_instruction->base, |
| 4302 | mem_slot->depends_on_compile_var); |
| 4263 | 4303 | |
| 4264 | | out_val->ok = true; |
| 4265 | 4304 | out_val->data.x_ptr.len = 1; |
| 4266 | 4305 | out_val->data.x_ptr.is_c_str = false; |
| 4267 | 4306 | out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1); |
| ... | ... | @@ -4477,7 +4516,8 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc |
| 4477 | 4516 | if (ptr->static_value.ok) { |
| 4478 | 4517 | ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0]; |
| 4479 | 4518 | if (pointee->ok) { |
| 4480 | | ConstExprValue *out_val = ir_get_out_val(&load_ptr_instruction->base); |
| 4519 | ConstExprValue *out_val = ir_build_const_from(ira, &load_ptr_instruction->base, |
| 4520 | pointee->depends_on_compile_var); |
| 4481 | 4521 | *out_val = *pointee; |
| 4482 | 4522 | return child_type; |
| 4483 | 4523 | } |
| ... | ... | @@ -4576,8 +4616,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi |
| 4576 | 4616 | case TypeTableEntryIdFn: |
| 4577 | 4617 | case TypeTableEntryIdTypeDecl: |
| 4578 | 4618 | { |
| 4579 | | ConstExprValue *out_val = ir_get_out_val(&typeof_instruction->base); |
| 4580 | | out_val->ok = true; |
| 4619 | ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base, false); |
| 4581 | 4620 | // TODO depends_on_compile_var should be set based on whether the type of the expression |
| 4582 | 4621 | // depends_on_compile_var. but we currently don't have a thing to tell us if the type of |
| 4583 | 4622 | // something depends on a compile var |
| ... | ... | @@ -4609,9 +4648,8 @@ static TypeTableEntry *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira, |
| 4609 | 4648 | return ira->codegen->builtin_types.entry_invalid; |
| 4610 | 4649 | } |
| 4611 | 4650 | |
| 4612 | | ConstExprValue *out_val = ir_get_out_val(&to_ptr_type_instruction->base); |
| 4613 | | out_val->ok = true; |
| 4614 | | out_val->depends_on_compile_var = type_value->static_value.depends_on_compile_var; |
| 4651 | ConstExprValue *out_val = ir_build_const_from(ira, &to_ptr_type_instruction->base, |
| 4652 | type_value->static_value.depends_on_compile_var); |
| 4615 | 4653 | out_val->data.x_type = ptr_type; |
| 4616 | 4654 | return ira->codegen->builtin_types.entry_type; |
| 4617 | 4655 | } |
| ... | ... | @@ -4630,9 +4668,8 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 4630 | 4668 | return ira->codegen->builtin_types.entry_invalid; |
| 4631 | 4669 | } |
| 4632 | 4670 | |
| 4633 | | ConstExprValue *out_val = ir_get_out_val(&ptr_type_child_instruction->base); |
| 4634 | | out_val->ok = true; |
| 4635 | | out_val->depends_on_compile_var = type_value->static_value.depends_on_compile_var; |
| 4671 | ConstExprValue *out_val = ir_build_const_from(ira, &ptr_type_child_instruction->base, |
| 4672 | type_value->static_value.depends_on_compile_var); |
| 4636 | 4673 | out_val->data.x_type = type_entry->data.pointer.child_type; |
| 4637 | 4674 | return ira->codegen->builtin_types.entry_type; |
| 4638 | 4675 | } |
| ... | ... | @@ -4734,10 +4771,6 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl |
| 4734 | 4771 | while (ira->block_queue_index < ira->old_bb_queue.length) { |
| 4735 | 4772 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); |
| 4736 | 4773 | |
| 4737 | | fprintf(stderr, "===%zu====", old_instruction->debug_id); |
| 4738 | | ir_print(stderr, ira->new_irb.exec, 4); |
| 4739 | | fprintf(stderr, "========"); |
| 4740 | | |
| 4741 | 4774 | if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) { |
| 4742 | 4775 | ira->instruction_index += 1; |
| 4743 | 4776 | continue; |