| ... | @@ -415,12 +415,14 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, TypeTableEntry *type_entry, | ... | @@ -415,12 +415,14 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, TypeTableEntry *type_entry, |
| 415 | return *fn; | 415 | return *fn; |
| 416 | } | 416 | } |
| 417 | | 417 | |
| 418 | static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type) { | 418 | static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type, bool is_volatile) { |
| 419 | if (type_has_bits(type)) { | 419 | if (type_has_bits(type)) { |
| 420 | if (handle_is_ptr(type)) { | 420 | if (handle_is_ptr(type)) { |
| 421 | return ptr; | 421 | return ptr; |
| 422 | } else { | 422 | } else { |
| 423 | return LLVMBuildLoad(g->builder, ptr, ""); | 423 | LLVMValueRef result = LLVMBuildLoad(g->builder, ptr, ""); |
| | 424 | LLVMSetVolatile(result, is_volatile); |
| | 425 | return result; |
| 424 | } | 426 | } |
| 425 | } else { | 427 | } else { |
| 426 | return nullptr; | 428 | return nullptr; |
| ... | @@ -1191,6 +1193,7 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -1191,6 +1193,7 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst |
| 1191 | case IrUnOpInvalid: | 1193 | case IrUnOpInvalid: |
| 1192 | case IrUnOpError: | 1194 | case IrUnOpError: |
| 1193 | case IrUnOpMaybe: | 1195 | case IrUnOpMaybe: |
| | 1196 | case IrUnOpDereference: |
| 1194 | zig_unreachable(); | 1197 | zig_unreachable(); |
| 1195 | case IrUnOpNegation: | 1198 | case IrUnOpNegation: |
| 1196 | case IrUnOpNegationWrap: | 1199 | case IrUnOpNegationWrap: |
| ... | @@ -1214,16 +1217,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -1214,16 +1217,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst |
| 1214 | } | 1217 | } |
| 1215 | case IrUnOpBinNot: | 1218 | case IrUnOpBinNot: |
| 1216 | return LLVMBuildNot(g->builder, expr, ""); | 1219 | return LLVMBuildNot(g->builder, expr, ""); |
| 1217 | case IrUnOpDereference: | | |
| 1218 | { | | |
| 1219 | assert(expr_type->id == TypeTableEntryIdPointer); | | |
| 1220 | if (!type_has_bits(expr_type)) { | | |
| 1221 | return nullptr; | | |
| 1222 | } else { | | |
| 1223 | TypeTableEntry *child_type = expr_type->data.pointer.child_type; | | |
| 1224 | return get_handle_value(g, expr, child_type); | | |
| 1225 | } | | |
| 1226 | } | | |
| 1227 | } | 1220 | } |
| 1228 | | 1221 | |
| 1229 | zig_unreachable(); | 1222 | zig_unreachable(); |
| ... | @@ -1289,8 +1282,15 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, | ... | @@ -1289,8 +1282,15 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 1289 | } | 1282 | } |
| 1290 | | 1283 | |
| 1291 | static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) { | 1284 | static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) { |
| | 1285 | TypeTableEntry *child_type = instruction->base.value.type; |
| | 1286 | if (!type_has_bits(child_type)) { |
| | 1287 | return nullptr; |
| | 1288 | } |
| 1292 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); | 1289 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); |
| 1293 | return get_handle_value(g, ptr, instruction->base.value.type); | 1290 | TypeTableEntry *ptr_type = instruction->ptr->value.type; |
| | 1291 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| | 1292 | bool is_volatile = ptr_type->data.pointer.is_volatile; |
| | 1293 | return get_handle_value(g, ptr, child_type, is_volatile); |
| 1294 | } | 1294 | } |
| 1295 | | 1295 | |
| 1296 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { | 1296 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { |
| ... | @@ -1329,8 +1329,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -1329,8 +1329,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 1329 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); | 1329 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); |
| 1330 | TypeTableEntry *array_ptr_type = instruction->array_ptr->value.type; | 1330 | TypeTableEntry *array_ptr_type = instruction->array_ptr->value.type; |
| 1331 | assert(array_ptr_type->id == TypeTableEntryIdPointer); | 1331 | assert(array_ptr_type->id == TypeTableEntryIdPointer); |
| | 1332 | bool is_volatile = array_ptr_type->data.pointer.is_volatile; |
| 1332 | TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type; | 1333 | TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type; |
| 1333 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type); | 1334 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, is_volatile); |
| 1334 | LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index); | 1335 | LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index); |
| 1335 | assert(subscript_value); | 1336 | assert(subscript_value); |
| 1336 | | 1337 | |
| ... | @@ -1607,12 +1608,13 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, | ... | @@ -1607,12 +1608,13 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 1607 | { | 1608 | { |
| 1608 | TypeTableEntry *ptr_type = instruction->value->value.type; | 1609 | TypeTableEntry *ptr_type = instruction->value->value.type; |
| 1609 | assert(ptr_type->id == TypeTableEntryIdPointer); | 1610 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| | 1611 | bool is_volatile = ptr_type->data.pointer.is_volatile; |
| 1610 | TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type; | 1612 | TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type; |
| 1611 | assert(maybe_type->id == TypeTableEntryIdMaybe); | 1613 | assert(maybe_type->id == TypeTableEntryIdMaybe); |
| 1612 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; | 1614 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; |
| 1613 | bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn); | 1615 | bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn); |
| 1614 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); | 1616 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); |
| 1615 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type); | 1617 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, is_volatile); |
| 1616 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { | 1618 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { |
| 1617 | LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); | 1619 | LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); |
| 1618 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeOk"); | 1620 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeOk"); |
| ... | @@ -1627,7 +1629,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, | ... | @@ -1627,7 +1629,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 1627 | if (maybe_is_ptr) { | 1629 | if (maybe_is_ptr) { |
| 1628 | return maybe_ptr; | 1630 | return maybe_ptr; |
| 1629 | } else { | 1631 | } else { |
| 1630 | LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type); | 1632 | LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, is_volatile); |
| 1631 | return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, ""); | 1633 | return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, ""); |
| 1632 | } | 1634 | } |
| 1633 | } | 1635 | } |
| ... | @@ -2066,10 +2068,12 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -2066,10 +2068,12 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI |
| 2066 | | 2068 | |
| 2067 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) { | 2069 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) { |
| 2068 | TypeTableEntry *ptr_type = get_underlying_type(instruction->value->value.type); | 2070 | TypeTableEntry *ptr_type = get_underlying_type(instruction->value->value.type); |
| | 2071 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| | 2072 | bool is_volatile = ptr_type->data.pointer.is_volatile; |
| 2069 | TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type); | 2073 | TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type); |
| 2070 | TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type); | 2074 | TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type); |
| 2071 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); | 2075 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); |
| 2072 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type); | 2076 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, is_volatile); |
| 2073 | | 2077 | |
| 2074 | if (type_has_bits(child_type)) { | 2078 | if (type_has_bits(child_type)) { |
| 2075 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); | 2079 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| ... | @@ -2081,10 +2085,12 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab | ... | @@ -2081,10 +2085,12 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab |
| 2081 | | 2085 | |
| 2082 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) { | 2086 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) { |
| 2083 | TypeTableEntry *ptr_type = get_underlying_type(instruction->value->value.type); | 2087 | TypeTableEntry *ptr_type = get_underlying_type(instruction->value->value.type); |
| | 2088 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| | 2089 | bool is_volatile = ptr_type->data.pointer.is_volatile; |
| 2084 | TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type); | 2090 | TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type); |
| 2085 | TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type); | 2091 | TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type); |
| 2086 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); | 2092 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); |
| 2087 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type); | 2093 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, is_volatile); |
| 2088 | | 2094 | |
| 2089 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { | 2095 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { |
| 2090 | LLVMValueRef err_val; | 2096 | LLVMValueRef err_val; |
| ... | @@ -2193,7 +2199,7 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -2193,7 +2199,7 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI |
| 2193 | return enum_val; | 2199 | return enum_val; |
| 2194 | | 2200 | |
| 2195 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, enum_val, enum_gen_tag_index, ""); | 2201 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, enum_val, enum_gen_tag_index, ""); |
| 2196 | return get_handle_value(g, tag_field_ptr, tag_type); | 2202 | return get_handle_value(g, tag_field_ptr, tag_type, false); |
| 2197 | } | 2203 | } |
| 2198 | | 2204 | |
| 2199 | static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) { | 2205 | static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) { |