| ... | @@ -721,17 +721,23 @@ static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_in | ... | @@ -721,17 +721,23 @@ static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_in |
| 721 | return new_instruction; | 721 | return new_instruction; |
| 722 | } | 722 | } |
| 723 | | 723 | |
| 724 | static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, VariableTableEntry *var) { | 724 | static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| | 725 | VariableTableEntry *var, bool is_const) |
| | 726 | { |
| 725 | IrInstructionVarPtr *instruction = ir_build_instruction<IrInstructionVarPtr>(irb, scope, source_node); | 727 | IrInstructionVarPtr *instruction = ir_build_instruction<IrInstructionVarPtr>(irb, scope, source_node); |
| 726 | instruction->var = var; | 728 | instruction->var = var; |
| | 729 | instruction->is_const = is_const; |
| 727 | | 730 | |
| 728 | ir_ref_var(var); | 731 | ir_ref_var(var); |
| 729 | | 732 | |
| 730 | return &instruction->base; | 733 | return &instruction->base; |
| 731 | } | 734 | } |
| 732 | | 735 | |
| 733 | static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, VariableTableEntry *var) { | 736 | static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 734 | IrInstruction *new_instruction = ir_build_var_ptr(irb, old_instruction->scope, old_instruction->source_node, var); | 737 | VariableTableEntry *var, bool is_const) |
| | 738 | { |
| | 739 | IrInstruction *new_instruction = ir_build_var_ptr(irb, old_instruction->scope, |
| | 740 | old_instruction->source_node, var, is_const); |
| 735 | ir_link_new_instruction(new_instruction, old_instruction); | 741 | ir_link_new_instruction(new_instruction, old_instruction); |
| 736 | return new_instruction; | 742 | return new_instruction; |
| 737 | | 743 | |
| ... | @@ -3401,7 +3407,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld | ... | @@ -3401,7 +3407,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld |
| 3401 | { | 3407 | { |
| 3402 | TldVar *tld_var = (TldVar *)tld; | 3408 | TldVar *tld_var = (TldVar *)tld; |
| 3403 | VariableTableEntry *var = tld_var->var; | 3409 | VariableTableEntry *var = tld_var->var; |
| 3404 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var); | 3410 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var, false); |
| 3405 | if (lval != LValPurposeNone) | 3411 | if (lval != LValPurposeNone) |
| 3406 | return var_ptr; | 3412 | return var_ptr; |
| 3407 | else | 3413 | else |
| ... | @@ -3449,7 +3455,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3449,7 +3455,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3449 | | 3455 | |
| 3450 | VariableTableEntry *var = find_variable(irb->codegen, scope, variable_name); | 3456 | VariableTableEntry *var = find_variable(irb->codegen, scope, variable_name); |
| 3451 | if (var) { | 3457 | if (var) { |
| 3452 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, node, var); | 3458 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, node, var, lval == LValPurposeAddressOfConst); |
| 3453 | if (lval != LValPurposeNone) | 3459 | if (lval != LValPurposeNone) |
| 3454 | return var_ptr; | 3460 | return var_ptr; |
| 3455 | else | 3461 | else |
| ... | @@ -4309,7 +4315,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -4309,7 +4315,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4309 | | 4315 | |
| 4310 | IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); | 4316 | IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); |
| 4311 | ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, undefined_value); | 4317 | ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, undefined_value); |
| 4312 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var); | 4318 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var, false); |
| 4313 | | 4319 | |
| 4314 | AstNode *index_var_source_node; | 4320 | AstNode *index_var_source_node; |
| 4315 | VariableTableEntry *index_var; | 4321 | VariableTableEntry *index_var; |
| ... | @@ -4327,7 +4333,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -4327,7 +4333,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4327 | IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); | 4333 | IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); |
| 4328 | IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); | 4334 | IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); |
| 4329 | ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, zero); | 4335 | ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, zero); |
| 4330 | IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var); | 4336 | IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var, false); |
| 4331 | | 4337 | |
| 4332 | | 4338 | |
| 4333 | IrBasicBlock *cond_block = ir_build_basic_block(irb, child_scope, "ForCond"); | 4339 | IrBasicBlock *cond_block = ir_build_basic_block(irb, child_scope, "ForCond"); |
| ... | @@ -4351,7 +4357,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -4351,7 +4357,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4351 | } else { | 4357 | } else { |
| 4352 | elem_val = ir_build_load_ptr(irb, child_scope, node, elem_ptr); | 4358 | elem_val = ir_build_load_ptr(irb, child_scope, node, elem_ptr); |
| 4353 | } | 4359 | } |
| 4354 | ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val); | 4360 | ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val)); |
| 4355 | | 4361 | |
| 4356 | LoopStackItem *loop_stack_item = irb->loop_stack.add_one(); | 4362 | LoopStackItem *loop_stack_item = irb->loop_stack.add_one(); |
| 4357 | loop_stack_item->break_block = end_block; | 4363 | loop_stack_item->break_block = end_block; |
| ... | @@ -4365,7 +4371,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -4365,7 +4371,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4365 | | 4371 | |
| 4366 | ir_set_cursor_at_end(irb, continue_block); | 4372 | ir_set_cursor_at_end(irb, continue_block); |
| 4367 | IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); | 4373 | IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); |
| 4368 | ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val); | 4374 | ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)); |
| 4369 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); | 4375 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); |
| 4370 | | 4376 | |
| 4371 | ir_set_cursor_at_end(irb, end_block); | 4377 | ir_set_cursor_at_end(irb, end_block); |
| ... | @@ -7545,9 +7551,15 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -7545,9 +7551,15 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 7545 | size_t next_proto_i = 0; | 7551 | size_t next_proto_i = 0; |
| 7546 | | 7552 | |
| 7547 | if (first_arg_ptr) { | 7553 | if (first_arg_ptr) { |
| 7548 | IrInstruction *first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); | 7554 | IrInstruction *first_arg; |
| 7549 | if (first_arg->value.type->id == TypeTableEntryIdInvalid) | 7555 | assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer); |
| 7550 | return ira->codegen->builtin_types.entry_invalid; | 7556 | if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) { |
| | 7557 | first_arg = first_arg_ptr; |
| | 7558 | } else { |
| | 7559 | first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); |
| | 7560 | if (first_arg->value.type->id == TypeTableEntryIdInvalid) |
| | 7561 | return ira->codegen->builtin_types.entry_invalid; |
| | 7562 | } |
| 7551 | | 7563 | |
| 7552 | if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, first_arg, &impl_fn->child_scope, | 7564 | if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, first_arg, &impl_fn->child_scope, |
| 7553 | &next_proto_i, generic_id, &fn_type_id, casted_args, impl_fn)) | 7565 | &next_proto_i, generic_id, &fn_type_id, casted_args, impl_fn)) |
| ... | @@ -7612,9 +7624,15 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -7612,9 +7624,15 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 7612 | IrInstruction **casted_args = allocate<IrInstruction *>(call_param_count); | 7624 | IrInstruction **casted_args = allocate<IrInstruction *>(call_param_count); |
| 7613 | size_t next_arg_index = 0; | 7625 | size_t next_arg_index = 0; |
| 7614 | if (first_arg_ptr) { | 7626 | if (first_arg_ptr) { |
| 7615 | IrInstruction *first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); | 7627 | IrInstruction *first_arg; |
| 7616 | if (first_arg->value.type->id == TypeTableEntryIdInvalid) | 7628 | assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer); |
| 7617 | return ira->codegen->builtin_types.entry_invalid; | 7629 | if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) { |
| | 7630 | first_arg = first_arg_ptr; |
| | 7631 | } else { |
| | 7632 | first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); |
| | 7633 | if (first_arg->value.type->id == TypeTableEntryIdInvalid) |
| | 7634 | return ira->codegen->builtin_types.entry_invalid; |
| | 7635 | } |
| 7618 | | 7636 | |
| 7619 | TypeTableEntry *param_type = fn_type_id->param_info[next_arg_index].type; | 7637 | TypeTableEntry *param_type = fn_type_id->param_info[next_arg_index].type; |
| 7620 | if (param_type->id == TypeTableEntryIdInvalid) | 7638 | if (param_type->id == TypeTableEntryIdInvalid) |
| ... | @@ -8090,7 +8108,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP | ... | @@ -8090,7 +8108,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 8090 | return resolved_type; | 8108 | return resolved_type; |
| 8091 | } | 8109 | } |
| 8092 | | 8110 | |
| 8093 | static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruction, VariableTableEntry *var) { | 8111 | static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| | 8112 | VariableTableEntry *var, bool is_const_ptr) |
| | 8113 | { |
| 8094 | assert(var->value.type); | 8114 | assert(var->value.type); |
| 8095 | if (var->value.type->id == TypeTableEntryIdInvalid) | 8115 | if (var->value.type->id == TypeTableEntryIdInvalid) |
| 8096 | return var->value.type; | 8116 | return var->value.type; |
| ... | @@ -8110,9 +8130,10 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -8110,9 +8130,10 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc |
| 8110 | | 8130 | |
| 8111 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { | 8131 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { |
| 8112 | ConstPtrSpecial ptr_special = is_comptime ? ConstPtrSpecialInline : ConstPtrSpecialNone; | 8132 | ConstPtrSpecial ptr_special = is_comptime ? ConstPtrSpecialInline : ConstPtrSpecialNone; |
| 8113 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, false, ptr_special, var->src_is_const); | 8133 | bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; |
| | 8134 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, false, ptr_special, is_const); |
| 8114 | } else { | 8135 | } else { |
| 8115 | ir_build_var_ptr_from(&ira->new_irb, instruction, var); | 8136 | ir_build_var_ptr_from(&ira->new_irb, instruction, var, false); |
| 8116 | type_ensure_zero_bits_known(ira->codegen, var->value.type); | 8137 | type_ensure_zero_bits_known(ira->codegen, var->value.type); |
| 8117 | return get_pointer_to_type(ira->codegen, var->value.type, var->src_is_const); | 8138 | return get_pointer_to_type(ira->codegen, var->value.type, var->src_is_const); |
| 8118 | } | 8139 | } |
| ... | @@ -8120,7 +8141,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -8120,7 +8141,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc |
| 8120 | | 8141 | |
| 8121 | static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { | 8142 | static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { |
| 8122 | VariableTableEntry *var = var_ptr_instruction->var; | 8143 | VariableTableEntry *var = var_ptr_instruction->var; |
| 8123 | return ir_analyze_var_ptr(ira, &var_ptr_instruction->base, var); | 8144 | return ir_analyze_var_ptr(ira, &var_ptr_instruction->base, var, var_ptr_instruction->is_const); |
| 8124 | } | 8145 | } |
| 8125 | | 8146 | |
| 8126 | static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { | 8147 | static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { |
| ... | @@ -8313,7 +8334,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source | ... | @@ -8313,7 +8334,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 8313 | { | 8334 | { |
| 8314 | TldVar *tld_var = (TldVar *)tld; | 8335 | TldVar *tld_var = (TldVar *)tld; |
| 8315 | VariableTableEntry *var = tld_var->var; | 8336 | VariableTableEntry *var = tld_var->var; |
| 8316 | return ir_analyze_var_ptr(ira, source_instruction, var); | 8337 | return ir_analyze_var_ptr(ira, source_instruction, var, false); |
| 8317 | } | 8338 | } |
| 8318 | case TldIdFn: | 8339 | case TldIdFn: |
| 8319 | { | 8340 | { |
| ... | @@ -8549,6 +8570,12 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru | ... | @@ -8549,6 +8570,12 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 8549 | if (value->value.type->id == TypeTableEntryIdInvalid) | 8570 | if (value->value.type->id == TypeTableEntryIdInvalid) |
| 8550 | return value->value.type; | 8571 | return value->value.type; |
| 8551 | | 8572 | |
| | 8573 | assert(ptr->value.type->id == TypeTableEntryIdPointer); |
| | 8574 | if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) { |
| | 8575 | ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant")); |
| | 8576 | return ira->codegen->builtin_types.entry_invalid; |
| | 8577 | } |
| | 8578 | |
| 8552 | TypeTableEntry *child_type = ptr->value.type->data.pointer.child_type; | 8579 | TypeTableEntry *child_type = ptr->value.type->data.pointer.child_type; |
| 8553 | IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type); | 8580 | IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type); |
| 8554 | if (casted_value == ira->codegen->invalid_instruction) | 8581 | if (casted_value == ira->codegen->invalid_instruction) |
| ... | @@ -8580,7 +8607,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru | ... | @@ -8580,7 +8607,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 8580 | IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr; | 8607 | IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr; |
| 8581 | VariableTableEntry *var = var_ptr_inst->var; | 8608 | VariableTableEntry *var = var_ptr_inst->var; |
| 8582 | new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.scope, | 8609 | new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.scope, |
| 8583 | store_ptr_instruction->base.source_node, var); | 8610 | store_ptr_instruction->base.source_node, var, false); |
| 8584 | assert(var->mem_slot_index != SIZE_MAX); | 8611 | assert(var->mem_slot_index != SIZE_MAX); |
| 8585 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | 8612 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| 8586 | mem_slot->special = ConstValSpecialRuntime; | 8613 | mem_slot->special = ConstValSpecialRuntime; |