| ... | @@ -2530,8 +2530,10 @@ static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *s | ... | @@ -2530,8 +2530,10 @@ static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *s |
| 2530 | bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime) | 2530 | bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime) |
| 2531 | { | 2531 | { |
| 2532 | VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name, src_is_const, gen_is_const, is_shadowable, is_comptime); | 2532 | VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name, src_is_const, gen_is_const, is_shadowable, is_comptime); |
| 2533 | if (is_comptime != nullptr || gen_is_const) | 2533 | if (is_comptime != nullptr || gen_is_const) { |
| 2534 | var->mem_slot_index = exec_next_mem_slot(irb->exec); | 2534 | var->mem_slot_index = exec_next_mem_slot(irb->exec); |
| | 2535 | var->owner_exec = irb->exec; |
| | 2536 | } |
| 2535 | assert(var->child_scope); | 2537 | assert(var->child_scope); |
| 2536 | return var; | 2538 | return var; |
| 2537 | } | 2539 | } |
| ... | @@ -7037,48 +7039,48 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node | ... | @@ -7037,48 +7039,48 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node |
| 7037 | if (expected_type != nullptr && type_is_invalid(expected_type)) | 7039 | if (expected_type != nullptr && type_is_invalid(expected_type)) |
| 7038 | return codegen->invalid_instruction; | 7040 | return codegen->invalid_instruction; |
| 7039 | | 7041 | |
| 7040 | IrExecutable ir_executable = {0}; | 7042 | IrExecutable *ir_executable = allocate<IrExecutable>(1); |
| 7041 | ir_executable.source_node = source_node; | 7043 | ir_executable->source_node = source_node; |
| 7042 | ir_executable.parent_exec = parent_exec; | 7044 | ir_executable->parent_exec = parent_exec; |
| 7043 | ir_executable.name = exec_name; | 7045 | ir_executable->name = exec_name; |
| 7044 | ir_executable.is_inline = true; | 7046 | ir_executable->is_inline = true; |
| 7045 | ir_executable.fn_entry = fn_entry; | 7047 | ir_executable->fn_entry = fn_entry; |
| 7046 | ir_executable.c_import_buf = c_import_buf; | 7048 | ir_executable->c_import_buf = c_import_buf; |
| 7047 | ir_executable.begin_scope = scope; | 7049 | ir_executable->begin_scope = scope; |
| 7048 | ir_gen(codegen, node, scope, &ir_executable); | 7050 | ir_gen(codegen, node, scope, ir_executable); |
| 7049 | | 7051 | |
| 7050 | if (ir_executable.invalid) | 7052 | if (ir_executable->invalid) |
| 7051 | return codegen->invalid_instruction; | 7053 | return codegen->invalid_instruction; |
| 7052 | | 7054 | |
| 7053 | if (codegen->verbose_ir) { | 7055 | if (codegen->verbose_ir) { |
| 7054 | fprintf(stderr, "\nSource: "); | 7056 | fprintf(stderr, "\nSource: "); |
| 7055 | ast_render(codegen, stderr, node, 4); | 7057 | ast_render(codegen, stderr, node, 4); |
| 7056 | fprintf(stderr, "\n{ // (IR)\n"); | 7058 | fprintf(stderr, "\n{ // (IR)\n"); |
| 7057 | ir_print(codegen, stderr, &ir_executable, 4); | 7059 | ir_print(codegen, stderr, ir_executable, 4); |
| 7058 | fprintf(stderr, "}\n"); | 7060 | fprintf(stderr, "}\n"); |
| 7059 | } | 7061 | } |
| 7060 | IrExecutable analyzed_executable = {0}; | 7062 | IrExecutable *analyzed_executable = allocate<IrExecutable>(1); |
| 7061 | analyzed_executable.source_node = source_node; | 7063 | analyzed_executable->source_node = source_node; |
| 7062 | analyzed_executable.parent_exec = parent_exec; | 7064 | analyzed_executable->parent_exec = parent_exec; |
| 7063 | analyzed_executable.source_exec = &ir_executable; | 7065 | analyzed_executable->source_exec = ir_executable; |
| 7064 | analyzed_executable.name = exec_name; | 7066 | analyzed_executable->name = exec_name; |
| 7065 | analyzed_executable.is_inline = true; | 7067 | analyzed_executable->is_inline = true; |
| 7066 | analyzed_executable.fn_entry = fn_entry; | 7068 | analyzed_executable->fn_entry = fn_entry; |
| 7067 | analyzed_executable.c_import_buf = c_import_buf; | 7069 | analyzed_executable->c_import_buf = c_import_buf; |
| 7068 | analyzed_executable.backward_branch_count = backward_branch_count; | 7070 | analyzed_executable->backward_branch_count = backward_branch_count; |
| 7069 | analyzed_executable.backward_branch_quota = backward_branch_quota; | 7071 | analyzed_executable->backward_branch_quota = backward_branch_quota; |
| 7070 | analyzed_executable.begin_scope = scope; | 7072 | analyzed_executable->begin_scope = scope; |
| 7071 | TypeTableEntry *result_type = ir_analyze(codegen, &ir_executable, &analyzed_executable, expected_type, node); | 7073 | TypeTableEntry *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node); |
| 7072 | if (type_is_invalid(result_type)) | 7074 | if (type_is_invalid(result_type)) |
| 7073 | return codegen->invalid_instruction; | 7075 | return codegen->invalid_instruction; |
| 7074 | | 7076 | |
| 7075 | if (codegen->verbose_ir) { | 7077 | if (codegen->verbose_ir) { |
| 7076 | fprintf(stderr, "{ // (analyzed)\n"); | 7078 | fprintf(stderr, "{ // (analyzed)\n"); |
| 7077 | ir_print(codegen, stderr, &analyzed_executable, 4); | 7079 | ir_print(codegen, stderr, analyzed_executable, 4); |
| 7078 | fprintf(stderr, "}\n"); | 7080 | fprintf(stderr, "}\n"); |
| 7079 | } | 7081 | } |
| 7080 | | 7082 | |
| 7081 | return ir_exec_const_result(codegen, &analyzed_executable); | 7083 | return ir_exec_const_result(codegen, analyzed_executable); |
| 7082 | } | 7084 | } |
| 7083 | | 7085 | |
| 7084 | static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { | 7086 | static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { |
| ... | @@ -9334,6 +9336,8 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -9334,6 +9336,8 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 9334 | IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, explicit_type); | 9336 | IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, explicit_type); |
| 9335 | bool is_comptime_var = ir_get_var_is_comptime(var); | 9337 | bool is_comptime_var = ir_get_var_is_comptime(var); |
| 9336 | | 9338 | |
| | 9339 | bool var_class_requires_const = false; |
| | 9340 | |
| 9337 | TypeTableEntry *result_type = casted_init_value->value.type; | 9341 | TypeTableEntry *result_type = casted_init_value->value.type; |
| 9338 | if (type_is_invalid(result_type)) { | 9342 | if (type_is_invalid(result_type)) { |
| 9339 | result_type = ira->codegen->builtin_types.entry_invalid; | 9343 | result_type = ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -9345,6 +9349,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -9345,6 +9349,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 9345 | result_type = ira->codegen->builtin_types.entry_invalid; | 9349 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 9346 | break; | 9350 | break; |
| 9347 | case VarClassRequiredConst: | 9351 | case VarClassRequiredConst: |
| | 9352 | var_class_requires_const = true; |
| 9348 | if (!var->src_is_const && !is_comptime_var) { | 9353 | if (!var->src_is_const && !is_comptime_var) { |
| 9349 | ir_add_error_node(ira, source_node, | 9354 | ir_add_error_node(ira, source_node, |
| 9350 | buf_sprintf("variable of type '%s' must be const or comptime", | 9355 | buf_sprintf("variable of type '%s' must be const or comptime", |
| ... | @@ -9366,8 +9371,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -9366,8 +9371,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 9366 | return ira->codegen->builtin_types.entry_void; | 9371 | return ira->codegen->builtin_types.entry_void; |
| 9367 | } | 9372 | } |
| 9368 | | 9373 | |
| 9369 | bool is_comptime = ir_get_var_is_comptime(var); | | |
| 9370 | | | |
| 9371 | if (decl_var_instruction->align_value == nullptr) { | 9374 | if (decl_var_instruction->align_value == nullptr) { |
| 9372 | var->align_bytes = get_abi_alignment(ira->codegen, result_type); | 9375 | var->align_bytes = get_abi_alignment(ira->codegen, result_type); |
| 9373 | } else { | 9376 | } else { |
| ... | @@ -9382,12 +9385,12 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -9382,12 +9385,12 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 9382 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | 9385 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| 9383 | *mem_slot = casted_init_value->value; | 9386 | *mem_slot = casted_init_value->value; |
| 9384 | | 9387 | |
| 9385 | if (is_comptime) { | 9388 | if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) { |
| 9386 | ir_build_const_from(ira, &decl_var_instruction->base); | 9389 | ir_build_const_from(ira, &decl_var_instruction->base); |
| 9387 | return ira->codegen->builtin_types.entry_void; | 9390 | return ira->codegen->builtin_types.entry_void; |
| 9388 | } | 9391 | } |
| 9389 | } | 9392 | } |
| 9390 | } else if (is_comptime) { | 9393 | } else if (is_comptime_var) { |
| 9391 | ir_add_error(ira, &decl_var_instruction->base, | 9394 | ir_add_error(ira, &decl_var_instruction->base, |
| 9392 | buf_sprintf("cannot store runtime value in compile time variable")); | 9395 | buf_sprintf("cannot store runtime value in compile time variable")); |
| 9393 | var->value->type = ira->codegen->builtin_types.entry_invalid; | 9396 | var->value->type = ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -9690,6 +9693,10 @@ static VariableTableEntry *get_fn_var_by_index(FnTableEntry *fn_entry, size_t in | ... | @@ -9690,6 +9693,10 @@ static VariableTableEntry *get_fn_var_by_index(FnTableEntry *fn_entry, size_t in |
| 9690 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, | 9693 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 9691 | VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr) | 9694 | VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr) |
| 9692 | { | 9695 | { |
| | 9696 | if (var->mem_slot_index != SIZE_MAX && var->owner_exec->analysis == nullptr) { |
| | 9697 | assert(ira->codegen->errors.length != 0); |
| | 9698 | return ira->codegen->invalid_instruction; |
| | 9699 | } |
| 9693 | assert(var->value->type); | 9700 | assert(var->value->type); |
| 9694 | if (type_is_invalid(var->value->type)) | 9701 | if (type_is_invalid(var->value->type)) |
| 9695 | return ira->codegen->invalid_instruction; | 9702 | return ira->codegen->invalid_instruction; |
| ... | @@ -9700,9 +9707,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, | ... | @@ -9700,9 +9707,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 9700 | if (var->value->special == ConstValSpecialStatic) { | 9707 | if (var->value->special == ConstValSpecialStatic) { |
| 9701 | mem_slot = var->value; | 9708 | mem_slot = var->value; |
| 9702 | } else { | 9709 | } else { |
| 9703 | // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing. | 9710 | if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) { |
| 9704 | if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) | 9711 | // find the relevant exec_context |
| 9705 | mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | 9712 | assert(var->owner_exec != nullptr); |
| | 9713 | assert(var->owner_exec->analysis != nullptr); |
| | 9714 | IrExecContext *exec_context = &var->owner_exec->analysis->exec_context; |
| | 9715 | assert(var->mem_slot_index < exec_context->mem_slot_count); |
| | 9716 | mem_slot = &exec_context->mem_slot_list[var->mem_slot_index]; |
| | 9717 | } |
| 9706 | } | 9718 | } |
| 9707 | | 9719 | |
| 9708 | bool is_const = (var->value->type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; | 9720 | bool is_const = (var->value->type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; |
| ... | @@ -15328,8 +15340,8 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl | ... | @@ -15328,8 +15340,8 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl |
| 15328 | assert(!old_exec->invalid); | 15340 | assert(!old_exec->invalid); |
| 15329 | assert(expected_type == nullptr || !type_is_invalid(expected_type)); | 15341 | assert(expected_type == nullptr || !type_is_invalid(expected_type)); |
| 15330 | | 15342 | |
| 15331 | IrAnalyze ir_analyze_data = {}; | 15343 | IrAnalyze *ira = allocate<IrAnalyze>(1); |
| 15332 | IrAnalyze *ira = &ir_analyze_data; | 15344 | old_exec->analysis = ira; |
| 15333 | ira->codegen = codegen; | 15345 | ira->codegen = codegen; |
| 15334 | ira->explicit_return_type = expected_type; | 15346 | ira->explicit_return_type = expected_type; |
| 15335 | | 15347 | |