authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-03 14:13:57-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-03 14:13:57-04:00
logc8333d0cc9a2941ea35f1202073dabd9058beebc
tree4af6d5e7611cfb3b1f24626a5c8618bde7550f78
parent1a0111d4c36578b64d8532724afd9be9ca61d3d1

add concept of inline for, inline while, inline var


8 files changed, 217 insertions(+), 108 deletions(-)

doc/langref.md+3-3
...@@ -15,7 +15,7 @@ ErrorValueDecl = "error" Symbol ";"...@@ -15,7 +15,7 @@ ErrorValueDecl = "error" Symbol ";"
1515
16GlobalVarDecl = VariableDeclaration ";"16GlobalVarDecl = VariableDeclaration ";"
1717
18VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) "=" Expression18VariableDeclaration = option("inline") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
1919
20ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}"20ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}"
2121
...@@ -79,9 +79,9 @@ SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" Symbol "|") Expre...@@ -79,9 +79,9 @@ SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" Symbol "|") Expre
7979
80SwitchItem = Expression | (Expression "..." Expression)80SwitchItem = Expression | (Expression "..." Expression)
8181
82WhileExpression = "while" "(" Expression option(";" Expression) ")" Expression82WhileExpression = option("inline") "while" "(" Expression option(";" Expression) ")" Expression
8383
84ForExpression = "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") Expression84ForExpression = option("inline") "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") Expression
8585
86BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression86BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression
8787
src/all_types.hpp+13-1
...@@ -301,6 +301,7 @@ struct AstNodeVariableDeclaration {...@@ -301,6 +301,7 @@ struct AstNodeVariableDeclaration {
301 TopLevelDecl top_level_decl;301 TopLevelDecl top_level_decl;
302 Buf *symbol;302 Buf *symbol;
303 bool is_const;303 bool is_const;
304 bool is_inline;
304 bool is_extern;305 bool is_extern;
305 // one or both of type and expr will be non null306 // one or both of type and expr will be non null
306 AstNode *type;307 AstNode *type;
...@@ -522,6 +523,7 @@ struct AstNodeWhileExpr {...@@ -522,6 +523,7 @@ struct AstNodeWhileExpr {
522 AstNode *condition;523 AstNode *condition;
523 AstNode *continue_expr;524 AstNode *continue_expr;
524 AstNode *body;525 AstNode *body;
526 bool is_inline;
525527
526 // populated by semantic analyzer528 // populated by semantic analyzer
527 bool condition_always_true;529 bool condition_always_true;
...@@ -536,6 +538,7 @@ struct AstNodeForExpr {...@@ -536,6 +538,7 @@ struct AstNodeForExpr {
536 AstNode *index_node; // always a symbol, might be null538 AstNode *index_node; // always a symbol, might be null
537 AstNode *body;539 AstNode *body;
538 bool elem_is_ptr;540 bool elem_is_ptr;
541 bool is_inline;
539542
540 // populated by semantic analyzer543 // populated by semantic analyzer
541 bool contains_break;544 bool contains_break;
...@@ -1337,7 +1340,9 @@ struct VariableTableEntry {...@@ -1337,7 +1340,9 @@ struct VariableTableEntry {
1337 Buf name;1340 Buf name;
1338 TypeTableEntry *type;1341 TypeTableEntry *type;
1339 LLVMValueRef value_ref;1342 LLVMValueRef value_ref;
1340 bool is_const;1343 bool src_is_const;
1344 bool gen_is_const;
1345 bool is_inline;
1341 // which node is the declaration of the variable1346 // which node is the declaration of the variable
1342 AstNode *decl_node;1347 AstNode *decl_node;
1343 // which node contains the ConstExprValue for this variable's value1348 // which node contains the ConstExprValue for this variable's value
...@@ -1457,6 +1462,10 @@ struct IrInstruction {...@@ -1457,6 +1462,10 @@ struct IrInstruction {
1457 size_t ref_count;1462 size_t ref_count;
1458 IrInstruction *other;1463 IrInstruction *other;
1459 ReturnKnowledge return_knowledge;1464 ReturnKnowledge return_knowledge;
1465 // if this is true, this instruction should not cause compile errors.
1466 // for example, we can write to a variable with src_is_const true but
1467 // gen_is_const false.
1468 bool gen_only;
1460};1469};
14611470
1462struct IrInstructionCondBr {1471struct IrInstructionCondBr {
...@@ -1465,12 +1474,14 @@ struct IrInstructionCondBr {...@@ -1465,12 +1474,14 @@ struct IrInstructionCondBr {
1465 IrInstruction *condition;1474 IrInstruction *condition;
1466 IrBasicBlock *then_block;1475 IrBasicBlock *then_block;
1467 IrBasicBlock *else_block;1476 IrBasicBlock *else_block;
1477 bool is_inline;
1468};1478};
14691479
1470struct IrInstructionBr {1480struct IrInstructionBr {
1471 IrInstruction base;1481 IrInstruction base;
14721482
1473 IrBasicBlock *dest_block;1483 IrBasicBlock *dest_block;
1484 bool is_inline;
1474};1485};
14751486
1476struct IrInstructionSwitchBrCase {1487struct IrInstructionSwitchBrCase {
...@@ -1485,6 +1496,7 @@ struct IrInstructionSwitchBr {...@@ -1485,6 +1496,7 @@ struct IrInstructionSwitchBr {
1485 IrBasicBlock *else_block;1496 IrBasicBlock *else_block;
1486 size_t case_count;1497 size_t case_count;
1487 IrInstructionSwitchBrCase *cases;1498 IrInstructionSwitchBrCase *cases;
1499 bool is_inline;
1488};1500};
14891501
1490struct IrInstructionPhi {1502struct IrInstructionPhi {
src/analyze.cpp+5-4
...@@ -3026,7 +3026,7 @@ static bool var_is_pure(VariableTableEntry *var, BlockContext *context) {...@@ -3026,7 +3026,7 @@ static bool var_is_pure(VariableTableEntry *var, BlockContext *context) {
3026 // variable was declared in the current function, so it's OK.3026 // variable was declared in the current function, so it's OK.
3027 return true;3027 return true;
3028 }3028 }
3029 return var->is_const && var->type->deep_const;3029 return var->src_is_const && var->type->deep_const;
3030}3030}
30313031
3032static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var,3032static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var,
...@@ -3036,7 +3036,7 @@ static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, Variabl...@@ -3036,7 +3036,7 @@ static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, Variabl
3036 if (!var_is_pure(var, context)) {3036 if (!var_is_pure(var, context)) {
3037 mark_impure_fn(g, context, source_node);3037 mark_impure_fn(g, context, source_node);
3038 }3038 }
3039 if (var->is_const && var->val_node) {3039 if (var->src_is_const && var->val_node) {
3040 ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val;3040 ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val;
3041 if (other_const_val->ok) {3041 if (other_const_val->ok) {
3042 return resolve_expr_const_val_as_other_expr(g, source_node, var->val_node,3042 return resolve_expr_const_val_as_other_expr(g, source_node, var->val_node,
...@@ -3188,7 +3188,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc...@@ -3188,7 +3188,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
3188 Buf *name = lhs_node->data.symbol_expr.symbol;3188 Buf *name = lhs_node->data.symbol_expr.symbol;
3189 VariableTableEntry *var = find_variable(g, block_context, name);3189 VariableTableEntry *var = find_variable(g, block_context, name);
3190 if (var) {3190 if (var) {
3191 if (var->is_const) {3191 if (var->src_is_const) {
3192 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));3192 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));
3193 expected_rhs_type = g->builtin_types.entry_invalid;3193 expected_rhs_type = g->builtin_types.entry_invalid;
3194 } else {3194 } else {
...@@ -3736,7 +3736,8 @@ static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_...@@ -3736,7 +3736,8 @@ static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_
3736 context->fn_entry->variable_list.append(variable_entry);3736 context->fn_entry->variable_list.append(variable_entry);
3737 }3737 }
37383738
3739 variable_entry->is_const = is_const;3739 variable_entry->src_is_const = is_const;
3740 variable_entry->gen_is_const = is_const;
3740 variable_entry->decl_node = source_node;3741 variable_entry->decl_node = source_node;
3741 variable_entry->val_node = val_node;3742 variable_entry->val_node = val_node;
37423743
src/codegen.cpp+3-3
...@@ -4105,7 +4105,7 @@ static void build_all_basic_blocks(CodeGen *g, FnTableEntry *fn) {...@@ -4105,7 +4105,7 @@ static void build_all_basic_blocks(CodeGen *g, FnTableEntry *fn) {
4105static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef init_val,4105static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef init_val,
4106 TypeTableEntry *type_entry)4106 TypeTableEntry *type_entry)
4107{4107{
4108 assert(var->is_const);4108 assert(var->gen_is_const);
4109 assert(var->import);4109 assert(var->import);
4110 assert(type_entry);4110 assert(type_entry);
4111 bool is_local_to_unit = true;4111 bool is_local_to_unit = true;
...@@ -4183,12 +4183,12 @@ static void do_code_gen(CodeGen *g) {...@@ -4183,12 +4183,12 @@ static void do_code_gen(CodeGen *g) {
4183 LLVMSetUnnamedAddr(global_value, true);4183 LLVMSetUnnamedAddr(global_value, true);
41844184
4185 // TODO debug info for function pointers4185 // TODO debug info for function pointers
4186 if (var->is_const && var->type->id != TypeTableEntryIdFn) {4186 if (var->gen_is_const && var->type->id != TypeTableEntryIdFn) {
4187 gen_global_var(g, var, init_val, var->type);4187 gen_global_var(g, var, init_val, var->type);
4188 }4188 }
4189 }4189 }
41904190
4191 LLVMSetGlobalConstant(global_value, var->is_const);4191 LLVMSetGlobalConstant(global_value, var->gen_is_const);
41924192
4193 var->value_ref = global_value;4193 var->value_ref = global_value;
4194 }4194 }
src/ir.cpp+105-72
...@@ -200,6 +200,7 @@ static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {...@@ -200,6 +200,7 @@ static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
200200
201template<typename T>201template<typename T>
202static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) {202static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) {
203 assert(source_node);
203 T *special_instruction = ir_create_instruction<T>(irb->exec, source_node);204 T *special_instruction = ir_create_instruction<T>(irb->exec, source_node);
204 ir_instruction_append(irb->current_basic_block, &special_instruction->base);205 ir_instruction_append(irb->current_basic_block, &special_instruction->base);
205 return special_instruction;206 return special_instruction;
...@@ -220,7 +221,7 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInst...@@ -220,7 +221,7 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInst
220}221}
221222
222static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrInstruction *condition,223static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrInstruction *condition,
223 IrBasicBlock *then_block, IrBasicBlock *else_block)224 IrBasicBlock *then_block, IrBasicBlock *else_block, bool is_inline)
224{225{
225 IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, source_node);226 IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, source_node);
226 cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;227 cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
...@@ -228,6 +229,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI...@@ -228,6 +229,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI
228 cond_br_instruction->condition = condition;229 cond_br_instruction->condition = condition;
229 cond_br_instruction->then_block = then_block;230 cond_br_instruction->then_block = then_block;
230 cond_br_instruction->else_block = else_block;231 cond_br_instruction->else_block = else_block;
232 cond_br_instruction->is_inline = is_inline;
231233
232 ir_ref_instruction(condition);234 ir_ref_instruction(condition);
233 ir_ref_bb(then_block);235 ir_ref_bb(then_block);
...@@ -237,10 +239,10 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI...@@ -237,10 +239,10 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI
237}239}
238240
239static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_instruction,241static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_instruction,
240 IrInstruction *condition, IrBasicBlock *then_block, IrBasicBlock *else_block)242 IrInstruction *condition, IrBasicBlock *then_block, IrBasicBlock *else_block, bool is_inline)
241{243{
242 IrInstruction *new_instruction = ir_build_cond_br(irb, old_instruction->source_node,244 IrInstruction *new_instruction = ir_build_cond_br(irb, old_instruction->source_node,
243 condition, then_block, else_block);245 condition, then_block, else_block, is_inline);
244 ir_link_new_instruction(new_instruction, old_instruction);246 ir_link_new_instruction(new_instruction, old_instruction);
245 return new_instruction;247 return new_instruction;
246}248}
...@@ -517,22 +519,23 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr...@@ -517,22 +519,23 @@ static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instr
517 return new_instruction;519 return new_instruction;
518}520}
519521
520static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block) {522static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block, bool is_inline) {
521 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);523 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);
522 br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;524 br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
523 br_instruction->base.static_value.ok = true;525 br_instruction->base.static_value.ok = true;
524 br_instruction->dest_block = dest_block;526 br_instruction->dest_block = dest_block;
527 br_instruction->is_inline = is_inline;
525528
526 ir_ref_bb(dest_block);529 ir_ref_bb(dest_block);
527530
528 return &br_instruction->base;531 return &br_instruction->base;
529}532}
530533
531//static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {534static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {
532// IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block);535 IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block, false);
533// ir_link_new_instruction(new_instruction, old_instruction);536 ir_link_new_instruction(new_instruction, old_instruction);
534// return new_instruction;537 return new_instruction;
535//}538}
536539
537static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {540static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {
538 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node);541 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node);
...@@ -634,7 +637,7 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,...@@ -634,7 +637,7 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,
634 decl_var_instruction->var_type = var_type;637 decl_var_instruction->var_type = var_type;
635 decl_var_instruction->init_value = init_value;638 decl_var_instruction->init_value = init_value;
636639
637 ir_ref_instruction(var_type);640 if (var_type) ir_ref_instruction(var_type);
638 ir_ref_instruction(init_value);641 ir_ref_instruction(init_value);
639642
640 return &decl_var_instruction->base;643 return &decl_var_instruction->base;
...@@ -775,13 +778,14 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {...@@ -775,13 +778,14 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
775}778}
776779
777static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockContext *scope,780static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockContext *scope,
778 Buf *name, bool is_const, bool is_shadowable)781 Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline)
779{782{
780 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);783 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
781 variable_entry->block_context = scope;784 variable_entry->block_context = scope;
782 variable_entry->import = node->owner;785 variable_entry->import = node->owner;
783 variable_entry->shadowable = is_shadowable;786 variable_entry->shadowable = is_shadowable;
784 variable_entry->mem_slot_index = SIZE_MAX;787 variable_entry->mem_slot_index = SIZE_MAX;
788 variable_entry->is_inline = is_inline;
785789
786 if (name) {790 if (name) {
787 buf_init_from_buf(&variable_entry->name, name);791 buf_init_from_buf(&variable_entry->name, name);
...@@ -817,7 +821,8 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockC...@@ -817,7 +821,8 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockC
817 buf_init_from_str(&variable_entry->name, "_anon");821 buf_init_from_str(&variable_entry->name, "_anon");
818 }822 }
819823
820 variable_entry->is_const = is_const;824 variable_entry->src_is_const = src_is_const;
825 variable_entry->gen_is_const = gen_is_const;
821 variable_entry->decl_node = node;826 variable_entry->decl_node = node;
822827
823 return variable_entry;828 return variable_entry;
...@@ -825,10 +830,12 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockC...@@ -825,10 +830,12 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockC
825830
826// Set name to nullptr to make the variable anonymous (not visible to programmer).831// Set name to nullptr to make the variable anonymous (not visible to programmer).
827static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, BlockContext *scope, Buf *name,832static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, BlockContext *scope, Buf *name,
828 bool is_const, bool is_shadowable)833 bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline)
829{834{
830 VariableTableEntry *var = add_local_var(irb->codegen, node, scope, name, is_const, is_shadowable);835 VariableTableEntry *var = add_local_var(irb->codegen, node, scope, name,
831 var->mem_slot_index = exec_next_mem_slot(irb->exec);836 src_is_const, gen_is_const, is_shadowable, is_inline);
837 if (is_inline || gen_is_const)
838 var->mem_slot_index = exec_next_mem_slot(irb->exec);
832 return var;839 return var;
833}840}
834841
...@@ -1189,14 +1196,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) {...@@ -1189,14 +1196,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) {
1189 IrBasicBlock *else_block = ir_build_basic_block(irb, "Else");1196 IrBasicBlock *else_block = ir_build_basic_block(irb, "Else");
1190 IrBasicBlock *endif_block = ir_build_basic_block(irb, "EndIf");1197 IrBasicBlock *endif_block = ir_build_basic_block(irb, "EndIf");
11911198
1192 ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block);1199 ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block, false);
11931200
1194 ir_set_cursor_at_end(irb, then_block);1201 ir_set_cursor_at_end(irb, then_block);
1195 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, node->block_context);1202 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, node->block_context);
1196 if (then_expr_result == irb->codegen->invalid_instruction)1203 if (then_expr_result == irb->codegen->invalid_instruction)
1197 return then_expr_result;1204 return then_expr_result;
1198 IrBasicBlock *after_then_block = irb->current_basic_block;1205 IrBasicBlock *after_then_block = irb->current_basic_block;
1199 ir_build_br(irb, node, endif_block);1206 ir_build_br(irb, node, endif_block, false);
12001207
1201 ir_set_cursor_at_end(irb, else_block);1208 ir_set_cursor_at_end(irb, else_block);
1202 IrInstruction *else_expr_result;1209 IrInstruction *else_expr_result;
...@@ -1208,7 +1215,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) {...@@ -1208,7 +1215,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) {
1208 else_expr_result = ir_build_const_void(irb, node);1215 else_expr_result = ir_build_const_void(irb, node);
1209 }1216 }
1210 IrBasicBlock *after_else_block = irb->current_basic_block;1217 IrBasicBlock *after_else_block = irb->current_basic_block;
1211 ir_build_br(irb, node, endif_block);1218 ir_build_br(irb, node, endif_block, false);
12121219
1213 ir_set_cursor_at_end(irb, endif_block);1220 ir_set_cursor_at_end(irb, endif_block);
1214 IrInstruction **incoming_values = allocate<IrInstruction *>(2);1221 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
...@@ -1333,8 +1340,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) {...@@ -1333,8 +1340,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) {
1333 bool is_shadowable = false;1340 bool is_shadowable = false;
1334 bool is_const = variable_declaration->is_const;1341 bool is_const = variable_declaration->is_const;
1335 bool is_extern = variable_declaration->is_extern;1342 bool is_extern = variable_declaration->is_extern;
1343 bool is_inline = variable_declaration->is_inline;
1336 VariableTableEntry *var = ir_add_local_var(irb, node, node->block_context,1344 VariableTableEntry *var = ir_add_local_var(irb, node, node->block_context,
1337 variable_declaration->symbol, is_const, is_shadowable);1345 variable_declaration->symbol, is_const, is_const, is_shadowable, is_inline);
13381346
1339 if (!is_extern && !variable_declaration->expr) {1347 if (!is_extern && !variable_declaration->expr) {
1340 var->type = irb->codegen->builtin_types.entry_invalid;1348 var->type = irb->codegen->builtin_types.entry_invalid;
...@@ -1356,18 +1364,18 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {...@@ -1356,18 +1364,18 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {
1356 ir_build_basic_block(irb, "WhileContinue") : cond_block;1364 ir_build_basic_block(irb, "WhileContinue") : cond_block;
1357 IrBasicBlock *end_block = ir_build_basic_block(irb, "WhileEnd");1365 IrBasicBlock *end_block = ir_build_basic_block(irb, "WhileEnd");
13581366
1359 ir_build_br(irb, node, cond_block);1367 bool is_inline = node->data.while_expr.is_inline;
1368 ir_build_br(irb, node, cond_block, is_inline);
13601369
1361 if (continue_expr_node) {1370 if (continue_expr_node) {
1362 ir_set_cursor_at_end(irb, continue_block);1371 ir_set_cursor_at_end(irb, continue_block);
1363 ir_gen_node(irb, continue_expr_node, node->block_context);1372 ir_gen_node(irb, continue_expr_node, node->block_context);
1364 ir_build_br(irb, node, cond_block);1373 ir_build_br(irb, node, cond_block, is_inline);
1365
1366 }1374 }
13671375
1368 ir_set_cursor_at_end(irb, cond_block);1376 ir_set_cursor_at_end(irb, cond_block);
1369 IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, node->block_context);1377 IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, node->block_context);
1370 ir_build_cond_br(irb, node->data.while_expr.condition, cond_val, body_block, end_block);1378 ir_build_cond_br(irb, node->data.while_expr.condition, cond_val, body_block, end_block, is_inline);
13711379
1372 ir_set_cursor_at_end(irb, body_block);1380 ir_set_cursor_at_end(irb, body_block);
13731381
...@@ -1377,7 +1385,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {...@@ -1377,7 +1385,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {
1377 irb->break_block_stack.pop();1385 irb->break_block_stack.pop();
1378 irb->continue_block_stack.pop();1386 irb->continue_block_stack.pop();
13791387
1380 ir_build_br(irb, node, continue_block);1388 ir_build_br(irb, node, continue_block, is_inline);
1381 ir_set_cursor_at_end(irb, end_block);1389 ir_set_cursor_at_end(irb, end_block);
13821390
1383 return ir_build_const_void(irb, node);1391 return ir_build_const_void(irb, node);
...@@ -1411,30 +1419,36 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) {...@@ -1411,30 +1419,36 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) {
1411 } else {1419 } else {
1412 elem_var_type = ir_build_ptr_type_child(irb, elem_node, pointer_type);1420 elem_var_type = ir_build_ptr_type_child(irb, elem_node, pointer_type);
1413 }1421 }
1422 bool is_inline = node->data.for_expr.is_inline;
14141423
1415 BlockContext *child_scope = new_block_context(node, parent_scope);1424 BlockContext *child_scope = new_block_context(node, parent_scope);
1416 child_scope->parent_loop_node = node;1425 child_scope->parent_loop_node = node;
1417 elem_node->block_context = child_scope;1426 elem_node->block_context = child_scope;
14181427
1419 // TODO make it an error to write to element variable or i variable.1428 // TODO make it an error to write to element variable or i variable.
1420
1421 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;1429 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
1422 node->data.for_expr.elem_var = ir_add_local_var(irb, elem_node, child_scope, elem_var_name, false, false);1430 node->data.for_expr.elem_var = ir_add_local_var(irb, elem_node, child_scope, elem_var_name,
1431 true, false, false, is_inline);
1423 IrInstruction *undefined_value = ir_build_const_undefined(irb, elem_node);1432 IrInstruction *undefined_value = ir_build_const_undefined(irb, elem_node);
1424 ir_build_var_decl(irb, elem_node, node->data.for_expr.elem_var, elem_var_type, undefined_value); 1433 ir_build_var_decl(irb, elem_node, node->data.for_expr.elem_var, elem_var_type, undefined_value);
1425 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.elem_var);1434 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.elem_var);
14261435
1436 AstNode *index_var_source_node;
1427 if (index_node) {1437 if (index_node) {
1438 index_var_source_node = index_node;
1428 Buf *index_var_name = index_node->data.symbol_expr.symbol;1439 Buf *index_var_name = index_node->data.symbol_expr.symbol;
1429 index_node->block_context = child_scope;1440 index_node->block_context = child_scope;
1430 node->data.for_expr.index_var = ir_add_local_var(irb, index_node, child_scope, index_var_name, false, false);1441 node->data.for_expr.index_var = ir_add_local_var(irb, index_node, child_scope, index_var_name,
1442 true, false, false, is_inline);
1431 } else {1443 } else {
1432 node->data.for_expr.index_var = ir_add_local_var(irb, node, child_scope, nullptr, false, true);1444 index_var_source_node = node;
1445 node->data.for_expr.index_var = ir_add_local_var(irb, node, child_scope, nullptr,
1446 true, false, true, is_inline);
1433 }1447 }
1434 IrInstruction *usize = ir_build_const_type(irb, node, irb->codegen->builtin_types.entry_usize);1448 IrInstruction *usize = ir_build_const_type(irb, node, irb->codegen->builtin_types.entry_usize);
1435 IrInstruction *zero = ir_build_const_usize(irb, node, 0);1449 IrInstruction *zero = ir_build_const_usize(irb, node, 0);
1436 IrInstruction *one = ir_build_const_usize(irb, node, 1);1450 IrInstruction *one = ir_build_const_usize(irb, node, 1);
1437 ir_build_var_decl(irb, index_node, node->data.for_expr.index_var, usize, zero); 1451 ir_build_var_decl(irb, index_var_source_node, node->data.for_expr.index_var, usize, zero);
1438 IrInstruction *index_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.index_var);1452 IrInstruction *index_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.index_var);
14391453
14401454
...@@ -1444,12 +1458,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) {...@@ -1444,12 +1458,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) {
1444 IrBasicBlock *continue_block = ir_build_basic_block(irb, "ForContinue");1458 IrBasicBlock *continue_block = ir_build_basic_block(irb, "ForContinue");
14451459
1446 IrInstruction *len_val = ir_build_read_field(irb, node, array_val, irb->codegen->len_buf);1460 IrInstruction *len_val = ir_build_read_field(irb, node, array_val, irb->codegen->len_buf);
1447 ir_build_br(irb, node, cond_block);1461 ir_build_br(irb, node, cond_block, is_inline);
14481462
1449 ir_set_cursor_at_end(irb, cond_block);1463 ir_set_cursor_at_end(irb, cond_block);
1450 IrInstruction *index_val = ir_build_load_ptr(irb, node, index_ptr);1464 IrInstruction *index_val = ir_build_load_ptr(irb, node, index_ptr);
1451 IrInstruction *cond = ir_build_bin_op(irb, node, IrBinOpCmpLessThan, index_val, len_val);1465 IrInstruction *cond = ir_build_bin_op(irb, node, IrBinOpCmpLessThan, index_val, len_val);
1452 ir_build_cond_br(irb, node, cond, body_block, end_block);1466 ir_build_cond_br(irb, node, cond, body_block, end_block, is_inline);
14531467
1454 ir_set_cursor_at_end(irb, body_block);1468 ir_set_cursor_at_end(irb, body_block);
1455 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, node, array_val, index_val);1469 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, node, array_val, index_val);
...@@ -1467,12 +1481,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) {...@@ -1467,12 +1481,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) {
1467 irb->break_block_stack.pop();1481 irb->break_block_stack.pop();
1468 irb->continue_block_stack.pop();1482 irb->continue_block_stack.pop();
14691483
1470 ir_build_br(irb, node, continue_block);1484 ir_build_br(irb, node, continue_block, is_inline);
14711485
1472 ir_set_cursor_at_end(irb, continue_block);1486 ir_set_cursor_at_end(irb, continue_block);
1473 IrInstruction *new_index_val = ir_build_bin_op(irb, node, IrBinOpAdd, index_val, one);1487 IrInstruction *new_index_val = ir_build_bin_op(irb, node, IrBinOpAdd, index_val, one);
1474 ir_build_store_ptr(irb, node, index_ptr, new_index_val);1488 ir_build_store_ptr(irb, node, index_ptr, new_index_val);
1475 ir_build_br(irb, node, cond_block);1489 ir_build_br(irb, node, cond_block, is_inline);
14761490
1477 ir_set_cursor_at_end(irb, end_block);1491 ir_set_cursor_at_end(irb, end_block);
1478 return ir_build_const_void(irb, node);1492 return ir_build_const_void(irb, node);
...@@ -1911,23 +1925,41 @@ static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {...@@ -1911,23 +1925,41 @@ static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
1911}1925}
19121926
19131927
1914static ConstExprValue *ir_get_out_val(IrInstruction *instruction) {1928static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_instruction,
1915 instruction->other = instruction;1929 bool depends_on_compile_var)
1916 return &instruction->static_value;1930{
1931 IrInstruction *new_instruction;
1932 if (old_instruction->id == IrInstructionIdVarPtr) {
1933 IrInstructionVarPtr *old_var_ptr_instruction = (IrInstructionVarPtr *)old_instruction;
1934 IrInstructionVarPtr *var_ptr_instruction = ir_create_instruction<IrInstructionVarPtr>(ira->new_irb.exec,
1935 old_instruction->source_node);
1936 var_ptr_instruction->var = old_var_ptr_instruction->var;
1937 new_instruction = &var_ptr_instruction->base;
1938 } else if (old_instruction->id == IrInstructionIdFieldPtr) {
1939 zig_panic("TODO");
1940 } else if (old_instruction->id == IrInstructionIdElemPtr) {
1941 zig_panic("TODO");
1942 } else {
1943 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec,
1944 old_instruction->source_node);
1945 new_instruction = &const_instruction->base;
1946 }
1947 ir_link_new_instruction(new_instruction, old_instruction);
1948 ConstExprValue *const_val = &new_instruction->static_value;
1949 const_val->ok = true;
1950 const_val->depends_on_compile_var = depends_on_compile_var;
1951 return const_val;
1917}1952}
19181953
1919static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instruction) {1954static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instruction) {
1920 ConstExprValue *const_val = ir_get_out_val(instruction);1955 ir_build_const_from(ira, instruction, false);
1921 const_val->ok = true;
1922 return ira->codegen->builtin_types.entry_void;1956 return ira->codegen->builtin_types.entry_void;
1923}1957}
19241958
1925static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value,1959static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value,
1926 bool depends_on_compile_var)1960 bool depends_on_compile_var)
1927{1961{
1928 ConstExprValue *const_val = ir_get_out_val(instruction);1962 ConstExprValue *const_val = ir_build_const_from(ira, instruction, depends_on_compile_var);
1929 const_val->ok = true;
1930 const_val->depends_on_compile_var = depends_on_compile_var;
1931 bignum_init_unsigned(&const_val->data.x_bignum, value);1963 bignum_init_unsigned(&const_val->data.x_bignum, value);
1932 return ira->codegen->builtin_types.entry_usize;1964 return ira->codegen->builtin_types.entry_usize;
1933}1965}
...@@ -2295,7 +2327,8 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -2295,7 +2327,8 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
2295 ConstExprValue *op1_val = &casted_op1->static_value;2327 ConstExprValue *op1_val = &casted_op1->static_value;
2296 ConstExprValue *op2_val = &casted_op2->static_value;2328 ConstExprValue *op2_val = &casted_op2->static_value;
2297 if (op1_val->ok && op2_val->ok) {2329 if (op1_val->ok && op2_val->ok) {
2298 ConstExprValue *out_val = ir_get_out_val(&bin_op_instruction->base);2330 bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
2331 ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var);
22992332
2300 assert(op1->type_entry->id == TypeTableEntryIdBool);2333 assert(op1->type_entry->id == TypeTableEntryIdBool);
2301 assert(op2->type_entry->id == TypeTableEntryIdBool);2334 assert(op2->type_entry->id == TypeTableEntryIdBool);
...@@ -2306,14 +2339,10 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -2306,14 +2339,10 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
2306 } else {2339 } else {
2307 zig_unreachable();2340 zig_unreachable();
2308 }2341 }
2309 out_val->ok = true;
2310 out_val->depends_on_compile_var = op1_val->depends_on_compile_var ||
2311 op2_val->depends_on_compile_var;
2312 return bool_type;2342 return bool_type;
2313 }2343 }
23142344
2315 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id, op1->other, op2->other);2345 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id, op1->other, op2->other);
2316
2317 return bool_type;2346 return bool_type;
2318}2347}
23192348
...@@ -2425,9 +2454,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -2425,9 +2454,8 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
2425 }2454 }
2426 }2455 }
24272456
2428 ConstExprValue *out_val = ir_get_out_val(&bin_op_instruction->base);2457 bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
2429 out_val->ok = true;2458 ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base, depends_on_compile_var);
2430 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
2431 out_val->data.x_bool = answer;2459 out_val->data.x_bool = answer;
2432 return ira->codegen->builtin_types.entry_bool;2460 return ira->codegen->builtin_types.entry_bool;
2433 }2461 }
...@@ -4108,12 +4136,15 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr...@@ -4108,12 +4136,15 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr
41084136
4109 // TODO detect backward jumps4137 // TODO detect backward jumps
41104138
4111 ir_inline_bb(ira, old_dest_block);4139 if (br_instruction->is_inline || old_dest_block->ref_count == 1) {
4112 return ira->codegen->builtin_types.entry_unreachable;4140 ir_inline_bb(ira, old_dest_block);
4141 return ira->codegen->builtin_types.entry_unreachable;
4142 }
41134143
4114 //IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);4144 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);
4115 //ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);4145 ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);
4116 //return ira->codegen->builtin_types.entry_unreachable;4146 ir_finish_bb(ira);
4147 return ira->codegen->builtin_types.entry_unreachable;
4117}4148}
41184149
4119static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {4150static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {
...@@ -4129,13 +4160,20 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct...@@ -4129,13 +4160,20 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
4129 IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ?4160 IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ?
4130 cond_br_instruction->then_block : cond_br_instruction->else_block;4161 cond_br_instruction->then_block : cond_br_instruction->else_block;
41314162
4132 ir_inline_bb(ira, old_dest_block);4163 if (cond_br_instruction->is_inline || old_dest_block->ref_count == 1) {
4164 ir_inline_bb(ira, old_dest_block);
4165 return ira->codegen->builtin_types.entry_unreachable;
4166 }
4167 } else if (cond_br_instruction->is_inline) {
4168 add_node_error(ira->codegen, condition->source_node,
4169 buf_sprintf("unable to evaluate constant expression"));
4170 ir_finish_bb(ira);
4133 return ira->codegen->builtin_types.entry_unreachable;4171 return ira->codegen->builtin_types.entry_unreachable;
4134 }4172 }
41354173
4136 IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block);4174 IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block);
4137 IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block);4175 IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block);
4138 ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block);4176 ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block, false);
4139 ir_finish_bb(ira);4177 ir_finish_bb(ira);
4140 return ira->codegen->builtin_types.entry_unreachable;4178 return ira->codegen->builtin_types.entry_unreachable;
4141}4179}
...@@ -4206,7 +4244,8 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -4206,7 +4244,8 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
4206 IrInstruction *value = phi_instruction->incoming_values[i]->other;4244 IrInstruction *value = phi_instruction->incoming_values[i]->other;
4207 assert(value->type_entry);4245 assert(value->type_entry);
4208 if (value->static_value.ok) {4246 if (value->static_value.ok) {
4209 ConstExprValue *out_val = ir_get_out_val(&phi_instruction->base);4247 ConstExprValue *out_val = ir_build_const_from(ira, &phi_instruction->base,
4248 value->static_value.depends_on_compile_var);
4210 *out_val = value->static_value;4249 *out_val = value->static_value;
4211 } else {4250 } else {
4212 phi_instruction->base.other = value;4251 phi_instruction->base.other = value;
...@@ -4259,9 +4298,9 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct...@@ -4259,9 +4298,9 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct
4259 if (var->mem_slot_index != SIZE_MAX) {4298 if (var->mem_slot_index != SIZE_MAX) {
4260 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];4299 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
4261 if (mem_slot->ok) {4300 if (mem_slot->ok) {
4262 ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base);4301 ConstExprValue *out_val = ir_build_const_from(ira, &var_ptr_instruction->base,
4302 mem_slot->depends_on_compile_var);
42634303
4264 out_val->ok = true;
4265 out_val->data.x_ptr.len = 1;4304 out_val->data.x_ptr.len = 1;
4266 out_val->data.x_ptr.is_c_str = false;4305 out_val->data.x_ptr.is_c_str = false;
4267 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);4306 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
...@@ -4477,7 +4516,8 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc...@@ -4477,7 +4516,8 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc
4477 if (ptr->static_value.ok) {4516 if (ptr->static_value.ok) {
4478 ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0];4517 ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0];
4479 if (pointee->ok) {4518 if (pointee->ok) {
4480 ConstExprValue *out_val = ir_get_out_val(&load_ptr_instruction->base);4519 ConstExprValue *out_val = ir_build_const_from(ira, &load_ptr_instruction->base,
4520 pointee->depends_on_compile_var);
4481 *out_val = *pointee;4521 *out_val = *pointee;
4482 return child_type;4522 return child_type;
4483 }4523 }
...@@ -4576,8 +4616,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi...@@ -4576,8 +4616,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
4576 case TypeTableEntryIdFn:4616 case TypeTableEntryIdFn:
4577 case TypeTableEntryIdTypeDecl:4617 case TypeTableEntryIdTypeDecl:
4578 {4618 {
4579 ConstExprValue *out_val = ir_get_out_val(&typeof_instruction->base);4619 ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base, false);
4580 out_val->ok = true;
4581 // TODO depends_on_compile_var should be set based on whether the type of the expression 4620 // TODO depends_on_compile_var should be set based on whether the type of the expression
4582 // depends_on_compile_var. but we currently don't have a thing to tell us if the type of4621 // depends_on_compile_var. but we currently don't have a thing to tell us if the type of
4583 // something depends on a compile var4622 // something depends on a compile var
...@@ -4609,9 +4648,8 @@ static TypeTableEntry *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,...@@ -4609,9 +4648,8 @@ static TypeTableEntry *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
4609 return ira->codegen->builtin_types.entry_invalid;4648 return ira->codegen->builtin_types.entry_invalid;
4610 }4649 }
46114650
4612 ConstExprValue *out_val = ir_get_out_val(&to_ptr_type_instruction->base);4651 ConstExprValue *out_val = ir_build_const_from(ira, &to_ptr_type_instruction->base,
4613 out_val->ok = true;4652 type_value->static_value.depends_on_compile_var);
4614 out_val->depends_on_compile_var = type_value->static_value.depends_on_compile_var;
4615 out_val->data.x_type = ptr_type;4653 out_val->data.x_type = ptr_type;
4616 return ira->codegen->builtin_types.entry_type;4654 return ira->codegen->builtin_types.entry_type;
4617}4655}
...@@ -4630,9 +4668,8 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,...@@ -4630,9 +4668,8 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
4630 return ira->codegen->builtin_types.entry_invalid;4668 return ira->codegen->builtin_types.entry_invalid;
4631 }4669 }
46324670
4633 ConstExprValue *out_val = ir_get_out_val(&ptr_type_child_instruction->base);4671 ConstExprValue *out_val = ir_build_const_from(ira, &ptr_type_child_instruction->base,
4634 out_val->ok = true;4672 type_value->static_value.depends_on_compile_var);
4635 out_val->depends_on_compile_var = type_value->static_value.depends_on_compile_var;
4636 out_val->data.x_type = type_entry->data.pointer.child_type;4673 out_val->data.x_type = type_entry->data.pointer.child_type;
4637 return ira->codegen->builtin_types.entry_type;4674 return ira->codegen->builtin_types.entry_type;
4638}4675}
...@@ -4734,10 +4771,6 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl...@@ -4734,10 +4771,6 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
4734 while (ira->block_queue_index < ira->old_bb_queue.length) {4771 while (ira->block_queue_index < ira->old_bb_queue.length) {
4735 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);4772 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
47364773
4737 fprintf(stderr, "===%zu====", old_instruction->debug_id);
4738 ir_print(stderr, ira->new_irb.exec, 4);
4739 fprintf(stderr, "========");
4740
4741 if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) {4774 if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) {
4742 ira->instruction_index += 1;4775 ira->instruction_index += 1;
4743 continue;4776 continue;
src/ir_print.cpp+8-5
...@@ -231,14 +231,15 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction...@@ -231,14 +231,15 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
231}231}
232232
233static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {233static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {
234 const char *var_or_const = decl_var_instruction->var->is_const ? "const" : "var";234 const char *inline_kw = decl_var_instruction->var->is_inline ? "inline " : "";
235 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
235 const char *name = buf_ptr(&decl_var_instruction->var->name);236 const char *name = buf_ptr(&decl_var_instruction->var->name);
236 if (decl_var_instruction->var_type) {237 if (decl_var_instruction->var_type) {
237 fprintf(irp->f, "%s %s: ", var_or_const, name);238 fprintf(irp->f, "%s%s %s: ", inline_kw, var_or_const, name);
238 ir_print_other_instruction(irp, decl_var_instruction->var_type);239 ir_print_other_instruction(irp, decl_var_instruction->var_type);
239 fprintf(irp->f, " = ");240 fprintf(irp->f, " = ");
240 } else {241 } else {
241 fprintf(irp->f, "%s %s = ", var_or_const, name);242 fprintf(irp->f, "%s%s %s = ", inline_kw, var_or_const, name);
242 }243 }
243 ir_print_other_instruction(irp, decl_var_instruction->init_value);244 ir_print_other_instruction(irp, decl_var_instruction->init_value);
244}245}
...@@ -275,7 +276,8 @@ static void ir_print_builtin_call(IrPrint *irp, IrInstructionBuiltinCall *call_i...@@ -275,7 +276,8 @@ static void ir_print_builtin_call(IrPrint *irp, IrInstructionBuiltinCall *call_i
275276
276277
277static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {278static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
278 fprintf(irp->f, "if (");279 const char *inline_kw = cond_br_instruction->is_inline ? "inline " : "";
280 fprintf(irp->f, "%sif (", inline_kw);
279 ir_print_other_instruction(irp, cond_br_instruction->condition);281 ir_print_other_instruction(irp, cond_br_instruction->condition);
280 fprintf(irp->f, ") ");282 fprintf(irp->f, ") ");
281 ir_print_other_block(irp, cond_br_instruction->then_block);283 ir_print_other_block(irp, cond_br_instruction->then_block);
...@@ -284,7 +286,8 @@ static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruct...@@ -284,7 +286,8 @@ static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruct
284}286}
285287
286static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {288static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
287 fprintf(irp->f, "goto ");289 const char *inline_kw = br_instruction->is_inline ? "inline " : "";
290 fprintf(irp->f, "%sgoto ", inline_kw);
288 ir_print_other_block(irp, br_instruction->dest_block);291 ir_print_other_block(irp, br_instruction->dest_block);
289}292}
290293
src/parser.cpp+67-20
...@@ -1450,29 +1450,50 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {...@@ -1450,29 +1450,50 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
1450}1450}
14511451
1452/*1452/*
1453VariableDeclaration : ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression))1453VariableDeclaration = option("inline") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
1454*/1454*/
1455static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory,1455static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory,
1456 VisibMod visib_mod)1456 VisibMod visib_mod)
1457{1457{
1458 Token *first_token = &pc->tokens->at(*token_index);1458 Token *first_token = &pc->tokens->at(*token_index);
1459 Token *var_token;
14591460
1460 bool is_const;1461 bool is_const;
1462 bool is_inline;
1463 if (first_token->id == TokenIdKeywordInline) {
1464 is_inline = true;
1465 var_token = &pc->tokens->at(*token_index + 1);
1466
1467 if (var_token->id == TokenIdKeywordVar) {
1468 is_const = false;
1469 } else if (var_token->id == TokenIdKeywordConst) {
1470 is_const = true;
1471 } else if (mandatory) {
1472 ast_invalid_token_error(pc, var_token);
1473 } else {
1474 return nullptr;
1475 }
14611476
1462 if (first_token->id == TokenIdKeywordVar) {1477 *token_index += 2;
1478 } else if (first_token->id == TokenIdKeywordVar) {
1479 is_inline = false;
1463 is_const = false;1480 is_const = false;
1481 var_token = first_token;
1482 *token_index += 1;
1464 } else if (first_token->id == TokenIdKeywordConst) {1483 } else if (first_token->id == TokenIdKeywordConst) {
1484 is_inline = false;
1465 is_const = true;1485 is_const = true;
1486 var_token = first_token;
1487 *token_index += 1;
1466 } else if (mandatory) {1488 } else if (mandatory) {
1467 ast_invalid_token_error(pc, first_token);1489 ast_invalid_token_error(pc, first_token);
1468 } else {1490 } else {
1469 return nullptr;1491 return nullptr;
1470 }1492 }
14711493
1472 *token_index += 1;1494 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_token);
1473
1474 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, first_token);
14751495
1496 node->data.variable_declaration.is_inline = is_inline;
1476 node->data.variable_declaration.is_const = is_const;1497 node->data.variable_declaration.is_const = is_const;
1477 node->data.variable_declaration.top_level_decl.visib_mod = visib_mod;1498 node->data.variable_declaration.top_level_decl.visib_mod = visib_mod;
14781499
...@@ -1529,21 +1550,33 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, size_t *token_index, bo...@@ -1529,21 +1550,33 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, size_t *token_index, bo
1529}1550}
15301551
1531/*1552/*
1532WhileExpression = "while" "(" Expression option(";" Expression) ")" Expression1553WhileExpression = option("inline") "while" "(" Expression option(";" Expression) ")" Expression
1533*/1554*/
1534static AstNode *ast_parse_while_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1555static AstNode *ast_parse_while_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
1535 Token *token = &pc->tokens->at(*token_index);1556 Token *first_token = &pc->tokens->at(*token_index);
1557 Token *while_token;
15361558
1537 if (token->id != TokenIdKeywordWhile) {1559 bool is_inline;
1538 if (mandatory) {1560 if (first_token->id == TokenIdKeywordInline) {
1539 ast_expect_token(pc, token, TokenIdKeywordWhile);1561 is_inline = true;
1562 while_token = &pc->tokens->at(*token_index + 1);
1563 if (while_token->id == TokenIdKeywordWhile) {
1564 *token_index += 2;
1565 } else if (mandatory) {
1566 ast_expect_token(pc, first_token, TokenIdKeywordWhile);
1540 } else {1567 } else {
1541 return nullptr;1568 return nullptr;
1542 }1569 }
1570 } else if (first_token->id == TokenIdKeywordWhile) {
1571 is_inline = false;
1572 *token_index += 1;
1573 } else if (mandatory) {
1574 ast_expect_token(pc, first_token, TokenIdKeywordWhile);
1575 } else {
1576 return nullptr;
1543 }1577 }
1544 *token_index += 1;1578 AstNode *node = ast_create_node(pc, NodeTypeWhileExpr, while_token);
15451579 node->data.while_expr.is_inline = is_inline;
1546 AstNode *node = ast_create_node(pc, NodeTypeWhileExpr, token);
15471580
1548 ast_eat_token(pc, token_index, TokenIdLParen);1581 ast_eat_token(pc, token_index, TokenIdLParen);
1549 node->data.while_expr.condition = ast_parse_expression(pc, token_index, true);1582 node->data.while_expr.condition = ast_parse_expression(pc, token_index, true);
...@@ -1575,21 +1608,35 @@ static AstNode *ast_parse_symbol(ParseContext *pc, size_t *token_index) {...@@ -1575,21 +1608,35 @@ static AstNode *ast_parse_symbol(ParseContext *pc, size_t *token_index) {
1575}1608}
15761609
1577/*1610/*
1578ForExpression = "for" "(" Expression ")" option("|" option("*") "Symbol" option("," "Symbol") "|") Expression1611ForExpression = option("inline") "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") Expression
1579*/1612*/
1580static AstNode *ast_parse_for_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1613static AstNode *ast_parse_for_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
1581 Token *token = &pc->tokens->at(*token_index);1614 Token *first_token = &pc->tokens->at(*token_index);
1615 Token *for_token;
15821616
1583 if (token->id != TokenIdKeywordFor) {1617 bool is_inline;
1584 if (mandatory) {1618 if (first_token->id == TokenIdKeywordInline) {
1585 ast_expect_token(pc, token, TokenIdKeywordFor);1619 is_inline = true;
1620 for_token = &pc->tokens->at(*token_index + 1);
1621 if (for_token->id == TokenIdKeywordFor) {
1622 *token_index += 2;
1623 } else if (mandatory) {
1624 ast_expect_token(pc, first_token, TokenIdKeywordFor);
1586 } else {1625 } else {
1587 return nullptr;1626 return nullptr;
1588 }1627 }
1628 } else if (first_token->id == TokenIdKeywordFor) {
1629 for_token = first_token;
1630 is_inline = false;
1631 *token_index += 1;
1632 } else if (mandatory) {
1633 ast_expect_token(pc, first_token, TokenIdKeywordFor);
1634 } else {
1635 return nullptr;
1589 }1636 }
1590 *token_index += 1;
15911637
1592 AstNode *node = ast_create_node(pc, NodeTypeForExpr, token);1638 AstNode *node = ast_create_node(pc, NodeTypeForExpr, for_token);
1639 node->data.for_expr.is_inline = is_inline;
15931640
1594 ast_eat_token(pc, token_index, TokenIdLParen);1641 ast_eat_token(pc, token_index, TokenIdLParen);
1595 node->data.for_expr.array_expr = ast_parse_expression(pc, token_index, true);1642 node->data.for_expr.array_expr = ast_parse_expression(pc, token_index, true);
test/self_hosted2.zig created+13
...@@ -0,0 +1,13 @@
1fn add(a: i32, b: i32) -> i32 {
2 a + b
3}
4
5fn assert(ok: bool) {
6 if (!ok) @unreachable();
7}
8
9fn testAdd() {
10 @setFnTest(this, true);
11
12 assert(add(2, 3) == 5);
13}