| ... | ... | @@ -44,12 +44,6 @@ struct IrAnalyze { |
| 44 | 44 | IrBasicBlock *const_predecessor_bb; |
| 45 | 45 | }; |
| 46 | 46 | |
| 47 | | struct LVal { |
| 48 | | bool is_ptr; |
| 49 | | bool is_const; |
| 50 | | bool is_volatile; |
| 51 | | }; |
| 52 | | |
| 53 | 47 | static const LVal LVAL_NONE = { false, false, false }; |
| 54 | 48 | static const LVal LVAL_PTR = { true, false, false }; |
| 55 | 49 | |
| ... | ... | @@ -534,6 +528,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection |
| 534 | 528 | return IrInstructionIdSetGlobalSection; |
| 535 | 529 | } |
| 536 | 530 | |
| 531 | static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclRef *) { |
| 532 | return IrInstructionIdDeclRef; |
| 533 | } |
| 534 | |
| 537 | 535 | template<typename T> |
| 538 | 536 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 539 | 537 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -686,14 +684,20 @@ static IrInstruction *ir_build_const_type(IrBuilder *irb, Scope *scope, AstNode |
| 686 | 684 | return instruction; |
| 687 | 685 | } |
| 688 | 686 | |
| 689 | | static IrInstruction *ir_build_const_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, FnTableEntry *fn_entry) { |
| 690 | | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node); |
| 687 | static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, FnTableEntry *fn_entry) { |
| 688 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node); |
| 691 | 689 | const_instruction->base.value.type = fn_entry->type_entry; |
| 692 | 690 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 693 | 691 | const_instruction->base.value.data.x_fn = fn_entry; |
| 694 | 692 | return &const_instruction->base; |
| 695 | 693 | } |
| 696 | 694 | |
| 695 | static IrInstruction *ir_build_const_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, FnTableEntry *fn_entry) { |
| 696 | IrInstruction *instruction = ir_create_const_fn(irb, scope, source_node, fn_entry); |
| 697 | ir_instruction_append(irb->current_basic_block, instruction); |
| 698 | return instruction; |
| 699 | } |
| 700 | |
| 697 | 701 | static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNode *source_node, ImportTableEntry *import) { |
| 698 | 702 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node); |
| 699 | 703 | const_instruction->base.value.type = irb->codegen->builtin_types.entry_namespace; |
| ... | ... | @@ -2088,6 +2092,17 @@ static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope, |
| 2088 | 2092 | return &instruction->base; |
| 2089 | 2093 | } |
| 2090 | 2094 | |
| 2095 | static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2096 | Tld *tld, LVal lval) |
| 2097 | { |
| 2098 | IrInstructionDeclRef *instruction = ir_build_instruction<IrInstructionDeclRef>( |
| 2099 | irb, scope, source_node); |
| 2100 | instruction->tld = tld; |
| 2101 | instruction->lval = lval; |
| 2102 | |
| 2103 | return &instruction->base; |
| 2104 | } |
| 2105 | |
| 2091 | 2106 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { |
| 2092 | 2107 | return nullptr; |
| 2093 | 2108 | } |
| ... | ... | @@ -2727,6 +2742,10 @@ static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGl |
| 2727 | 2742 | } |
| 2728 | 2743 | } |
| 2729 | 2744 | |
| 2745 | static IrInstruction *ir_instruction_declref_get_dep(IrInstructionDeclRef *instruction, size_t index) { |
| 2746 | return nullptr; |
| 2747 | } |
| 2748 | |
| 2730 | 2749 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { |
| 2731 | 2750 | switch (instruction->id) { |
| 2732 | 2751 | case IrInstructionIdInvalid: |
| ... | ... | @@ -2909,6 +2928,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 2909 | 2928 | return ir_instruction_setglobalalign_get_dep((IrInstructionSetGlobalAlign *) instruction, index); |
| 2910 | 2929 | case IrInstructionIdSetGlobalSection: |
| 2911 | 2930 | return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index); |
| 2931 | case IrInstructionIdDeclRef: |
| 2932 | return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index); |
| 2912 | 2933 | } |
| 2913 | 2934 | zig_unreachable(); |
| 2914 | 2935 | } |
| ... | ... | @@ -3574,52 +3595,6 @@ static IrInstruction *ir_gen_var_literal(IrBuilder *irb, Scope *scope, AstNode * |
| 3574 | 3595 | return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var); |
| 3575 | 3596 | } |
| 3576 | 3597 | |
| 3577 | | static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld *tld, |
| 3578 | | LVal lval, Scope *scope) |
| 3579 | | { |
| 3580 | | resolve_top_level_decl(irb->codegen, tld, lval.is_ptr); |
| 3581 | | if (tld->resolution == TldResolutionInvalid) |
| 3582 | | return irb->codegen->invalid_instruction; |
| 3583 | | |
| 3584 | | switch (tld->id) { |
| 3585 | | case TldIdContainer: |
| 3586 | | zig_unreachable(); |
| 3587 | | case TldIdVar: |
| 3588 | | { |
| 3589 | | TldVar *tld_var = (TldVar *)tld; |
| 3590 | | VariableTableEntry *var = tld_var->var; |
| 3591 | | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var, |
| 3592 | | !lval.is_ptr || lval.is_const, lval.is_ptr && lval.is_volatile); |
| 3593 | | if (lval.is_ptr) |
| 3594 | | return var_ptr; |
| 3595 | | else |
| 3596 | | return ir_build_load_ptr(irb, scope, source_node, var_ptr); |
| 3597 | | } |
| 3598 | | case TldIdFn: |
| 3599 | | { |
| 3600 | | TldFn *tld_fn = (TldFn *)tld; |
| 3601 | | FnTableEntry *fn_entry = tld_fn->fn_entry; |
| 3602 | | assert(fn_entry->type_entry); |
| 3603 | | IrInstruction *ref_instruction = ir_build_const_fn(irb, scope, source_node, fn_entry); |
| 3604 | | if (lval.is_ptr) |
| 3605 | | return ir_build_ref(irb, scope, source_node, ref_instruction, true, false); |
| 3606 | | else |
| 3607 | | return ref_instruction; |
| 3608 | | } |
| 3609 | | case TldIdTypeDef: |
| 3610 | | { |
| 3611 | | TldTypeDef *tld_typedef = (TldTypeDef *)tld; |
| 3612 | | TypeTableEntry *typedef_type = tld_typedef->type_entry; |
| 3613 | | IrInstruction *ref_instruction = ir_build_const_type(irb, scope, source_node, typedef_type); |
| 3614 | | if (lval.is_ptr) |
| 3615 | | return ir_build_ref(irb, scope, source_node, ref_instruction, true, false); |
| 3616 | | else |
| 3617 | | return ref_instruction; |
| 3618 | | } |
| 3619 | | } |
| 3620 | | zig_unreachable(); |
| 3621 | | } |
| 3622 | | |
| 3623 | 3598 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 3624 | 3599 | assert(node->type == NodeTypeSymbol); |
| 3625 | 3600 | |
| ... | ... | @@ -3656,7 +3631,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3656 | 3631 | |
| 3657 | 3632 | Tld *tld = find_decl(irb->codegen, scope, variable_name); |
| 3658 | 3633 | if (tld) |
| 3659 | | return ir_gen_decl_ref(irb, node, tld, lval, scope); |
| 3634 | return ir_build_decl_ref(irb, scope, node, tld, lval); |
| 3660 | 3635 | |
| 3661 | 3636 | if (node->owner->any_imports_failed) { |
| 3662 | 3637 | // skip the error message since we had a failing import in this file |
| ... | ... | @@ -12152,6 +12127,75 @@ static TypeTableEntry *ir_analyze_instruction_can_implicit_cast(IrAnalyze *ira, |
| 12152 | 12127 | return ira->codegen->builtin_types.entry_bool; |
| 12153 | 12128 | } |
| 12154 | 12129 | |
| 12130 | static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 12131 | IrInstructionDeclRef *instruction) |
| 12132 | { |
| 12133 | Tld *tld = instruction->tld; |
| 12134 | LVal lval = instruction->lval; |
| 12135 | |
| 12136 | resolve_top_level_decl(ira->codegen, tld, lval.is_ptr); |
| 12137 | if (tld->resolution == TldResolutionInvalid) |
| 12138 | return ira->codegen->builtin_types.entry_invalid; |
| 12139 | |
| 12140 | switch (tld->id) { |
| 12141 | case TldIdContainer: |
| 12142 | zig_unreachable(); |
| 12143 | case TldIdVar: |
| 12144 | { |
| 12145 | TldVar *tld_var = (TldVar *)tld; |
| 12146 | VariableTableEntry *var = tld_var->var; |
| 12147 | |
| 12148 | IrInstruction *var_ptr = ir_get_var_ptr(ira, &instruction->base, var, |
| 12149 | !lval.is_ptr || lval.is_const, lval.is_ptr && lval.is_volatile); |
| 12150 | if (type_is_invalid(var_ptr->value.type)) |
| 12151 | return ira->codegen->builtin_types.entry_invalid; |
| 12152 | |
| 12153 | if (lval.is_ptr) { |
| 12154 | ir_link_new_instruction(var_ptr, &instruction->base); |
| 12155 | return var_ptr->value.type; |
| 12156 | } else { |
| 12157 | IrInstruction *loaded_instr = ir_get_deref(ira, &instruction->base, var_ptr); |
| 12158 | ir_link_new_instruction(loaded_instr, &instruction->base); |
| 12159 | return loaded_instr->value.type; |
| 12160 | } |
| 12161 | } |
| 12162 | case TldIdFn: |
| 12163 | { |
| 12164 | TldFn *tld_fn = (TldFn *)tld; |
| 12165 | FnTableEntry *fn_entry = tld_fn->fn_entry; |
| 12166 | assert(fn_entry->type_entry); |
| 12167 | |
| 12168 | IrInstruction *ref_instruction = ir_create_const_fn(&ira->new_irb, instruction->base.scope, |
| 12169 | instruction->base.source_node, fn_entry); |
| 12170 | if (lval.is_ptr) { |
| 12171 | IrInstruction *ptr_instr = ir_get_ref(ira, &instruction->base, ref_instruction, true, false); |
| 12172 | ir_link_new_instruction(ptr_instr, &instruction->base); |
| 12173 | return ptr_instr->value.type; |
| 12174 | } else { |
| 12175 | ir_link_new_instruction(ref_instruction, &instruction->base); |
| 12176 | return ref_instruction->value.type; |
| 12177 | } |
| 12178 | } |
| 12179 | case TldIdTypeDef: |
| 12180 | { |
| 12181 | TldTypeDef *tld_typedef = (TldTypeDef *)tld; |
| 12182 | TypeTableEntry *typedef_type = tld_typedef->type_entry; |
| 12183 | |
| 12184 | IrInstruction *ref_instruction = ir_create_const_type(&ira->new_irb, instruction->base.scope, |
| 12185 | instruction->base.source_node, typedef_type); |
| 12186 | if (lval.is_ptr) { |
| 12187 | IrInstruction *ptr_inst = ir_get_ref(ira, &instruction->base, ref_instruction, true, false); |
| 12188 | ir_link_new_instruction(ptr_inst, &instruction->base); |
| 12189 | return ptr_inst->value.type; |
| 12190 | } else { |
| 12191 | ir_link_new_instruction(ref_instruction, &instruction->base); |
| 12192 | return ref_instruction->value.type; |
| 12193 | } |
| 12194 | } |
| 12195 | } |
| 12196 | zig_unreachable(); |
| 12197 | } |
| 12198 | |
| 12155 | 12199 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 12156 | 12200 | switch (instruction->id) { |
| 12157 | 12201 | case IrInstructionIdInvalid: |
| ... | ... | @@ -12317,6 +12361,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 12317 | 12361 | return ir_analyze_instruction_test_type(ira, (IrInstructionTestType *)instruction); |
| 12318 | 12362 | case IrInstructionIdCanImplicitCast: |
| 12319 | 12363 | return ir_analyze_instruction_can_implicit_cast(ira, (IrInstructionCanImplicitCast *)instruction); |
| 12364 | case IrInstructionIdDeclRef: |
| 12365 | return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction); |
| 12320 | 12366 | case IrInstructionIdMaybeWrap: |
| 12321 | 12367 | case IrInstructionIdErrWrapCode: |
| 12322 | 12368 | case IrInstructionIdErrWrapPayload: |
| ... | ... | @@ -12495,6 +12541,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 12495 | 12541 | case IrInstructionIdTestType: |
| 12496 | 12542 | case IrInstructionIdTypeName: |
| 12497 | 12543 | case IrInstructionIdCanImplicitCast: |
| 12544 | case IrInstructionIdDeclRef: |
| 12498 | 12545 | return false; |
| 12499 | 12546 | case IrInstructionIdAsm: |
| 12500 | 12547 | { |