diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-08-29 16:52:31 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-08-29 16:52:31 -0400 |
| commit | 816689a3b1c98ec008438e7f868e1a123889b2a7 (patch) | |
| tree | 84dcf5e1cb51689543fea4c39b4c9f24dde681e9 | |
| parent | be94299666e57486be6bdb8fee2b79dbf3623c5d (diff) | |
| download | zig-816689a3b1c98ec008438e7f868e1a123889b2a7.tar.gz zig-816689a3b1c98ec008438e7f868e1a123889b2a7.zip | |
ptrCast gives compile error for increasing alignment
See #37
| -rw-r--r-- | src/all_types.hpp | 1 | ||||
| -rw-r--r-- | src/analyze.cpp | 27 | ||||
| -rw-r--r-- | src/analyze.hpp | 2 | ||||
| -rw-r--r-- | src/ir.cpp | 17 | ||||
| -rw-r--r-- | std/os/darwin.zig | 2 | ||||
| -rw-r--r-- | std/special/builtin.zig | 6 | ||||
| -rw-r--r-- | std/special/compiler_rt/udivmod.zig | 10 | ||||
| -rw-r--r-- | test/cases/align.zig | 9 | ||||
| -rw-r--r-- | test/compare_output.zig | 4 | ||||
| -rw-r--r-- | test/compile_errors.zig | 11 |
10 files changed, 69 insertions, 20 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index b43ecedcd6..461270357b 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -913,6 +913,7 @@ struct FnTypeId { size_t next_param_index; bool is_var_args; CallingConvention cc; + uint32_t alignment; }; uint32_t fn_type_id_hash(FnTypeId*); diff --git a/src/analyze.cpp b/src/analyze.cpp index 69a50253d2..35ccd3b4d3 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2899,14 +2899,29 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { } } -bool type_is_codegen_pointer(TypeTableEntry *type) { - if (type->id == TypeTableEntryIdPointer) return true; - if (type->id == TypeTableEntryIdFn) return true; +TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type) { + if (type->id == TypeTableEntryIdPointer) return type; + if (type->id == TypeTableEntryIdFn) return type; if (type->id == TypeTableEntryIdMaybe) { - if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return true; - if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return true; + if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return type->data.maybe.child_type; + if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return type->data.maybe.child_type; + } + return nullptr; +} + +bool type_is_codegen_pointer(TypeTableEntry *type) { + return get_codegen_ptr_type(type) != nullptr; +} + +uint32_t get_ptr_align(TypeTableEntry *type) { + TypeTableEntry *ptr_type = get_codegen_ptr_type(type); + if (ptr_type->id == TypeTableEntryIdPointer) { + return ptr_type->data.pointer.alignment; + } else if (ptr_type->id == TypeTableEntryIdFn) { + return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment; + } else { + zig_unreachable(); } - return false; } AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) { diff --git a/src/analyze.hpp b/src/analyze.hpp index 79a2cf1daf..9e9e066126 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -52,6 +52,8 @@ VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name); Tld *find_decl(CodeGen *g, Scope *scope, Buf *name); void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node); bool type_is_codegen_pointer(TypeTableEntry *type); +TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type); +uint32_t get_ptr_align(TypeTableEntry *type); TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry); TypeTableEntry *container_ref_type(TypeTableEntry *type_entry); bool type_is_complete(TypeTableEntry *type_entry); diff --git a/src/ir.cpp b/src/ir.cpp index 37877e1b34..f7f097e99d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10830,7 +10830,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc if (ptr_type->data.pointer.unaligned_bit_count == 0) { return_type = get_pointer_to_type_extra(ira->codegen, child_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, - get_abi_alignment(ira->codegen, child_type), 0, 0); + ptr_type->data.pointer.alignment, 0, 0); } else { uint64_t elem_val_scalar; if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar)) @@ -10841,8 +10841,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc return_type = get_pointer_to_type_extra(ira->codegen, child_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, - get_abi_alignment(ira->codegen, child_type), - (uint32_t)bit_offset, (uint32_t)bit_width); + 1, (uint32_t)bit_offset, (uint32_t)bit_width); } } else if (array_type->id == TypeTableEntryIdPointer) { return_type = array_type; @@ -14457,6 +14456,18 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc return dest_type; } + uint32_t src_align_bytes = get_ptr_align(src_type); + uint32_t dest_align_bytes = get_ptr_align(dest_type); + + if (dest_align_bytes > src_align_bytes) { + ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment")); + add_error_note(ira->codegen, msg, ptr->source_node, + buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes)); + add_error_note(ira->codegen, msg, dest_type_value->source_node, + buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes)); + return ira->codegen->builtin_types.entry_invalid; + } + IrInstruction *result = ir_build_ptr_cast(&ira->new_irb, instruction->base.scope, instruction->base.source_node, nullptr, ptr); ir_link_new_instruction(result, &instruction->base); diff --git a/std/os/darwin.zig b/std/os/darwin.zig index fcd356156e..8a034f966b 100644 --- a/std/os/darwin.zig +++ b/std/os/darwin.zig @@ -172,7 +172,7 @@ pub fn fork() -> usize { pub fn pipe(fds: &[2]i32) -> usize { comptime assert(i32.bit_count == c_int.bit_count); - errnoWrap(c.pipe(@ptrCast(&c_int, &(*fds)[0]))) + errnoWrap(c.pipe(@ptrCast(&c_int, fds))) } pub fn mkdir(path: &const u8, mode: u32) -> usize { diff --git a/std/special/builtin.zig b/std/special/builtin.zig index ede7b4abb8..95a41b07b5 100644 --- a/std/special/builtin.zig +++ b/std/special/builtin.zig @@ -49,8 +49,8 @@ fn generic_fmod(comptime T: type, x: T, y: T) -> T { const exp_bits = if (T == f32) 9 else 12; const bits_minus_1 = T.bit_count - 1; const mask = if (T == f32) 0xff else 0x7ff; - var ux = *@ptrCast(&const uint, &x); - var uy = *@ptrCast(&const uint, &y); + var ux = @bitCast(uint, x); + var uy = @bitCast(uint, y); var ex = i32((ux >> digits) & mask); var ey = i32((uy >> digits) & mask); 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 { } else { ux |= uint(sx) << bits_minus_1; } - return *@ptrCast(&const T, &ux); + return @bitCast(T, ux); } fn isNan(comptime T: type, bits: T) -> bool { diff --git a/std/special/compiler_rt/udivmod.zig b/std/special/compiler_rt/udivmod.zig index ef15e77546..efe5e85a73 100644 --- a/std/special/compiler_rt/udivmod.zig +++ b/std/special/compiler_rt/udivmod.zig @@ -54,7 +54,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: if (maybe_rem) |rem| { r[high] = n[high] % d[high]; r[low] = 0; - *rem = *@ptrCast(&DoubleInt, &r[0]); // TODO issue #421 + *rem = *@ptrCast(&align @alignOf(SingleInt) DoubleInt, &r[0]); // TODO issue #421 } return n[high] / d[high]; } @@ -66,7 +66,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: if (maybe_rem) |rem| { r[low] = n[low]; r[high] = n[high] & (d[high] - 1); - *rem = *@ptrCast(&DoubleInt, &r[0]); // TODO issue #421 + *rem = *@ptrCast(&align @alignOf(SingleInt) DoubleInt, &r[0]); // TODO issue #421 } return n[high] >> Log2SingleInt(@ctz(d[high])); } @@ -106,7 +106,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: sr = @ctz(d[low]); q[high] = n[high] >> Log2SingleInt(sr); q[low] = (n[high] << Log2SingleInt(SingleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr)); - return *@ptrCast(&DoubleInt, &q[0]); // TODO issue #421 + return *@ptrCast(&align @alignOf(SingleInt) DoubleInt, &q[0]); // TODO issue #421 } // K X // --- @@ -180,13 +180,13 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // r.all -= b; // carry = 1; // } - r_all = *@ptrCast(&DoubleInt, &r[0]); // TODO issue #421 + r_all = *@ptrCast(&align @alignOf(SingleInt) DoubleInt, &r[0]); // TODO issue #421 const s: SignedDoubleInt = SignedDoubleInt(b -% r_all -% 1) >> (DoubleInt.bit_count - 1); carry = u32(s & 1); r_all -= b & @bitCast(DoubleInt, s); r = *@ptrCast(&[2]SingleInt, &r_all); // TODO issue #421 } - const q_all = ((*@ptrCast(&DoubleInt, &q[0])) << 1) | carry; // TODO issue #421 + const q_all = ((*@ptrCast(&align @alignOf(SingleInt) DoubleInt, &q[0])) << 1) | carry; // TODO issue #421 if (maybe_rem) |rem| { *rem = r_all; } diff --git a/test/cases/align.zig b/test/cases/align.zig index 383d0389b5..ee68408226 100644 --- a/test/cases/align.zig +++ b/test/cases/align.zig @@ -53,3 +53,12 @@ test "implicitly decreasing slice alignment" { assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7); } fn addUnalignedSlice(a: []align 1 const u32, b: []align 1 const u32) -> u32 { a[0] + b[0] } + +test "specifying alignment allows pointer cast" { + testBytesAlign(0x33); +} +fn testBytesAlign(b: u8) { + var bytes align 4 = []u8{b, b, b, b}; + const ptr = @ptrCast(&u32, &bytes[0]); + assert(*ptr == 0x33333333); +} diff --git a/test/compare_output.zig b/test/compare_output.zig index bf2255881b..39318c31a0 100644 --- a/test/compare_output.zig +++ b/test/compare_output.zig @@ -262,8 +262,8 @@ pub fn addCases(cases: &tests.CompareOutputContext) { \\const c = @cImport(@cInclude("stdlib.h")); \\ \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int { - \\ const a_int = @ptrCast(&i32, a ?? unreachable); - \\ const b_int = @ptrCast(&i32, b ?? unreachable); + \\ const a_int = @ptrCast(&align 1 i32, a ?? unreachable); + \\ const b_int = @ptrCast(&align 1 i32, b ?? unreachable); \\ if (*a_int < *b_int) { \\ -1 \\ } else if (*a_int > *b_int) { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 03110f98e7..96898d1744 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2011,4 +2011,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\} , ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align 1 u32'"); + + cases.add("increase pointer alignment in @ptrCast", + \\export fn entry() -> u32 { + \\ var bytes: [4]u8 align 4 = []u8{0x01, 0x02, 0x03, 0x04}; + \\ const ptr = @ptrCast(&u32, &bytes[0]); + \\ return *ptr; + \\} + , + ".tmp_source.zig:3:17: error: cast increases pointer alignment", + ".tmp_source.zig:3:38: note: '&u8' has alignment 1", + ".tmp_source.zig:3:27: note: '&u32' has alignment 4"); } |
