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 {
12351235 LLVMValueRef value_ref;
12361236 bool src_is_const;
12371237 bool gen_is_const;
1238 bool is_inline;
1238 IrInstruction *is_comptime;
12391239 // which node is the declaration of the variable
12401240 AstNode *decl_node;
12411241 ZigLLVMDILocalVariable *di_loc_var;
......@@ -1451,6 +1451,7 @@ enum IrInstructionId {
14511451 IrInstructionIdErrWrapCode,
14521452 IrInstructionIdErrWrapPayload,
14531453 IrInstructionIdFnProto,
1454 IrInstructionIdTestComptime,
14541455};
14551456
14561457struct IrInstruction {
......@@ -1472,14 +1473,14 @@ struct IrInstructionCondBr {
14721473 IrInstruction *condition;
14731474 IrBasicBlock *then_block;
14741475 IrBasicBlock *else_block;
1475 bool is_inline;
1476 IrInstruction *is_comptime;
14761477};
14771478
14781479struct IrInstructionBr {
14791480 IrInstruction base;
14801481
14811482 IrBasicBlock *dest_block;
1482 bool is_inline;
1483 IrInstruction *is_comptime;
14831484};
14841485
14851486struct IrInstructionSwitchBrCase {
......@@ -1494,7 +1495,7 @@ struct IrInstructionSwitchBr {
14941495 IrBasicBlock *else_block;
14951496 size_t case_count;
14961497 IrInstructionSwitchBrCase *cases;
1497 bool is_inline;
1498 IrInstruction *is_comptime;
14981499};
14991500
15001501struct IrInstructionSwitchVar {
......@@ -2070,6 +2071,13 @@ struct IrInstructionFnProto {
20702071 IrInstruction *return_type;
20712072};
20722073
2074// true if the target value is compile time known, false otherwise
2075struct IrInstructionTestComptime {
2076 IrInstruction base;
2077
2078 IrInstruction *value;
2079};
2080
20732081enum LValPurpose {
20742082 LValPurposeNone,
20752083 LValPurposeAssign,
src/analyze.cpp+9
......@@ -2924,3 +2924,12 @@ void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry) {
29242924 resolve_union_type(g, type_entry);
29252925 }
29262926}
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);
7676bool type_requires_comptime(TypeTableEntry *type_entry);
7777void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry);
7878void complete_enum(CodeGen *g, TypeTableEntry *enum_type);
79bool ir_get_var_is_comptime(VariableTableEntry *var);
7980
8081ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
8182ScopeDefer *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
16461646}
16471647
16481648static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutable *executable, IrInstructionSwitchBr *instruction) {
1649 assert(!instruction->is_inline);
1650
16511649 LLVMValueRef target_value = ir_llvm_value(g, instruction->target_value);
16521650 LLVMBasicBlockRef else_block = instruction->else_block->llvm_block;
16531651 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,
21972195 case IrInstructionIdMemberCount:
21982196 case IrInstructionIdAlignOf:
21992197 case IrInstructionIdFnProto:
2198 case IrInstructionIdTestComptime:
22002199 zig_unreachable();
22012200 case IrInstructionIdReturn:
22022201 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
......@@ -2897,7 +2896,7 @@ static void do_code_gen(CodeGen *g) {
28972896 if (!type_has_bits(var->type)) {
28982897 continue;
28992898 }
2900 if (var->is_inline)
2899 if (ir_get_var_is_comptime(var))
29012900 continue;
29022901
29032902 if (var->src_arg_index == SIZE_MAX) {
src/ir.cpp+203-102
......@@ -22,7 +22,7 @@ struct IrExecContext {
2222struct LoopStackItem {
2323 IrBasicBlock *break_block;
2424 IrBasicBlock *continue_block;
25 bool is_inline;
25 IrInstruction *is_comptime;
2626};
2727
2828struct IrBuilder {
......@@ -443,6 +443,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFnProto *) {
443443 return IrInstructionIdFnProto;
444444}
445445
446static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) {
447 return IrInstructionIdTestComptime;
448}
449
446450template<typename T>
447451static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
448452 T *special_instruction = allocate<T>(1);
......@@ -475,7 +479,7 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, Scope *scope, AstNode *sourc
475479}
476480
477481static 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)
479483{
480484 IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, scope, source_node);
481485 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
483487 cond_br_instruction->condition = condition;
484488 cond_br_instruction->then_block = then_block;
485489 cond_br_instruction->else_block = else_block;
486 cond_br_instruction->is_inline = is_inline;
490 cond_br_instruction->is_comptime = is_comptime;
487491
488492 ir_ref_instruction(condition);
489493 ir_ref_bb(then_block);
490494 ir_ref_bb(else_block);
495 if (is_comptime) ir_ref_instruction(is_comptime);
491496
492497 return &cond_br_instruction->base;
493498}
494499
495500static 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)
497502{
498503 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);
500505 ir_link_new_instruction(new_instruction, old_instruction);
501506 return new_instruction;
502507}
......@@ -859,30 +864,30 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr
859864}
860865
861866static 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)
863868{
864869 IrInstructionBr *br_instruction = ir_create_instruction<IrInstructionBr>(irb->exec, scope, source_node);
865870 br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
866871 br_instruction->base.static_value.special = ConstValSpecialStatic;
867872 br_instruction->dest_block = dest_block;
868 br_instruction->is_inline = is_inline;
873 br_instruction->is_comptime = is_comptime;
869874
870875 ir_ref_bb(dest_block);
876 if (is_comptime) ir_ref_instruction(is_comptime);
871877
872878 return &br_instruction->base;
873879}
874880
875881static 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)
877883{
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);
879885 ir_instruction_append(irb->current_basic_block, instruction);
880886 return instruction;
881887}
882888
883889static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {
884 IrInstruction *new_instruction = ir_build_br(irb, old_instruction->scope,
885 old_instruction->source_node, dest_block, false);
890 IrInstruction *new_instruction = ir_build_br(irb, old_instruction->scope, old_instruction->source_node, dest_block, nullptr);
886891 ir_link_new_instruction(new_instruction, old_instruction);
887892 return new_instruction;
888893}
......@@ -1291,7 +1296,7 @@ static IrInstruction *ir_build_ctz_from(IrBuilder *irb, IrInstruction *old_instr
12911296}
12921297
12931298static 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)
12951300{
12961301 IrInstructionSwitchBr *instruction = ir_build_instruction<IrInstructionSwitchBr>(irb, scope, source_node);
12971302 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 *
13001305 instruction->else_block = else_block;
13011306 instruction->case_count = case_count;
13021307 instruction->cases = cases;
1303 instruction->is_inline = is_inline;
1308 instruction->is_comptime = is_comptime;
13041309
13051310 ir_ref_instruction(target_value);
1311 if (is_comptime) ir_ref_instruction(is_comptime);
13061312 ir_ref_bb(else_block);
13071313
13081314 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 *
13151321
13161322static IrInstruction *ir_build_switch_br_from(IrBuilder *irb, IrInstruction *old_instruction,
13171323 IrInstruction *target_value, IrBasicBlock *else_block, size_t case_count,
1318 IrInstructionSwitchBrCase *cases, bool is_inline)
1324 IrInstructionSwitchBrCase *cases, IrInstruction *is_comptime)
13191325{
13201326 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);
13221328 ir_link_new_instruction(new_instruction, old_instruction);
13231329 return new_instruction;
13241330}
......@@ -1846,6 +1852,15 @@ static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *s
18461852 return &instruction->base;
18471853}
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
18491864static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
18501865 results[ReturnKindUnconditional] = 0;
18511866 results[ReturnKindError] = 0;
......@@ -1902,7 +1917,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
19021917 }
19031918
19041919 Scope *outer_scope = fn_entry->child_scope;
1905 bool is_inline = ir_should_inline(irb);
19061920
19071921 AstNode *expr_node = node->data.return_expr.expr;
19081922 switch (node->data.return_expr.kind) {
......@@ -1945,7 +1959,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
19451959
19461960 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "ErrRetReturn");
19471961 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
19501965 ir_set_cursor_at_end(irb, return_block);
19511966 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,
19691984
19701985 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn");
19711986 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
19741990 ir_set_cursor_at_end(irb, return_block);
19751991 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,
19882004}
19892005
19902006static 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)
19922008{
19932009 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
19942010 variable_entry->parent_scope = parent_scope;
19952011 variable_entry->shadowable = is_shadowable;
19962012 variable_entry->mem_slot_index = SIZE_MAX;
1997 variable_entry->is_inline = is_inline;
2013 variable_entry->is_comptime = is_comptime;
19982014 variable_entry->src_arg_index = SIZE_MAX;
19992015
20002016 if (name) {
......@@ -2043,11 +2059,10 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco
20432059// Set name to nullptr to make the variable anonymous (not visible to programmer).
20442060// After you call this function var->child_scope has the variable in scope
20452061static 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)
20472063{
2048 VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name,
2049 src_is_const, gen_is_const, is_shadowable, is_inline);
2050 if (is_inline || gen_is_const)
2064 VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name, src_is_const, gen_is_const, is_shadowable, is_comptime);
2065 if (is_comptime != nullptr || gen_is_const)
20512066 var->mem_slot_index = exec_next_mem_slot(irb->exec);
20522067 assert(var->child_scope);
20532068 return var;
......@@ -2123,19 +2138,24 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no
21232138static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node) {
21242139 assert(node->type == NodeTypeBinOpExpr);
21252140
2126 bool is_inline = ir_should_inline(irb);
2127
21282141 IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope);
21292142 if (val1 == irb->codegen->invalid_instruction)
21302143 return irb->codegen->invalid_instruction;
21312144 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
21332153 // block for when val1 == false
21342154 IrBasicBlock *false_block = ir_build_basic_block(irb, scope, "BoolOrFalse");
21352155 // block for when val1 == true (don't even evaluate the second part)
21362156 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
21402160 ir_set_cursor_at_end(irb, false_block);
21412161 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
21432163 return irb->codegen->invalid_instruction;
21442164 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
21482168 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
21602180static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *node) {
21612181 assert(node->type == NodeTypeBinOpExpr);
21622182
2163 bool is_inline = ir_should_inline(irb);
2164
21652183 IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope);
21662184 if (val1 == irb->codegen->invalid_instruction)
21672185 return irb->codegen->invalid_instruction;
21682186 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
21702195 // block for when val1 == true
21712196 IrBasicBlock *true_block = ir_build_basic_block(irb, scope, "BoolAndTrue");
21722197 // block for when val1 == false (don't even evaluate the second part)
21732198 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
21772202 ir_set_cursor_at_end(irb, true_block);
21782203 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
21802205 return irb->codegen->invalid_instruction;
21812206 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
21852210 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
22002225 AstNode *op1_node = node->data.bin_op_expr.op1;
22012226 AstNode *op2_node = node->data.bin_op_expr.op2;
22022227
2203 bool is_inline = ir_should_inline(irb);
2204
22052228 IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf);
22062229 if (maybe_ptr == irb->codegen->invalid_instruction)
22072230 return irb->codegen->invalid_instruction;
22082231
22092232 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
22112241 IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "MaybeNonNull");
22122242 IrBasicBlock *null_block = ir_build_basic_block(irb, parent_scope, "MaybeNull");
22132243 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
22162246 ir_set_cursor_at_end(irb, null_block);
22172247 IrInstruction *null_result = ir_gen_node(irb, op2_node, parent_scope);
22182248 if (null_result == irb->codegen->invalid_instruction)
22192249 return irb->codegen->invalid_instruction;
22202250 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
22232253 ir_set_cursor_at_end(irb, ok_block);
22242254 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);
22252255 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
22262256 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
22292259 ir_set_cursor_at_end(irb, end_block);
22302260 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
......@@ -2944,6 +2974,13 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
29442974 if (condition == irb->codegen->invalid_instruction)
29452975 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
29472984 AstNode *then_node = node->data.if_bool_expr.then_block;
29482985 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
29512988 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "Else");
29522989 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;
2955 ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_inline);
2991 ir_build_cond_br(irb, scope, condition->source_node, condition, then_block, else_block, is_comptime);
29562992
29572993 ir_set_cursor_at_end(irb, then_block);
29582994 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, scope);
29592995 if (then_expr_result == irb->codegen->invalid_instruction)
29602996 return then_expr_result;
29612997 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
29643000 ir_set_cursor_at_end(irb, else_block);
29653001 IrInstruction *else_expr_result;
......@@ -2971,7 +3007,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
29713007 else_expr_result = ir_build_const_void(irb, scope, node);
29723008 }
29733009 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
29763012 ir_set_cursor_at_end(irb, endif_block);
29773013 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
......@@ -3162,9 +3198,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
31623198 bool is_shadowable = false;
31633199 bool is_const = variable_declaration->is_const;
31643200 bool is_extern = variable_declaration->is_extern;
3165 bool is_inline = ir_should_inline(irb) || variable_declaration->is_inline;
3166 VariableTableEntry *var = ir_create_var(irb, node, scope,
3167 variable_declaration->symbol, is_const, is_const, is_shadowable, is_inline);
3201 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
3202 ir_should_inline(irb) || variable_declaration->is_inline);
3203 VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
3204 is_const, is_const, is_shadowable, is_comptime);
31683205 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node
31693206 // is inside var->child_scope
31703207
......@@ -3192,29 +3229,30 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
31923229 ir_build_basic_block(irb, scope, "WhileContinue") : cond_block;
31933230 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;
3196 ir_build_br(irb, scope, node, cond_block, is_inline);
3232 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
3233 ir_should_inline(irb) || node->data.while_expr.is_inline);
3234 ir_build_br(irb, scope, node, cond_block, is_comptime);
31973235
31983236 if (continue_expr_node) {
31993237 ir_set_cursor_at_end(irb, continue_block);
32003238 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);
32023240 }
32033241
32043242 ir_set_cursor_at_end(irb, cond_block);
32053243 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
32083246 ir_set_cursor_at_end(irb, body_block);
32093247
32103248 LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
32113249 loop_stack_item->break_block = end_block;
32123250 loop_stack_item->continue_block = continue_block;
3213 loop_stack_item->is_inline = is_inline;
3251 loop_stack_item->is_comptime = is_comptime;
32143252 ir_gen_node(irb, node->data.while_expr.body, scope);
32153253 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);
32183256 ir_set_cursor_at_end(irb, end_block);
32193257
32203258 return ir_build_const_void(irb, scope, node);
......@@ -3248,14 +3286,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
32483286 } else {
32493287 elem_var_type = ir_build_ptr_type_child(irb, parent_scope, elem_node, pointer_type);
32503288 }
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
32533293 Scope *child_scope = create_loop_scope(node, parent_scope);
32543294
32553295 // TODO make it an error to write to element variable or i variable.
32563296 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,
3258 true, false, false, is_inline);
3297 VariableTableEntry *elem_var = ir_create_var(irb, elem_node, child_scope, elem_var_name, true, false, false, is_comptime);
32593298 child_scope = elem_var->child_scope;
32603299
32613300 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
32673306 if (index_node) {
32683307 index_var_source_node = index_node;
32693308 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);
32713310 } else {
32723311 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);
32743313 }
32753314 child_scope = index_var->child_scope;
32763315
......@@ -3287,12 +3326,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
32873326 IrBasicBlock *continue_block = ir_build_basic_block(irb, child_scope, "ForContinue");
32883327
32893328 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
32923331 ir_set_cursor_at_end(irb, cond_block);
32933332 IrInstruction *index_val = ir_build_load_ptr(irb, child_scope, node, index_ptr);
32943333 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
32973336 ir_set_cursor_at_end(irb, body_block);
32983337 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
33073346 LoopStackItem *loop_stack_item = irb->loop_stack.add_one();
33083347 loop_stack_item->break_block = end_block;
33093348 loop_stack_item->continue_block = continue_block;
3310 loop_stack_item->is_inline = is_inline;
3349 loop_stack_item->is_comptime = is_comptime;
33113350 ir_gen_node(irb, body_node, child_scope);
33123351 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
33163355 ir_set_cursor_at_end(irb, continue_block);
33173356 IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false);
33183357 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
33213360 ir_set_cursor_at_end(irb, end_block);
33223361 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 *
34673506 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "MaybeElse");
34683507 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;
3471 ir_build_cond_br(irb, scope, node, is_nonnull_value, then_block, else_block, is_inline);
3509 IrInstruction *is_comptime;
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
34733517 ir_set_cursor_at_end(irb, then_block);
34743518 IrInstruction *var_type = nullptr;
......@@ -3480,7 +3524,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
34803524 bool is_shadowable = false;
34813525 bool is_const = var_decl->is_const;
34823526 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
34853529 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, expr_value, false);
34863530 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 *
34893533 if (then_expr_result == irb->codegen->invalid_instruction)
34903534 return then_expr_result;
34913535 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
34943538 ir_set_cursor_at_end(irb, else_block);
34953539 IrInstruction *else_expr_result;
......@@ -3501,7 +3545,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
35013545 else_expr_result = ir_build_const_void(irb, scope, node);
35023546 }
35033547 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
35063550 ir_set_cursor_at_end(irb, endif_block);
35073551 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
......@@ -3515,7 +3559,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
35153559}
35163560
35173561static 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,
35193563 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
35203564{
35213565 assert(switch_node->type == NodeTypeSwitchExpr);
......@@ -3532,7 +3576,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
35323576 bool is_shadowable = false;
35333577 bool is_const = true;
35343578 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);
35363580 child_scope = var->child_scope;
35373581 IrInstruction *var_value;
35383582 if (prong_value) {
......@@ -3550,7 +3594,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
35503594 IrInstruction *expr_result = ir_gen_node(irb, expr_node, child_scope);
35513595 if (expr_result == irb->codegen->invalid_instruction)
35523596 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);
35543598 incoming_blocks->append(irb->current_basic_block);
35553599 incoming_values->append(expr_result);
35563600 return true;
......@@ -3570,7 +3614,13 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
35703614
35713615 size_t prong_count = node->data.switch_expr.prongs.length;
35723616 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
35753625 ZigList<IrInstruction *> incoming_values = {0};
35763626 ZigList<IrBasicBlock *> incoming_blocks = {0};
......@@ -3592,7 +3642,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
35923642 IrBasicBlock *prev_block = irb->current_basic_block;
35933643 ir_set_cursor_at_end(irb, else_block);
35943644 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))
35963646 {
35973647 return irb->codegen->invalid_instruction;
35983648 }
......@@ -3650,11 +3700,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
36503700
36513701 assert(ok_bit);
36523702 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
36553705 ir_set_cursor_at_end(irb, range_block_yes);
36563706 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))
36583708 {
36593709 return irb->codegen->invalid_instruction;
36603710 }
......@@ -3683,7 +3733,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
36833733 IrBasicBlock *prev_block = irb->current_basic_block;
36843734 ir_set_cursor_at_end(irb, prong_block);
36853735 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))
36873737 {
36883738 return irb->codegen->invalid_instruction;
36893739 }
......@@ -3695,9 +3745,9 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
36953745 }
36963746
36973747 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);
36993749 } 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);
37013751 }
37023752
37033753 if (!else_prong) {
......@@ -3754,8 +3804,9 @@ static IrInstruction *ir_gen_label(IrBuilder *irb, Scope *scope, AstNode *node)
37543804 scope_block->label_table.put(label_name, label);
37553805 }
37563806
3757 bool is_inline = ir_should_inline(irb);
3758 ir_build_br(irb, scope, node, label_block, is_inline);
3807 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
3808 ir_should_inline(irb));
3809 ir_build_br(irb, scope, node, label_block, is_comptime);
37593810 ir_set_cursor_at_end(irb, label_block);
37603811 return ir_build_const_void(irb, scope, node);
37613812}
......@@ -3785,11 +3836,18 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)
37853836 return irb->codegen->invalid_instruction;
37863837 }
37873838
3788 bool is_inline = ir_should_inline(irb) || node->data.break_expr.is_inline;
37893839 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
37903848 IrBasicBlock *dest_block = loop_stack_item->break_block;
37913849 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);
37933851}
37943852
37953853static 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
38013859 return irb->codegen->invalid_instruction;
38023860 }
38033861
3804 bool is_inline = ir_should_inline(irb) || node->data.continue_expr.is_inline;
38053862 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
38063871 IrBasicBlock *dest_block = loop_stack_item->continue_block;
38073872 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);
38093874}
38103875
38113876static 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
38633928 AstNode *op2_node = node->data.unwrap_err_expr.op2;
38643929 AstNode *var_node = node->data.unwrap_err_expr.symbol;
38653930
3866 bool is_inline = ir_should_inline(irb);
3867
38683931 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf);
38693932 if (err_union_ptr == irb->codegen->invalid_instruction)
38703933 return irb->codegen->invalid_instruction;
38713934
38723935 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
38743944 IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrOk");
38753945 IrBasicBlock *err_block = ir_build_basic_block(irb, parent_scope, "UnwrapErrError");
38763946 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
38793949 ir_set_cursor_at_end(irb, err_block);
38803950 Scope *err_scope;
......@@ -3886,7 +3956,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
38863956 bool is_const = true;
38873957 bool is_shadowable = false;
38883958 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);
38903960 err_scope = var->child_scope;
38913961 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
38923962 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
38973967 if (err_result == irb->codegen->invalid_instruction)
38983968 return irb->codegen->invalid_instruction;
38993969 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
39023972 ir_set_cursor_at_end(irb, ok_block);
39033973 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false);
39043974 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
39053975 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
39083978 ir_set_cursor_at_end(irb, end_block);
39093979 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
......@@ -4108,9 +4178,10 @@ static bool ir_goto_pass2(IrBuilder *irb) {
41084178 }
41094179 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);
41124183 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);
41144185 }
41154186
41164187 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
41764247 add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1);
41774248}
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
41794252static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) {
41804253 ira->new_irb.exec->invalid = true;
41814254 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
59676040 var->type = result_type;
59686041 assert(var->type);
59696042
6043 bool is_comptime = ir_get_var_is_comptime(var);
6044
59706045 if (casted_init_value->static_value.special != ConstValSpecialRuntime) {
59716046 if (var->mem_slot_index != SIZE_MAX) {
59726047 assert(var->mem_slot_index < ira->exec_context.mem_slot_count);
59736048 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
59746049 *mem_slot = casted_init_value->static_value;
59756050
5976 if (var->is_inline) {
6051 if (is_comptime) {
59776052 ir_build_const_from(ira, &decl_var_instruction->base, false);
59786053 return ira->codegen->builtin_types.entry_void;
59796054 }
59806055 }
5981 } else if (var->is_inline) {
6056 } else if (is_comptime) {
59826057 ir_add_error(ira, &decl_var_instruction->base,
59836058 buf_sprintf("cannot store runtime value in compile time variable"));
59846059 var->type = ira->codegen->builtin_types.entry_invalid;
......@@ -6586,9 +6661,12 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
65866661static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
65876662 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)
65906669 return ir_inline_bb(ira, &br_instruction->base, old_dest_block);
6591 }
65926670
65936671 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);
65946672 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
66006678 if (condition->type_entry->id == TypeTableEntryIdInvalid)
66016679 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)) {
66046686 bool cond_is_true;
66056687 if (!ir_resolve_bool(ira, condition, &cond_is_true))
66066688 return ir_unreach_error(ira);
......@@ -6608,7 +6690,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
66086690 IrBasicBlock *old_dest_block = cond_is_true ?
66096691 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)
66126694 return ir_inline_bb(ira, &cond_br_instruction->base, old_dest_block);
66136695 }
66146696
......@@ -6620,7 +6702,7 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
66206702 IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block);
66216703 IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block);
66226704 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);
66246706 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
66256707}
66266708
......@@ -6723,6 +6805,8 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc
67236805 if (var->type->id == TypeTableEntryIdInvalid)
67246806 return var->type;
67256807
6808 bool is_comptime = ir_get_var_is_comptime(var);
6809
67266810 ConstExprValue *mem_slot = nullptr;
67276811 FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope);
67286812 if (var->src_is_const && var->value) {
......@@ -6730,12 +6814,12 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc
67306814 assert(mem_slot->special != ConstValSpecialRuntime);
67316815 } else if (fn_entry) {
67326816 // 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))
67346818 mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
67356819 }
67366820
67376821 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {
6738 ConstPtrSpecial ptr_special = var->is_inline ? ConstPtrSpecialInline : ConstPtrSpecialNone;
6822 ConstPtrSpecial ptr_special = is_comptime ? ConstPtrSpecialInline : ConstPtrSpecialNone;
67396823 return ir_analyze_const_ptr(ira, instruction, mem_slot, var->type, false, ptr_special, var->src_is_const);
67406824 } else {
67416825 ir_build_var_ptr_from(&ira->new_irb, instruction, var);
......@@ -7827,9 +7911,12 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
78277911 return ir_unreach_error(ira);
78287912
78297913 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)) {
78337920 ConstExprValue *target_val = ir_resolve_const(ira, target_value, UndefBad);
78347921 if (!target_val)
78357922 return ir_unreach_error(ira);
......@@ -7856,7 +7943,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_br(IrAnalyze *ira,
78567943
78577944 if (const_values_equal(target_val, case_val, target_value->type_entry)) {
78587945 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) {
78607947 return ir_inline_bb(ira, &switch_br_instruction->base, old_dest_block);
78617948 } else {
78627949 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,
78987985
78997986 IrBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block);
79007987 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);
79027989 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
79037990}
79047991
......@@ -9520,6 +9607,16 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc
95209607 return ira->codegen->builtin_types.entry_type;
95219608}
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
95239620static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
95249621 switch (instruction->id) {
95259622 case IrInstructionIdInvalid:
......@@ -9662,6 +9759,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
96629759 return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction);
96639760 case IrInstructionIdFnProto:
96649761 return ir_analyze_instruction_fn_proto(ira, (IrInstructionFnProto *)instruction);
9762 case IrInstructionIdTestComptime:
9763 return ir_analyze_instruction_test_comptime(ira, (IrInstructionTestComptime *)instruction);
96659764 case IrInstructionIdMaybeWrap:
96669765 case IrInstructionIdErrWrapCode:
96679766 case IrInstructionIdErrWrapPayload:
......@@ -9823,6 +9922,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
98239922 case IrInstructionIdErrWrapCode:
98249923 case IrInstructionIdErrWrapPayload:
98259924 case IrInstructionIdFnProto:
9925 case IrInstructionIdTestComptime:
98269926 return false;
98279927 case IrInstructionIdAsm:
98289928 {
......@@ -9832,3 +9932,4 @@ bool ir_has_side_effects(IrInstruction *instruction) {
98329932 }
98339933 zig_unreachable();
98349934}
9935
src/ir_print.cpp+30-9
......@@ -310,17 +310,20 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
310310}
311311
312312static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {
313 const char *inline_kw = decl_var_instruction->var->is_inline ? "inline " : "";
314313 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
315314 const char *name = buf_ptr(&decl_var_instruction->var->name);
316315 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);
318317 ir_print_other_instruction(irp, decl_var_instruction->var_type);
319318 fprintf(irp->f, " = ");
320319 } else {
321 fprintf(irp->f, "%s%s %s = ", inline_kw, var_or_const, name);
320 fprintf(irp->f, "%s %s = ", var_or_const, name);
322321 }
323322 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 }
324327}
325328
326329static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
......@@ -347,19 +350,25 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
347350}
348351
349352static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
350 const char *inline_kw = cond_br_instruction->is_inline ? "inline " : "";
351 fprintf(irp->f, "%sif (", inline_kw);
353 fprintf(irp->f, "if (");
352354 ir_print_other_instruction(irp, cond_br_instruction->condition);
353355 fprintf(irp->f, ") ");
354356 ir_print_other_block(irp, cond_br_instruction->then_block);
355357 fprintf(irp->f, " else ");
356358 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 }
357363}
358364
359365static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
360 const char *inline_kw = br_instruction->is_inline ? "inline " : "";
361 fprintf(irp->f, "%sgoto ", inline_kw);
366 fprintf(irp->f, "goto ");
362367 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 }
363372}
364373
365374static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
......@@ -597,8 +606,7 @@ static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) {
597606}
598607
599608static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction) {
600 const char *inline_kw = instruction->is_inline ? "inline " : "";
601 fprintf(irp->f, "%sswitch (", inline_kw);
609 fprintf(irp->f, "switch (");
602610 ir_print_other_instruction(irp, instruction->target_value);
603611 fprintf(irp->f, ") ");
604612 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)
610618 }
611619 fprintf(irp->f, "else => ");
612620 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 }
613625}
614626
615627static void ir_print_switch_var(IrPrint *irp, IrInstructionSwitchVar *instruction) {
......@@ -893,6 +905,12 @@ static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) {
893905 ir_print_other_instruction(irp, instruction->return_type);
894906}
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
896914static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
897915 ir_print_prefix(irp, instruction);
898916 switch (instruction->id) {
......@@ -1126,6 +1144,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
11261144 case IrInstructionIdFnProto:
11271145 ir_print_fn_proto(irp, (IrInstructionFnProto *)instruction);
11281146 break;
1147 case IrInstructionIdTestComptime:
1148 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
1149 break;
11291150 }
11301151 fprintf(irp->f, "\n");
11311152}