| ... | @@ -155,6 +155,8 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -155,6 +155,8 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 155 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); | 155 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); |
| 156 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | 156 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 157 | ConstExprValue *out_val, ConstExprValue *ptr_val); | 157 | ConstExprValue *out_val, ConstExprValue *ptr_val); |
| | 158 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, |
| | 159 | ZigType *dest_type, IrInstruction *dest_type_src); |
| 158 | | 160 | |
| 159 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { | 161 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 160 | assert(get_src_ptr_type(const_val->type) != nullptr); | 162 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | @@ -8573,17 +8575,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted | ... | @@ -8573,17 +8575,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted |
| 8573 | return result; | 8575 | return result; |
| 8574 | } | 8576 | } |
| 8575 | | 8577 | |
| 8576 | // *T and [*]T can always cast to *c_void | | |
| 8577 | if (wanted_type->id == ZigTypeIdPointer && | | |
| 8578 | wanted_type->data.pointer.ptr_len == PtrLenSingle && | | |
| 8579 | wanted_type->data.pointer.child_type == g->builtin_types.entry_c_void && | | |
| 8580 | actual_type->id == ZigTypeIdPointer && | | |
| 8581 | (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && | | |
| 8582 | (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile)) | | |
| 8583 | { | | |
| 8584 | return result; | | |
| 8585 | } | | |
| 8586 | | | |
| 8587 | // pointer const | 8578 | // pointer const |
| 8588 | if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) { | 8579 | if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) { |
| 8589 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, | 8580 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, |
| ... | @@ -11156,6 +11147,33 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -11156,6 +11147,33 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 11156 | } | 11147 | } |
| 11157 | } | 11148 | } |
| 11158 | | 11149 | |
| | 11150 | // cast from *T and [*]T to *c_void and ?*c_void |
| | 11151 | // but don't do it if the actual type is a double pointer |
| | 11152 | if (actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.child_type->id != ZigTypeIdPointer) { |
| | 11153 | ZigType *dest_ptr_type = nullptr; |
| | 11154 | if (wanted_type->id == ZigTypeIdPointer && |
| | 11155 | wanted_type->data.pointer.ptr_len == PtrLenSingle && |
| | 11156 | wanted_type->data.pointer.child_type == ira->codegen->builtin_types.entry_c_void) |
| | 11157 | { |
| | 11158 | dest_ptr_type = wanted_type; |
| | 11159 | } else if (wanted_type->id == ZigTypeIdOptional && |
| | 11160 | wanted_type->data.maybe.child_type->id == ZigTypeIdPointer && |
| | 11161 | wanted_type->data.maybe.child_type->data.pointer.ptr_len == PtrLenSingle && |
| | 11162 | wanted_type->data.maybe.child_type->data.pointer.child_type == ira->codegen->builtin_types.entry_c_void) |
| | 11163 | { |
| | 11164 | dest_ptr_type = wanted_type->data.maybe.child_type; |
| | 11165 | } |
| | 11166 | if (dest_ptr_type != nullptr && |
| | 11167 | (!actual_type->data.pointer.is_const || dest_ptr_type->data.pointer.is_const) && |
| | 11168 | (!actual_type->data.pointer.is_volatile || dest_ptr_type->data.pointer.is_volatile) && |
| | 11169 | actual_type->data.pointer.bit_offset == dest_ptr_type->data.pointer.bit_offset && |
| | 11170 | actual_type->data.pointer.unaligned_bit_count == dest_ptr_type->data.pointer.unaligned_bit_count && |
| | 11171 | get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type)) |
| | 11172 | { |
| | 11173 | return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr); |
| | 11174 | } |
| | 11175 | } |
| | 11176 | |
| 11159 | // cast from T to *T where T is zero bits | 11177 | // cast from T to *T where T is zero bits |
| 11160 | if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle && | 11178 | if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle && |
| 11161 | types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, | 11179 | types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, |
| ... | @@ -20234,79 +20252,75 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 | ... | @@ -20234,79 +20252,75 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 20234 | return result; | 20252 | return result; |
| 20235 | } | 20253 | } |
| 20236 | | 20254 | |
| 20237 | static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) { | 20255 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, |
| | 20256 | ZigType *dest_type, IrInstruction *dest_type_src) |
| | 20257 | { |
| 20238 | Error err; | 20258 | Error err; |
| 20239 | | 20259 | |
| 20240 | IrInstruction *dest_type_value = instruction->dest_type->other; | | |
| 20241 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); | | |
| 20242 | if (type_is_invalid(dest_type)) | | |
| 20243 | return ira->codegen->builtin_types.entry_invalid; | | |
| 20244 | | | |
| 20245 | IrInstruction *ptr = instruction->ptr->other; | | |
| 20246 | ZigType *src_type = ptr->value.type; | 20260 | ZigType *src_type = ptr->value.type; |
| 20247 | if (type_is_invalid(src_type)) | 20261 | assert(!type_is_invalid(src_type)); |
| 20248 | return ira->codegen->builtin_types.entry_invalid; | | |
| 20249 | | 20262 | |
| 20250 | // We have a check for zero bits later so we use get_src_ptr_type to | 20263 | // We have a check for zero bits later so we use get_src_ptr_type to |
| 20251 | // validate src_type and dest_type. | 20264 | // validate src_type and dest_type. |
| 20252 | | 20265 | |
| 20253 | if (get_src_ptr_type(src_type) == nullptr) { | 20266 | if (get_src_ptr_type(src_type) == nullptr) { |
| 20254 | ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); | 20267 | ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); |
| 20255 | return ira->codegen->builtin_types.entry_invalid; | 20268 | return ira->codegen->invalid_instruction; |
| 20256 | } | 20269 | } |
| 20257 | | 20270 | |
| 20258 | if (get_src_ptr_type(dest_type) == nullptr) { | 20271 | if (get_src_ptr_type(dest_type) == nullptr) { |
| 20259 | ir_add_error(ira, dest_type_value, | 20272 | ir_add_error(ira, dest_type_src, |
| 20260 | buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); | 20273 | buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); |
| 20261 | return ira->codegen->builtin_types.entry_invalid; | 20274 | return ira->codegen->invalid_instruction; |
| 20262 | } | 20275 | } |
| 20263 | | 20276 | |
| 20264 | if (get_ptr_const(src_type) && !get_ptr_const(dest_type)) { | 20277 | if (get_ptr_const(src_type) && !get_ptr_const(dest_type)) { |
| 20265 | ir_add_error(ira, &instruction->base, buf_sprintf("cast discards const qualifier")); | 20278 | ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier")); |
| 20266 | return ira->codegen->builtin_types.entry_invalid; | 20279 | return ira->codegen->invalid_instruction; |
| 20267 | } | 20280 | } |
| 20268 | | 20281 | |
| 20269 | if (instr_is_comptime(ptr)) { | 20282 | if (instr_is_comptime(ptr)) { |
| 20270 | ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk); | 20283 | ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk); |
| 20271 | if (!val) | 20284 | if (!val) |
| 20272 | return ira->codegen->builtin_types.entry_invalid; | 20285 | return ira->codegen->invalid_instruction; |
| 20273 | | 20286 | |
| 20274 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 20287 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node, |
| 20275 | copy_const_val(out_val, val, false); | 20288 | dest_type); |
| 20276 | out_val->type = dest_type; | 20289 | copy_const_val(&result->value, val, false); |
| 20277 | return dest_type; | 20290 | result->value.type = dest_type; |
| | 20291 | return result; |
| 20278 | } | 20292 | } |
| 20279 | | 20293 | |
| 20280 | uint32_t src_align_bytes; | 20294 | uint32_t src_align_bytes; |
| 20281 | if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes))) | 20295 | if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes))) |
| 20282 | return ira->codegen->builtin_types.entry_invalid; | 20296 | return ira->codegen->invalid_instruction; |
| 20283 | | 20297 | |
| 20284 | uint32_t dest_align_bytes; | 20298 | uint32_t dest_align_bytes; |
| 20285 | if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes))) | 20299 | if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes))) |
| 20286 | return ira->codegen->builtin_types.entry_invalid; | 20300 | return ira->codegen->invalid_instruction; |
| 20287 | | 20301 | |
| 20288 | if (dest_align_bytes > src_align_bytes) { | 20302 | if (dest_align_bytes > src_align_bytes) { |
| 20289 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment")); | 20303 | ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment")); |
| 20290 | add_error_note(ira->codegen, msg, ptr->source_node, | 20304 | add_error_note(ira->codegen, msg, ptr->source_node, |
| 20291 | buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes)); | 20305 | buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes)); |
| 20292 | add_error_note(ira->codegen, msg, dest_type_value->source_node, | 20306 | add_error_note(ira->codegen, msg, dest_type_src->source_node, |
| 20293 | buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes)); | 20307 | buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes)); |
| 20294 | return ira->codegen->builtin_types.entry_invalid; | 20308 | return ira->codegen->invalid_instruction; |
| 20295 | } | 20309 | } |
| 20296 | | 20310 | |
| 20297 | IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, instruction->base.scope, | 20311 | IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope, |
| 20298 | instruction->base.source_node, nullptr, ptr); | 20312 | source_instr->source_node, nullptr, ptr); |
| 20299 | casted_ptr->value.type = dest_type; | 20313 | casted_ptr->value.type = dest_type; |
| 20300 | | 20314 | |
| 20301 | if (type_has_bits(dest_type) && !type_has_bits(src_type)) { | 20315 | if (type_has_bits(dest_type) && !type_has_bits(src_type)) { |
| 20302 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, | 20316 | ErrorMsg *msg = ir_add_error(ira, source_instr, |
| 20303 | buf_sprintf("'%s' and '%s' do not have the same in-memory representation", | 20317 | buf_sprintf("'%s' and '%s' do not have the same in-memory representation", |
| 20304 | buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); | 20318 | buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); |
| 20305 | add_error_note(ira->codegen, msg, ptr->source_node, | 20319 | add_error_note(ira->codegen, msg, ptr->source_node, |
| 20306 | buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name))); | 20320 | buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name))); |
| 20307 | add_error_note(ira->codegen, msg, dest_type_value->source_node, | 20321 | add_error_note(ira->codegen, msg, dest_type_src->source_node, |
| 20308 | buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name))); | 20322 | buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name))); |
| 20309 | return ira->codegen->builtin_types.entry_invalid; | 20323 | return ira->codegen->invalid_instruction; |
| 20310 | } | 20324 | } |
| 20311 | | 20325 | |
| 20312 | // Keep the bigger alignment, it can only help- | 20326 | // Keep the bigger alignment, it can only help- |
| ... | @@ -20315,10 +20329,28 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr | ... | @@ -20315,10 +20329,28 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr |
| 20315 | if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) { | 20329 | if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) { |
| 20316 | result = ir_align_cast(ira, casted_ptr, src_align_bytes, false); | 20330 | result = ir_align_cast(ira, casted_ptr, src_align_bytes, false); |
| 20317 | if (type_is_invalid(result->value.type)) | 20331 | if (type_is_invalid(result->value.type)) |
| 20318 | return ira->codegen->builtin_types.entry_invalid; | 20332 | return ira->codegen->invalid_instruction; |
| 20319 | } else { | 20333 | } else { |
| 20320 | result = casted_ptr; | 20334 | result = casted_ptr; |
| 20321 | } | 20335 | } |
| | 20336 | return result; |
| | 20337 | } |
| | 20338 | |
| | 20339 | static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) { |
| | 20340 | IrInstruction *dest_type_value = instruction->dest_type->other; |
| | 20341 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); |
| | 20342 | if (type_is_invalid(dest_type)) |
| | 20343 | return ira->codegen->builtin_types.entry_invalid; |
| | 20344 | |
| | 20345 | IrInstruction *ptr = instruction->ptr->other; |
| | 20346 | ZigType *src_type = ptr->value.type; |
| | 20347 | if (type_is_invalid(src_type)) |
| | 20348 | return ira->codegen->builtin_types.entry_invalid; |
| | 20349 | |
| | 20350 | IrInstruction *result = ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value); |
| | 20351 | if (type_is_invalid(result->value.type)) |
| | 20352 | return ira->codegen->builtin_types.entry_invalid; |
| | 20353 | |
| 20322 | ir_link_new_instruction(result, &instruction->base); | 20354 | ir_link_new_instruction(result, &instruction->base); |
| 20323 | return result->value.type; | 20355 | return result->value.type; |
| 20324 | } | 20356 | } |