authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-26 12:34:16-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-26 12:34:16-04:00
logddd98a7f10767e2bea43fb35405a9414a02ecbdf
tree51f769dadbca2a6736fb0f8ce42cfc68039bba3f
parentf7f563ea53cf58c772003a46624b87dad9c4311d
signaturelock-open Commit is signed but in an unrecognized format.

prevent ptr cast from forcing alignment resolution unnecessarily


3 files changed, 42 insertions(+), 22 deletions(-)

src/ir.cpp+24-20
...@@ -237,7 +237,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val)...@@ -237,7 +237,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val)
237static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,237static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
238 ZigValue *out_val, ZigValue *ptr_val);238 ZigValue *out_val, ZigValue *ptr_val);
239static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr,239static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr,
240 IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on);240 IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on,
241 bool keep_bigger_alignment);
241static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstGen *value, UndefAllowed undef_allowed);242static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstGen *value, UndefAllowed undef_allowed);
242static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);243static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
243static IrInstGen *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInst* source_instr, IrInstGen *target,244static 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,...@@ -15066,7 +15067,8 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
15066 dest_ptr_type = wanted_type->data.maybe.child_type;15067 dest_ptr_type = wanted_type->data.maybe.child_type;
15067 }15068 }
15068 if (dest_ptr_type != nullptr) {15069 if (dest_ptr_type != nullptr) {
15069 return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true);15070 return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true,
15071 false);
15070 }15072 }
15071 }15073 }
1507215074
...@@ -15108,7 +15110,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,...@@ -15108,7 +15110,7 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
15108 actual_type->data.pointer.child_type, source_node,15110 actual_type->data.pointer.child_type, source_node,
15109 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)15111 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
15110 {15112 {
15111 return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true);15113 return ir_analyze_ptr_cast(ira, source_instr, value, source_instr, wanted_type, source_instr, true, false);
15112 }15114 }
1511315115
15114 // cast from integer to C pointer15116 // cast from integer to C pointer
...@@ -18576,7 +18578,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i...@@ -18576,7 +18578,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
1857618578
18577 result_loc->written = true;18579 result_loc->written = true;
18578 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,18580 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
18579 &parent_result_loc->base, ptr_type, &result_cast->base.source_instruction->base, false);18581 &parent_result_loc->base, ptr_type, &result_cast->base.source_instruction->base, false, false);
18580 return result_loc->resolved_loc;18582 return result_loc->resolved_loc;
18581 }18583 }
18582 case ResultLocIdBitCast: {18584 case ResultLocIdBitCast: {
...@@ -18670,7 +18672,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i...@@ -18670,7 +18672,7 @@ static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_i
1867018672
18671 result_loc->written = true;18673 result_loc->written = true;
18672 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,18674 result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
18673 &parent_result_loc->base, ptr_type, &result_bit_cast->base.source_instruction->base, false);18675 &parent_result_loc->base, ptr_type, &result_bit_cast->base.source_instruction->base, false, false);
18674 return result_loc->resolved_loc;18676 return result_loc->resolved_loc;
18675 }18677 }
18676 }18678 }
...@@ -22947,7 +22949,7 @@ static IrInstGen *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstSrcSwi...@@ -22947,7 +22949,7 @@ static IrInstGen *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstSrcSwi
22947 ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes,22949 ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes,
22948 ref_type->data.pointer.allow_zero);22950 ref_type->data.pointer.allow_zero);
22949 return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr,22951 return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr,
22950 &instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false);22952 &instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false, false);
22951 } else {22953 } else {
22952 ir_add_error(ira, &instruction->base.base,22954 ir_add_error(ira, &instruction->base.base,
22953 buf_sprintf("switch on type '%s' provides no expression parameter", buf_ptr(&target_type->name)));22955 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,...@@ -23030,7 +23032,7 @@ static IrInstGen *ir_analyze_instruction_switch_else_var(IrAnalyze *ira,
23030 ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes,23032 ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes,
23031 ref_type->data.pointer.allow_zero);23033 ref_type->data.pointer.allow_zero);
23032 return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr,23034 return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr,
23033 &instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false);23035 &instruction->target_value_ptr->base, new_target_value_ptr_type, &instruction->base.base, false, false);
23034 }23036 }
2303523037
23036 return target_value_ptr;23038 return target_value_ptr;
...@@ -27814,7 +27816,8 @@ static IrInstGen *ir_align_cast(IrAnalyze *ira, IrInstGen *target, uint32_t alig...@@ -27814,7 +27816,8 @@ static IrInstGen *ir_align_cast(IrAnalyze *ira, IrInstGen *target, uint32_t alig
27814}27816}
2781527817
27816static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr,27818static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr,
27817 IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on)27819 IrInst *ptr_src, ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on,
27820 bool keep_bigger_alignment)
27818{27821{
27819 Error err;27822 Error err;
2782027823
...@@ -27853,14 +27856,16 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn...@@ -27853,14 +27856,16 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
27853 ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));27856 ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));
27854 return ira->codegen->invalid_inst_gen;27857 return ira->codegen->invalid_inst_gen;
27855 }27858 }
27856 uint32_t src_align_bytes;
27857 if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
27858 return ira->codegen->invalid_inst_gen;
27859
27860 uint32_t dest_align_bytes;27859 uint32_t dest_align_bytes;
27861 if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))27860 if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
27862 return ira->codegen->invalid_inst_gen;27861 return ira->codegen->invalid_inst_gen;
2786327862
27863 uint32_t src_align_bytes = 0;
27864 if (keep_bigger_alignment || dest_align_bytes != 1) {
27865 if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
27866 return ira->codegen->invalid_inst_gen;
27867 }
27868
27864 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))27869 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
27865 return ira->codegen->invalid_inst_gen;27870 return ira->codegen->invalid_inst_gen;
2786627871
...@@ -27935,16 +27940,15 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn...@@ -27935,16 +27940,15 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
27935 }27940 }
27936 result->value->type = dest_type;27941 result->value->type = dest_type;
2793727942
27938 // Keep the bigger alignment, it can only help-27943 // Keep the bigger alignment, it can only help- unless the target is zero bits.
27939 // unless the target is zero bits.27944 if (keep_bigger_alignment && src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
27940 if (src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
27941 result = ir_align_cast(ira, result, src_align_bytes, false);27945 result = ir_align_cast(ira, result, src_align_bytes, false);
27942 }27946 }
2794327947
27944 return result;27948 return result;
27945 }27949 }
2794627950
27947 if (dest_align_bytes > src_align_bytes) {27951 if (src_align_bytes != 0 && dest_align_bytes > src_align_bytes) {
27948 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));27952 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
27949 add_error_note(ira->codegen, msg, ptr_src->source_node,27953 add_error_note(ira->codegen, msg, ptr_src->source_node,
27950 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes));27954 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...@@ -27955,10 +27959,9 @@ static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrIn
2795527959
27956 IrInstGen *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);27960 IrInstGen *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
2795727961
27958 // Keep the bigger alignment, it can only help-27962 // Keep the bigger alignment, it can only help- unless the target is zero bits.
27959 // unless the target is zero bits.
27960 IrInstGen *result;27963 IrInstGen *result;
27961 if (src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {27964 if (keep_bigger_alignment && src_align_bytes > dest_align_bytes && type_has_bits(ira->codegen, dest_type)) {
27962 result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);27965 result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);
27963 if (type_is_invalid(result->value->type))27966 if (type_is_invalid(result->value->type))
27964 return ira->codegen->invalid_inst_gen;27967 return ira->codegen->invalid_inst_gen;
...@@ -27979,8 +27982,9 @@ static IrInstGen *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstSrcPtrCa...@@ -27979,8 +27982,9 @@ static IrInstGen *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstSrcPtrCa
27979 if (type_is_invalid(src_type))27982 if (type_is_invalid(src_type))
27980 return ira->codegen->invalid_inst_gen;27983 return ira->codegen->invalid_inst_gen;
2798127984
27985 bool keep_bigger_alignment = true;
27982 return ir_analyze_ptr_cast(ira, &instruction->base.base, ptr, &instruction->ptr->base,27986 return ir_analyze_ptr_cast(ira, &instruction->base.base, ptr, &instruction->ptr->base,
27983 dest_type, &dest_type_value->base, instruction->safety_check_on);27987 dest_type, &dest_type_value->base, instruction->safety_check_on, keep_bigger_alignment);
27984}27988}
2798527989
27986static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue *val, size_t len) {27990static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ZigValue *val, size_t len) {
test/stage1/behavior/async_fn.zig+16
...@@ -1547,3 +1547,19 @@ test "noasync on function calls" {...@@ -1547,3 +1547,19 @@ test "noasync on function calls" {
1547 expectEqual(@as(i32, 42), noasync S1.c().b);1547 expectEqual(@as(i32, 42), noasync S1.c().b);
1548 expectEqual(@as(i32, 42), (try noasync S1.d()).b);1548 expectEqual(@as(i32, 42), (try noasync S1.d()).b);
1549}1549}
1550
1551test "avoid forcing frame alignment resolution implicit cast to *c_void" {
1552 const S = struct {
1553 var x: ?*c_void = null;
1554
1555 fn foo() bool {
1556 suspend {
1557 x = @frame();
1558 }
1559 return true;
1560 }
1561 };
1562 var frame = async S.foo();
1563 resume @ptrCast(anyframe->bool, @alignCast(@alignOf(@Frame(S.foo)), S.x));
1564 expect(noasync await frame);
1565}
test/stage1/behavior/cast.zig+2-2
...@@ -462,10 +462,10 @@ fn foobar(func: PFN_void) void {...@@ -462,10 +462,10 @@ fn foobar(func: PFN_void) void {
462462
463test "implicit ptr to *c_void" {463test "implicit ptr to *c_void" {
464 var a: u32 = 1;464 var a: u32 = 1;
465 var ptr: *c_void = &a;465 var ptr: *align(@alignOf(u32)) c_void = &a;
466 var b: *u32 = @ptrCast(*u32, ptr);466 var b: *u32 = @ptrCast(*u32, ptr);
467 expect(b.* == 1);467 expect(b.* == 1);
468 var ptr2: ?*c_void = &a;468 var ptr2: ?*align(@alignOf(u32)) c_void = &a;
469 var c: *u32 = @ptrCast(*u32, ptr2.?);469 var c: *u32 = @ptrCast(*u32, ptr2.?);
470 expect(c.* == 1);470 expect(c.* == 1);
471}471}