| ... | ... | @@ -44,9 +44,21 @@ 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 | static const LVal LVAL_NONE = { false, false, false }; |
| 54 | static const LVal LVAL_PTR = { true, false, false }; |
| 55 | |
| 56 | static LVal make_lval_addr(bool is_const, bool is_volatile) { |
| 57 | return { true, is_const, is_volatile }; |
| 58 | } |
| 59 | |
| 47 | 60 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); |
| 48 | | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, |
| 49 | | LValPurpose lval); |
| 61 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval); |
| 50 | 62 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 51 | 63 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type); |
| 52 | 64 | |
| ... | ... | @@ -1042,14 +1054,13 @@ static IrInstruction *ir_build_unreachable_from(IrBuilder *irb, IrInstruction *o |
| 1042 | 1054 | } |
| 1043 | 1055 | |
| 1044 | 1056 | static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1045 | | IrInstruction *ptr, IrInstruction *value, bool is_volatile) |
| 1057 | IrInstruction *ptr, IrInstruction *value) |
| 1046 | 1058 | { |
| 1047 | 1059 | IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, scope, source_node); |
| 1048 | 1060 | instruction->base.value.special = ConstValSpecialStatic; |
| 1049 | 1061 | instruction->base.value.type = irb->codegen->builtin_types.entry_void; |
| 1050 | 1062 | instruction->ptr = ptr; |
| 1051 | 1063 | instruction->value = value; |
| 1052 | | instruction->is_volatile = is_volatile; |
| 1053 | 1064 | |
| 1054 | 1065 | ir_ref_instruction(ptr, irb->current_basic_block); |
| 1055 | 1066 | ir_ref_instruction(value, irb->current_basic_block); |
| ... | ... | @@ -1058,10 +1069,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode * |
| 1058 | 1069 | } |
| 1059 | 1070 | |
| 1060 | 1071 | static IrInstruction *ir_build_store_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 1061 | | IrInstruction *ptr, IrInstruction *value, bool is_volatile) |
| 1072 | IrInstruction *ptr, IrInstruction *value) |
| 1062 | 1073 | { |
| 1063 | 1074 | IrInstruction *new_instruction = ir_build_store_ptr(irb, old_instruction->scope, |
| 1064 | | old_instruction->source_node, ptr, value, is_volatile); |
| 1075 | old_instruction->source_node, ptr, value); |
| 1065 | 1076 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1066 | 1077 | return new_instruction; |
| 1067 | 1078 | } |
| ... | ... | @@ -1450,11 +1461,12 @@ static IrInstruction *ir_build_array_len(IrBuilder *irb, Scope *scope, AstNode * |
| 1450 | 1461 | } |
| 1451 | 1462 | |
| 1452 | 1463 | static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value, |
| 1453 | | bool is_const) |
| 1464 | bool is_const, bool is_volatile) |
| 1454 | 1465 | { |
| 1455 | 1466 | IrInstructionRef *instruction = ir_build_instruction<IrInstructionRef>(irb, scope, source_node); |
| 1456 | 1467 | instruction->value = value; |
| 1457 | 1468 | instruction->is_const = is_const; |
| 1469 | instruction->is_volatile = is_volatile; |
| 1458 | 1470 | |
| 1459 | 1471 | ir_ref_instruction(value, irb->current_basic_block); |
| 1460 | 1472 | |
| ... | ... | @@ -1462,10 +1474,10 @@ static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source |
| 1462 | 1474 | } |
| 1463 | 1475 | |
| 1464 | 1476 | static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value, |
| 1465 | | bool is_const) |
| 1477 | bool is_const, bool is_volatile) |
| 1466 | 1478 | { |
| 1467 | 1479 | IrInstruction *new_instruction = ir_build_ref(irb, old_instruction->scope, old_instruction->source_node, |
| 1468 | | value, is_const); |
| 1480 | value, is_const, is_volatile); |
| 1469 | 1481 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1470 | 1482 | return new_instruction; |
| 1471 | 1483 | } |
| ... | ... | @@ -2980,7 +2992,7 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { |
| 2980 | 2992 | return nullptr; |
| 2981 | 2993 | } |
| 2982 | 2994 | |
| 2983 | | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 2995 | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 2984 | 2996 | assert(node->type == NodeTypeReturnExpr); |
| 2985 | 2997 | |
| 2986 | 2998 | FnTableEntry *fn_entry = exec_fn_entry(irb->exec); |
| ... | ... | @@ -3068,7 +3080,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3068 | 3080 | case ReturnKindError: |
| 3069 | 3081 | { |
| 3070 | 3082 | assert(expr_node); |
| 3071 | | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 3083 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR); |
| 3072 | 3084 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 3073 | 3085 | return irb->codegen->invalid_instruction; |
| 3074 | 3086 | IrInstruction *err_union_val = ir_build_load_ptr(irb, scope, node, err_union_ptr); |
| ... | ... | @@ -3086,7 +3098,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3086 | 3098 | |
| 3087 | 3099 | ir_set_cursor_at_end(irb, continue_block); |
| 3088 | 3100 | IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false); |
| 3089 | | if (lval != LValPurposeNone) |
| 3101 | if (lval.is_ptr) |
| 3090 | 3102 | return unwrapped_ptr; |
| 3091 | 3103 | else |
| 3092 | 3104 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); |
| ... | ... | @@ -3094,7 +3106,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3094 | 3106 | case ReturnKindMaybe: |
| 3095 | 3107 | { |
| 3096 | 3108 | assert(expr_node); |
| 3097 | | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 3109 | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR); |
| 3098 | 3110 | if (maybe_val_ptr == irb->codegen->invalid_instruction) |
| 3099 | 3111 | return irb->codegen->invalid_instruction; |
| 3100 | 3112 | IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); |
| ... | ... | @@ -3112,7 +3124,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3112 | 3124 | |
| 3113 | 3125 | ir_set_cursor_at_end(irb, continue_block); |
| 3114 | 3126 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false); |
| 3115 | | if (lval != LValPurposeNone) |
| 3127 | if (lval.is_ptr) |
| 3116 | 3128 | return unwrapped_ptr; |
| 3117 | 3129 | else |
| 3118 | 3130 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); |
| ... | ... | @@ -3293,18 +3305,18 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no |
| 3293 | 3305 | } |
| 3294 | 3306 | |
| 3295 | 3307 | static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 3296 | | IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPurposeAssign); |
| 3308 | IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LVAL_PTR); |
| 3297 | 3309 | IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); |
| 3298 | 3310 | |
| 3299 | 3311 | if (lvalue == irb->codegen->invalid_instruction || rvalue == irb->codegen->invalid_instruction) |
| 3300 | 3312 | return irb->codegen->invalid_instruction; |
| 3301 | 3313 | |
| 3302 | | ir_build_store_ptr(irb, scope, node, lvalue, rvalue, false); |
| 3314 | ir_build_store_ptr(irb, scope, node, lvalue, rvalue); |
| 3303 | 3315 | return ir_build_const_void(irb, scope, node); |
| 3304 | 3316 | } |
| 3305 | 3317 | |
| 3306 | 3318 | static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) { |
| 3307 | | IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPurposeAssign); |
| 3319 | IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LVAL_PTR); |
| 3308 | 3320 | if (lvalue == irb->codegen->invalid_instruction) |
| 3309 | 3321 | return lvalue; |
| 3310 | 3322 | IrInstruction *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); |
| ... | ... | @@ -3312,7 +3324,7 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no |
| 3312 | 3324 | if (op2 == irb->codegen->invalid_instruction) |
| 3313 | 3325 | return op2; |
| 3314 | 3326 | IrInstruction *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); |
| 3315 | | ir_build_store_ptr(irb, scope, node, lvalue, result, false); |
| 3327 | ir_build_store_ptr(irb, scope, node, lvalue, result); |
| 3316 | 3328 | return ir_build_const_void(irb, scope, node); |
| 3317 | 3329 | } |
| 3318 | 3330 | |
| ... | ... | @@ -3406,7 +3418,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As |
| 3406 | 3418 | AstNode *op1_node = node->data.bin_op_expr.op1; |
| 3407 | 3419 | AstNode *op2_node = node->data.bin_op_expr.op2; |
| 3408 | 3420 | |
| 3409 | | IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf); |
| 3421 | IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LVAL_PTR); |
| 3410 | 3422 | if (maybe_ptr == irb->codegen->invalid_instruction) |
| 3411 | 3423 | return irb->codegen->invalid_instruction; |
| 3412 | 3424 | |
| ... | ... | @@ -3574,9 +3586,9 @@ static IrInstruction *ir_gen_var_literal(IrBuilder *irb, Scope *scope, AstNode * |
| 3574 | 3586 | } |
| 3575 | 3587 | |
| 3576 | 3588 | static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld *tld, |
| 3577 | | LValPurpose lval, Scope *scope) |
| 3589 | LVal lval, Scope *scope) |
| 3578 | 3590 | { |
| 3579 | | resolve_top_level_decl(irb->codegen, tld, lval != LValPurposeNone); |
| 3591 | resolve_top_level_decl(irb->codegen, tld, lval.is_ptr); |
| 3580 | 3592 | if (tld->resolution == TldResolutionInvalid) |
| 3581 | 3593 | return irb->codegen->invalid_instruction; |
| 3582 | 3594 | |
| ... | ... | @@ -3587,8 +3599,8 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld |
| 3587 | 3599 | { |
| 3588 | 3600 | TldVar *tld_var = (TldVar *)tld; |
| 3589 | 3601 | VariableTableEntry *var = tld_var->var; |
| 3590 | | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var, lval == LValPurposeAddressOfConst); |
| 3591 | | if (lval != LValPurposeNone) |
| 3602 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var, !lval.is_ptr || lval.is_const); |
| 3603 | if (lval.is_ptr) |
| 3592 | 3604 | return var_ptr; |
| 3593 | 3605 | else |
| 3594 | 3606 | return ir_build_load_ptr(irb, scope, source_node, var_ptr); |
| ... | ... | @@ -3599,8 +3611,8 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld |
| 3599 | 3611 | FnTableEntry *fn_entry = tld_fn->fn_entry; |
| 3600 | 3612 | assert(fn_entry->type_entry); |
| 3601 | 3613 | IrInstruction *ref_instruction = ir_build_const_fn(irb, scope, source_node, fn_entry); |
| 3602 | | if (lval != LValPurposeNone) |
| 3603 | | return ir_build_ref(irb, scope, source_node, ref_instruction, true); |
| 3614 | if (lval.is_ptr) |
| 3615 | return ir_build_ref(irb, scope, source_node, ref_instruction, true, false); |
| 3604 | 3616 | else |
| 3605 | 3617 | return ref_instruction; |
| 3606 | 3618 | } |
| ... | ... | @@ -3609,8 +3621,8 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld |
| 3609 | 3621 | TldTypeDef *tld_typedef = (TldTypeDef *)tld; |
| 3610 | 3622 | TypeTableEntry *typedef_type = tld_typedef->type_entry; |
| 3611 | 3623 | IrInstruction *ref_instruction = ir_build_const_type(irb, scope, source_node, typedef_type, false); |
| 3612 | | if (lval != LValPurposeNone) |
| 3613 | | return ir_build_ref(irb, scope, source_node, ref_instruction, true); |
| 3624 | if (lval.is_ptr) |
| 3625 | return ir_build_ref(irb, scope, source_node, ref_instruction, true, false); |
| 3614 | 3626 | else |
| 3615 | 3627 | return ref_instruction; |
| 3616 | 3628 | } |
| ... | ... | @@ -3618,7 +3630,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld |
| 3618 | 3630 | zig_unreachable(); |
| 3619 | 3631 | } |
| 3620 | 3632 | |
| 3621 | | static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 3633 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 3622 | 3634 | assert(node->type == NodeTypeSymbol); |
| 3623 | 3635 | |
| 3624 | 3636 | Buf *variable_name = node->data.symbol_expr.symbol; |
| ... | ... | @@ -3626,8 +3638,8 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3626 | 3638 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); |
| 3627 | 3639 | if (primitive_table_entry) { |
| 3628 | 3640 | IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value, false); |
| 3629 | | if (lval != LValPurposeNone) { |
| 3630 | | return ir_build_ref(irb, scope, node, value, lval == LValPurposeAddressOfConst); |
| 3641 | if (lval.is_ptr) { |
| 3642 | return ir_build_ref(irb, scope, node, value, lval.is_const, lval.is_volatile); |
| 3631 | 3643 | } else { |
| 3632 | 3644 | return value; |
| 3633 | 3645 | } |
| ... | ... | @@ -3635,8 +3647,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3635 | 3647 | |
| 3636 | 3648 | VariableTableEntry *var = find_variable(irb->codegen, scope, variable_name); |
| 3637 | 3649 | if (var) { |
| 3638 | | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, node, var, lval == LValPurposeAddressOfConst); |
| 3639 | | if (lval != LValPurposeNone) |
| 3650 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, node, var, |
| 3651 | !lval.is_ptr || lval.is_const); |
| 3652 | if (lval.is_ptr) |
| 3640 | 3653 | return var_ptr; |
| 3641 | 3654 | else |
| 3642 | 3655 | return ir_build_load_ptr(irb, scope, node, var_ptr); |
| ... | ... | @@ -3658,12 +3671,11 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3658 | 3671 | return irb->codegen->invalid_instruction; |
| 3659 | 3672 | } |
| 3660 | 3673 | |
| 3661 | | static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 3674 | static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 3662 | 3675 | assert(node->type == NodeTypeArrayAccessExpr); |
| 3663 | 3676 | |
| 3664 | 3677 | AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr; |
| 3665 | | IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, |
| 3666 | | LValPurposeAddressOf); |
| 3678 | IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LVAL_PTR); |
| 3667 | 3679 | if (array_ref_instruction == irb->codegen->invalid_instruction) |
| 3668 | 3680 | return array_ref_instruction; |
| 3669 | 3681 | |
| ... | ... | @@ -3674,25 +3686,24 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode |
| 3674 | 3686 | |
| 3675 | 3687 | IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, |
| 3676 | 3688 | subscript_instruction, true); |
| 3677 | | if (lval != LValPurposeNone) |
| 3689 | if (lval.is_ptr) |
| 3678 | 3690 | return ptr_instruction; |
| 3679 | 3691 | |
| 3680 | 3692 | return ir_build_load_ptr(irb, scope, node, ptr_instruction); |
| 3681 | 3693 | } |
| 3682 | 3694 | |
| 3683 | | static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 3695 | static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 3684 | 3696 | assert(node->type == NodeTypeFieldAccessExpr); |
| 3685 | 3697 | |
| 3686 | 3698 | AstNode *container_ref_node = node->data.field_access_expr.struct_expr; |
| 3687 | 3699 | Buf *field_name = node->data.field_access_expr.field_name; |
| 3688 | 3700 | |
| 3689 | | IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, |
| 3690 | | LValPurposeAddressOf); |
| 3701 | IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LVAL_PTR); |
| 3691 | 3702 | if (container_ref_instruction == irb->codegen->invalid_instruction) |
| 3692 | 3703 | return container_ref_instruction; |
| 3693 | 3704 | |
| 3694 | 3705 | IrInstruction *ptr_instruction = ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name); |
| 3695 | | if (lval != LValPurposeNone) |
| 3706 | if (lval.is_ptr) |
| 3696 | 3707 | return ptr_instruction; |
| 3697 | 3708 | |
| 3698 | 3709 | return ir_build_load_ptr(irb, scope, node, ptr_instruction); |
| ... | ... | @@ -4199,20 +4210,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4199 | 4210 | return ir_build_set_global_section(irb, scope, node, tld_var, arg1_value); |
| 4200 | 4211 | } |
| 4201 | 4212 | } |
| 4202 | | case BuiltinFnIdVolatileStore: |
| 4203 | | { |
| 4204 | | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 4205 | | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 4206 | | if (arg0_value == irb->codegen->invalid_instruction) |
| 4207 | | return arg0_value; |
| 4208 | | |
| 4209 | | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); |
| 4210 | | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); |
| 4211 | | if (arg1_value == irb->codegen->invalid_instruction) |
| 4212 | | return arg1_value; |
| 4213 | | |
| 4214 | | return ir_build_store_ptr(irb, scope, node, arg0_value, arg1_value, true); |
| 4215 | | } |
| 4216 | 4213 | } |
| 4217 | 4214 | zig_unreachable(); |
| 4218 | 4215 | } |
| ... | ... | @@ -4295,7 +4292,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4295 | 4292 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); |
| 4296 | 4293 | } |
| 4297 | 4294 | |
| 4298 | | static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LValPurpose lval) { |
| 4295 | static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { |
| 4299 | 4296 | assert(node->type == NodeTypePrefixOpExpr); |
| 4300 | 4297 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 4301 | 4298 | |
| ... | ... | @@ -4307,38 +4304,38 @@ static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, Ast |
| 4307 | 4304 | } |
| 4308 | 4305 | |
| 4309 | 4306 | static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id) { |
| 4310 | | return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone); |
| 4307 | return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LVAL_NONE); |
| 4311 | 4308 | } |
| 4312 | 4309 | |
| 4313 | | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) { |
| 4314 | | if (lval == LValPurposeNone) |
| 4310 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval) { |
| 4311 | if (!lval.is_ptr) |
| 4315 | 4312 | return value; |
| 4316 | 4313 | if (value == irb->codegen->invalid_instruction) |
| 4317 | 4314 | return value; |
| 4318 | 4315 | |
| 4319 | 4316 | // We needed a pointer to a value, but we got a value. So we create |
| 4320 | 4317 | // an instruction which just makes a const pointer of it. |
| 4321 | | return ir_build_ref(irb, scope, value->source_node, value, true); |
| 4318 | return ir_build_ref(irb, scope, value->source_node, value, true, false); |
| 4322 | 4319 | } |
| 4323 | 4320 | |
| 4324 | | static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node, bool is_const, LValPurpose lval) { |
| 4321 | static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node, |
| 4322 | bool is_const, bool is_volatile, LVal lval) |
| 4323 | { |
| 4325 | 4324 | assert(node->type == NodeTypePrefixOpExpr); |
| 4326 | 4325 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 4327 | 4326 | |
| 4328 | | IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, |
| 4329 | | is_const ? LValPurposeAddressOfConst : LValPurposeAddressOf); |
| 4327 | IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, make_lval_addr(is_const, is_volatile)); |
| 4330 | 4328 | if (value == irb->codegen->invalid_instruction) |
| 4331 | 4329 | return value; |
| 4332 | 4330 | |
| 4333 | | |
| 4334 | 4331 | return ir_lval_wrap(irb, scope, value, lval); |
| 4335 | 4332 | } |
| 4336 | 4333 | |
| 4337 | | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 4334 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 4338 | 4335 | assert(node->type == NodeTypePrefixOpExpr); |
| 4339 | 4336 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 4340 | 4337 | |
| 4341 | | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 4338 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR); |
| 4342 | 4339 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 4343 | 4340 | return irb->codegen->invalid_instruction; |
| 4344 | 4341 | |
| ... | ... | @@ -4346,25 +4343,25 @@ static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode |
| 4346 | 4343 | if (payload_ptr == irb->codegen->invalid_instruction) |
| 4347 | 4344 | return irb->codegen->invalid_instruction; |
| 4348 | 4345 | |
| 4349 | | if (lval == LValPurposeNone) |
| 4350 | | return ir_build_load_ptr(irb, scope, node, payload_ptr); |
| 4351 | | else |
| 4346 | if (lval.is_ptr) |
| 4352 | 4347 | return payload_ptr; |
| 4348 | |
| 4349 | return ir_build_load_ptr(irb, scope, node, payload_ptr); |
| 4353 | 4350 | } |
| 4354 | 4351 | |
| 4355 | | static IrInstruction *ir_gen_maybe_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 4352 | static IrInstruction *ir_gen_maybe_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 4356 | 4353 | assert(node->type == NodeTypePrefixOpExpr); |
| 4357 | 4354 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 4358 | 4355 | |
| 4359 | | IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 4356 | IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR); |
| 4360 | 4357 | if (maybe_ptr == irb->codegen->invalid_instruction) |
| 4361 | 4358 | return irb->codegen->invalid_instruction; |
| 4362 | 4359 | |
| 4363 | 4360 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true); |
| 4364 | | if (lval == LValPurposeNone) |
| 4365 | | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); |
| 4366 | | else |
| 4361 | if (lval.is_ptr) |
| 4367 | 4362 | return unwrapped_ptr; |
| 4363 | |
| 4364 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); |
| 4368 | 4365 | } |
| 4369 | 4366 | |
| 4370 | 4367 | static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *node) { |
| ... | ... | @@ -4378,7 +4375,7 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod |
| 4378 | 4375 | return ir_build_bool_not(irb, scope, node, value); |
| 4379 | 4376 | } |
| 4380 | 4377 | |
| 4381 | | static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 4378 | static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 4382 | 4379 | assert(node->type == NodeTypePrefixOpExpr); |
| 4383 | 4380 | |
| 4384 | 4381 | PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op; |
| ... | ... | @@ -4395,9 +4392,13 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 4395 | 4392 | case PrefixOpNegationWrap: |
| 4396 | 4393 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval); |
| 4397 | 4394 | case PrefixOpAddressOf: |
| 4398 | | return ir_gen_address_of(irb, scope, node, false, lval); |
| 4395 | return ir_gen_address_of(irb, scope, node, false, false, lval); |
| 4399 | 4396 | case PrefixOpConstAddressOf: |
| 4400 | | return ir_gen_address_of(irb, scope, node, true, lval); |
| 4397 | return ir_gen_address_of(irb, scope, node, true, false, lval); |
| 4398 | case PrefixOpVolatileAddressOf: |
| 4399 | return ir_gen_address_of(irb, scope, node, false, true, lval); |
| 4400 | case PrefixOpConstVolatileAddressOf: |
| 4401 | return ir_gen_address_of(irb, scope, node, true, true, lval); |
| 4401 | 4402 | case PrefixOpDereference: |
| 4402 | 4403 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); |
| 4403 | 4404 | case PrefixOpMaybe: |
| ... | ... | @@ -4559,7 +4560,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4559 | 4560 | } |
| 4560 | 4561 | assert(elem_node->type == NodeTypeSymbol); |
| 4561 | 4562 | |
| 4562 | | IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LValPurposeAddressOf); |
| 4563 | IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, parent_scope, LVAL_PTR); |
| 4563 | 4564 | if (array_val_ptr == irb->codegen->invalid_instruction) |
| 4564 | 4565 | return array_val_ptr; |
| 4565 | 4566 | |
| ... | ... | @@ -4627,7 +4628,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4627 | 4628 | } else { |
| 4628 | 4629 | elem_val = ir_build_load_ptr(irb, child_scope, node, elem_ptr); |
| 4629 | 4630 | } |
| 4630 | | ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val, false)); |
| 4631 | ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val)); |
| 4631 | 4632 | |
| 4632 | 4633 | LoopStackItem *loop_stack_item = irb->loop_stack.add_one(); |
| 4633 | 4634 | loop_stack_item->break_block = end_block; |
| ... | ... | @@ -4641,7 +4642,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4641 | 4642 | |
| 4642 | 4643 | ir_set_cursor_at_end(irb, continue_block); |
| 4643 | 4644 | IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); |
| 4644 | | ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val, false)); |
| 4645 | ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)); |
| 4645 | 4646 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); |
| 4646 | 4647 | |
| 4647 | 4648 | ir_set_cursor_at_end(irb, end_block); |
| ... | ... | @@ -4783,7 +4784,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4783 | 4784 | AstNode *else_node = node->data.if_var_expr.else_node; |
| 4784 | 4785 | bool var_is_ptr = node->data.if_var_expr.var_is_ptr; |
| 4785 | 4786 | |
| 4786 | | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| 4787 | IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR); |
| 4787 | 4788 | if (maybe_val_ptr == irb->codegen->invalid_instruction) |
| 4788 | 4789 | return maybe_val_ptr; |
| 4789 | 4790 | |
| ... | ... | @@ -4859,7 +4860,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 4859 | 4860 | Buf *var_symbol = node->data.try_expr.var_symbol; |
| 4860 | 4861 | Buf *err_symbol = node->data.try_expr.err_symbol; |
| 4861 | 4862 | |
| 4862 | | IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPurposeAddressOf); |
| 4863 | IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LVAL_PTR); |
| 4863 | 4864 | if (err_val_ptr == irb->codegen->invalid_instruction) |
| 4864 | 4865 | return err_val_ptr; |
| 4865 | 4866 | |
| ... | ... | @@ -4987,7 +4988,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4987 | 4988 | assert(node->type == NodeTypeSwitchExpr); |
| 4988 | 4989 | |
| 4989 | 4990 | AstNode *target_node = node->data.switch_expr.expr; |
| 4990 | | IrInstruction *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPurposeAddressOf); |
| 4991 | IrInstruction *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LVAL_PTR); |
| 4991 | 4992 | if (target_value_ptr == irb->codegen->invalid_instruction) |
| 4992 | 4993 | return target_value_ptr; |
| 4993 | 4994 | IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr); |
| ... | ... | @@ -5175,7 +5176,7 @@ static IrInstruction *ir_gen_goto(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 5175 | 5176 | return ir_build_unreachable(irb, scope, node); |
| 5176 | 5177 | } |
| 5177 | 5178 | |
| 5178 | | static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LValPurpose lval) { |
| 5179 | static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval) { |
| 5179 | 5180 | assert(node->type == NodeTypeCompTime); |
| 5180 | 5181 | |
| 5181 | 5182 | Scope *child_scope = create_comptime_scope(node, parent_scope); |
| ... | ... | @@ -5285,7 +5286,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 5285 | 5286 | AstNode *op2_node = node->data.unwrap_err_expr.op2; |
| 5286 | 5287 | AstNode *var_node = node->data.unwrap_err_expr.symbol; |
| 5287 | 5288 | |
| 5288 | | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf); |
| 5289 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LVAL_PTR); |
| 5289 | 5290 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 5290 | 5291 | return irb->codegen->invalid_instruction; |
| 5291 | 5292 | |
| ... | ... | @@ -5423,7 +5424,7 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5423 | 5424 | } |
| 5424 | 5425 | |
| 5425 | 5426 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, |
| 5426 | | LValPurpose lval) |
| 5427 | LVal lval) |
| 5427 | 5428 | { |
| 5428 | 5429 | assert(scope); |
| 5429 | 5430 | switch (node->type) { |
| ... | ... | @@ -5522,16 +5523,14 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 5522 | 5523 | zig_unreachable(); |
| 5523 | 5524 | } |
| 5524 | 5525 | |
| 5525 | | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, |
| 5526 | | LValPurpose lval) |
| 5527 | | { |
| 5526 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval) { |
| 5528 | 5527 | IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval); |
| 5529 | 5528 | irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction); |
| 5530 | 5529 | return result; |
| 5531 | 5530 | } |
| 5532 | 5531 | |
| 5533 | 5532 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) { |
| 5534 | | return ir_gen_node_extra(irb, node, scope, LValPurposeNone); |
| 5533 | return ir_gen_node_extra(irb, node, scope, LVAL_NONE); |
| 5535 | 5534 | } |
| 5536 | 5535 | |
| 5537 | 5536 | static bool ir_goto_pass2(IrBuilder *irb) { |
| ... | ... | @@ -5589,7 +5588,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 5589 | 5588 | // Entry block gets a reference because we enter it to begin. |
| 5590 | 5589 | ir_ref_bb(irb->current_basic_block); |
| 5591 | 5590 | |
| 5592 | | IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValPurposeNone); |
| 5591 | IrInstruction *result = ir_gen_node_extra(irb, node, scope, LVAL_NONE); |
| 5593 | 5592 | assert(result); |
| 5594 | 5593 | if (irb->exec->invalid) |
| 5595 | 5594 | return false; |
| ... | ... | @@ -6178,7 +6177,7 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio |
| 6178 | 6177 | |
| 6179 | 6178 | static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 6180 | 6179 | ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var, |
| 6181 | | ConstPtrSpecial special, bool ptr_is_const) |
| 6180 | ConstPtrSpecial special, bool ptr_is_const, bool ptr_is_volatile) |
| 6182 | 6181 | { |
| 6183 | 6182 | if (pointee_type->id == TypeTableEntryIdMetaType) { |
| 6184 | 6183 | TypeTableEntry *type_entry = pointee->data.x_type; |
| ... | ... | @@ -6190,10 +6189,12 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr |
| 6190 | 6189 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, |
| 6191 | 6190 | depends_on_compile_var || pointee->depends_on_compile_var); |
| 6192 | 6191 | type_ensure_zero_bits_known(ira->codegen, type_entry); |
| 6193 | | const_val->data.x_type = get_pointer_to_type(ira->codegen, type_entry, ptr_is_const); |
| 6192 | const_val->data.x_type = get_pointer_to_type_volatile(ira->codegen, type_entry, |
| 6193 | ptr_is_const, ptr_is_volatile); |
| 6194 | 6194 | return pointee_type; |
| 6195 | 6195 | } else { |
| 6196 | | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, ptr_is_const); |
| 6196 | TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, pointee_type, |
| 6197 | ptr_is_const, ptr_is_volatile); |
| 6197 | 6198 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, |
| 6198 | 6199 | depends_on_compile_var || pointee->depends_on_compile_var); |
| 6199 | 6200 | const_val->data.x_ptr.base_ptr = pointee; |
| ... | ... | @@ -6433,7 +6434,9 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so |
| 6433 | 6434 | return result; |
| 6434 | 6435 | } |
| 6435 | 6436 | |
| 6436 | | static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) { |
| 6437 | static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_instr, |
| 6438 | IrInstruction *value, TypeTableEntry *wanted_type) |
| 6439 | { |
| 6437 | 6440 | if (instr_is_comptime(value)) { |
| 6438 | 6441 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| 6439 | 6442 | if (!val) |
| ... | ... | @@ -6454,7 +6457,7 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_ |
| 6454 | 6457 | return load_ptr_inst->ptr; |
| 6455 | 6458 | } else { |
| 6456 | 6459 | IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope, |
| 6457 | | source_instr->source_node, value, true); |
| 6460 | source_instr->source_node, value, true, false); |
| 6458 | 6461 | new_instruction->value.type = wanted_type; |
| 6459 | 6462 | |
| 6460 | 6463 | TypeTableEntry *child_type = wanted_type->data.pointer.child_type; |
| ... | ... | @@ -6997,7 +7000,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 6997 | 7000 | } |
| 6998 | 7001 | |
| 6999 | 7002 | static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value, |
| 7000 | | bool is_const) |
| 7003 | bool is_const, bool is_volatile) |
| 7001 | 7004 | { |
| 7002 | 7005 | if (value->value.type->id == TypeTableEntryIdInvalid) |
| 7003 | 7006 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -7007,13 +7010,14 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst |
| 7007 | 7010 | if (!val) |
| 7008 | 7011 | return ira->codegen->builtin_types.entry_invalid; |
| 7009 | 7012 | return ir_analyze_const_ptr(ira, source_instruction, val, value->value.type, |
| 7010 | | value->value.depends_on_compile_var, ConstPtrSpecialNone, is_const); |
| 7013 | value->value.depends_on_compile_var, ConstPtrSpecialNone, is_const, is_volatile); |
| 7011 | 7014 | } |
| 7012 | 7015 | |
| 7013 | | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, value->value.type, true); |
| 7016 | TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, value->value.type, is_const, is_volatile); |
| 7014 | 7017 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 7015 | 7018 | assert(fn_entry); |
| 7016 | | IrInstruction *new_instruction = ir_build_ref_from(&ira->new_irb, source_instruction, value, is_const); |
| 7019 | IrInstruction *new_instruction = ir_build_ref_from(&ira->new_irb, source_instruction, |
| 7020 | value, is_const, is_volatile); |
| 7017 | 7021 | fn_entry->alloca_list.append(new_instruction); |
| 7018 | 7022 | return ptr_type; |
| 7019 | 7023 | } |
| ... | ... | @@ -8700,7 +8704,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc |
| 8700 | 8704 | bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; |
| 8701 | 8705 | depends_on_compile_var = mem_slot->depends_on_compile_var || depends_on_compile_var || is_comptime; |
| 8702 | 8706 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, |
| 8703 | | depends_on_compile_var, ptr_special, is_const); |
| 8707 | depends_on_compile_var, ptr_special, is_const, false); |
| 8704 | 8708 | } else { |
| 8705 | 8709 | ir_build_var_ptr_from(&ira->new_irb, instruction, var, false); |
| 8706 | 8710 | type_ensure_zero_bits_known(ira->codegen, var->value.type); |
| ... | ... | @@ -8786,7 +8790,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 8786 | 8790 | return ir_analyze_var_ptr(ira, &elem_ptr_instruction->base, var, true, depends_on_compile_var); |
| 8787 | 8791 | } else { |
| 8788 | 8792 | return ir_analyze_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val, |
| 8789 | | ira->codegen->builtin_types.entry_void, depends_on_compile_var, ConstPtrSpecialNone, true); |
| 8793 | ira->codegen->builtin_types.entry_void, depends_on_compile_var, ConstPtrSpecialNone, |
| 8794 | true, false); |
| 8790 | 8795 | } |
| 8791 | 8796 | } else { |
| 8792 | 8797 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| ... | ... | @@ -8894,7 +8899,7 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| 8894 | 8899 | bool depends_on_compile_var = container_ptr->value.depends_on_compile_var; |
| 8895 | 8900 | IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, field_ptr_instruction->base.scope, |
| 8896 | 8901 | field_ptr_instruction->base.source_node, fn_entry, container_ptr, depends_on_compile_var); |
| 8897 | | return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value, true); |
| 8902 | return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value, true, false); |
| 8898 | 8903 | } |
| 8899 | 8904 | } |
| 8900 | 8905 | ir_add_error_node(ira, field_ptr_instruction->base.source_node, |
| ... | ... | @@ -8911,6 +8916,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 8911 | 8916 | |
| 8912 | 8917 | assert(container_ptr->value.type->id == TypeTableEntryIdPointer); |
| 8913 | 8918 | bool is_const = container_ptr->value.type->data.pointer.is_const; |
| 8919 | bool is_volatile = container_ptr->value.type->data.pointer.is_volatile; |
| 8914 | 8920 | if (bare_type->id == TypeTableEntryIdStruct) { |
| 8915 | 8921 | if (bare_type->data.structure.is_invalid) |
| 8916 | 8922 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -8929,12 +8935,12 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 8929 | 8935 | bool depends_on_compile_var = field_val->depends_on_compile_var || |
| 8930 | 8936 | struct_val->depends_on_compile_var || ptr_val->depends_on_compile_var; |
| 8931 | 8937 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, field_val, |
| 8932 | | field_val->type, depends_on_compile_var, ConstPtrSpecialNone, is_const); |
| 8938 | field_val->type, depends_on_compile_var, ConstPtrSpecialNone, is_const, is_volatile); |
| 8933 | 8939 | } |
| 8934 | 8940 | } |
| 8935 | 8941 | } |
| 8936 | 8942 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| 8937 | | return get_pointer_to_type(ira->codegen, field->type_entry, is_const); |
| 8943 | return get_pointer_to_type_volatile(ira->codegen, field->type_entry, is_const, is_volatile); |
| 8938 | 8944 | } else { |
| 8939 | 8945 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 8940 | 8946 | field_ptr_instruction, container_ptr, container_type); |
| ... | ... | @@ -8946,7 +8952,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 8946 | 8952 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); |
| 8947 | 8953 | if (field) { |
| 8948 | 8954 | ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| 8949 | | return get_pointer_to_type(ira->codegen, field->type_entry, is_const); |
| 8955 | return get_pointer_to_type_volatile(ira->codegen, field->type_entry, is_const, is_volatile); |
| 8950 | 8956 | } else { |
| 8951 | 8957 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 8952 | 8958 | field_ptr_instruction, container_ptr, container_type); |
| ... | ... | @@ -8992,8 +8998,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 8992 | 8998 | const_val->data.x_fn = fn_entry; |
| 8993 | 8999 | |
| 8994 | 9000 | bool ptr_is_const = true; |
| 9001 | bool ptr_is_volatile = false; |
| 8995 | 9002 | return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry, |
| 8996 | | depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const); |
| 9003 | depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); |
| 8997 | 9004 | } |
| 8998 | 9005 | case TldIdTypeDef: |
| 8999 | 9006 | { |
| ... | ... | @@ -9008,8 +9015,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 9008 | 9015 | const_val->data.x_type = tld_typedef->type_entry; |
| 9009 | 9016 | |
| 9010 | 9017 | bool ptr_is_const = true; |
| 9018 | bool ptr_is_volatile = false; |
| 9011 | 9019 | return ir_analyze_const_ptr(ira, source_instruction, const_val, ira->codegen->builtin_types.entry_type, |
| 9012 | | depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const); |
| 9020 | depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); |
| 9013 | 9021 | } |
| 9014 | 9022 | } |
| 9015 | 9023 | zig_unreachable(); |
| ... | ... | @@ -9051,8 +9059,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9051 | 9059 | |
| 9052 | 9060 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 9053 | 9061 | bool ptr_is_const = true; |
| 9062 | bool ptr_is_volatile = false; |
| 9054 | 9063 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, |
| 9055 | | usize, false, ConstPtrSpecialNone, ptr_is_const); |
| 9064 | usize, false, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); |
| 9056 | 9065 | } else { |
| 9057 | 9066 | ir_add_error_node(ira, source_node, |
| 9058 | 9067 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), |
| ... | ... | @@ -9074,8 +9083,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9074 | 9083 | |
| 9075 | 9084 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 9076 | 9085 | bool ptr_is_const = true; |
| 9086 | bool ptr_is_volatile = false; |
| 9077 | 9087 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, |
| 9078 | | usize, false, ConstPtrSpecialNone, ptr_is_const); |
| 9088 | usize, false, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); |
| 9079 | 9089 | } else { |
| 9080 | 9090 | ir_add_error_node(ira, source_node, |
| 9081 | 9091 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), |
| ... | ... | @@ -9111,15 +9121,17 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9111 | 9121 | if (field) { |
| 9112 | 9122 | if (field->type_entry->id == TypeTableEntryIdVoid) { |
| 9113 | 9123 | bool ptr_is_const = true; |
| 9124 | bool ptr_is_volatile = false; |
| 9114 | 9125 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9115 | 9126 | create_const_enum_tag(child_type, field->value), child_type, depends_on_compile_var, |
| 9116 | | ConstPtrSpecialNone, ptr_is_const); |
| 9127 | ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); |
| 9117 | 9128 | } else { |
| 9118 | 9129 | bool ptr_is_const = true; |
| 9130 | bool ptr_is_volatile = false; |
| 9119 | 9131 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9120 | 9132 | create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false), |
| 9121 | 9133 | child_type->data.enumeration.tag_type, depends_on_compile_var, |
| 9122 | | ConstPtrSpecialNone, ptr_is_const); |
| 9134 | ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); |
| 9123 | 9135 | } |
| 9124 | 9136 | } |
| 9125 | 9137 | } |
| ... | ... | @@ -9142,8 +9154,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9142 | 9154 | const_val->data.x_pure_err = err_table_entry->value; |
| 9143 | 9155 | |
| 9144 | 9156 | bool ptr_is_const = true; |
| 9157 | bool ptr_is_volatile = false; |
| 9145 | 9158 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val, |
| 9146 | | child_type, depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const); |
| 9159 | child_type, depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); |
| 9147 | 9160 | } |
| 9148 | 9161 | |
| 9149 | 9162 | ir_add_error(ira, &field_ptr_instruction->base, |
| ... | ... | @@ -9152,17 +9165,19 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9152 | 9165 | } else if (child_type->id == TypeTableEntryIdInt) { |
| 9153 | 9166 | if (buf_eql_str(field_name, "bit_count")) { |
| 9154 | 9167 | bool ptr_is_const = true; |
| 9168 | bool ptr_is_volatile = false; |
| 9155 | 9169 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9156 | 9170 | create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, |
| 9157 | 9171 | child_type->data.integral.bit_count, false), |
| 9158 | 9172 | ira->codegen->builtin_types.entry_num_lit_int, depends_on_compile_var, |
| 9159 | | ConstPtrSpecialNone, ptr_is_const); |
| 9173 | ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); |
| 9160 | 9174 | } else if (buf_eql_str(field_name, "is_signed")) { |
| 9161 | 9175 | bool ptr_is_const = true; |
| 9176 | bool ptr_is_volatile = false; |
| 9162 | 9177 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9163 | 9178 | create_const_bool(ira->codegen, child_type->data.integral.is_signed), |
| 9164 | 9179 | ira->codegen->builtin_types.entry_bool, depends_on_compile_var, |
| 9165 | | ConstPtrSpecialNone, ptr_is_const); |
| 9180 | ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile); |
| 9166 | 9181 | } else { |
| 9167 | 9182 | ir_add_error(ira, &field_ptr_instruction->base, |
| 9168 | 9183 | buf_sprintf("type '%s' has no member called '%s'", |
| ... | ... | @@ -9288,12 +9303,11 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 9288 | 9303 | } |
| 9289 | 9304 | new_ptr_inst->value.type = ptr->value.type; |
| 9290 | 9305 | ir_build_store_ptr(&ira->new_irb, store_ptr_instruction->base.scope, |
| 9291 | | store_ptr_instruction->base.source_node, new_ptr_inst, casted_value, false); |
| 9306 | store_ptr_instruction->base.source_node, new_ptr_inst, casted_value); |
| 9292 | 9307 | return ir_analyze_void(ira, &store_ptr_instruction->base); |
| 9293 | 9308 | } |
| 9294 | 9309 | |
| 9295 | | ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value, |
| 9296 | | store_ptr_instruction->is_volatile); |
| 9310 | ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value); |
| 9297 | 9311 | return ira->codegen->builtin_types.entry_void; |
| 9298 | 9312 | } |
| 9299 | 9313 | |
| ... | ... | @@ -10337,7 +10351,7 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira, |
| 10337 | 10351 | |
| 10338 | 10352 | static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) { |
| 10339 | 10353 | IrInstruction *value = ref_instruction->value->other; |
| 10340 | | return ir_analyze_ref(ira, &ref_instruction->base, value, ref_instruction->is_const); |
| 10354 | return ir_analyze_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile); |
| 10341 | 10355 | } |
| 10342 | 10356 | |
| 10343 | 10357 | static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction, |