mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
prevent ptr cast from forcing alignment resolution unnecessarily
This commit is contained in:
parent
f7f563ea53
commit
ddd98a7f10
44
src/ir.cpp
44
src/ir.cpp
@ -237,7 +237,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val)
|
||||
static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
|
||||
ZigValue *out_val, ZigValue *ptr_val);
|
||||
static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr,
|
||||
IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on);
|
||||
IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on,
|
||||
bool keep_bigger_alignment);
|
||||
static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstGen *value, UndefAllowed undef_allowed);
|
||||
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
|
||||
static IrInstGen *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInst* source_instr, IrInstGen *target,
|
||||
@ -15066,7 +15067,8 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
|
||||
dest_ptr_type = wanted_type->data.maybe.child_type;
|
||||
}
|
||||
if (dest_ptr_type != nullptr) {
|
||||
return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true);
|
||||
return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15108,7 +15110,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
|
||||
actual_type->data.pointer.child_type, source_node,
|
||||
!wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
|
||||
{
|
||||
return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true);
|
||||
return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true, false);
|
||||
}
|
||||
|
||||
// cast from integer to C pointer
|
||||
@ -18576,7 +18578,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
|
||||
|
||||
result_loc->written = true;
|
||||
result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
|
||||
&parent_result_loc->base, ptr_type, &result_cast->base.source_instruction->base, false);
|
||||
&parent_result_loc->base, ptr_type, &result_cast->base.source_instruction->base, false, false);
|
||||
return result_loc->resolved_loc;
|
||||
}
|
||||
case ResultLocIdBitCast: {
|
||||
@ -18670,7 +18672,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
|
||||
|
||||
result_loc->written = true;
|
||||
result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
|
||||
&parent_result_loc->base, ptr_type, &result_bit_cast->base.source_instruction->base, false);
|
||||
&parent_result_loc->base, ptr_type, &result_bit_cast->base.source_instruction->base, false, false);
|
||||
return result_loc->resolved_loc;
|
||||
}
|
||||
}
|
||||
@ -22947,7 +22949,7 @@ static IrInstGen *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstSrcSwi
|
||||
ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes,
|
||||
ref_type->data.pointer.allow_zero);
|
||||
return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr,
|
||||
&instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false);
|
||||
&instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false, false);
|
||||
} else {
|
||||
ir_add_error(ira, &instruction->base.base,
|
||||
buf_sprintf("switch on type '%s' provides no expression parameter", buf_ptr(&target_type->name)));
|
||||
@ -23030,7 +23032,7 @@ static IrInstGen *ir_analyze_instruction_switch_else_var(IrAnalyze *ira,
|
||||
ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes,
|
||||
ref_type->data.pointer.allow_zero);
|
||||
return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr,
|
||||
&instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false);
|
||||
&instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false, false);
|
||||
}
|
||||
|
||||
return target_value_ptr;
|
||||
@ -27814,7 +27816,8 @@ static IrInstGen *ir_align_cast(IrAnalyze *ira, IrInstGen *target, uint32_t alig
|
||||
}
|
||||
|
||||
static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr,
|
||||
IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on)
|
||||
IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on,
|
||||
bool keep_bigger_alignment)
|
||||
{
|
||||
Error err;
|
||||
|
||||
@ -27853,14 +27856,16 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
|
||||
ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
uint32_t src_align_bytes;
|
||||
if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
uint32_t dest_align_bytes;
|
||||
if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
uint32_t src_align_bytes = 0;
|
||||
if (keep_bigger_alignment || dest_align_bytes != 1) {
|
||||
if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
|
||||
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
@ -27935,16 +27940,15 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
|
||||
}
|
||||
result->value->type = dest_type;
|
||||
|
||||
// Keep the bigger alignment, it can only help-
|
||||
// unless the target is zero bits.
|
||||
if (src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
|
||||
// Keep the bigger alignment, it can only help- unless the target is zero bits.
|
||||
if (keep_bigger_alignment && src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
|
||||
result = ir_align_cast(ira, result, src_align_bytes, false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (dest_align_bytes > src_align_bytes) {
|
||||
if (src_align_bytes != 0 && dest_align_bytes > src_align_bytes) {
|
||||
ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
|
||||
add_error_note(ira->codegen, msg, ptr_src->source_node,
|
||||
buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes));
|
||||
@ -27955,10 +27959,9 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
|
||||
|
||||
IrInstGen *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
|
||||
|
||||
// Keep the bigger alignment, it can only help-
|
||||
// unless the target is zero bits.
|
||||
// Keep the bigger alignment, it can only help- unless the target is zero bits.
|
||||
IrInstGen *result;
|
||||
if (src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
|
||||
if (keep_bigger_alignment && src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
|
||||
result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);
|
||||
if (type_is_invalid(result->value->type))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
@ -27979,8 +27982,9 @@ static IrInstGen *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstSrcPtrCa
|
||||
if (type_is_invalid(src_type))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
bool keep_bigger_alignment = true;
|
||||
return ir_analyze_ptr_cast(ira, &instruction->base.base, ptr, &instruction->ptr->base,
|
||||
dest_type, &dest_type_value->base, instruction->safety_check_on);
|
||||
dest_type, &dest_type_value->base, instruction->safety_check_on, keep_bigger_alignment);
|
||||
}
|
||||
|
||||
static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue *val, size_t len) {
|
||||
|
||||
@ -1547,3 +1547,19 @@ test "noasync on function calls" {
|
||||
expectEqual(@as(i32, 42), noasync S1.c().b);
|
||||
expectEqual(@as(i32, 42), (try noasync S1.d()).b);
|
||||
}
|
||||
|
||||
test "avoid forcing frame alignment resolution implicit cast to *c_void" {
|
||||
const S = struct {
|
||||
var x: ?*c_void = null;
|
||||
|
||||
fn foo() bool {
|
||||
suspend {
|
||||
x = @frame();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
var frame = async S.foo();
|
||||
resume @ptrCast(anyframe->bool, @alignCast(@alignOf(@Frame(S.foo)), S.x));
|
||||
expect(noasync await frame);
|
||||
}
|
||||
|
||||
@ -462,10 +462,10 @@ fn foobar(func: PFN_void) void {
|
||||
|
||||
test "implicit ptr to *c_void" {
|
||||
var a: u32 = 1;
|
||||
var ptr: *c_void = &a;
|
||||
var ptr: *align(@alignOf(u32)) c_void = &a;
|
||||
var b: *u32 = @ptrCast(*u32, ptr);
|
||||
expect(b.* == 1);
|
||||
var ptr2: ?*c_void = &a;
|
||||
var ptr2: ?*align(@alignOf(u32)) c_void = &a;
|
||||
var c: *u32 = @ptrCast(*u32, ptr2.?);
|
||||
expect(c.* == 1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user