authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-04 21:49:27-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-04 21:49:27-05:00
log419e75eb2313b4910921185211201317cbbb400c
tree3ad2166c30e84a6d7ce075fb48741e336eb87027
parent0d7abc6368a826490f8985634882300b50d81cba

remove volatileStore builtin; add volatile pointers

closes #238

10 files changed, 213 insertions(+), 172 deletions(-)

doc/langref.md+1-1
...@@ -143,7 +143,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")...@@ -143,7 +143,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
143143
144StructLiteralField = "." Symbol "=" Expression144StructLiteralField = "." Symbol "=" Expression
145145
146PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"146PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"
147147
148PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl148PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
149149
src/all_types.hpp+7-10
...@@ -490,6 +490,8 @@ enum PrefixOp {...@@ -490,6 +490,8 @@ enum PrefixOp {
490 PrefixOpNegationWrap,490 PrefixOpNegationWrap,
491 PrefixOpAddressOf,491 PrefixOpAddressOf,
492 PrefixOpConstAddressOf,492 PrefixOpConstAddressOf,
493 PrefixOpVolatileAddressOf,
494 PrefixOpConstVolatileAddressOf,
493 PrefixOpDereference,495 PrefixOpDereference,
494 PrefixOpMaybe,496 PrefixOpMaybe,
495 PrefixOpError,497 PrefixOpError,
...@@ -806,6 +808,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);...@@ -806,6 +808,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
806struct TypeTableEntryPointer {808struct TypeTableEntryPointer {
807 TypeTableEntry *child_type;809 TypeTableEntry *child_type;
808 bool is_const;810 bool is_const;
811 bool is_volatile;
809};812};
810813
811struct TypeTableEntryInt {814struct TypeTableEntryInt {
...@@ -991,7 +994,7 @@ struct TypeTableEntry {...@@ -991,7 +994,7 @@ struct TypeTableEntry {
991 } data;994 } data;
992995
993 // use these fields to make sure we don't duplicate type table entries for the same type996 // use these fields to make sure we don't duplicate type table entries for the same type
994 TypeTableEntry *pointer_parent[2];997 TypeTableEntry *pointer_parent[2][2]; // [0 - mut, 1 - const][0 - normal, 1 - volatile]
995 TypeTableEntry *unknown_size_array_parent[2];998 TypeTableEntry *unknown_size_array_parent[2];
996 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;999 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
997 TypeTableEntry *maybe_parent;1000 TypeTableEntry *maybe_parent;
...@@ -1113,7 +1116,6 @@ enum BuiltinFnId {...@@ -1113,7 +1116,6 @@ enum BuiltinFnId {
1113 BuiltinFnIdCanImplicitCast,1116 BuiltinFnIdCanImplicitCast,
1114 BuiltinFnIdSetGlobalAlign,1117 BuiltinFnIdSetGlobalAlign,
1115 BuiltinFnIdSetGlobalSection,1118 BuiltinFnIdSetGlobalSection,
1116 BuiltinFnIdVolatileStore,
1117};1119};
11181120
1119struct BuiltinFnEntry {1121struct BuiltinFnEntry {
...@@ -1692,7 +1694,6 @@ struct IrInstructionStorePtr {...@@ -1692,7 +1694,6 @@ struct IrInstructionStorePtr {
16921694
1693 IrInstruction *ptr;1695 IrInstruction *ptr;
1694 IrInstruction *value;1696 IrInstruction *value;
1695 bool is_volatile;
1696};1697};
16971698
1698struct IrInstructionFieldPtr {1699struct IrInstructionFieldPtr {
...@@ -1943,6 +1944,7 @@ struct IrInstructionRef {...@@ -1943,6 +1944,7 @@ struct IrInstructionRef {
1943 IrInstruction *value;1944 IrInstruction *value;
1944 LLVMValueRef tmp_ptr;1945 LLVMValueRef tmp_ptr;
1945 bool is_const;1946 bool is_const;
1947 bool is_volatile;
1946};1948};
19471949
1948struct IrInstructionMinValue {1950struct IrInstructionMinValue {
...@@ -2062,6 +2064,7 @@ struct IrInstructionMemset {...@@ -2062,6 +2064,7 @@ struct IrInstructionMemset {
2062 IrInstruction *dest_ptr;2064 IrInstruction *dest_ptr;
2063 IrInstruction *byte;2065 IrInstruction *byte;
2064 IrInstruction *count;2066 IrInstruction *count;
2067 bool is_volatile;
2065};2068};
20662069
2067struct IrInstructionMemcpy {2070struct IrInstructionMemcpy {
...@@ -2070,6 +2073,7 @@ struct IrInstructionMemcpy {...@@ -2070,6 +2073,7 @@ struct IrInstructionMemcpy {
2070 IrInstruction *dest_ptr;2073 IrInstruction *dest_ptr;
2071 IrInstruction *src_ptr;2074 IrInstruction *src_ptr;
2072 IrInstruction *count;2075 IrInstruction *count;
2076 bool is_volatile;
2073};2077};
20742078
2075struct IrInstructionSlice {2079struct IrInstructionSlice {
...@@ -2267,13 +2271,6 @@ struct IrInstructionSetGlobalSection {...@@ -2267,13 +2271,6 @@ struct IrInstructionSetGlobalSection {
2267 IrInstruction *value;2271 IrInstruction *value;
2268};2272};
22692273
2270enum LValPurpose {
2271 LValPurposeNone,
2272 LValPurposeAssign,
2273 LValPurposeAddressOf,
2274 LValPurposeAddressOfConst,
2275};
2276
2277static const size_t slice_ptr_index = 0;2274static const size_t slice_ptr_index = 0;
2278static const size_t slice_len_index = 1;2275static const size_t slice_len_index = 1;
22792276
src/analyze.cpp+32-27
...@@ -269,43 +269,48 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {...@@ -269,43 +269,48 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
269 return get_int_type(g, false, bits_needed_for_unsigned(x));269 return get_int_type(g, false, bits_needed_for_unsigned(x));
270}270}
271271
272TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {272TypeTableEntry *get_pointer_to_type_volatile(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_volatile) {
273 assert(child_type->id != TypeTableEntryIdInvalid);273 assert(child_type->id != TypeTableEntryIdInvalid);
274 TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];274 TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)][(is_volatile ? 1 : 0)];
275 if (*parent_pointer) {275 if (*parent_pointer)
276 return *parent_pointer;276 return *parent_pointer;
277 } else {
278 type_ensure_zero_bits_known(g, child_type);
279277
280 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer);278 type_ensure_zero_bits_known(g, child_type);
281279
282 const char *const_str = is_const ? "const " : "";280 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer);
283 buf_resize(&entry->name, 0);
284 buf_appendf(&entry->name, "&%s%s", const_str, buf_ptr(&child_type->name));
285
286 TypeTableEntry *canon_child_type = get_underlying_type(child_type);
287 assert(canon_child_type->id != TypeTableEntryIdInvalid);
288281
289 entry->zero_bits = !type_has_bits(canon_child_type);282 const char *const_str = is_const ? "const " : "";
283 const char *volatile_str = is_volatile ? "volatile " : "";
284 buf_resize(&entry->name, 0);
285 buf_appendf(&entry->name, "&%s%s%s", const_str, volatile_str, buf_ptr(&child_type->name));
290286
291 if (!entry->zero_bits) {287 TypeTableEntry *canon_child_type = get_underlying_type(child_type);
292 entry->type_ref = LLVMPointerType(child_type->type_ref, 0);288 assert(canon_child_type->id != TypeTableEntryIdInvalid);
293289
294 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);290 entry->zero_bits = !type_has_bits(canon_child_type);
295 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
296 assert(child_type->di_type);
297 entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type,
298 debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name));
299 } else {
300 entry->di_type = g->builtin_types.entry_void->di_type;
301 }
302291
303 entry->data.pointer.child_type = child_type;292 if (!entry->zero_bits) {
304 entry->data.pointer.is_const = is_const;293 entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
305294
306 *parent_pointer = entry;295 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
307 return entry;296 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
297 assert(child_type->di_type);
298 entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type,
299 debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name));
300 } else {
301 entry->di_type = g->builtin_types.entry_void->di_type;
308 }302 }
303
304 entry->data.pointer.child_type = child_type;
305 entry->data.pointer.is_const = is_const;
306 entry->data.pointer.is_volatile = is_volatile;
307
308 *parent_pointer = entry;
309 return entry;
310}
311
312TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
313 return get_pointer_to_type_volatile(g, child_type, is_const, false);
309}314}
310315
311TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {316TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
src/analyze.hpp+1
...@@ -15,6 +15,7 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);...@@ -15,6 +15,7 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
15ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);15ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
16TypeTableEntry *new_type_table_entry(TypeTableEntryId id);16TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
17TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);17TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
18TypeTableEntry *get_pointer_to_type_volatile(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_volatile);
18bool is_node_void_expr(AstNode *node);19bool is_node_void_expr(AstNode *node);
19uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);20uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
20TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bits);21TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bits);
src/ast_render.cpp+2
...@@ -68,6 +68,8 @@ static const char *prefix_op_str(PrefixOp prefix_op) {...@@ -68,6 +68,8 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
68 case PrefixOpBinNot: return "~";68 case PrefixOpBinNot: return "~";
69 case PrefixOpAddressOf: return "&";69 case PrefixOpAddressOf: return "&";
70 case PrefixOpConstAddressOf: return "&const ";70 case PrefixOpConstAddressOf: return "&const ";
71 case PrefixOpVolatileAddressOf: return "&volatile ";
72 case PrefixOpConstVolatileAddressOf: return "&const volatile ";
71 case PrefixOpDereference: return "*";73 case PrefixOpDereference: return "*";
72 case PrefixOpMaybe: return "?";74 case PrefixOpMaybe: return "?";
73 case PrefixOpError: return "%";75 case PrefixOpError: return "%";
src/codegen.cpp+14-8
...@@ -1294,18 +1294,19 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir...@@ -1294,18 +1294,19 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
1294 LLVMValueRef value = ir_llvm_value(g, instruction->value);1294 LLVMValueRef value = ir_llvm_value(g, instruction->value);
12951295
1296 assert(instruction->ptr->value.type->id == TypeTableEntryIdPointer);1296 assert(instruction->ptr->value.type->id == TypeTableEntryIdPointer);
1297 TypeTableEntry *op1_type = instruction->ptr->value.type->data.pointer.child_type;1297 TypeTableEntry *ptr_type = get_underlying_type(instruction->ptr->value.type);
1298 TypeTableEntry *child_type = get_underlying_type(ptr_type->data.pointer.child_type);
12981299
1299 if (!type_has_bits(op1_type)) {1300 if (!type_has_bits(child_type)) {
1300 return nullptr;1301 return nullptr;
1301 }1302 }
1302 if (handle_is_ptr(op1_type)) {1303 if (handle_is_ptr(child_type)) {
1303 return gen_struct_memcpy(g, value, ptr, op1_type);1304 return gen_struct_memcpy(g, value, ptr, child_type);
1304 }1305 }
13051306
1306 LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr);1307 LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr);
13071308
1308 LLVMSetVolatile(llvm_instruction, instruction->is_volatile);1309 LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile);
13091310
1310 return nullptr;1311 return nullptr;
1311}1312}
...@@ -1803,12 +1804,15 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns...@@ -1803,12 +1804,15 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns
18031804
1804 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");1805 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
18051806
1807 LLVMValueRef is_volatile = instruction->is_volatile ?
1808 LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type());
1809
1806 LLVMValueRef params[] = {1810 LLVMValueRef params[] = {
1807 dest_ptr_casted, // dest pointer1811 dest_ptr_casted, // dest pointer
1808 char_val, // source pointer1812 char_val, // source pointer
1809 len_val, // byte count1813 len_val, // byte count
1810 LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes1814 LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes
1811 LLVMConstNull(LLVMInt1Type()), // is volatile1815 is_volatile,
1812 };1816 };
18131817
1814 LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");1818 LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");
...@@ -1825,12 +1829,15 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns...@@ -1825,12 +1829,15 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
1825 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");1829 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
1826 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");1830 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
18271831
1832 LLVMValueRef is_volatile = instruction->is_volatile ?
1833 LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type());
1834
1828 LLVMValueRef params[] = {1835 LLVMValueRef params[] = {
1829 dest_ptr_casted, // dest pointer1836 dest_ptr_casted, // dest pointer
1830 src_ptr_casted, // source pointer1837 src_ptr_casted, // source pointer
1831 len_val, // byte count1838 len_val, // byte count
1832 LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes1839 LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes
1833 LLVMConstNull(LLVMInt1Type()), // is volatile1840 is_volatile,
1834 };1841 };
18351842
1836 LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, "");1843 LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, "");
...@@ -3690,7 +3697,6 @@ static void define_builtin_fns(CodeGen *g) {...@@ -3690,7 +3697,6 @@ static void define_builtin_fns(CodeGen *g) {
3690 create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2);3697 create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2);
3691 create_builtin_fn(g, BuiltinFnIdSetGlobalAlign, "setGlobalAlign", 2);3698 create_builtin_fn(g, BuiltinFnIdSetGlobalAlign, "setGlobalAlign", 2);
3692 create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);3699 create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);
3693 create_builtin_fn(g, BuiltinFnIdVolatileStore, "volatileStore", 2);
3694}3700}
36953701
3696static void init(CodeGen *g, Buf *source_path) {3702static void init(CodeGen *g, Buf *source_path) {
src/ir.cpp+132-118
...@@ -44,9 +44,21 @@ struct IrAnalyze {...@@ -44,9 +44,21 @@ struct IrAnalyze {
44 IrBasicBlock *const_predecessor_bb;44 IrBasicBlock *const_predecessor_bb;
45};45};
4646
47struct LVal {
48 bool is_ptr;
49 bool is_const;
50 bool is_volatile;
51};
52
53static const LVal LVAL_NONE = { false, false, false };
54static const LVal LVAL_PTR = { true, false, false };
55
56static LVal make_lval_addr(bool is_const, bool is_volatile) {
57 return { true, is_const, is_volatile };
58}
59
47static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);60static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
48static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope,61static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval);
49 LValPurpose lval);
50static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);62static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
51static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);63static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);
5264
...@@ -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}
10431055
1044static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,1056static 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;
10531064
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}
10591070
1060static IrInstruction *ir_build_store_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,1071static 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}
14511462
1452static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,1463static 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;
14581470
1459 ir_ref_instruction(value, irb->current_basic_block);1471 ir_ref_instruction(value, irb->current_basic_block);
14601472
...@@ -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}
14631475
1464static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value,1476static 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}
29822994
2983static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {2995static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
2984 assert(node->type == NodeTypeReturnExpr);2996 assert(node->type == NodeTypeReturnExpr);
29852997
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,
30863098
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 else3103 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,
31123124
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 else3129 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}
32943306
3295static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {3307static 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);
32983310
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;
33013313
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}
33053317
3306static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) {3318static 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}
33183330
...@@ -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;
34083420
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;
34123424
...@@ -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}
35753587
3576static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld *tld,3588static 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;
35823594
...@@ -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 else3605 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 else3616 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 else3626 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}
36203632
3621static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {3633static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
3622 assert(node->type == NodeTypeSymbol);3634 assert(node->type == NodeTypeSymbol);
36233635
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,
36353647
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 else3654 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}
36603673
3661static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {3674static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
3662 assert(node->type == NodeTypeArrayAccessExpr);3675 assert(node->type == NodeTypeArrayAccessExpr);
36633676
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;
36693681
...@@ -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
36743686
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;
36793691
3680 return ir_build_load_ptr(irb, scope, node, ptr_instruction);3692 return ir_build_load_ptr(irb, scope, node, ptr_instruction);
3681}3693}
36823694
3683static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {3695static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
3684 assert(node->type == NodeTypeFieldAccessExpr);3696 assert(node->type == NodeTypeFieldAccessExpr);
36853697
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;
36883700
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;
36933704
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;
36973708
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}
42974294
4298static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LValPurpose lval) {4295static 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;
43014298
...@@ -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}
43084305
4309static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id) {4306static 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}
43124309
4313static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) {4310static 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;
43184315
4319 // We needed a pointer to a value, but we got a value. So we create4316 // 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}
43234320
4324static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node, bool is_const, LValPurpose lval) {4321static 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;
43274326
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;
43324330
4333
4334 return ir_lval_wrap(irb, scope, value, lval);4331 return ir_lval_wrap(irb, scope, value, lval);
4335}4332}
43364333
4337static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {4334static 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;
43404337
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;
43444341
...@@ -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;
43484345
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}
43544351
4355static IrInstruction *ir_gen_maybe_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {4352static 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;
43584355
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;
43624359
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}
43694366
4370static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *node) {4367static 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}
43804377
4381static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {4378static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
4382 assert(node->type == NodeTypePrefixOpExpr);4379 assert(node->type == NodeTypePrefixOpExpr);
43834380
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);
45614562
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;
45654566
...@@ -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));
46314632
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
46414642
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);
46464647
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;
47854786
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;
47894790
...@@ -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;
48614862
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;
48654866
...@@ -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);
49884989
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}
51775178
5178static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LValPurpose lval) {5179static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval) {
5179 assert(node->type == NodeTypeCompTime);5180 assert(node->type == NodeTypeCompTime);
51805181
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;
52875288
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;
52915292
...@@ -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}
54245425
5425static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,5426static 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}
55245525
5525static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope,5526static 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}
55325531
5533static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) {5532static 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}
55365535
5537static bool ir_goto_pass2(IrBuilder *irb) {5536static 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);
55915590
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
61786177
6179static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,6178static 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}
64356436
6436static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) {6437static 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;
64596462
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}
69987001
6999static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,7002static 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 }
70127015
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
89118916
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;
89938999
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;
90099016
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
90519059
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
90749083
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;
91439155
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 }
91489161
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 }
92949309
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}
92999313
...@@ -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,
1033710351
10338static TypeTableEntry *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) {10352static 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}
1034210356
10343static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,10357static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
src/ir_print.cpp+2-4
...@@ -299,9 +299,6 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)...@@ -299,9 +299,6 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)
299 ir_print_var_instruction(irp, instruction->ptr);299 ir_print_var_instruction(irp, instruction->ptr);
300 fprintf(irp->f, " = ");300 fprintf(irp->f, " = ");
301 ir_print_other_instruction(irp, instruction->value);301 ir_print_other_instruction(irp, instruction->value);
302 if (instruction->is_volatile) {
303 fprintf(irp->f, " // volatile");
304 }
305}302}
306303
307static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {304static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {
...@@ -512,7 +509,8 @@ static void ir_print_array_len(IrPrint *irp, IrInstructionArrayLen *instruction)...@@ -512,7 +509,8 @@ static void ir_print_array_len(IrPrint *irp, IrInstructionArrayLen *instruction)
512509
513static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {510static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
514 const char *const_str = instruction->is_const ? "const " : "";511 const char *const_str = instruction->is_const ? "const " : "";
515 fprintf(irp->f, "%sref ", const_str);512 const char *volatile_str = instruction->is_volatile ? "volatile " : "";
513 fprintf(irp->f, "%s%sref ", const_str, volatile_str);
516 ir_print_other_instruction(irp, instruction->value);514 ir_print_other_instruction(irp, instruction->value);
517}515}
518516
src/parser.cpp+13-4
...@@ -996,7 +996,7 @@ static PrefixOp tok_to_prefix_op(Token *token) {...@@ -996,7 +996,7 @@ static PrefixOp tok_to_prefix_op(Token *token) {
996996
997/*997/*
998PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression998PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
999PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"999PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"
1000*/1000*/
1001static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1001static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
1002 Token *token = &pc->tokens->at(*token_index);1002 Token *token = &pc->tokens->at(*token_index);
...@@ -1036,10 +1036,19 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,...@@ -1036,10 +1036,19 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,
1036 }1036 }
10371037
1038 if (prefix_op == PrefixOpAddressOf) {1038 if (prefix_op == PrefixOpAddressOf) {
1039 Token *token = &pc->tokens->at(*token_index);1039 Token *const_or_volatile_tok = &pc->tokens->at(*token_index);
1040 if (token->id == TokenIdKeywordConst) {1040 if (const_or_volatile_tok->id == TokenIdKeywordConst) {
1041 *token_index += 1;
1042 Token *volatile_token = &pc->tokens->at(*token_index);
1043 if (volatile_token->id == TokenIdKeywordVolatile) {
1044 *token_index += 1;
1045 prefix_op = PrefixOpConstVolatileAddressOf;
1046 } else {
1047 prefix_op = PrefixOpConstAddressOf;
1048 }
1049 } else if (const_or_volatile_tok->id == TokenIdKeywordVolatile) {
1050 prefix_op = PrefixOpVolatileAddressOf;
1041 *token_index += 1;1051 *token_index += 1;
1042 prefix_op = PrefixOpConstAddressOf;
1043 }1052 }
1044 }1053 }
10451054
test/cases/misc.zig+9
...@@ -566,3 +566,12 @@ fn typeName() {...@@ -566,3 +566,12 @@ fn typeName() {
566 assert(str.eql(@typeName(&usize), "&usize"));566 assert(str.eql(@typeName(&usize), "&usize"));
567 }567 }
568}568}
569
570fn volatileLoadAndStore() {
571 @setFnTest(this);
572
573 var number: i32 = 1234;
574 const ptr = &volatile number;
575 *ptr += 1;
576 assert(*ptr == 1235);
577}