mirror of
https://github.com/ziglang/zig.git
synced 2025-01-23 18:31:44 +00:00
parent
be94299666
commit
816689a3b1
@ -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*);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
17
src/ir.cpp
17
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);
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user