| ... | @@ -44,9 +44,21 @@ struct IrAnalyze { | ... | @@ -44,9 +44,21 @@ struct IrAnalyze { |
| 44 | IrBasicBlock *const_predecessor_bb; | 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 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); | 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, | 61 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval); |
| 49 | LValPurpose lval); | | |
| 50 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); | 62 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 51 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type); | 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,14 +1054,13 @@ static IrInstruction *ir_build_unreachable_from(IrBuilder *irb, IrInstruction *o |
| 1042 | } | 1054 | } |
| 1043 | | 1055 | |
| 1044 | static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | 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 | IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, scope, source_node); | 1059 | IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, scope, source_node); |
| 1048 | instruction->base.value.special = ConstValSpecialStatic; | 1060 | instruction->base.value.special = ConstValSpecialStatic; |
| 1049 | instruction->base.value.type = irb->codegen->builtin_types.entry_void; | 1061 | instruction->base.value.type = irb->codegen->builtin_types.entry_void; |
| 1050 | instruction->ptr = ptr; | 1062 | instruction->ptr = ptr; |
| 1051 | instruction->value = value; | 1063 | instruction->value = value; |
| 1052 | instruction->is_volatile = is_volatile; | | |
| 1053 | | 1064 | |
| 1054 | ir_ref_instruction(ptr, irb->current_basic_block); | 1065 | ir_ref_instruction(ptr, irb->current_basic_block); |
| 1055 | ir_ref_instruction(value, irb->current_basic_block); | 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,10 +1069,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode * |
| 1058 | } | 1069 | } |
| 1059 | | 1070 | |
| 1060 | static IrInstruction *ir_build_store_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, | 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 | IrInstruction *new_instruction = ir_build_store_ptr(irb, old_instruction->scope, | 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 | ir_link_new_instruction(new_instruction, old_instruction); | 1076 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1066 | return new_instruction; | 1077 | return new_instruction; |
| 1067 | } | 1078 | } |
| ... | @@ -1450,11 +1461,12 @@ static IrInstruction *ir_build_array_len(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -1450,11 +1461,12 @@ static IrInstruction *ir_build_array_len(IrBuilder *irb, Scope *scope, AstNode * |
| 1450 | } | 1461 | } |
| 1451 | | 1462 | |
| 1452 | static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value, | 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 | IrInstructionRef *instruction = ir_build_instruction<IrInstructionRef>(irb, scope, source_node); | 1466 | IrInstructionRef *instruction = ir_build_instruction<IrInstructionRef>(irb, scope, source_node); |
| 1456 | instruction->value = value; | 1467 | instruction->value = value; |
| 1457 | instruction->is_const = is_const; | 1468 | instruction->is_const = is_const; |
| | 1469 | instruction->is_volatile = is_volatile; |
| 1458 | | 1470 | |
| 1459 | ir_ref_instruction(value, irb->current_basic_block); | 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,10 +1474,10 @@ static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source |
| 1462 | } | 1474 | } |
| 1463 | | 1475 | |
| 1464 | static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value, | 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 | IrInstruction *new_instruction = ir_build_ref(irb, old_instruction->scope, old_instruction->source_node, | 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 | ir_link_new_instruction(new_instruction, old_instruction); | 1481 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1470 | return new_instruction; | 1482 | return new_instruction; |
| 1471 | } | 1483 | } |
| ... | @@ -2980,7 +2992,7 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { | ... | @@ -2980,7 +2992,7 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { |
| 2980 | return nullptr; | 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 | assert(node->type == NodeTypeReturnExpr); | 2996 | assert(node->type == NodeTypeReturnExpr); |
| 2985 | | 2997 | |
| 2986 | FnTableEntry *fn_entry = exec_fn_entry(irb->exec); | 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,7 +3080,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3068 | case ReturnKindError: | 3080 | case ReturnKindError: |
| 3069 | { | 3081 | { |
| 3070 | assert(expr_node); | 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 | if (err_union_ptr == irb->codegen->invalid_instruction) | 3084 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 3073 | return irb->codegen->invalid_instruction; | 3085 | return irb->codegen->invalid_instruction; |
| 3074 | IrInstruction *err_union_val = ir_build_load_ptr(irb, scope, node, err_union_ptr); | 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,7 +3098,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3086 | | 3098 | |
| 3087 | ir_set_cursor_at_end(irb, continue_block); | 3099 | ir_set_cursor_at_end(irb, continue_block); |
| 3088 | IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false); | 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 | return unwrapped_ptr; | 3102 | return unwrapped_ptr; |
| 3091 | else | 3103 | else |
| 3092 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); | 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,7 +3106,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3094 | case ReturnKindMaybe: | 3106 | case ReturnKindMaybe: |
| 3095 | { | 3107 | { |
| 3096 | assert(expr_node); | 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 | if (maybe_val_ptr == irb->codegen->invalid_instruction) | 3110 | if (maybe_val_ptr == irb->codegen->invalid_instruction) |
| 3099 | return irb->codegen->invalid_instruction; | 3111 | return irb->codegen->invalid_instruction; |
| 3100 | IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); | 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,7 +3124,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3112 | | 3124 | |
| 3113 | ir_set_cursor_at_end(irb, continue_block); | 3125 | ir_set_cursor_at_end(irb, continue_block); |
| 3114 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false); | 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 | return unwrapped_ptr; | 3128 | return unwrapped_ptr; |
| 3117 | else | 3129 | else |
| 3118 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); | 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,18 +3305,18 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no |
| 3293 | } | 3305 | } |
| 3294 | | 3306 | |
| 3295 | static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) { | 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 | IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); | 3309 | IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); |
| 3298 | | 3310 | |
| 3299 | if (lvalue == irb->codegen->invalid_instruction || rvalue == irb->codegen->invalid_instruction) | 3311 | if (lvalue == irb->codegen->invalid_instruction || rvalue == irb->codegen->invalid_instruction) |
| 3300 | return irb->codegen->invalid_instruction; | 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 | return ir_build_const_void(irb, scope, node); | 3315 | return ir_build_const_void(irb, scope, node); |
| 3304 | } | 3316 | } |
| 3305 | | 3317 | |
| 3306 | static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) { | 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 | if (lvalue == irb->codegen->invalid_instruction) | 3320 | if (lvalue == irb->codegen->invalid_instruction) |
| 3309 | return lvalue; | 3321 | return lvalue; |
| 3310 | IrInstruction *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); | 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,7 +3324,7 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no |
| 3312 | if (op2 == irb->codegen->invalid_instruction) | 3324 | if (op2 == irb->codegen->invalid_instruction) |
| 3313 | return op2; | 3325 | return op2; |
| 3314 | IrInstruction *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); | 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 | return ir_build_const_void(irb, scope, node); | 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,7 +3418,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As |
| 3406 | AstNode *op1_node = node->data.bin_op_expr.op1; | 3418 | AstNode *op1_node = node->data.bin_op_expr.op1; |
| 3407 | AstNode *op2_node = node->data.bin_op_expr.op2; | 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 | if (maybe_ptr == irb->codegen->invalid_instruction) | 3422 | if (maybe_ptr == irb->codegen->invalid_instruction) |
| 3411 | return irb->codegen->invalid_instruction; | 3423 | return irb->codegen->invalid_instruction; |
| 3412 | | 3424 | |
| ... | @@ -3574,9 +3586,9 @@ static IrInstruction *ir_gen_var_literal(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -3574,9 +3586,9 @@ static IrInstruction *ir_gen_var_literal(IrBuilder *irb, Scope *scope, AstNode * |
| 3574 | } | 3586 | } |
| 3575 | | 3587 | |
| 3576 | static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld *tld, | 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 | if (tld->resolution == TldResolutionInvalid) | 3592 | if (tld->resolution == TldResolutionInvalid) |
| 3581 | return irb->codegen->invalid_instruction; | 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,8 +3599,8 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld |
| 3587 | { | 3599 | { |
| 3588 | TldVar *tld_var = (TldVar *)tld; | 3600 | TldVar *tld_var = (TldVar *)tld; |
| 3589 | VariableTableEntry *var = tld_var->var; | 3601 | VariableTableEntry *var = tld_var->var; |
| 3590 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var, lval == LValPurposeAddressOfConst); | 3602 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var, !lval.is_ptr || lval.is_const); |
| 3591 | if (lval != LValPurposeNone) | 3603 | if (lval.is_ptr) |
| 3592 | return var_ptr; | 3604 | return var_ptr; |
| 3593 | else | 3605 | else |
| 3594 | return ir_build_load_ptr(irb, scope, source_node, var_ptr); | 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,8 +3611,8 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld |
| 3599 | FnTableEntry *fn_entry = tld_fn->fn_entry; | 3611 | FnTableEntry *fn_entry = tld_fn->fn_entry; |
| 3600 | assert(fn_entry->type_entry); | 3612 | assert(fn_entry->type_entry); |
| 3601 | IrInstruction *ref_instruction = ir_build_const_fn(irb, scope, source_node, fn_entry); | 3613 | IrInstruction *ref_instruction = ir_build_const_fn(irb, scope, source_node, fn_entry); |
| 3602 | if (lval != LValPurposeNone) | 3614 | if (lval.is_ptr) |
| 3603 | return ir_build_ref(irb, scope, source_node, ref_instruction, true); | 3615 | return ir_build_ref(irb, scope, source_node, ref_instruction, true, false); |
| 3604 | else | 3616 | else |
| 3605 | return ref_instruction; | 3617 | return ref_instruction; |
| 3606 | } | 3618 | } |
| ... | @@ -3609,8 +3621,8 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld | ... | @@ -3609,8 +3621,8 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld |
| 3609 | TldTypeDef *tld_typedef = (TldTypeDef *)tld; | 3621 | TldTypeDef *tld_typedef = (TldTypeDef *)tld; |
| 3610 | TypeTableEntry *typedef_type = tld_typedef->type_entry; | 3622 | TypeTableEntry *typedef_type = tld_typedef->type_entry; |
| 3611 | IrInstruction *ref_instruction = ir_build_const_type(irb, scope, source_node, typedef_type, false); | 3623 | IrInstruction *ref_instruction = ir_build_const_type(irb, scope, source_node, typedef_type, false); |
| 3612 | if (lval != LValPurposeNone) | 3624 | if (lval.is_ptr) |
| 3613 | return ir_build_ref(irb, scope, source_node, ref_instruction, true); | 3625 | return ir_build_ref(irb, scope, source_node, ref_instruction, true, false); |
| 3614 | else | 3626 | else |
| 3615 | return ref_instruction; | 3627 | return ref_instruction; |
| 3616 | } | 3628 | } |
| ... | @@ -3618,7 +3630,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld | ... | @@ -3618,7 +3630,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld |
| 3618 | zig_unreachable(); | 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 | assert(node->type == NodeTypeSymbol); | 3634 | assert(node->type == NodeTypeSymbol); |
| 3623 | | 3635 | |
| 3624 | Buf *variable_name = node->data.symbol_expr.symbol; | 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,8 +3638,8 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3626 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); | 3638 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); |
| 3627 | if (primitive_table_entry) { | 3639 | if (primitive_table_entry) { |
| 3628 | IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value, false); | 3640 | IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value, false); |
| 3629 | if (lval != LValPurposeNone) { | 3641 | if (lval.is_ptr) { |
| 3630 | return ir_build_ref(irb, scope, node, value, lval == LValPurposeAddressOfConst); | 3642 | return ir_build_ref(irb, scope, node, value, lval.is_const, lval.is_volatile); |
| 3631 | } else { | 3643 | } else { |
| 3632 | return value; | 3644 | return value; |
| 3633 | } | 3645 | } |
| ... | @@ -3635,8 +3647,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -3635,8 +3647,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3635 | | 3647 | |
| 3636 | VariableTableEntry *var = find_variable(irb->codegen, scope, variable_name); | 3648 | VariableTableEntry *var = find_variable(irb->codegen, scope, variable_name); |
| 3637 | if (var) { | 3649 | if (var) { |
| 3638 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, node, var, lval == LValPurposeAddressOfConst); | 3650 | IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, node, var, |
| 3639 | if (lval != LValPurposeNone) | 3651 | !lval.is_ptr || lval.is_const); |
| | 3652 | if (lval.is_ptr) |
| 3640 | return var_ptr; | 3653 | return var_ptr; |
| 3641 | else | 3654 | else |
| 3642 | return ir_build_load_ptr(irb, scope, node, var_ptr); | 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,12 +3671,11 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3658 | return irb->codegen->invalid_instruction; | 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 | assert(node->type == NodeTypeArrayAccessExpr); | 3675 | assert(node->type == NodeTypeArrayAccessExpr); |
| 3663 | | 3676 | |
| 3664 | AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr; | 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, | 3678 | IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LVAL_PTR); |
| 3666 | LValPurposeAddressOf); | | |
| 3667 | if (array_ref_instruction == irb->codegen->invalid_instruction) | 3679 | if (array_ref_instruction == irb->codegen->invalid_instruction) |
| 3668 | return array_ref_instruction; | 3680 | return array_ref_instruction; |
| 3669 | | 3681 | |
| ... | @@ -3674,25 +3686,24 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -3674,25 +3686,24 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode |
| 3674 | | 3686 | |
| 3675 | IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, | 3687 | IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, |
| 3676 | subscript_instruction, true); | 3688 | subscript_instruction, true); |
| 3677 | if (lval != LValPurposeNone) | 3689 | if (lval.is_ptr) |
| 3678 | return ptr_instruction; | 3690 | return ptr_instruction; |
| 3679 | | 3691 | |
| 3680 | return ir_build_load_ptr(irb, scope, node, ptr_instruction); | 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 | assert(node->type == NodeTypeFieldAccessExpr); | 3696 | assert(node->type == NodeTypeFieldAccessExpr); |
| 3685 | | 3697 | |
| 3686 | AstNode *container_ref_node = node->data.field_access_expr.struct_expr; | 3698 | AstNode *container_ref_node = node->data.field_access_expr.struct_expr; |
| 3687 | Buf *field_name = node->data.field_access_expr.field_name; | 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, | 3701 | IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LVAL_PTR); |
| 3690 | LValPurposeAddressOf); | | |
| 3691 | if (container_ref_instruction == irb->codegen->invalid_instruction) | 3702 | if (container_ref_instruction == irb->codegen->invalid_instruction) |
| 3692 | return container_ref_instruction; | 3703 | return container_ref_instruction; |
| 3693 | | 3704 | |
| 3694 | IrInstruction *ptr_instruction = ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name); | 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 | return ptr_instruction; | 3707 | return ptr_instruction; |
| 3697 | | 3708 | |
| 3698 | return ir_build_load_ptr(irb, scope, node, ptr_instruction); | 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,20 +4210,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4199 | return ir_build_set_global_section(irb, scope, node, tld_var, arg1_value); | 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 | zig_unreachable(); | 4214 | zig_unreachable(); |
| 4218 | } | 4215 | } |
| ... | @@ -4295,7 +4292,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -4295,7 +4292,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4295 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); | 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 | assert(node->type == NodeTypePrefixOpExpr); | 4296 | assert(node->type == NodeTypePrefixOpExpr); |
| 4300 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | 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,38 +4304,38 @@ static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, Ast |
| 4307 | } | 4304 | } |
| 4308 | | 4305 | |
| 4309 | static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id) { | 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) { | 4310 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval) { |
| 4314 | if (lval == LValPurposeNone) | 4311 | if (!lval.is_ptr) |
| 4315 | return value; | 4312 | return value; |
| 4316 | if (value == irb->codegen->invalid_instruction) | 4313 | if (value == irb->codegen->invalid_instruction) |
| 4317 | return value; | 4314 | return value; |
| 4318 | | 4315 | |
| 4319 | // We needed a pointer to a value, but we got a value. So we create | 4316 | // We needed a pointer to a value, but we got a value. So we create |
| 4320 | // an instruction which just makes a const pointer of it. | 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 | assert(node->type == NodeTypePrefixOpExpr); | 4324 | assert(node->type == NodeTypePrefixOpExpr); |
| 4326 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | 4325 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 4327 | | 4326 | |
| 4328 | IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, | 4327 | IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, make_lval_addr(is_const, is_volatile)); |
| 4329 | is_const ? LValPurposeAddressOfConst : LValPurposeAddressOf); | | |
| 4330 | if (value == irb->codegen->invalid_instruction) | 4328 | if (value == irb->codegen->invalid_instruction) |
| 4331 | return value; | 4329 | return value; |
| 4332 | | 4330 | |
| 4333 | | | |
| 4334 | return ir_lval_wrap(irb, scope, value, lval); | 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 | assert(node->type == NodeTypePrefixOpExpr); | 4335 | assert(node->type == NodeTypePrefixOpExpr); |
| 4339 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | 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 | if (err_union_ptr == irb->codegen->invalid_instruction) | 4339 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 4343 | return irb->codegen->invalid_instruction; | 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,25 +4343,25 @@ static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode |
| 4346 | if (payload_ptr == irb->codegen->invalid_instruction) | 4343 | if (payload_ptr == irb->codegen->invalid_instruction) |
| 4347 | return irb->codegen->invalid_instruction; | 4344 | return irb->codegen->invalid_instruction; |
| 4348 | | 4345 | |
| 4349 | if (lval == LValPurposeNone) | 4346 | if (lval.is_ptr) |
| 4350 | return ir_build_load_ptr(irb, scope, node, payload_ptr); | | |
| 4351 | else | | |
| 4352 | return payload_ptr; | 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 | assert(node->type == NodeTypePrefixOpExpr); | 4353 | assert(node->type == NodeTypePrefixOpExpr); |
| 4357 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | 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 | if (maybe_ptr == irb->codegen->invalid_instruction) | 4357 | if (maybe_ptr == irb->codegen->invalid_instruction) |
| 4361 | return irb->codegen->invalid_instruction; | 4358 | return irb->codegen->invalid_instruction; |
| 4362 | | 4359 | |
| 4363 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true); | 4360 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true); |
| 4364 | if (lval == LValPurposeNone) | 4361 | if (lval.is_ptr) |
| 4365 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); | | |
| 4366 | else | | |
| 4367 | return unwrapped_ptr; | 4362 | return unwrapped_ptr; |
| | 4363 | |
| | 4364 | return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); |
| 4368 | } | 4365 | } |
| 4369 | | 4366 | |
| 4370 | static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *node) { | 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,7 +4375,7 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod |
| 4378 | return ir_build_bool_not(irb, scope, node, value); | 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 | assert(node->type == NodeTypePrefixOpExpr); | 4379 | assert(node->type == NodeTypePrefixOpExpr); |
| 4383 | | 4380 | |
| 4384 | PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op; | 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,9 +4392,13 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 4395 | case PrefixOpNegationWrap: | 4392 | case PrefixOpNegationWrap: |
| 4396 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval); | 4393 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval); |
| 4397 | case PrefixOpAddressOf: | 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 | case PrefixOpConstAddressOf: | 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 | case PrefixOpDereference: | 4402 | case PrefixOpDereference: |
| 4402 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); | 4403 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); |
| 4403 | case PrefixOpMaybe: | 4404 | case PrefixOpMaybe: |
| ... | @@ -4559,7 +4560,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -4559,7 +4560,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4559 | } | 4560 | } |
| 4560 | assert(elem_node->type == NodeTypeSymbol); | 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 | if (array_val_ptr == irb->codegen->invalid_instruction) | 4564 | if (array_val_ptr == irb->codegen->invalid_instruction) |
| 4564 | return array_val_ptr; | 4565 | return array_val_ptr; |
| 4565 | | 4566 | |
| ... | @@ -4627,7 +4628,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -4627,7 +4628,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4627 | } else { | 4628 | } else { |
| 4628 | elem_val = ir_build_load_ptr(irb, child_scope, node, elem_ptr); | 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 | LoopStackItem *loop_stack_item = irb->loop_stack.add_one(); | 4633 | LoopStackItem *loop_stack_item = irb->loop_stack.add_one(); |
| 4633 | loop_stack_item->break_block = end_block; | 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,7 +4642,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 4641 | | 4642 | |
| 4642 | ir_set_cursor_at_end(irb, continue_block); | 4643 | ir_set_cursor_at_end(irb, continue_block); |
| 4643 | IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); | 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 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); | 4646 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); |
| 4646 | | 4647 | |
| 4647 | ir_set_cursor_at_end(irb, end_block); | 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,7 +4784,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4783 | AstNode *else_node = node->data.if_var_expr.else_node; | 4784 | AstNode *else_node = node->data.if_var_expr.else_node; |
| 4784 | bool var_is_ptr = node->data.if_var_expr.var_is_ptr; | 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 | if (maybe_val_ptr == irb->codegen->invalid_instruction) | 4788 | if (maybe_val_ptr == irb->codegen->invalid_instruction) |
| 4788 | return maybe_val_ptr; | 4789 | return maybe_val_ptr; |
| 4789 | | 4790 | |
| ... | @@ -4859,7 +4860,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -4859,7 +4860,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 4859 | Buf *var_symbol = node->data.try_expr.var_symbol; | 4860 | Buf *var_symbol = node->data.try_expr.var_symbol; |
| 4860 | Buf *err_symbol = node->data.try_expr.err_symbol; | 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 | if (err_val_ptr == irb->codegen->invalid_instruction) | 4864 | if (err_val_ptr == irb->codegen->invalid_instruction) |
| 4864 | return err_val_ptr; | 4865 | return err_val_ptr; |
| 4865 | | 4866 | |
| ... | @@ -4987,7 +4988,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -4987,7 +4988,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4987 | assert(node->type == NodeTypeSwitchExpr); | 4988 | assert(node->type == NodeTypeSwitchExpr); |
| 4988 | | 4989 | |
| 4989 | AstNode *target_node = node->data.switch_expr.expr; | 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 | if (target_value_ptr == irb->codegen->invalid_instruction) | 4992 | if (target_value_ptr == irb->codegen->invalid_instruction) |
| 4992 | return target_value_ptr; | 4993 | return target_value_ptr; |
| 4993 | IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr); | 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,7 +5176,7 @@ static IrInstruction *ir_gen_goto(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 5175 | return ir_build_unreachable(irb, scope, node); | 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 | assert(node->type == NodeTypeCompTime); | 5180 | assert(node->type == NodeTypeCompTime); |
| 5180 | | 5181 | |
| 5181 | Scope *child_scope = create_comptime_scope(node, parent_scope); | 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,7 +5286,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 5285 | AstNode *op2_node = node->data.unwrap_err_expr.op2; | 5286 | AstNode *op2_node = node->data.unwrap_err_expr.op2; |
| 5286 | AstNode *var_node = node->data.unwrap_err_expr.symbol; | 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 | if (err_union_ptr == irb->codegen->invalid_instruction) | 5290 | if (err_union_ptr == irb->codegen->invalid_instruction) |
| 5290 | return irb->codegen->invalid_instruction; | 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,7 +5424,7 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5423 | } | 5424 | } |
| 5424 | | 5425 | |
| 5425 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, | 5426 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, |
| 5426 | LValPurpose lval) | 5427 | LVal lval) |
| 5427 | { | 5428 | { |
| 5428 | assert(scope); | 5429 | assert(scope); |
| 5429 | switch (node->type) { | 5430 | switch (node->type) { |
| ... | @@ -5522,16 +5523,14 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -5522,16 +5523,14 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 5522 | zig_unreachable(); | 5523 | zig_unreachable(); |
| 5523 | } | 5524 | } |
| 5524 | | 5525 | |
| 5525 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, | 5526 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval) { |
| 5526 | LValPurpose lval) | | |
| 5527 | { | | |
| 5528 | IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval); | 5527 | IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval); |
| 5529 | irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction); | 5528 | irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction); |
| 5530 | return result; | 5529 | return result; |
| 5531 | } | 5530 | } |
| 5532 | | 5531 | |
| 5533 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) { | 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 | static bool ir_goto_pass2(IrBuilder *irb) { | 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,7 +5588,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 5589 | // Entry block gets a reference because we enter it to begin. | 5588 | // Entry block gets a reference because we enter it to begin. |
| 5590 | ir_ref_bb(irb->current_basic_block); | 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 | assert(result); | 5592 | assert(result); |
| 5594 | if (irb->exec->invalid) | 5593 | if (irb->exec->invalid) |
| 5595 | return false; | 5594 | return false; |
| ... | @@ -6178,7 +6177,7 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio | ... | @@ -6178,7 +6177,7 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio |
| 6178 | | 6177 | |
| 6179 | static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction, | 6178 | static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 6180 | ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var, | 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 | if (pointee_type->id == TypeTableEntryIdMetaType) { | 6182 | if (pointee_type->id == TypeTableEntryIdMetaType) { |
| 6184 | TypeTableEntry *type_entry = pointee->data.x_type; | 6183 | TypeTableEntry *type_entry = pointee->data.x_type; |
| ... | @@ -6190,10 +6189,12 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr | ... | @@ -6190,10 +6189,12 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr |
| 6190 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, | 6189 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, |
| 6191 | depends_on_compile_var || pointee->depends_on_compile_var); | 6190 | depends_on_compile_var || pointee->depends_on_compile_var); |
| 6192 | type_ensure_zero_bits_known(ira->codegen, type_entry); | 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 | return pointee_type; | 6194 | return pointee_type; |
| 6195 | } else { | 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 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, | 6198 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, |
| 6198 | depends_on_compile_var || pointee->depends_on_compile_var); | 6199 | depends_on_compile_var || pointee->depends_on_compile_var); |
| 6199 | const_val->data.x_ptr.base_ptr = pointee; | 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,7 +6434,9 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so |
| 6433 | return result; | 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 | if (instr_is_comptime(value)) { | 6440 | if (instr_is_comptime(value)) { |
| 6438 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | 6441 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| 6439 | if (!val) | 6442 | if (!val) |
| ... | @@ -6454,7 +6457,7 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -6454,7 +6457,7 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_ |
| 6454 | return load_ptr_inst->ptr; | 6457 | return load_ptr_inst->ptr; |
| 6455 | } else { | 6458 | } else { |
| 6456 | IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope, | 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 | new_instruction->value.type = wanted_type; | 6461 | new_instruction->value.type = wanted_type; |
| 6459 | | 6462 | |
| 6460 | TypeTableEntry *child_type = wanted_type->data.pointer.child_type; | 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,7 +7000,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 6997 | } | 7000 | } |
| 6998 | | 7001 | |
| 6999 | static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value, | 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 | if (value->value.type->id == TypeTableEntryIdInvalid) | 7005 | if (value->value.type->id == TypeTableEntryIdInvalid) |
| 7003 | return ira->codegen->builtin_types.entry_invalid; | 7006 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -7007,13 +7010,14 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -7007,13 +7010,14 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst |
| 7007 | if (!val) | 7010 | if (!val) |
| 7008 | return ira->codegen->builtin_types.entry_invalid; | 7011 | return ira->codegen->builtin_types.entry_invalid; |
| 7009 | return ir_analyze_const_ptr(ira, source_instruction, val, value->value.type, | 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 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | 7017 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 7015 | assert(fn_entry); | 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 | fn_entry->alloca_list.append(new_instruction); | 7021 | fn_entry->alloca_list.append(new_instruction); |
| 7018 | return ptr_type; | 7022 | return ptr_type; |
| 7019 | } | 7023 | } |
| ... | @@ -8700,7 +8704,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -8700,7 +8704,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc |
| 8700 | bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; | 8704 | bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; |
| 8701 | depends_on_compile_var = mem_slot->depends_on_compile_var || depends_on_compile_var || is_comptime; | 8705 | depends_on_compile_var = mem_slot->depends_on_compile_var || depends_on_compile_var || is_comptime; |
| 8702 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, | 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 | } else { | 8708 | } else { |
| 8705 | ir_build_var_ptr_from(&ira->new_irb, instruction, var, false); | 8709 | ir_build_var_ptr_from(&ira->new_irb, instruction, var, false); |
| 8706 | type_ensure_zero_bits_known(ira->codegen, var->value.type); | 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,7 +8790,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 8786 | return ir_analyze_var_ptr(ira, &elem_ptr_instruction->base, var, true, depends_on_compile_var); | 8790 | return ir_analyze_var_ptr(ira, &elem_ptr_instruction->base, var, true, depends_on_compile_var); |
| 8787 | } else { | 8791 | } else { |
| 8788 | return ir_analyze_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val, | 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 | } else { | 8796 | } else { |
| 8792 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, | 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,7 +8899,7 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| 8894 | bool depends_on_compile_var = container_ptr->value.depends_on_compile_var; | 8899 | bool depends_on_compile_var = container_ptr->value.depends_on_compile_var; |
| 8895 | IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, field_ptr_instruction->base.scope, | 8900 | IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, field_ptr_instruction->base.scope, |
| 8896 | field_ptr_instruction->base.source_node, fn_entry, container_ptr, depends_on_compile_var); | 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 | ir_add_error_node(ira, field_ptr_instruction->base.source_node, | 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,6 +8916,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 8911 | | 8916 | |
| 8912 | assert(container_ptr->value.type->id == TypeTableEntryIdPointer); | 8917 | assert(container_ptr->value.type->id == TypeTableEntryIdPointer); |
| 8913 | bool is_const = container_ptr->value.type->data.pointer.is_const; | 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 | if (bare_type->id == TypeTableEntryIdStruct) { | 8920 | if (bare_type->id == TypeTableEntryIdStruct) { |
| 8915 | if (bare_type->data.structure.is_invalid) | 8921 | if (bare_type->data.structure.is_invalid) |
| 8916 | return ira->codegen->builtin_types.entry_invalid; | 8922 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -8929,12 +8935,12 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -8929,12 +8935,12 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 8929 | bool depends_on_compile_var = field_val->depends_on_compile_var || | 8935 | bool depends_on_compile_var = field_val->depends_on_compile_var || |
| 8930 | struct_val->depends_on_compile_var || ptr_val->depends_on_compile_var; | 8936 | struct_val->depends_on_compile_var || ptr_val->depends_on_compile_var; |
| 8931 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, field_val, | 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 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | 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 | } else { | 8944 | } else { |
| 8939 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | 8945 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 8940 | field_ptr_instruction, container_ptr, container_type); | 8946 | field_ptr_instruction, container_ptr, container_type); |
| ... | @@ -8946,7 +8952,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -8946,7 +8952,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 8946 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); | 8952 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); |
| 8947 | if (field) { | 8953 | if (field) { |
| 8948 | ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | 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 | } else { | 8956 | } else { |
| 8951 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | 8957 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 8952 | field_ptr_instruction, container_ptr, container_type); | 8958 | field_ptr_instruction, container_ptr, container_type); |
| ... | @@ -8992,8 +8998,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source | ... | @@ -8992,8 +8998,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 8992 | const_val->data.x_fn = fn_entry; | 8998 | const_val->data.x_fn = fn_entry; |
| 8993 | | 8999 | |
| 8994 | bool ptr_is_const = true; | 9000 | bool ptr_is_const = true; |
| | 9001 | bool ptr_is_volatile = false; |
| 8995 | return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry, | 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 | case TldIdTypeDef: | 9005 | case TldIdTypeDef: |
| 8999 | { | 9006 | { |
| ... | @@ -9008,8 +9015,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source | ... | @@ -9008,8 +9015,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 9008 | const_val->data.x_type = tld_typedef->type_entry; | 9015 | const_val->data.x_type = tld_typedef->type_entry; |
| 9009 | | 9016 | |
| 9010 | bool ptr_is_const = true; | 9017 | bool ptr_is_const = true; |
| | 9018 | bool ptr_is_volatile = false; |
| 9011 | return ir_analyze_const_ptr(ira, source_instruction, const_val, ira->codegen->builtin_types.entry_type, | 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 | zig_unreachable(); | 9023 | zig_unreachable(); |
| ... | @@ -9051,8 +9059,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -9051,8 +9059,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9051 | | 9059 | |
| 9052 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; | 9060 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 9053 | bool ptr_is_const = true; | 9061 | bool ptr_is_const = true; |
| | 9062 | bool ptr_is_volatile = false; |
| 9054 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, | 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 | } else { | 9065 | } else { |
| 9057 | ir_add_error_node(ira, source_node, | 9066 | ir_add_error_node(ira, source_node, |
| 9058 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), | 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,8 +9083,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9074 | | 9083 | |
| 9075 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; | 9084 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 9076 | bool ptr_is_const = true; | 9085 | bool ptr_is_const = true; |
| | 9086 | bool ptr_is_volatile = false; |
| 9077 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, | 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 | } else { | 9089 | } else { |
| 9080 | ir_add_error_node(ira, source_node, | 9090 | ir_add_error_node(ira, source_node, |
| 9081 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), | 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,15 +9121,17 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9111 | if (field) { | 9121 | if (field) { |
| 9112 | if (field->type_entry->id == TypeTableEntryIdVoid) { | 9122 | if (field->type_entry->id == TypeTableEntryIdVoid) { |
| 9113 | bool ptr_is_const = true; | 9123 | bool ptr_is_const = true; |
| | 9124 | bool ptr_is_volatile = false; |
| 9114 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 9125 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9115 | create_const_enum_tag(child_type, field->value), child_type, depends_on_compile_var, | 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 | } else { | 9128 | } else { |
| 9118 | bool ptr_is_const = true; | 9129 | bool ptr_is_const = true; |
| | 9130 | bool ptr_is_volatile = false; |
| 9119 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 9131 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9120 | create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false), | 9132 | create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false), |
| 9121 | child_type->data.enumeration.tag_type, depends_on_compile_var, | 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,8 +9154,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9142 | const_val->data.x_pure_err = err_table_entry->value; | 9154 | const_val->data.x_pure_err = err_table_entry->value; |
| 9143 | | 9155 | |
| 9144 | bool ptr_is_const = true; | 9156 | bool ptr_is_const = true; |
| | 9157 | bool ptr_is_volatile = false; |
| 9145 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val, | 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 | ir_add_error(ira, &field_ptr_instruction->base, | 9162 | ir_add_error(ira, &field_ptr_instruction->base, |
| ... | @@ -9152,17 +9165,19 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -9152,17 +9165,19 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9152 | } else if (child_type->id == TypeTableEntryIdInt) { | 9165 | } else if (child_type->id == TypeTableEntryIdInt) { |
| 9153 | if (buf_eql_str(field_name, "bit_count")) { | 9166 | if (buf_eql_str(field_name, "bit_count")) { |
| 9154 | bool ptr_is_const = true; | 9167 | bool ptr_is_const = true; |
| | 9168 | bool ptr_is_volatile = false; |
| 9155 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 9169 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9156 | create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, | 9170 | create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, |
| 9157 | child_type->data.integral.bit_count, false), | 9171 | child_type->data.integral.bit_count, false), |
| 9158 | ira->codegen->builtin_types.entry_num_lit_int, depends_on_compile_var, | 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 | } else if (buf_eql_str(field_name, "is_signed")) { | 9174 | } else if (buf_eql_str(field_name, "is_signed")) { |
| 9161 | bool ptr_is_const = true; | 9175 | bool ptr_is_const = true; |
| | 9176 | bool ptr_is_volatile = false; |
| 9162 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 9177 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9163 | create_const_bool(ira->codegen, child_type->data.integral.is_signed), | 9178 | create_const_bool(ira->codegen, child_type->data.integral.is_signed), |
| 9164 | ira->codegen->builtin_types.entry_bool, depends_on_compile_var, | 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 | } else { | 9181 | } else { |
| 9167 | ir_add_error(ira, &field_ptr_instruction->base, | 9182 | ir_add_error(ira, &field_ptr_instruction->base, |
| 9168 | buf_sprintf("type '%s' has no member called '%s'", | 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,12 +9303,11 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 9288 | } | 9303 | } |
| 9289 | new_ptr_inst->value.type = ptr->value.type; | 9304 | new_ptr_inst->value.type = ptr->value.type; |
| 9290 | ir_build_store_ptr(&ira->new_irb, store_ptr_instruction->base.scope, | 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 | return ir_analyze_void(ira, &store_ptr_instruction->base); | 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, | 9310 | ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value); |
| 9296 | store_ptr_instruction->is_volatile); | | |
| 9297 | return ira->codegen->builtin_types.entry_void; | 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,7 +10351,7 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira, |
| 10337 | | 10351 | |
| 10338 | static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) { | 10352 | static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) { |
| 10339 | IrInstruction *value = ref_instruction->value->other; | 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 | static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction, | 10357 | static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction, |