authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-19 00:04:51-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-19 00:04:51-05:00
log09c34352f8a87ed9597b4af0de564aa7d831761a
tree6ab441882b48c972b9dd61d0797e4671e5af341f
parent956ff8a7f98cad2f5f9b043e8a896609ea41f952

IR: if and switch guaranteed compile time if target expr is


6 files changed, 257 insertions(+), 118 deletions(-)

src/all_types.hpp+12-4
...@@ -1235,7 +1235,7 @@ struct VariableTableEntry {...@@ -1235,7 +1235,7 @@ struct VariableTableEntry {
1235 LLVMValueRef value_ref;1235 LLVMValueRef value_ref;
1236 bool src_is_const;1236 bool src_is_const;
1237 bool gen_is_const;1237 bool gen_is_const;
1238 bool is_inline;1238 IrInstruction *is_comptime;
1239 // which node is the declaration of the variable1239 // which node is the declaration of the variable
1240 AstNode *decl_node;1240 AstNode *decl_node;
1241 ZigLLVMDILocalVariable *di_loc_var;1241 ZigLLVMDILocalVariable *di_loc_var;
...@@ -1451,6 +1451,7 @@ enum IrInstructionId {...@@ -1451,6 +1451,7 @@ enum IrInstructionId {
1451 IrInstructionIdErrWrapCode,1451 IrInstructionIdErrWrapCode,
1452 IrInstructionIdErrWrapPayload,1452 IrInstructionIdErrWrapPayload,
1453 IrInstructionIdFnProto,1453 IrInstructionIdFnProto,
1454 IrInstructionIdTestComptime,
1454};1455};
14551456
1456struct IrInstruction {1457struct IrInstruction {
...@@ -1472,14 +1473,14 @@ struct IrInstructionCondBr {...@@ -1472,14 +1473,14 @@ struct IrInstructionCondBr {
1472 IrInstruction *condition;1473 IrInstruction *condition;
1473 IrBasicBlock *then_block;1474 IrBasicBlock *then_block;
1474 IrBasicBlock *else_block;1475 IrBasicBlock *else_block;
1475 bool is_inline;1476 IrInstruction *is_comptime;
1476};1477};
14771478
1478struct IrInstructionBr {1479struct IrInstructionBr {
1479 IrInstruction base;1480 IrInstruction base;
14801481
1481 IrBasicBlock *dest_block;1482 IrBasicBlock *dest_block;
1482 bool is_inline;1483 IrInstruction *is_comptime;
1483};1484};
14841485
1485struct IrInstructionSwitchBrCase {1486struct IrInstructionSwitchBrCase {
...@@ -1494,7 +1495,7 @@ struct IrInstructionSwitchBr {...@@ -1494,7 +1495,7 @@ struct IrInstructionSwitchBr {
1494 IrBasicBlock *else_block;1495 IrBasicBlock *else_block;
1495 size_t case_count;1496 size_t case_count;
1496 IrInstructionSwitchBrCase *cases;1497 IrInstructionSwitchBrCase *cases;
1497 bool is_inline;1498 IrInstruction *is_comptime;
1498};1499};
14991500
1500struct IrInstructionSwitchVar {1501struct IrInstructionSwitchVar {
...@@ -2070,6 +2071,13 @@ struct IrInstructionFnProto {...@@ -2070,6 +2071,13 @@ struct IrInstructionFnProto {
2070 IrInstruction *return_type;2071 IrInstruction *return_type;
2071};2072};
20722073
2074// true if the target value is compile time known, false otherwise
2075struct IrInstructionTestComptime {
2076 IrInstruction base;
2077
2078 IrInstruction *value;
2079};
2080
2073enum LValPurpose {2081enum LValPurpose {
2074 LValPurposeNone,2082 LValPurposeNone,
2075 LValPurposeAssign,2083 LValPurposeAssign,
src/analyze.cpp+9
...@@ -2924,3 +2924,12 @@ void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry) {...@@ -2924,3 +2924,12 @@ void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry) {
2924 resolve_union_type(g, type_entry);2924 resolve_union_type(g, type_entry);
2925 }2925 }
2926}2926}
2927
2928bool ir_get_var_is_comptime(VariableTableEntry *var) {
2929 if (!var->is_comptime)
2930 return false;
2931 if (var->is_comptime->other)
2932 return var->is_comptime->other->static_value.data.x_bool;
2933 return var->is_comptime->static_value.data.x_bool;
2934}
2935
src/analyze.hpp+1
...@@ -76,6 +76,7 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope);...@@ -76,6 +76,7 @@ FnTableEntry *scope_get_fn_if_root(Scope *scope);
76bool type_requires_comptime(TypeTableEntry *type_entry);76bool type_requires_comptime(TypeTableEntry *type_entry);
77void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry);77void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry);
78void complete_enum(CodeGen *g, TypeTableEntry *enum_type);78void complete_enum(CodeGen *g, TypeTableEntry *enum_type);
79bool ir_get_var_is_comptime(VariableTableEntry *var);
7980
80ScopeBlock *create_block_scope(AstNode *node, Scope *parent);81ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
81ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);82ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);
src/codegen.cpp+2-3
...@@ -1646,8 +1646,6 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru...@@ -1646,8 +1646,6 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru
1646}1646}
16471647
1648static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutable *executable, IrInstructionSwitchBr *instruction) {1648static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutable *executable, IrInstructionSwitchBr *instruction) {
1649 assert(!instruction->is_inline);
1650
1651 LLVMValueRef target_value = ir_llvm_value(g, instruction->target_value);1649 LLVMValueRef target_value = ir_llvm_value(g, instruction->target_value);
1652 LLVMBasicBlockRef else_block = instruction->else_block->llvm_block;1650 LLVMBasicBlockRef else_block = instruction->else_block->llvm_block;
1653 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_value, else_block, instruction->case_count);1651 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_value, else_block, instruction->case_count);
...@@ -2197,6 +2195,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2197,6 +2195,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2197 case IrInstructionIdMemberCount:2195 case IrInstructionIdMemberCount:
2198 case IrInstructionIdAlignOf:2196 case IrInstructionIdAlignOf:
2199 case IrInstructionIdFnProto:2197 case IrInstructionIdFnProto:
2198 case IrInstructionIdTestComptime:
2200 zig_unreachable();2199 zig_unreachable();
2201 case IrInstructionIdReturn:2200 case IrInstructionIdReturn:
2202 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);2201 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
...@@ -2897,7 +2896,7 @@ static void do_code_gen(CodeGen *g) {...@@ -2897,7 +2896,7 @@ static void do_code_gen(CodeGen *g) {
2897 if (!type_has_bits(var->type)) {2896 if (!type_has_bits(var->type)) {
2898 continue;2897 continue;
2899 }2898 }
2900 if (var->is_inline)2899 if (ir_get_var_is_comptime(var))
2901 continue;2900 continue;
29022901
2903 if (var->src_arg_index == SIZE_MAX) {2902 if (var->src_arg_index == SIZE_MAX) {
src/ir.cpp+203-102
...@@ -22,7 +22,7 @@ struct IrExecContext {...@@ -22,7 +22,7 @@ struct IrExecContext {
22struct LoopStackItem {22struct LoopStackItem {
23 IrBasicBlock *break_block;23 IrBasicBlock *break_block;
24 IrBasicBlock *continue_block;24 IrBasicBlock *continue_block;
25 bool is_inline;25 IrInstruction *is_comptime;
26};26};
2727
28struct IrBuilder {28struct IrBuilder {
...@@ -443,6 +443,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFnProto *) {...@@ -443,6 +443,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFnProto *) {
443 return IrInstructionIdFnProto;443 return IrInstructionIdFnProto;
444}444}
445445
446static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) {
447 return IrInstructionIdTestComptime;
448}
449
446template<typename T>450template<typename T>
447static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {451static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
448 T *special_instruction = allocate<T>(1);452 T *special_instruction = allocate<T>(1);
...@@ -475,7 +479,7 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -475,7 +479,7 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, Scope *scope, AstNode *sourc
475}479}
476480
477static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *condition,481static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *condition,
478 IrBasicBlock *then_block, IrBasicBlock *else_block, bool is_inline)482 IrBasicBlock *then_block, IrBasicBlock *else_block, IrInstruction *is_comptime)
479{483{
480 IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, scope, source_node);484 IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, scope, source_node);
481 cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;485 cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
...@@ -483,20 +487,21 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so...@@ -483,20 +487,21 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
483 cond_br_instruction->condition = condition;487 cond_br_instruction->condition = condition;
484 cond_br_instruction->then_block = then_block;488 cond_br_instruction->then_block = then_block;
485 cond_br_instruction->else_block = else_block;489 cond_br_instruction->else_block = else_block;
486 cond_br_instruction->is_inline = is_inline;490 cond_br_instruction->is_comptime = is_comptime;
487491
488 ir_ref_instruction(condition);492 ir_ref_instruction(condition);
489 ir_ref_bb(then_block);493 ir_ref_bb(then_block);
490 ir_ref_bb(else_block);494 ir_ref_bb(else_block);
495 if (is_comptime) ir_ref_instruction(is_comptime);
491496
492 return &cond_br_instruction->base;497 return &cond_br_instruction->base;
493}498}
494499
495static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_instruction,500static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_instruction,
496 IrInstruction *condition, IrBasicBlock *then_block, IrBasicBlock *else_block, bool is_inline)501 IrInstruction *condition, IrBasicBlock *then_block, IrBasicBlock *else_block, IrInstruction *is_comptime)
497{502{
498 IrInstruction *new_instruction = ir_build_cond_br(irb, old_instruction->scope, old_instruction->source_node,503 IrInstruction *new_instruction = ir_build_cond_br(irb, old_instruction->scope, old_instruction->source_node,
499 condition, then_block, else_block, is_inline);504 condition, then_block, else_block, is_comptime);
500 ir_link_new_instruction(new_instruction, old_instruction);505 ir_link_new_instruction(new_instruction, old_instruction);
501 return new_instruction;506 return new_instruction;
502}507}
...@@ -859,30 +864,30 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr...@@ -859,30 +864,30 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr
859}864}
860865
861static IrInstruction *ir_create_br(IrBuilder *irb, Scope *scope, AstNode *source_node,866static IrInstruction *ir_create_br(IrBuilder *irb, Scope *scope, AstNode *source_node,
862 IrBasicBlock *dest_block, bool is_inline)867 IrBasicBlock *dest_block, IrInstruction *is_comptime)
863{868{
864 IrInstructionBr *br_instruction = ir_create_instruction<IrInstructionBr>(irb->exec, scope, source_node);869 IrInstructionBr *br_instruction = ir_create_instruction<IrInstructionBr>(irb->exec, scope, source_node);
865 br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;870 br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
866 br_instruction->base.static_value.special = ConstValSpecialStatic;871 br_instruction->base.static_value.special = ConstValSpecialStatic;
867 br_instruction->dest_block = dest_block;872 br_instruction->dest_block = dest_block;
868 br_instruction->is_inline = is_inline;873 br_instruction->is_comptime = is_comptime;
869874
870 ir_ref_bb(dest_block);875 ir_ref_bb(dest_block);
876 if (is_comptime) ir_ref_instruction(is_comptime);
871877
872 return &br_instruction->base;878 return &br_instruction->base;
873}879}
874880
875static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_node,881static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_node,
876 IrBasicBlock *dest_block, bool is_inline)882 IrBasicBlock *dest_block, IrInstruction *is_comptime)
877{883{
878 IrInstruction *instruction = ir_create_br(irb, scope, source_node, dest_block, is_inline);884 IrInstruction *instruction = ir_create_br(irb, scope, source_node, dest_block, is_comptime);
879 ir_instruction_append(irb->current_basic_block, instruction);885 ir_instruction_append(irb->current_basic_block, instruction);
880 return instruction;886 return instruction;
881}887}
882888
883static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {889static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {
884 IrInstruction *new_instruction = ir_build_br(irb, old_instruction->scope,890 IrInstruction *new_instruction = ir_build_br(irb, old_instruction->scope, old_instruction->source_node, dest_block, nullptr);
885 old_instruction->source_node, dest_block, false);
886 ir_link_new_instruction(new_instruction, old_instruction);891 ir_link_new_instruction(new_instruction, old_instruction);
887 return new_instruction;892 return new_instruction;
888}893}
...@@ -1291,7 +1296,7 @@ static IrInstruction *ir_build_ctz_from(IrBuilder *irb, IrInstruction *old_instr...@@ -1291,7 +1296,7 @@ static IrInstruction *ir_build_ctz_from(IrBuilder *irb, IrInstruction *old_instr
1291}1296}
12921297
1293static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target_value,1298static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target_value,
1294 IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, bool is_inline)1299 IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, IrInstruction *is_comptime)
1295{1300{
1296 IrInstructionSwitchBr *instruction = ir_build_instruction<IrInstructionSwitchBr>(irb, scope, source_node);1301 IrInstructionSwitchBr *instruction = ir_build_instruction<IrInstructionSwitchBr>(irb, scope, source_node);
1297 instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;1302 instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
...@@ -1300,9 +1305,10 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *...@@ -1300,9 +1305,10 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *
1300 instruction->else_block = else_block;1305 instruction->else_block = else_block;
1301 instruction->case_count = case_count;1306 instruction->case_count = case_count;
1302 instruction->cases = cases;1307 instruction->cases = cases;
1303 instruction->is_inline = is_inline;1308 instruction->is_comptime = is_comptime;
13041309
1305 ir_ref_instruction(target_value);1310 ir_ref_instruction(target_value);
1311 if (is_comptime) ir_ref_instruction(is_comptime);
1306 ir_ref_bb(else_block);1312 ir_ref_bb(else_block);
13071313
1308 for (size_t i = 0; i < case_count; i += 1) {1314 for (size_t i = 0; i < case_count; i += 1) {
...@@ -1315,10 +1321,10 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *...@@ -1315,10 +1321,10 @@ static IrInstruction *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *
13151321
1316static IrInstruction *ir_build_switch_br_from(IrBuilder *irb, IrInstruction *old_instruction,1322static IrInstruction *ir_build_switch_br_from(IrBuilder *irb, IrInstruction *old_instruction,
1317 IrInstruction *target_value, IrBasicBlock *else_block, size_t case_count,1323 IrInstruction *target_value, IrBasicBlock *else_block, size_t case_count,
1318 IrInstructionSwitchBrCase *cases, bool is_inline)1324 IrInstructionSwitchBrCase *cases, IrInstruction *is_comptime)
1319{1325{
1320 IrInstruction *new_instruction = ir_build_switch_br(irb, old_instruction->scope, old_instruction->source_node,1326 IrInstruction *new_instruction = ir_build_switch_br(irb, old_instruction->scope, old_instruction->source_node,
1321 target_value, else_block, case_count, cases, is_inline);1327 target_value, else_block, case_count, cases, is_comptime);
1322 ir_link_new_instruction(new_instruction, old_instruction);1328 ir_link_new_instruction(new_instruction, old_instruction);
1323 return new_instruction;1329 return new_instruction;
1324}1330}
...@@ -1846,6 +1852,15 @@ static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1846,6 +1852,15 @@ static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *s
1846 return &instruction->base;1852 return &instruction->base;
1847}1853}
18481854
1855static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1856 IrInstructionTestComptime *instruction = ir_build_instruction<IrInstructionTestComptime>(irb, scope, source_node);
1857 instruction->value = value;
1858
1859 ir_ref_instruction(value);
1860
1861 return &instruction->base;
1862}
1863
1849static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {1864static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
1850 results[ReturnKindUnconditional] = 0;1865 results[ReturnKindUnconditional] = 0;
1851 results[ReturnKindError] = 0;1866 results[ReturnKindError] = 0;
...@@ -1902,7 +1917,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -1902,7 +1917,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
1902 }1917 }
19031918
1904 Scope *outer_scope = fn_entry->child_scope;1919 Scope *outer_scope = fn_entry->child_scope;
1905 bool is_inline = ir_should_inline(irb);
19061920
1907 AstNode *expr_node = node->data.return_expr.expr;1921 AstNode *expr_node = node->data.return_expr.expr;
1908 switch (node->data.return_expr.kind) {1922 switch (node->data.return_expr.kind) {
...@@ -1945,7 +1959,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -1945,7 +1959,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
19451959
1946 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn");1960 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn");
1947 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "ErrRetContinue");1961 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "ErrRetContinue");
1948 ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_inline);1962 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb));
1963 ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime);
19491964
1950 ir_set_cursor_at_end(irb, return_block);1965 ir_set_cursor_at_end(irb, return_block);
1951 ir_gen_defers_for_block(irb, scope, outer_scope, true, false);1966 ir_gen_defers_for_block(irb, scope, outer_scope, true, false);
...@@ -1969,7 +1984,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -1969,7 +1984,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
19691984
1970 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn");1985 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn");
1971 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "MaybeRetContinue");1986 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "MaybeRetContinue");
1972 ir_build_cond_br(irb, scope, node, is_nonnull_val, continue_block, return_block, is_inline);1987 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb));
1988 ir_build_cond_br(irb, scope, node, is_nonnull_val, continue_block, return_block, is_comptime);
19731989
1974 ir_set_cursor_at_end(irb, return_block);1990 ir_set_cursor_at_end(irb, return_block);
1975 ir_gen_defers_for_block(irb, scope, outer_scope, false, true);1991 ir_gen_defers_for_block(irb, scope, outer_scope, false, true);
...@@ -1988,13 +2004,13 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -1988,13 +2004,13 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
1988}2004}
19892005
1990static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope,2006static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope,
1991 Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline)2007 Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime)
1992{2008{
1993 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);2009 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
1994 variable_entry->parent_scope = parent_scope;2010 variable_entry->parent_scope = parent_scope;
1995 variable_entry->shadowable = is_shadowable;2011 variable_entry->shadowable = is_shadowable;
1996 variable_entry->mem_slot_index = SIZE_MAX;2012 variable_entry->mem_slot_index = SIZE_MAX;
1997 variable_entry->is_inline = is_inline;2013 variable_entry->is_comptime = is_comptime;
1998 variable_entry->src_arg_index = SIZE_MAX;2014 variable_entry->src_arg_index = SIZE_MAX;
19992015
2000 if (name) {2016 if (name) {
...@@ -2043,11 +2059,10 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco...@@ -2043,11 +2059,10 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco
2043// Set name to nullptr to make the variable anonymous (not visible to programmer).2059// Set name to nullptr to make the variable anonymous (not visible to programmer).
2044// After you call this function var->child_scope has the variable in scope2060// After you call this function var->child_scope has the variable in scope
2045static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *name,2061static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *name,
2046 bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline)2062 bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime)
2047{2063{
2048 VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name,2064 VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name, src_is_const, gen_is_const, is_shadowable, is_comptime);
2049 src_is_const, gen_is_const, is_shadowable, is_inline);2065 if (is_comptime != nullptr || gen_is_const)
2050 if (is_inline || gen_is_const)
2051 var->mem_slot_index = exec_next_mem_slot(irb->exec);2066 var->mem_slot_index = exec_next_mem_slot(irb->exec);
2052 assert(var->child_scope);2067 assert(var->child_scope);
2053 return var;2068 return var;
...@@ -2123,19 +2138,24 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no...@@ -2123,19 +2138,24 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no
2123static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node) {2138static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node) {
2124 assert(node->type == NodeTypeBinOpExpr);2139 assert(node->type == NodeTypeBinOpExpr);
21252140
2126 bool is_inline = ir_should_inline(irb);
2127
2128 IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope);2141 IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope);
2129 if (val1 == irb->codegen->invalid_instruction)2142 if (val1 == irb->codegen->invalid_instruction)
2130 return irb->codegen->invalid_instruction;2143 return irb->codegen->invalid_instruction;
2131 IrBasicBlock *post_val1_block = irb->current_basic_block;2144 IrBasicBlock *post_val1_block = irb->current_basic_block;
21322145
2146 IrInstruction *is_comptime;
2147 if (ir_should_inline(irb)) {
2148 is_comptime = ir_build_const_bool(irb, scope, node, true);
2149 } else {
2150 is_comptime = ir_build_test_comptime(irb, scope, node, val1);
2151 }
2152
2133 // block for when val1 == false2153 // block for when val1 == false
2134 IrBasicBlock *false_block = ir_build_basic_block(irb, scope, "BoolOrFalse");2154 IrBasicBlock *false_block = ir_build_basic_block(irb, scope, "BoolOrFalse");
2135 // block for when val1 == true (don't even evaluate the second part)2155 // block for when val1 == true (don't even evaluate the second part)
2136 IrBasicBlock *true_block = ir_build_basic_block(irb, scope, "BoolOrTrue");2156 IrBasicBlock *true_block = ir_build_basic_block(irb, scope, "BoolOrTrue");
21372157
2138 ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_inline);2158 ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime);
21392159
2140 ir_set_cursor_at_end(irb, false_block);2160 ir_set_cursor_at_end(irb, false_block);
2141 IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);2161 IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
...@@ -2143,7 +2163,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node...@@ -2143,7 +2163,7 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node
2143 return irb->codegen->invalid_instruction;2163 return irb->codegen->invalid_instruction;
2144 IrBasicBlock *post_val2_block = irb->current_basic_block;2164 IrBasicBlock *post_val2_block = irb->current_basic_block;
21452165
2146 ir_build_br(irb, scope, node, true_block, is_inline);2166 ir_build_br(irb, scope, node, true_block, is_comptime);
21472167
2148 ir_set_cursor_at_end(irb, true_block);2168 ir_set_cursor_at_end(irb, true_block);
21492169
...@@ -2160,19 +2180,24 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node...@@ -2160,19 +2180,24 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node
2160static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *node) {2180static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *node) {
2161 assert(node->type == NodeTypeBinOpExpr);2181 assert(node->type == NodeTypeBinOpExpr);
21622182
2163 bool is_inline = ir_should_inline(irb);
2164
2165 IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope);2183 IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope);
2166 if (val1 == irb->codegen->invalid_instruction)2184 if (val1 == irb->codegen->invalid_instruction)
2167 return irb->codegen->invalid_instruction;2185 return irb->codegen->invalid_instruction;
2168 IrBasicBlock *post_val1_block = irb->current_basic_block;2186 IrBasicBlock *post_val1_block = irb->current_basic_block;
21692187
2188 IrInstruction *is_comptime;
2189 if (ir_should_inline(irb)) {
2190 is_comptime = ir_build_const_bool(irb, scope, node, true);
2191 } else {
2192 is_comptime = ir_build_test_comptime(irb, scope, node, val1);
2193 }
2194
2170 // block for when val1 == true2195 // block for when val1 == true
2171 IrBasicBlock *true_block = ir_build_basic_block(irb, scope, "BoolAndTrue");2196 IrBasicBlock *true_block = ir_build_basic_block(irb, scope, "BoolAndTrue");
2172 // block for when val1 == false (don't even evaluate the second part)2197 // block for when val1 == false (don't even evaluate the second part)
2173 IrBasicBlock *false_block = ir_build_basic_block(irb, scope, "BoolAndFalse");2198 IrBasicBlock *false_block = ir_build_basic_block(irb, scope, "BoolAndFalse");
21742199
2175 ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_inline);2200 ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime);
21762201
2177 ir_set_cursor_at_end(irb, true_block);2202 ir_set_cursor_at_end(irb, true_block);
2178 IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);2203 IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope);
...@@ -2180,7 +2205,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -2180,7 +2205,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
2180 return irb->codegen->invalid_instruction;2205 return irb->codegen->invalid_instruction;
2181 IrBasicBlock *post_val2_block = irb->current_basic_block;2206 IrBasicBlock *post_val2_block = irb->current_basic_block;
21822207
2183 ir_build_br(irb, scope, node, false_block, is_inline);2208 ir_build_br(irb, scope, node, false_block, is_comptime);
21842209
2185 ir_set_cursor_at_end(irb, false_block);2210 ir_set_cursor_at_end(irb, false_block);
21862211
...@@ -2200,31 +2225,36 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As...@@ -2200,31 +2225,36 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
2200 AstNode *op1_node = node->data.bin_op_expr.op1;2225 AstNode *op1_node = node->data.bin_op_expr.op1;
2201 AstNode *op2_node = node->data.bin_op_expr.op2;2226 AstNode *op2_node = node->data.bin_op_expr.op2;
22022227
2203 bool is_inline = ir_should_inline(irb);
2204
2205 IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf);2228 IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf);
2206 if (maybe_ptr == irb->codegen->invalid_instruction)2229 if (maybe_ptr == irb->codegen->invalid_instruction)
2207 return irb->codegen->invalid_instruction;2230 return irb->codegen->invalid_instruction;
22082231
2209 IrInstruction *is_non_null = ir_build_test_null(irb, parent_scope, node, maybe_ptr);2232 IrInstruction *is_non_null = ir_build_test_null(irb, parent_scope, node, maybe_ptr);
22102233
2234 IrInstruction *is_comptime;
2235 if (ir_should_inline(irb)) {
2236 is_comptime = ir_build_const_bool(irb, parent_scope, node, true);
2237 } else {
2238 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null);
2239 }
2240
2211 IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "MaybeNonNull");2241 IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "MaybeNonNull");
2212 IrBasicBlock *null_block = ir_build_basic_block(irb, parent_scope, "MaybeNull");2242 IrBasicBlock *null_block = ir_build_basic_block(irb, parent_scope, "MaybeNull");
2213 IrBasicBlock *end_block = ir_build_basic_block(irb, parent_scope, "MaybeEnd");2243 IrBasicBlock *end_block = ir_build_basic_block(irb, parent_scope, "MaybeEnd");
2214 ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_inline);2244 ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);
22152245
2216 ir_set_cursor_at_end(irb, null_block);2246 ir_set_cursor_at_end(irb, null_block);
2217 IrInstruction *null_result = ir_gen_node(irb, op2_node, parent_scope);2247 IrInstruction *null_result = ir_gen_node(irb, op2_node, parent_scope);
2218 if (null_result == irb->codegen->invalid_instruction)2248 if (null_result == irb->codegen->invalid_instruction)
2219 return irb->codegen->invalid_instruction;2249 return irb->codegen->invalid_instruction;
2220 IrBasicBlock *after_null_block = irb->current_basic_block;2250 IrBasicBlock *after_null_block = irb->current_basic_block;
2221 ir_build_br(irb, parent_scope, node, end_block, is_inline);2251 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
22222252
2223 ir_set_cursor_at_end(irb, ok_block);2253 ir_set_cursor_at_end(irb, ok_block);
2224 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);2254 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);
2225 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);2255 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
2226 IrBasicBlock *after_ok_block = irb->current_basic_block;2256 IrBasicBlock *after_ok_block = irb->current_basic_block;
2227 ir_build_br(irb, parent_scope, node, end_block, is_inline);2257 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
22282258
2229 ir_set_cursor_at_end(irb, end_block);2259 ir_set_cursor_at_end(irb, end_block);
2230 IrInstruction **incoming_values = allocate<IrInstruction *>(2);2260 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
...@@ -2944,6 +2974,13 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -2944,6 +2974,13 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
2944 if (condition == irb->codegen->invalid_instruction)2974 if (condition == irb->codegen->invalid_instruction)
2945 return condition;2975 return condition;
29462976
2977 IrInstruction *is_comptime;
2978 if (ir_should_inline(irb) || node->data.if_bool_expr.is_inline) {
2979 is_comptime = ir_build_const_bool(irb, scope, node, true);
2980 } else {
2981 is_comptime = ir_build_test_comptime(irb, scope, node, condition);
2982 }
2983
2947 AstNode *then_node = node->data.if_bool_expr.then_block;2984 AstNode *then_node = node->data.if_bool_expr.then_block;
2948 AstNode *else_node = node->data.if_bool_expr.else_node;2985 AstNode *else_node = node->data.if_bool_expr.else_node;
29492986
...@@ -2951,15 +2988,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -2951,15 +2988,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
2951 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "Else");2988 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "Else");
2952 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "EndIf");2989 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "EndIf");
29532990
2954 bool is_inline = ir_should_inline(irb) || node->data.if_bool_expr.is_inline;2991 ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_comptime);
2955 ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_inline);
29562992
2957 ir_set_cursor_at_end(irb, then_block);2993 ir_set_cursor_at_end(irb, then_block);
2958 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, scope);2994 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, scope);
2959 if (then_expr_result == irb->codegen->invalid_instruction)2995 if (then_expr_result == irb->codegen->invalid_instruction)
2960 return then_expr_result;2996 return then_expr_result;
2961 IrBasicBlock *after_then_block = irb->current_basic_block;2997 IrBasicBlock *after_then_block = irb->current_basic_block;
2962 ir_build_br(irb, scope, node, endif_block, is_inline);2998 ir_build_br(irb, scope, node, endif_block, is_comptime);
29632999
2964 ir_set_cursor_at_end(irb, else_block);3000 ir_set_cursor_at_end(irb, else_block);
2965 IrInstruction *else_expr_result;3001 IrInstruction *else_expr_result;
...@@ -2971,7 +3007,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -2971,7 +3007,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
2971 else_expr_result = ir_build_const_void(irb, scope, node);3007 else_expr_result = ir_build_const_void(irb, scope, node);
2972 }3008 }
2973 IrBasicBlock *after_else_block = irb->current_basic_block;3009 IrBasicBlock *after_else_block = irb->current_basic_block;
2974 ir_build_br(irb, scope, node, endif_block, is_inline);3010 ir_build_br(irb, scope, node, endif_block, is_comptime);
29753011
2976 ir_set_cursor_at_end(irb, endif_block);3012 ir_set_cursor_at_end(irb, endif_block);
2977 IrInstruction **incoming_values = allocate<IrInstruction *>(2);3013 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
...@@ -3162,9 +3198,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3162,9 +3198,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
3162 bool is_shadowable = false;3198 bool is_shadowable = false;
3163 bool is_const = variable_declaration->is_const;3199 bool is_const = variable_declaration->is_const;
3164 bool is_extern = variable_declaration->is_extern;3200 bool is_extern = variable_declaration->is_extern;
3165 bool is_inline = ir_should_inline(irb) || variable_declaration->is_inline;3201 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
3166 VariableTableEntry *var = ir_create_var(irb, node, scope,3202 ir_should_inline(irb) || variable_declaration->is_inline);
3167 variable_declaration->symbol, is_const, is_const, is_shadowable, is_inline);3203 VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
3204 is_const, is_const, is_shadowable, is_comptime);
3168 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node3205 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node
3169 // is inside var->child_scope3206 // is inside var->child_scope
31703207
...@@ -3192,29 +3229,30 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -3192,29 +3229,30 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
3192 ir_build_basic_block(irb, scope, "WhileContinue") : cond_block;3229 ir_build_basic_block(irb, scope, "WhileContinue") : cond_block;
3193 IrBasicBlock *end_block = ir_build_basic_block(irb, scope, "WhileEnd");3230 IrBasicBlock *end_block = ir_build_basic_block(irb, scope, "WhileEnd");
31943231
3195 bool is_inline = ir_should_inline(irb) || node->data.while_expr.is_inline;3232 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
3196 ir_build_br(irb, scope, node, cond_block, is_inline);3233 ir_should_inline(irb) || node->data.while_expr.is_inline);
3234 ir_build_br(irb, scope, node, cond_block, is_comptime);
31973235
3198 if (continue_expr_node) {3236 if (continue_expr_node) {
3199 ir_set_cursor_at_end(irb, continue_block);3237 ir_set_cursor_at_end(irb, continue_block);
3200 ir_gen_node(irb, continue_expr_node, scope);3238 ir_gen_node(irb, continue_expr_node, scope);
3201 ir_build_br(irb, scope, node, cond_block, is_inline);3239 ir_build_br(irb, scope, node, cond_block, is_comptime);
3202 }3240 }
32033241
3204 ir_set_cursor_at_end(irb, cond_block);3242 ir_set_cursor_at_end(irb, cond_block);
3205 IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope);3243 IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope);
3206 ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val, body_block, end_block, is_inline);3244 ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val, body_block, end_block, is_comptime);
32073245
3208 ir_set_cursor_at_end(irb, body_block);3246 ir_set_cursor_at_end(irb, body_block);
32093247
3210 LoopStackItem *loop_stack_item = irb->loop_stack.add_one();3248 LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
3211 loop_stack_item->break_block = end_block;3249 loop_stack_item->break_block = end_block;
3212 loop_stack_item->continue_block = continue_block;3250 loop_stack_item->continue_block = continue_block;
3213 loop_stack_item->is_inline = is_inline;3251 loop_stack_item->is_comptime = is_comptime;
3214 ir_gen_node(irb, node->data.while_expr.body, scope);3252 ir_gen_node(irb, node->data.while_expr.body, scope);
3215 irb->loop_stack.pop();3253 irb->loop_stack.pop();
32163254
3217 ir_build_br(irb, scope, node, continue_block, is_inline);3255 ir_build_br(irb, scope, node, continue_block, is_comptime);
3218 ir_set_cursor_at_end(irb, end_block);3256 ir_set_cursor_at_end(irb, end_block);
32193257
3220 return ir_build_const_void(irb, scope, node);3258 return ir_build_const_void(irb, scope, node);
...@@ -3248,14 +3286,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -3248,14 +3286,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
3248 } else {3286 } else {
3249 elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);3287 elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);
3250 }3288 }
3251 bool is_inline = ir_should_inline(irb) || node->data.for_expr.is_inline;3289
3290 IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node,
3291 ir_should_inline(irb) || node->data.for_expr.is_inline);
32523292
3253 Scope *child_scope = create_loop_scope(node, parent_scope);3293 Scope *child_scope = create_loop_scope(node, parent_scope);
32543294
3255 // TODO make it an error to write to element variable or i variable.3295 // TODO make it an error to write to element variable or i variable.
3256 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;3296 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
3257 VariableTableEntry *elem_var = ir_create_var(irb, elem_node, child_scope, elem_var_name,3297 VariableTableEntry *elem_var = ir_create_var(irb, elem_node, child_scope, elem_var_name, true, false, false, is_comptime);
3258 true, false, false, is_inline);
3259 child_scope = elem_var->child_scope;3298 child_scope = elem_var->child_scope;
32603299
3261 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);3300 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
...@@ -3267,10 +3306,10 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -3267,10 +3306,10 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
3267 if (index_node) {3306 if (index_node) {
3268 index_var_source_node = index_node;3307 index_var_source_node = index_node;
3269 Buf *index_var_name = index_node->data.symbol_expr.symbol;3308 Buf *index_var_name = index_node->data.symbol_expr.symbol;
3270 index_var = ir_create_var(irb, index_node, child_scope, index_var_name, true, false, false, is_inline);3309 index_var = ir_create_var(irb, index_node, child_scope, index_var_name, true, false, false, is_comptime);
3271 } else {3310 } else {
3272 index_var_source_node = node;3311 index_var_source_node = node;
3273 index_var = ir_create_var(irb, node, child_scope, nullptr, true, false, true, is_inline);3312 index_var = ir_create_var(irb, node, child_scope, nullptr, true, false, true, is_comptime);
3274 }3313 }
3275 child_scope = index_var->child_scope;3314 child_scope = index_var->child_scope;
32763315
...@@ -3287,12 +3326,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -3287,12 +3326,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
3287 IrBasicBlock *continue_block = ir_build_basic_block(irb, child_scope, "ForContinue");3326 IrBasicBlock *continue_block = ir_build_basic_block(irb, child_scope, "ForContinue");
32883327
3289 IrInstruction *len_val = ir_build_array_len(irb, child_scope, node, array_val);3328 IrInstruction *len_val = ir_build_array_len(irb, child_scope, node, array_val);
3290 ir_build_br(irb, child_scope, node, cond_block, is_inline);3329 ir_build_br(irb, child_scope, node, cond_block, is_comptime);
32913330
3292 ir_set_cursor_at_end(irb, cond_block);3331 ir_set_cursor_at_end(irb, cond_block);
3293 IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);3332 IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);
3294 IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);3333 IrInstruction *cond = ir_build_bin_op(irb, child_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
3295 ir_build_cond_br(irb, child_scope, node, cond, body_block, end_block, is_inline);3334 ir_build_cond_br(irb, child_scope, node, cond, body_block, end_block, is_comptime);
32963335
3297 ir_set_cursor_at_end(irb, body_block);3336 ir_set_cursor_at_end(irb, body_block);
3298 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false);3337 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, child_scope, node, array_val_ptr, index_val, false);
...@@ -3307,16 +3346,16 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -3307,16 +3346,16 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
3307 LoopStackItem *loop_stack_item = irb->loop_stack.add_one();3346 LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
3308 loop_stack_item->break_block = end_block;3347 loop_stack_item->break_block = end_block;
3309 loop_stack_item->continue_block = continue_block;3348 loop_stack_item->continue_block = continue_block;
3310 loop_stack_item->is_inline = is_inline;3349 loop_stack_item->is_comptime = is_comptime;
3311 ir_gen_node(irb, body_node, child_scope);3350 ir_gen_node(irb, body_node, child_scope);
3312 irb->loop_stack.pop();3351 irb->loop_stack.pop();
33133352
3314 ir_build_br(irb, child_scope, node, continue_block, is_inline);3353 ir_build_br(irb, child_scope, node, continue_block, is_comptime);
33153354
3316 ir_set_cursor_at_end(irb, continue_block);3355 ir_set_cursor_at_end(irb, continue_block);
3317 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);3356 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);
3318 ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val);3357 ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val);
3319 ir_build_br(irb, child_scope, node, cond_block, is_inline);3358 ir_build_br(irb, child_scope, node, cond_block, is_comptime);
33203359
3321 ir_set_cursor_at_end(irb, end_block);3360 ir_set_cursor_at_end(irb, end_block);
3322 return ir_build_const_void(irb, child_scope, node);3361 return ir_build_const_void(irb, child_scope, node);
...@@ -3467,8 +3506,13 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3467,8 +3506,13 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
3467 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "MaybeElse");3506 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "MaybeElse");
3468 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf");3507 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf");
34693508
3470 bool is_inline = ir_should_inline(irb) || node->data.if_var_expr.is_inline;3509 IrInstruction *is_comptime;
3471 ir_build_cond_br(irb, scope, node, is_nonnull_value, then_block, else_block, is_inline);3510 if (ir_should_inline(irb) || node->data.if_var_expr.is_inline) {
3511 is_comptime = ir_build_const_bool(irb, scope, node, true);
3512 } else {
3513 is_comptime = ir_build_test_comptime(irb, scope, node, is_nonnull_value);
3514 }
3515 ir_build_cond_br(irb, scope, node, is_nonnull_value, then_block, else_block, is_comptime);
34723516
3473 ir_set_cursor_at_end(irb, then_block);3517 ir_set_cursor_at_end(irb, then_block);
3474 IrInstruction *var_type = nullptr;3518 IrInstruction *var_type = nullptr;
...@@ -3480,7 +3524,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3480,7 +3524,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
3480 bool is_shadowable = false;3524 bool is_shadowable = false;
3481 bool is_const = var_decl->is_const;3525 bool is_const = var_decl->is_const;
3482 VariableTableEntry *var = ir_create_var(irb, node, scope,3526 VariableTableEntry *var = ir_create_var(irb, node, scope,
3483 var_decl->symbol, is_const, is_const, is_shadowable, is_inline);3527 var_decl->symbol, is_const, is_const, is_shadowable, is_comptime);
34843528
3485 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, expr_value, false);3529 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, expr_value, false);
3486 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value);3530 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value);
...@@ -3489,7 +3533,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3489,7 +3533,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
3489 if (then_expr_result == irb->codegen->invalid_instruction)3533 if (then_expr_result == irb->codegen->invalid_instruction)
3490 return then_expr_result;3534 return then_expr_result;
3491 IrBasicBlock *after_then_block = irb->current_basic_block;3535 IrBasicBlock *after_then_block = irb->current_basic_block;
3492 ir_build_br(irb, scope, node, endif_block, is_inline);3536 ir_build_br(irb, scope, node, endif_block, is_comptime);
34933537
3494 ir_set_cursor_at_end(irb, else_block);3538 ir_set_cursor_at_end(irb, else_block);
3495 IrInstruction *else_expr_result;3539 IrInstruction *else_expr_result;
...@@ -3501,7 +3545,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3501,7 +3545,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
3501 else_expr_result = ir_build_const_void(irb, scope, node);3545 else_expr_result = ir_build_const_void(irb, scope, node);
3502 }3546 }
3503 IrBasicBlock *after_else_block = irb->current_basic_block;3547 IrBasicBlock *after_else_block = irb->current_basic_block;
3504 ir_build_br(irb, scope, node, endif_block, is_inline);3548 ir_build_br(irb, scope, node, endif_block, is_comptime);
35053549
3506 ir_set_cursor_at_end(irb, endif_block);3550 ir_set_cursor_at_end(irb, endif_block);
3507 IrInstruction **incoming_values = allocate<IrInstruction *>(2);3551 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
...@@ -3515,7 +3559,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3515,7 +3559,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
3515}3559}
35163560
3517static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,3561static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,
3518 IrBasicBlock *end_block, bool is_inline, IrInstruction *target_value_ptr, IrInstruction *prong_value,3562 IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *target_value_ptr, IrInstruction *prong_value,
3519 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)3563 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
3520{3564{
3521 assert(switch_node->type == NodeTypeSwitchExpr);3565 assert(switch_node->type == NodeTypeSwitchExpr);
...@@ -3532,7 +3576,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit...@@ -3532,7 +3576,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
3532 bool is_shadowable = false;3576 bool is_shadowable = false;
3533 bool is_const = true;3577 bool is_const = true;
3534 VariableTableEntry *var = ir_create_var(irb, var_symbol_node, scope,3578 VariableTableEntry *var = ir_create_var(irb, var_symbol_node, scope,
3535 var_name, is_const, is_const, is_shadowable, is_inline);3579 var_name, is_const, is_const, is_shadowable, is_comptime);
3536 child_scope = var->child_scope;3580 child_scope = var->child_scope;
3537 IrInstruction *var_value;3581 IrInstruction *var_value;
3538 if (prong_value) {3582 if (prong_value) {
...@@ -3550,7 +3594,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit...@@ -3550,7 +3594,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
3550 IrInstruction *expr_result = ir_gen_node(irb, expr_node, child_scope);3594 IrInstruction *expr_result = ir_gen_node(irb, expr_node, child_scope);
3551 if (expr_result == irb->codegen->invalid_instruction)3595 if (expr_result == irb->codegen->invalid_instruction)
3552 return false;3596 return false;
3553 ir_build_br(irb, scope, switch_node, end_block, is_inline);3597 ir_build_br(irb, scope, switch_node, end_block, is_comptime);
3554 incoming_blocks->append(irb->current_basic_block);3598 incoming_blocks->append(irb->current_basic_block);
3555 incoming_values->append(expr_result);3599 incoming_values->append(expr_result);
3556 return true;3600 return true;
...@@ -3570,7 +3614,13 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3570,7 +3614,13 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
35703614
3571 size_t prong_count = node->data.switch_expr.prongs.length;3615 size_t prong_count = node->data.switch_expr.prongs.length;
3572 ZigList<IrInstructionSwitchBrCase> cases = {0};3616 ZigList<IrInstructionSwitchBrCase> cases = {0};
3573 bool is_inline = ir_should_inline(irb) || node->data.switch_expr.is_inline;3617
3618 IrInstruction *is_comptime;
3619 if (ir_should_inline(irb) || node->data.switch_expr.is_inline) {
3620 is_comptime = ir_build_const_bool(irb, scope, node, true);
3621 } else {
3622 is_comptime = ir_build_test_comptime(irb, scope, node, target_value);
3623 }
35743624
3575 ZigList<IrInstruction *> incoming_values = {0};3625 ZigList<IrInstruction *> incoming_values = {0};
3576 ZigList<IrBasicBlock *> incoming_blocks = {0};3626 ZigList<IrBasicBlock *> incoming_blocks = {0};
...@@ -3592,7 +3642,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3592,7 +3642,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
3592 IrBasicBlock *prev_block = irb->current_basic_block;3642 IrBasicBlock *prev_block = irb->current_basic_block;
3593 ir_set_cursor_at_end(irb, else_block);3643 ir_set_cursor_at_end(irb, else_block);
3594 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,3644 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
3595 is_inline, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))3645 is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
3596 {3646 {
3597 return irb->codegen->invalid_instruction;3647 return irb->codegen->invalid_instruction;
3598 }3648 }
...@@ -3650,11 +3700,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3650,11 +3700,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
36503700
3651 assert(ok_bit);3701 assert(ok_bit);
3652 assert(last_item_node);3702 assert(last_item_node);
3653 ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes, range_block_no, is_inline);3703 ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes, range_block_no, is_comptime);
36543704
3655 ir_set_cursor_at_end(irb, range_block_yes);3705 ir_set_cursor_at_end(irb, range_block_yes);
3656 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,3706 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
3657 is_inline, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))3707 is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values))
3658 {3708 {
3659 return irb->codegen->invalid_instruction;3709 return irb->codegen->invalid_instruction;
3660 }3710 }
...@@ -3683,7 +3733,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3683,7 +3733,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
3683 IrBasicBlock *prev_block = irb->current_basic_block;3733 IrBasicBlock *prev_block = irb->current_basic_block;
3684 ir_set_cursor_at_end(irb, prong_block);3734 ir_set_cursor_at_end(irb, prong_block);
3685 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,3735 if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block,
3686 is_inline, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values))3736 is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values))
3687 {3737 {
3688 return irb->codegen->invalid_instruction;3738 return irb->codegen->invalid_instruction;
3689 }3739 }
...@@ -3695,9 +3745,9 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -3695,9 +3745,9 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
3695 }3745 }
36963746
3697 if (cases.length == 0) {3747 if (cases.length == 0) {
3698 ir_build_br(irb, scope, node, else_block, is_inline);3748 ir_build_br(irb, scope, node, else_block, is_comptime);
3699 } else {3749 } else {
3700 ir_build_switch_br(irb, scope, node, target_value, else_block, cases.length, cases.items, is_inline);3750 ir_build_switch_br(irb, scope, node, target_value, else_block, cases.length, cases.items, is_comptime);
3701 }3751 }
37023752
3703 if (!else_prong) {3753 if (!else_prong) {
...@@ -3754,8 +3804,9 @@ static IrInstruction *ir_gen_label(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3754,8 +3804,9 @@ static IrInstruction *ir_gen_label(IrBuilder *irb, Scope *scope, AstNode *node)
3754 scope_block->label_table.put(label_name, label);3804 scope_block->label_table.put(label_name, label);
3755 }3805 }
37563806
3757 bool is_inline = ir_should_inline(irb);3807 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
3758 ir_build_br(irb, scope, node, label_block, is_inline);3808 ir_should_inline(irb));
3809 ir_build_br(irb, scope, node, label_block, is_comptime);
3759 ir_set_cursor_at_end(irb, label_block);3810 ir_set_cursor_at_end(irb, label_block);
3760 return ir_build_const_void(irb, scope, node);3811 return ir_build_const_void(irb, scope, node);
3761}3812}
...@@ -3785,11 +3836,18 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3785,11 +3836,18 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)
3785 return irb->codegen->invalid_instruction;3836 return irb->codegen->invalid_instruction;
3786 }3837 }
37873838
3788 bool is_inline = ir_should_inline(irb) || node->data.break_expr.is_inline;
3789 LoopStackItem *loop_stack_item = &irb->loop_stack.last();3839 LoopStackItem *loop_stack_item = &irb->loop_stack.last();
3840
3841 IrInstruction *is_comptime;
3842 if (ir_should_inline(irb) || node->data.break_expr.is_inline) {
3843 is_comptime = ir_build_const_bool(irb, scope, node, true);
3844 } else {
3845 is_comptime = loop_stack_item->is_comptime;
3846 }
3847
3790 IrBasicBlock *dest_block = loop_stack_item->break_block;3848 IrBasicBlock *dest_block = loop_stack_item->break_block;
3791 ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false);3849 ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false);
3792 return ir_build_br(irb, scope, node, dest_block, is_inline);3850 return ir_build_br(irb, scope, node, dest_block, is_comptime);
3793}3851}
37943852
3795static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *node) {3853static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -3801,11 +3859,18 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3801,11 +3859,18 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod
3801 return irb->codegen->invalid_instruction;3859 return irb->codegen->invalid_instruction;
3802 }3860 }
38033861
3804 bool is_inline = ir_should_inline(irb) || node->data.continue_expr.is_inline;
3805 LoopStackItem *loop_stack_item = &irb->loop_stack.last();3862 LoopStackItem *loop_stack_item = &irb->loop_stack.last();
3863
3864 IrInstruction *is_comptime;
3865 if (ir_should_inline(irb) || node->data.continue_expr.is_inline) {
3866 is_comptime = ir_build_const_bool(irb, scope, node, true);
3867 } else {
3868 is_comptime = loop_stack_item->is_comptime;
3869 }
3870
3806 IrBasicBlock *dest_block = loop_stack_item->continue_block;3871 IrBasicBlock *dest_block = loop_stack_item->continue_block;
3807 ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false);3872 ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false);
3808 return ir_build_br(irb, scope, node, dest_block, is_inline);3873 return ir_build_br(irb, scope, node, dest_block, is_comptime);
3809}3874}
38103875
3811static IrInstruction *ir_gen_type_literal(IrBuilder *irb, Scope *scope, AstNode *node) {3876static IrInstruction *ir_gen_type_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -3863,18 +3928,23 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -3863,18 +3928,23 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
3863 AstNode *op2_node = node->data.unwrap_err_expr.op2;3928 AstNode *op2_node = node->data.unwrap_err_expr.op2;
3864 AstNode *var_node = node->data.unwrap_err_expr.symbol;3929 AstNode *var_node = node->data.unwrap_err_expr.symbol;
38653930
3866 bool is_inline = ir_should_inline(irb);
3867
3868 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf);3931 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf);
3869 if (err_union_ptr == irb->codegen->invalid_instruction)3932 if (err_union_ptr == irb->codegen->invalid_instruction)
3870 return irb->codegen->invalid_instruction;3933 return irb->codegen->invalid_instruction;
38713934
3872 IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_ptr);3935 IrInstruction *is_err = ir_build_test_err(irb, parent_scope, node, err_union_ptr);
38733936
3937 IrInstruction *is_comptime;
3938 if (ir_should_inline(irb)) {
3939 is_comptime = ir_build_const_bool(irb, parent_scope, node, true);
3940 } else {
3941 is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err);
3942 }
3943
3874 IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrOk");3944 IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrOk");
3875 IrBasicBlock *err_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrError");3945 IrBasicBlock *err_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrError");
3876 IrBasicBlock *end_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrEnd");3946 IrBasicBlock *end_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrEnd");
3877 ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_inline);3947 ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime);
38783948
3879 ir_set_cursor_at_end(irb, err_block);3949 ir_set_cursor_at_end(irb, err_block);
3880 Scope *err_scope;3950 Scope *err_scope;
...@@ -3886,7 +3956,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -3886,7 +3956,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
3886 bool is_const = true;3956 bool is_const = true;
3887 bool is_shadowable = false;3957 bool is_shadowable = false;
3888 VariableTableEntry *var = ir_create_var(irb, node, parent_scope, var_name,3958 VariableTableEntry *var = ir_create_var(irb, node, parent_scope, var_name,
3889 is_const, is_const, is_shadowable, is_inline);3959 is_const, is_const, is_shadowable, is_comptime);
3890 err_scope = var->child_scope;3960 err_scope = var->child_scope;
3891 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);3961 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
3892 ir_build_var_decl(irb, err_scope, var_node, var, var_type, err_val);3962 ir_build_var_decl(irb, err_scope, var_node, var, var_type, err_val);
...@@ -3897,13 +3967,13 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -3897,13 +3967,13 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
3897 if (err_result == irb->codegen->invalid_instruction)3967 if (err_result == irb->codegen->invalid_instruction)
3898 return irb->codegen->invalid_instruction;3968 return irb->codegen->invalid_instruction;
3899 IrBasicBlock *after_err_block = irb->current_basic_block;3969 IrBasicBlock *after_err_block = irb->current_basic_block;
3900 ir_build_br(irb, err_scope, node, end_block, is_inline);3970 ir_build_br(irb, err_scope, node, end_block, is_comptime);
39013971
3902 ir_set_cursor_at_end(irb, ok_block);3972 ir_set_cursor_at_end(irb, ok_block);
3903 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false);3973 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false);
3904 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);3974 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
3905 IrBasicBlock *after_ok_block = irb->current_basic_block;3975 IrBasicBlock *after_ok_block = irb->current_basic_block;
3906 ir_build_br(irb, parent_scope, node, end_block, is_inline);3976 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
39073977
3908 ir_set_cursor_at_end(irb, end_block);3978 ir_set_cursor_at_end(irb, end_block);
3909 IrInstruction **incoming_values = allocate<IrInstruction *>(2);3979 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
...@@ -4108,9 +4178,10 @@ static bool ir_goto_pass2(IrBuilder *irb) {...@@ -4108,9 +4178,10 @@ static bool ir_goto_pass2(IrBuilder *irb) {
4108 }4178 }
4109 label->used = true;4179 label->used = true;
41104180
4111 bool is_inline = ir_should_inline(irb) || source_node->data.goto_expr.is_inline;4181 IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node,
4182 ir_should_inline(irb) || source_node->data.goto_expr.is_inline);
4112 ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false, false);4183 ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false, false);
4113 ir_build_br(irb, goto_item->scope, source_node, label->bb, is_inline);4184 ir_build_br(irb, goto_item->scope, source_node, label->bb, is_comptime);
4114 }4185 }
41154186
4116 for (size_t i = 0; i < irb->exec->all_labels.length; i += 1) {4187 for (size_t i = 0; i < irb->exec->all_labels.length; i += 1) {
...@@ -4176,6 +4247,8 @@ static void add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, ErrorMsg...@@ -4176,6 +4247,8 @@ static void add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, ErrorMsg
4176 add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1);4247 add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1);
4177}4248}
41784249
4250// TODO migrate the rest of the add_node_error errors to use this so that we get better
4251// messages for generic instantiations
4179static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) {4252static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) {
4180 ira->new_irb.exec->invalid = true;4253 ira->new_irb.exec->invalid = true;
4181 ErrorMsg *err_msg = add_node_error(ira->codegen, source_instruction->source_node, msg);4254 ErrorMsg *err_msg = add_node_error(ira->codegen, source_instruction->source_node, msg);
...@@ -5967,18 +6040,20 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc...@@ -5967,18 +6040,20 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
5967 var->type = result_type;6040 var->type = result_type;
5968 assert(var->type);6041 assert(var->type);
59696042
6043 bool is_comptime = ir_get_var_is_comptime(var);
6044
5970 if (casted_init_value->static_value.special != ConstValSpecialRuntime) {6045 if (casted_init_value->static_value.special != ConstValSpecialRuntime) {
5971 if (var->mem_slot_index != SIZE_MAX) {6046 if (var->mem_slot_index != SIZE_MAX) {
5972 assert(var->mem_slot_index < ira->exec_context.mem_slot_count);6047 assert(var->mem_slot_index < ira->exec_context.mem_slot_count);
5973 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];6048 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
5974 *mem_slot = casted_init_value->static_value;6049 *mem_slot = casted_init_value->static_value;
59756050
5976 if (var->is_inline) {6051 if (is_comptime) {
5977 ir_build_const_from(ira, &decl_var_instruction->base, false);6052 ir_build_const_from(ira, &decl_var_instruction->base, false);
5978 return ira->codegen->builtin_types.entry_void;6053 return ira->codegen->builtin_types.entry_void;
5979 }6054 }
5980 }6055 }
5981 } else if (var->is_inline) {6056 } else if (is_comptime) {
5982 ir_add_error(ira, &decl_var_instruction->base,6057 ir_add_error(ira, &decl_var_instruction->base,
5983 buf_sprintf("cannot store runtime value in compile time variable"));6058 buf_sprintf("cannot store runtime value in compile time variable"));
5984 var->type = ira->codegen->builtin_types.entry_invalid;6059 var->type = ira->codegen->builtin_types.entry_invalid;
...@@ -6586,9 +6661,12 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -6586,9 +6661,12 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
6586static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {6661static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
6587 IrBasicBlock *old_dest_block = br_instruction->dest_block;6662 IrBasicBlock *old_dest_block = br_instruction->dest_block;
65886663
6589 if (br_instruction->is_inline || old_dest_block->ref_count == 1) {6664 bool is_comptime;
6665 if (!ir_resolve_bool(ira, br_instruction->is_comptime->other, &is_comptime))
6666 return ir_unreach_error(ira);
6667
6668 if (is_comptime || old_dest_block->ref_count == 1)
6590 return ir_inline_bb(ira, &br_instruction->base, old_dest_block);6669 return ir_inline_bb(ira, &br_instruction->base, old_dest_block);
6591 }
65926670
6593 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);6671 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);
6594 ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);6672 ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);
...@@ -6600,7 +6678,11 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct...@@ -6600,7 +6678,11 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
6600 if (condition->type_entry->id == TypeTableEntryIdInvalid)6678 if (condition->type_entry->id == TypeTableEntryIdInvalid)
6601 return ir_unreach_error(ira);6679 return ir_unreach_error(ira);
66026680
6603 if (cond_br_instruction->is_inline || condition->static_value.special != ConstValSpecialRuntime) {6681 bool is_comptime;
6682 if (!ir_resolve_bool(ira, cond_br_instruction->is_comptime->other, &is_comptime))
6683 return ir_unreach_error(ira);
6684
6685 if (is_comptime || instr_is_comptime(condition)) {
6604 bool cond_is_true;6686 bool cond_is_true;
6605 if (!ir_resolve_bool(ira, condition, &cond_is_true))6687 if (!ir_resolve_bool(ira, condition, &cond_is_true))
6606 return ir_unreach_error(ira);6688 return ir_unreach_error(ira);
...@@ -6608,7 +6690,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct...@@ -6608,7 +6690,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
6608 IrBasicBlock *old_dest_block = cond_is_true ?6690 IrBasicBlock *old_dest_block = cond_is_true ?
6609 cond_br_instruction->then_block : cond_br_instruction->else_block;6691 cond_br_instruction->then_block : cond_br_instruction->else_block;
66106692
6611 if (cond_br_instruction->is_inline || old_dest_block->ref_count == 1)6693 if (is_comptime || old_dest_block->ref_count == 1)
6612 return ir_inline_bb(ira, &cond_br_instruction->base, old_dest_block);6694 return ir_inline_bb(ira, &cond_br_instruction->base, old_dest_block);
6613 }6695 }
66146696
...@@ -6620,7 +6702,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct...@@ -6620,7 +6702,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
6620 IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block);6702 IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block);
6621 IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block);6703 IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block);
6622 ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base,6704 ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base,
6623 casted_condition, new_then_block, new_else_block, false);6705 casted_condition, new_then_block, new_else_block, nullptr);
6624 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);6706 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
6625}6707}
66266708
...@@ -6723,6 +6805,8 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc...@@ -6723,6 +6805,8 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc
6723 if (var->type->id == TypeTableEntryIdInvalid)6805 if (var->type->id == TypeTableEntryIdInvalid)
6724 return var->type;6806 return var->type;
67256807
6808 bool is_comptime = ir_get_var_is_comptime(var);
6809
6726 ConstExprValue *mem_slot = nullptr;6810 ConstExprValue *mem_slot = nullptr;
6727 FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope);6811 FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope);
6728 if (var->src_is_const && var->value) {6812 if (var->src_is_const && var->value) {
...@@ -6730,12 +6814,12 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc...@@ -6730,12 +6814,12 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc
6730 assert(mem_slot->special != ConstValSpecialRuntime);6814 assert(mem_slot->special != ConstValSpecialRuntime);
6731 } else if (fn_entry) {6815 } else if (fn_entry) {
6732 // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing.6816 // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing.
6733 if (var->mem_slot_index != SIZE_MAX)6817 if (var->mem_slot_index != SIZE_MAX && (is_comptime || var->gen_is_const))
6734 mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];6818 mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
6735 }6819 }
67366820
6737 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {6821 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {
6738 ConstPtrSpecial ptr_special = var->is_inline ? ConstPtrSpecialInline : ConstPtrSpecialNone;6822 ConstPtrSpecial ptr_special = is_comptime ? ConstPtrSpecialInline : ConstPtrSpecialNone;
6739 return ir_analyze_const_ptr(ira, instruction, mem_slot, var->type, false, ptr_special, var->src_is_const);6823 return ir_analyze_const_ptr(ira, instruction, mem_slot, var->type, false, ptr_special, var->src_is_const);
6740 } else {6824 } else {
6741 ir_build_var_ptr_from(&ira->new_irb, instruction, var);6825 ir_build_var_ptr_from(&ira->new_irb, instruction, var);
...@@ -7827,9 +7911,12 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,...@@ -7827,9 +7911,12 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
7827 return ir_unreach_error(ira);7911 return ir_unreach_error(ira);
78287912
7829 size_t case_count = switch_br_instruction->case_count;7913 size_t case_count = switch_br_instruction->case_count;
7830 bool is_inline = ir_should_inline(&ira->new_irb) || switch_br_instruction->is_inline;
78317914
7832 if (is_inline || instr_is_comptime(target_value)) {7915 bool is_comptime;
7916 if (!ir_resolve_bool(ira, switch_br_instruction->is_comptime->other, &is_comptime))
7917 return ira->codegen->builtin_types.entry_invalid;
7918
7919 if (is_comptime || instr_is_comptime(target_value)) {
7833 ConstExprValue *target_val = ir_resolve_const(ira, target_value, UndefBad);7920 ConstExprValue *target_val = ir_resolve_const(ira, target_value, UndefBad);
7834 if (!target_val)7921 if (!target_val)
7835 return ir_unreach_error(ira);7922 return ir_unreach_error(ira);
...@@ -7856,7 +7943,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,...@@ -7856,7 +7943,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
78567943
7857 if (const_values_equal(target_val, case_val, target_value->type_entry)) {7944 if (const_values_equal(target_val, case_val, target_value->type_entry)) {
7858 IrBasicBlock *old_dest_block = old_case->block;7945 IrBasicBlock *old_dest_block = old_case->block;
7859 if (is_inline || old_dest_block->ref_count == 1) {7946 if (is_comptime || old_dest_block->ref_count == 1) {
7860 return ir_inline_bb(ira, &switch_br_instruction->base, old_dest_block);7947 return ir_inline_bb(ira, &switch_br_instruction->base, old_dest_block);
7861 } else {7948 } else {
7862 IrBasicBlock *new_dest_block = ir_get_new_bb(ira, old_dest_block);7949 IrBasicBlock *new_dest_block = ir_get_new_bb(ira, old_dest_block);
...@@ -7898,7 +7985,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,...@@ -7898,7 +7985,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
78987985
7899 IrBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block);7986 IrBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block);
7900 ir_build_switch_br_from(&ira->new_irb, &switch_br_instruction->base,7987 ir_build_switch_br_from(&ira->new_irb, &switch_br_instruction->base,
7901 target_value, new_else_block, case_count, cases, false);7988 target_value, new_else_block, case_count, cases, nullptr);
7902 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);7989 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
7903}7990}
79047991
...@@ -9520,6 +9607,16 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc...@@ -9520,6 +9607,16 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc
9520 return ira->codegen->builtin_types.entry_type;9607 return ira->codegen->builtin_types.entry_type;
9521}9608}
95229609
9610static TypeTableEntry *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) {
9611 IrInstruction *value = instruction->value->other;
9612 if (value->type_entry->id == TypeTableEntryIdInvalid)
9613 return ira->codegen->builtin_types.entry_invalid;
9614
9615 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, false);
9616 out_val->data.x_bool = instr_is_comptime(value);
9617 return ira->codegen->builtin_types.entry_bool;
9618}
9619
9523static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {9620static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
9524 switch (instruction->id) {9621 switch (instruction->id) {
9525 case IrInstructionIdInvalid:9622 case IrInstructionIdInvalid:
...@@ -9662,6 +9759,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -9662,6 +9759,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
9662 return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction);9759 return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction);
9663 case IrInstructionIdFnProto:9760 case IrInstructionIdFnProto:
9664 return ir_analyze_instruction_fn_proto(ira, (IrInstructionFnProto *)instruction);9761 return ir_analyze_instruction_fn_proto(ira, (IrInstructionFnProto *)instruction);
9762 case IrInstructionIdTestComptime:
9763 return ir_analyze_instruction_test_comptime(ira, (IrInstructionTestComptime *)instruction);
9665 case IrInstructionIdMaybeWrap:9764 case IrInstructionIdMaybeWrap:
9666 case IrInstructionIdErrWrapCode:9765 case IrInstructionIdErrWrapCode:
9667 case IrInstructionIdErrWrapPayload:9766 case IrInstructionIdErrWrapPayload:
...@@ -9823,6 +9922,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -9823,6 +9922,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
9823 case IrInstructionIdErrWrapCode:9922 case IrInstructionIdErrWrapCode:
9824 case IrInstructionIdErrWrapPayload:9923 case IrInstructionIdErrWrapPayload:
9825 case IrInstructionIdFnProto:9924 case IrInstructionIdFnProto:
9925 case IrInstructionIdTestComptime:
9826 return false;9926 return false;
9827 case IrInstructionIdAsm:9927 case IrInstructionIdAsm:
9828 {9928 {
...@@ -9832,3 +9932,4 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -9832,3 +9932,4 @@ bool ir_has_side_effects(IrInstruction *instruction) {
9832 }9932 }
9833 zig_unreachable();9933 zig_unreachable();
9834}9934}
9935
src/ir_print.cpp+30-9
...@@ -310,17 +310,20 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction...@@ -310,17 +310,20 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
310}310}
311311
312static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {312static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {
313 const char *inline_kw = decl_var_instruction->var->is_inline ? "inline " : "";
314 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";313 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
315 const char *name = buf_ptr(&decl_var_instruction->var->name);314 const char *name = buf_ptr(&decl_var_instruction->var->name);
316 if (decl_var_instruction->var_type) {315 if (decl_var_instruction->var_type) {
317 fprintf(irp->f, "%s%s %s: ", inline_kw, var_or_const, name);316 fprintf(irp->f, "%s %s: ", var_or_const, name);
318 ir_print_other_instruction(irp, decl_var_instruction->var_type);317 ir_print_other_instruction(irp, decl_var_instruction->var_type);
319 fprintf(irp->f, " = ");318 fprintf(irp->f, " = ");
320 } else {319 } else {
321 fprintf(irp->f, "%s%s %s = ", inline_kw, var_or_const, name);320 fprintf(irp->f, "%s %s = ", var_or_const, name);
322 }321 }
323 ir_print_other_instruction(irp, decl_var_instruction->init_value);322 ir_print_other_instruction(irp, decl_var_instruction->init_value);
323 if (decl_var_instruction->var->is_comptime != nullptr) {
324 fprintf(irp->f, " // comptime = ");
325 ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
326 }
324}327}
325328
326static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {329static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
...@@ -347,19 +350,25 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {...@@ -347,19 +350,25 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
347}350}
348351
349static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {352static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
350 const char *inline_kw = cond_br_instruction->is_inline ? "inline " : "";353 fprintf(irp->f, "if (");
351 fprintf(irp->f, "%sif (", inline_kw);
352 ir_print_other_instruction(irp, cond_br_instruction->condition);354 ir_print_other_instruction(irp, cond_br_instruction->condition);
353 fprintf(irp->f, ") ");355 fprintf(irp->f, ") ");
354 ir_print_other_block(irp, cond_br_instruction->then_block);356 ir_print_other_block(irp, cond_br_instruction->then_block);
355 fprintf(irp->f, " else ");357 fprintf(irp->f, " else ");
356 ir_print_other_block(irp, cond_br_instruction->else_block);358 ir_print_other_block(irp, cond_br_instruction->else_block);
359 if (cond_br_instruction->is_comptime != nullptr) {
360 fprintf(irp->f, " // comptime = ");
361 ir_print_other_instruction(irp, cond_br_instruction->is_comptime);
362 }
357}363}
358364
359static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {365static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
360 const char *inline_kw = br_instruction->is_inline ? "inline " : "";366 fprintf(irp->f, "goto ");
361 fprintf(irp->f, "%sgoto ", inline_kw);
362 ir_print_other_block(irp, br_instruction->dest_block);367 ir_print_other_block(irp, br_instruction->dest_block);
368 if (br_instruction->is_comptime != nullptr) {
369 fprintf(irp->f, " // comptime = ");
370 ir_print_other_instruction(irp, br_instruction->is_comptime);
371 }
363}372}
364373
365static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {374static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
...@@ -597,8 +606,7 @@ static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) {...@@ -597,8 +606,7 @@ static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) {
597}606}
598607
599static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction) {608static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction) {
600 const char *inline_kw = instruction->is_inline ? "inline " : "";609 fprintf(irp->f, "switch (");
601 fprintf(irp->f, "%sswitch (", inline_kw);
602 ir_print_other_instruction(irp, instruction->target_value);610 ir_print_other_instruction(irp, instruction->target_value);
603 fprintf(irp->f, ") ");611 fprintf(irp->f, ") ");
604 for (size_t i = 0; i < instruction->case_count; i += 1) {612 for (size_t i = 0; i < instruction->case_count; i += 1) {
...@@ -610,6 +618,10 @@ static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction)...@@ -610,6 +618,10 @@ static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction)
610 }618 }
611 fprintf(irp->f, "else => ");619 fprintf(irp->f, "else => ");
612 ir_print_other_block(irp, instruction->else_block);620 ir_print_other_block(irp, instruction->else_block);
621 if (instruction->is_comptime != nullptr) {
622 fprintf(irp->f, " // comptime = ");
623 ir_print_other_instruction(irp, instruction->is_comptime);
624 }
613}625}
614626
615static void ir_print_switch_var(IrPrint *irp, IrInstructionSwitchVar *instruction) {627static void ir_print_switch_var(IrPrint *irp, IrInstructionSwitchVar *instruction) {
...@@ -893,6 +905,12 @@ static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) {...@@ -893,6 +905,12 @@ static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) {
893 ir_print_other_instruction(irp, instruction->return_type);905 ir_print_other_instruction(irp, instruction->return_type);
894}906}
895907
908static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *instruction) {
909 fprintf(irp->f, "@testComptime(");
910 ir_print_other_instruction(irp, instruction->value);
911 fprintf(irp->f, ")");
912}
913
896static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {914static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
897 ir_print_prefix(irp, instruction);915 ir_print_prefix(irp, instruction);
898 switch (instruction->id) {916 switch (instruction->id) {
...@@ -1126,6 +1144,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1126,6 +1144,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1126 case IrInstructionIdFnProto:1144 case IrInstructionIdFnProto:
1127 ir_print_fn_proto(irp, (IrInstructionFnProto *)instruction);1145 ir_print_fn_proto(irp, (IrInstructionFnProto *)instruction);
1128 break;1146 break;
1147 case IrInstructionIdTestComptime:
1148 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
1149 break;
1129 }1150 }
1130 fprintf(irp->f, "\n");1151 fprintf(irp->f, "\n");
1131}1152}