authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-29 16:52:31-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-29 16:52:31-04:00
log816689a3b1c98ec008438e7f868e1a123889b2a7
tree84dcf5e1cb51689543fea4c39b4c9f24dde681e9
parentbe94299666e57486be6bdb8fee2b79dbf3623c5d

ptrCast gives compile error for increasing alignment

See #37

10 files changed, 69 insertions(+), 20 deletions(-)

src/all_types.hpp+1
...@@ -913,6 +913,7 @@ struct FnTypeId {...@@ -913,6 +913,7 @@ struct FnTypeId {
913 size_t next_param_index;913 size_t next_param_index;
914 bool is_var_args;914 bool is_var_args;
915 CallingConvention cc;915 CallingConvention cc;
916 uint32_t alignment;
916};917};
917918
918uint32_t fn_type_id_hash(FnTypeId*);919uint32_t fn_type_id_hash(FnTypeId*);
src/analyze.cpp+21-6
...@@ -2899,14 +2899,29 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {...@@ -2899,14 +2899,29 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
2899 }2899 }
2900}2900}
29012901
2902bool type_is_codegen_pointer(TypeTableEntry *type) {2902TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type) {
2903 if (type->id == TypeTableEntryIdPointer) return true;2903 if (type->id == TypeTableEntryIdPointer) return type;
2904 if (type->id == TypeTableEntryIdFn) return true;2904 if (type->id == TypeTableEntryIdFn) return type;
2905 if (type->id == TypeTableEntryIdMaybe) {2905 if (type->id == TypeTableEntryIdMaybe) {
2906 if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return true;2906 if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return type->data.maybe.child_type;
2907 if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return true;2907 if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return type->data.maybe.child_type;
2908 }
2909 return nullptr;
2910}
2911
2912bool type_is_codegen_pointer(TypeTableEntry *type) {
2913 return get_codegen_ptr_type(type) != nullptr;
2914}
2915
2916uint32_t get_ptr_align(TypeTableEntry *type) {
2917 TypeTableEntry *ptr_type = get_codegen_ptr_type(type);
2918 if (ptr_type->id == TypeTableEntryIdPointer) {
2919 return ptr_type->data.pointer.alignment;
2920 } else if (ptr_type->id == TypeTableEntryIdFn) {
2921 return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment;
2922 } else {
2923 zig_unreachable();
2908 }2924 }
2909 return false;
2910}2925}
29112926
2912AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) {2927AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) {
src/analyze.hpp+2
...@@ -52,6 +52,8 @@ VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);...@@ -52,6 +52,8 @@ VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
52Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);52Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
53void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);53void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
54bool type_is_codegen_pointer(TypeTableEntry *type);54bool type_is_codegen_pointer(TypeTableEntry *type);
55TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type);
56uint32_t get_ptr_align(TypeTableEntry *type);
55TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);57TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);
56TypeTableEntry *container_ref_type(TypeTableEntry *type_entry);58TypeTableEntry *container_ref_type(TypeTableEntry *type_entry);
57bool type_is_complete(TypeTableEntry *type_entry);59bool type_is_complete(TypeTableEntry *type_entry);
src/ir.cpp+14-3
...@@ -10830,7 +10830,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -10830,7 +10830,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
10830 if (ptr_type->data.pointer.unaligned_bit_count == 0) {10830 if (ptr_type->data.pointer.unaligned_bit_count == 0) {
10831 return_type = get_pointer_to_type_extra(ira->codegen, child_type,10831 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
10832 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,10832 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
10833 get_abi_alignment(ira->codegen, child_type), 0, 0);10833 ptr_type->data.pointer.alignment, 0, 0);
10834 } else {10834 } else {
10835 uint64_t elem_val_scalar;10835 uint64_t elem_val_scalar;
10836 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))10836 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
...@@ -10841,8 +10841,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -10841,8 +10841,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
1084110841
10842 return_type = get_pointer_to_type_extra(ira->codegen, child_type,10842 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
10843 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,10843 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
10844 get_abi_alignment(ira->codegen, child_type),10844 1, (uint32_t)bit_offset, (uint32_t)bit_width);
10845 (uint32_t)bit_offset, (uint32_t)bit_width);
10846 }10845 }
10847 } else if (array_type->id == TypeTableEntryIdPointer) {10846 } else if (array_type->id == TypeTableEntryIdPointer) {
10848 return_type = array_type;10847 return_type = array_type;
...@@ -14457,6 +14456,18 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc...@@ -14457,6 +14456,18 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc
14457 return dest_type;14456 return dest_type;
14458 }14457 }
1445914458
14459 uint32_t src_align_bytes = get_ptr_align(src_type);
14460 uint32_t dest_align_bytes = get_ptr_align(dest_type);
14461
14462 if (dest_align_bytes > src_align_bytes) {
14463 ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment"));
14464 add_error_note(ira->codegen, msg, ptr->source_node,
14465 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes));
14466 add_error_note(ira->codegen, msg, dest_type_value->source_node,
14467 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes));
14468 return ira->codegen->builtin_types.entry_invalid;
14469 }
14470
14460 IrInstruction *result = ir_build_ptr_cast(&ira->new_irb, instruction->base.scope,14471 IrInstruction *result = ir_build_ptr_cast(&ira->new_irb, instruction->base.scope,
14461 instruction->base.source_node, nullptr, ptr);14472 instruction->base.source_node, nullptr, ptr);
14462 ir_link_new_instruction(result, &instruction->base);14473 ir_link_new_instruction(result, &instruction->base);
std/os/darwin.zig+1-1
...@@ -172,7 +172,7 @@ pub fn fork() -> usize {...@@ -172,7 +172,7 @@ pub fn fork() -> usize {
172172
173pub fn pipe(fds: &[2]i32) -> usize {173pub fn pipe(fds: &[2]i32) -> usize {
174 comptime assert(i32.bit_count == c_int.bit_count);174 comptime assert(i32.bit_count == c_int.bit_count);
175 errnoWrap(c.pipe(@ptrCast(&c_int, &(*fds)[0])))175 errnoWrap(c.pipe(@ptrCast(&c_int, fds)))
176}176}
177177
178pub fn mkdir(path: &const u8, mode: u32) -> usize {178pub fn mkdir(path: &const u8, mode: u32) -> usize {
std/special/builtin.zig+3-3
...@@ -49,8 +49,8 @@ fn generic_fmod(comptime T: type, x: T, y: T) -> T {...@@ -49,8 +49,8 @@ fn generic_fmod(comptime T: type, x: T, y: T) -> T {
49 const exp_bits = if (T == f32) 9 else 12;49 const exp_bits = if (T == f32) 9 else 12;
50 const bits_minus_1 = T.bit_count - 1;50 const bits_minus_1 = T.bit_count - 1;
51 const mask = if (T == f32) 0xff else 0x7ff;51 const mask = if (T == f32) 0xff else 0x7ff;
52 var ux = *@ptrCast(&const uint, &x);52 var ux = @bitCast(uint, x);
53 var uy = *@ptrCast(&const uint, &y);53 var uy = @bitCast(uint, y);
54 var ex = i32((ux >> digits) & mask);54 var ex = i32((ux >> digits) & mask);
55 var ey = i32((uy >> digits) & mask);55 var ey = i32((uy >> digits) & mask);
56 const sx = if (T == f32) u32(ux & 0x80000000) else i32(ux >> bits_minus_1);56 const sx = if (T == f32) u32(ux & 0x80000000) else i32(ux >> bits_minus_1);
...@@ -113,7 +113,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) -> T {...@@ -113,7 +113,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) -> T {
113 } else {113 } else {
114 ux |= uint(sx) << bits_minus_1;114 ux |= uint(sx) << bits_minus_1;
115 }115 }
116 return *@ptrCast(&const T, &ux);116 return @bitCast(T, ux);
117}117}
118118
119fn isNan(comptime T: type, bits: T) -> bool {119fn isNan(comptime T: type, bits: T) -> bool {
std/special/compiler_rt/udivmod.zig+5-5
...@@ -54,7 +54,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:...@@ -54,7 +54,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
54 if (maybe_rem) |rem| {54 if (maybe_rem) |rem| {
55 r[high] = n[high] % d[high];55 r[high] = n[high] % d[high];
56 r[low] = 0;56 r[low] = 0;
57 *rem = *@ptrCast(&DoubleInt, &r[0]); // TODO issue #42157 *rem = *@ptrCast(&align @alignOf(SingleInt) DoubleInt, &r[0]); // TODO issue #421
58 }58 }
59 return n[high] / d[high];59 return n[high] / d[high];
60 }60 }
...@@ -66,7 +66,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:...@@ -66,7 +66,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
66 if (maybe_rem) |rem| {66 if (maybe_rem) |rem| {
67 r[low] = n[low];67 r[low] = n[low];
68 r[high] = n[high] & (d[high] - 1);68 r[high] = n[high] & (d[high] - 1);
69 *rem = *@ptrCast(&DoubleInt, &r[0]); // TODO issue #42169 *rem = *@ptrCast(&align @alignOf(SingleInt) DoubleInt, &r[0]); // TODO issue #421
70 }70 }
71 return n[high] >> Log2SingleInt(@ctz(d[high]));71 return n[high] >> Log2SingleInt(@ctz(d[high]));
72 }72 }
...@@ -106,7 +106,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:...@@ -106,7 +106,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
106 sr = @ctz(d[low]);106 sr = @ctz(d[low]);
107 q[high] = n[high] >> Log2SingleInt(sr);107 q[high] = n[high] >> Log2SingleInt(sr);
108 q[low] = (n[high] << Log2SingleInt(SingleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr));108 q[low] = (n[high] << Log2SingleInt(SingleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr));
109 return *@ptrCast(&DoubleInt, &q[0]); // TODO issue #421109 return *@ptrCast(&align @alignOf(SingleInt) DoubleInt, &q[0]); // TODO issue #421
110 }110 }
111 // K X111 // K X
112 // ---112 // ---
...@@ -180,13 +180,13 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:...@@ -180,13 +180,13 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
180 // r.all -= b;180 // r.all -= b;
181 // carry = 1;181 // carry = 1;
182 // }182 // }
183 r_all = *@ptrCast(&DoubleInt, &r[0]); // TODO issue #421183 r_all = *@ptrCast(&align @alignOf(SingleInt) DoubleInt, &r[0]); // TODO issue #421
184 const s: SignedDoubleInt = SignedDoubleInt(b -% r_all -% 1) >> (DoubleInt.bit_count - 1);184 const s: SignedDoubleInt = SignedDoubleInt(b -% r_all -% 1) >> (DoubleInt.bit_count - 1);
185 carry = u32(s & 1);185 carry = u32(s & 1);
186 r_all -= b & @bitCast(DoubleInt, s);186 r_all -= b & @bitCast(DoubleInt, s);
187 r = *@ptrCast(&[2]SingleInt, &r_all); // TODO issue #421187 r = *@ptrCast(&[2]SingleInt, &r_all); // TODO issue #421
188 }188 }
189 const q_all = ((*@ptrCast(&DoubleInt, &q[0])) << 1) | carry; // TODO issue #421189 const q_all = ((*@ptrCast(&align @alignOf(SingleInt) DoubleInt, &q[0])) << 1) | carry; // TODO issue #421
190 if (maybe_rem) |rem| {190 if (maybe_rem) |rem| {
191 *rem = r_all;191 *rem = r_all;
192 }192 }
test/cases/align.zig+9
...@@ -53,3 +53,12 @@ test "implicitly decreasing slice alignment" {...@@ -53,3 +53,12 @@ test "implicitly decreasing slice alignment" {
53 assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);53 assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);
54}54}
55fn addUnalignedSlice(a: []align 1 const u32, b: []align 1 const u32) -> u32 { a[0] + b[0] }55fn addUnalignedSlice(a: []align 1 const u32, b: []align 1 const u32) -> u32 { a[0] + b[0] }
56
57test "specifying alignment allows pointer cast" {
58 testBytesAlign(0x33);
59}
60fn testBytesAlign(b: u8) {
61 var bytes align 4 = []u8{b, b, b, b};
62 const ptr = @ptrCast(&u32, &bytes[0]);
63 assert(*ptr == 0x33333333);
64}
test/compare_output.zig+2-2
...@@ -262,8 +262,8 @@ pub fn addCases(cases: &tests.CompareOutputContext) {...@@ -262,8 +262,8 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
262 \\const c = @cImport(@cInclude("stdlib.h"));262 \\const c = @cImport(@cInclude("stdlib.h"));
263 \\263 \\
264 \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {264 \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {
265 \\ const a_int = @ptrCast(&i32, a ?? unreachable);265 \\ const a_int = @ptrCast(&align 1 i32, a ?? unreachable);
266 \\ const b_int = @ptrCast(&i32, b ?? unreachable);266 \\ const b_int = @ptrCast(&align 1 i32, b ?? unreachable);
267 \\ if (*a_int < *b_int) {267 \\ if (*a_int < *b_int) {
268 \\ -1268 \\ -1
269 \\ } else if (*a_int > *b_int) {269 \\ } else if (*a_int > *b_int) {
test/compile_errors.zig+11
...@@ -2011,4 +2011,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2011,4 +2011,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2011 \\}2011 \\}
2012 ,2012 ,
2013 ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align 1 u32'");2013 ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align 1 u32'");
2014
2015 cases.add("increase pointer alignment in @ptrCast",
2016 \\export fn entry() -> u32 {
2017 \\ var bytes: [4]u8 align 4 = []u8{0x01, 0x02, 0x03, 0x04};
2018 \\ const ptr = @ptrCast(&u32, &bytes[0]);
2019 \\ return *ptr;
2020 \\}
2021 ,
2022 ".tmp_source.zig:3:17: error: cast increases pointer alignment",
2023 ".tmp_source.zig:3:38: note: '&u8' has alignment 1",
2024 ".tmp_source.zig:3:27: note: '&u32' has alignment 4");
2014}2025}