mirror of
https://github.com/ziglang/zig.git
synced 2025-12-22 22:23:10 +00:00
stage2: fully implement Type.eql for pointers
Also fixed abiAlignment - for pointers it was returning the abi alignment inside the type, rather than of the pointer itself. There is now `ptrAlignment` for getting the alignment inside the type of pointers.
This commit is contained in:
parent
95cc457d97
commit
68f4eb0f67
14
BRANCH_TODO
14
BRANCH_TODO
@ -1,22 +1,14 @@
|
||||
this is my WIP branch scratch pad, to be deleted before merging into master
|
||||
|
||||
Merge TODO list:
|
||||
* don't have an explicit dbg_stmt zir instruction - instead merge it with
|
||||
var decl and assignment instructions, etc.
|
||||
- make it set sema.src where appropriate
|
||||
* uncomment the commented out stage2 tests
|
||||
* remove the LazySrcLoc.todo tag
|
||||
* update astgen.zig
|
||||
* finish updating Sema.zig
|
||||
* finish implementing SrcLoc byteOffset function
|
||||
* audit Module.zig for use of token_starts - it should only be when
|
||||
resolving LazySrcLoc
|
||||
* audit astgen.zig for use of token_starts - I think there should be no uses
|
||||
* audit all the .unneeded src locations
|
||||
* audit the calls in codegen toSrcLocWithDecl specifically if there is inlined function
|
||||
calls from other files.
|
||||
* uncomment the commented out stage2 tests
|
||||
* memory leaks on --watch update
|
||||
* memory leaks on test-stage2
|
||||
|
||||
Performance optimizations to look into:
|
||||
* astgen: pass *GenZir as the first arg, not *Module
|
||||
@ -41,3 +33,7 @@ Performance optimizations to look into:
|
||||
* in astgen, if a decl_val would be to a const variable or to a function, there could be
|
||||
a special zir.Inst.Ref form that means to refer to a decl as the operand. This
|
||||
would elide all the decl_val instructions in the ZIR.
|
||||
* don't have an explicit dbg_stmt zir instruction - instead merge it with
|
||||
var decl and assignment instructions, etc.
|
||||
- make it set sema.src where appropriate
|
||||
* look into not emitting redundant dbg stmts to TZIR
|
||||
|
||||
201
src/type.zig
201
src/type.zig
@ -169,6 +169,125 @@ pub const Type = extern union {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn ptrInfo(self: Type) Payload.Pointer {
|
||||
switch (self.tag()) {
|
||||
.single_const_pointer_to_comptime_int => return .{ .data = .{
|
||||
.pointee_type = Type.initTag(.comptime_int),
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = false,
|
||||
.@"volatile" = false,
|
||||
.size = .One,
|
||||
} },
|
||||
.const_slice_u8 => return .{ .data = .{
|
||||
.pointee_type = Type.initTag(.u8),
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = false,
|
||||
.@"volatile" = false,
|
||||
.size = .Slice,
|
||||
} },
|
||||
.single_const_pointer => return .{ .data = .{
|
||||
.pointee_type = self.castPointer().?.data,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = false,
|
||||
.@"volatile" = false,
|
||||
.size = .One,
|
||||
} },
|
||||
.single_mut_pointer => return .{ .data = .{
|
||||
.pointee_type = self.castPointer().?.data,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = true,
|
||||
.@"volatile" = false,
|
||||
.size = .One,
|
||||
} },
|
||||
.many_const_pointer => return .{ .data = .{
|
||||
.pointee_type = self.castPointer().?.data,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = false,
|
||||
.@"volatile" = false,
|
||||
.size = .Many,
|
||||
} },
|
||||
.many_mut_pointer => return .{ .data = .{
|
||||
.pointee_type = self.castPointer().?.data,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = true,
|
||||
.@"volatile" = false,
|
||||
.size = .Many,
|
||||
} },
|
||||
.c_const_pointer => return .{ .data = .{
|
||||
.pointee_type = self.castPointer().?.data,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = false,
|
||||
.@"volatile" = false,
|
||||
.size = .C,
|
||||
} },
|
||||
.c_mut_pointer => return .{ .data = .{
|
||||
.pointee_type = self.castPointer().?.data,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = true,
|
||||
.@"volatile" = false,
|
||||
.size = .C,
|
||||
} },
|
||||
.const_slice => return .{ .data = .{
|
||||
.pointee_type = self.castPointer().?.data,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = false,
|
||||
.@"volatile" = false,
|
||||
.size = .Slice,
|
||||
} },
|
||||
.mut_slice => return .{ .data = .{
|
||||
.pointee_type = self.castPointer().?.data,
|
||||
.sentinel = null,
|
||||
.@"align" = 0,
|
||||
.bit_offset = 0,
|
||||
.host_size = 0,
|
||||
.@"allowzero" = false,
|
||||
.mutable = true,
|
||||
.@"volatile" = false,
|
||||
.size = .Slice,
|
||||
} },
|
||||
|
||||
.pointer => return self.castTag(.pointer).?.*,
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eql(a: Type, b: Type) bool {
|
||||
// As a shortcut, if the small tags / addresses match, we're done.
|
||||
if (a.tag_if_small_enough == b.tag_if_small_enough)
|
||||
@ -191,25 +310,38 @@ pub const Type = extern union {
|
||||
return a.elemType().eql(b.elemType());
|
||||
},
|
||||
.Pointer => {
|
||||
// Hot path for common case:
|
||||
if (a.castPointer()) |a_payload| {
|
||||
if (b.castPointer()) |b_payload| {
|
||||
return a.tag() == b.tag() and eql(a_payload.data, b_payload.data);
|
||||
const info_a = a.ptrInfo().data;
|
||||
const info_b = b.ptrInfo().data;
|
||||
if (!info_a.pointee_type.eql(info_b.pointee_type))
|
||||
return false;
|
||||
if (info_a.size != info_b.size)
|
||||
return false;
|
||||
if (info_a.mutable != info_b.mutable)
|
||||
return false;
|
||||
if (info_a.@"volatile" != info_b.@"volatile")
|
||||
return false;
|
||||
if (info_a.@"allowzero" != info_b.@"allowzero")
|
||||
return false;
|
||||
if (info_a.bit_offset != info_b.bit_offset)
|
||||
return false;
|
||||
if (info_a.host_size != info_b.host_size)
|
||||
return false;
|
||||
|
||||
const sentinel_a = info_a.sentinel;
|
||||
const sentinel_b = info_b.sentinel;
|
||||
if (sentinel_a) |sa| {
|
||||
if (sentinel_b) |sb| {
|
||||
if (!sa.eql(sb))
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (sentinel_b != null)
|
||||
return false;
|
||||
}
|
||||
const is_slice_a = isSlice(a);
|
||||
const is_slice_b = isSlice(b);
|
||||
if (is_slice_a != is_slice_b)
|
||||
return false;
|
||||
|
||||
const ptr_size_a = ptrSize(a);
|
||||
const ptr_size_b = ptrSize(b);
|
||||
if (ptr_size_a != ptr_size_b)
|
||||
return false;
|
||||
|
||||
std.debug.panic("TODO implement more pointer Type equality comparison: {} and {}", .{
|
||||
a, b,
|
||||
});
|
||||
return true;
|
||||
},
|
||||
.Int => {
|
||||
// Detect that e.g. u64 != usize, even if the bits match on a particular target.
|
||||
@ -844,6 +976,35 @@ pub const Type = extern union {
|
||||
return fast_result;
|
||||
}
|
||||
|
||||
pub fn ptrAlignment(self: Type, target: Target) u32 {
|
||||
switch (self.tag()) {
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
.many_mut_pointer,
|
||||
.c_const_pointer,
|
||||
.c_mut_pointer,
|
||||
.const_slice,
|
||||
.mut_slice,
|
||||
.optional_single_const_pointer,
|
||||
.optional_single_mut_pointer,
|
||||
=> return self.cast(Payload.ElemType).?.data.abiAlignment(target),
|
||||
|
||||
.const_slice_u8 => return 1,
|
||||
|
||||
.pointer => {
|
||||
const ptr_info = self.castTag(.pointer).?.data;
|
||||
if (ptr_info.@"align" != 0) {
|
||||
return ptr_info.@"align";
|
||||
} else {
|
||||
return ptr_info.pointee_type.abiAlignment();
|
||||
}
|
||||
},
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts that hasCodeGenBits() is true.
|
||||
pub fn abiAlignment(self: Type, target: Target) u32 {
|
||||
return switch (self.tag()) {
|
||||
@ -885,15 +1046,9 @@ pub const Type = extern union {
|
||||
.mut_slice,
|
||||
.optional_single_const_pointer,
|
||||
.optional_single_mut_pointer,
|
||||
.pointer,
|
||||
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
|
||||
.pointer => {
|
||||
const payload = self.castTag(.pointer).?.data;
|
||||
|
||||
if (payload.@"align" != 0) return payload.@"align";
|
||||
return @divExact(target.cpu.arch.ptrBitWidth(), 8);
|
||||
},
|
||||
|
||||
.c_short => return @divExact(CType.short.sizeInBits(target), 8),
|
||||
.c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8),
|
||||
.c_int => return @divExact(CType.int.sizeInBits(target), 8),
|
||||
|
||||
@ -1502,27 +1502,27 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
"",
|
||||
);
|
||||
|
||||
//case.addCompareOutput(
|
||||
// \\export fn _start() noreturn {
|
||||
// \\ const a: anyerror!comptime_int = 42;
|
||||
// \\ const b: *const comptime_int = &(a catch unreachable);
|
||||
// \\ assert(b.* == 42);
|
||||
// \\
|
||||
// \\ exit();
|
||||
// \\}
|
||||
// \\fn assert(b: bool) void {
|
||||
// \\ if (!b) unreachable; // assertion failure
|
||||
// \\}
|
||||
// \\fn exit() noreturn {
|
||||
// \\ asm volatile ("syscall"
|
||||
// \\ :
|
||||
// \\ : [number] "{rax}" (231),
|
||||
// \\ [arg1] "{rdi}" (0)
|
||||
// \\ : "rcx", "r11", "memory"
|
||||
// \\ );
|
||||
// \\ unreachable;
|
||||
// \\}
|
||||
//, "");
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() noreturn {
|
||||
\\ const a: anyerror!comptime_int = 42;
|
||||
\\ const b: *const comptime_int = &(a catch unreachable);
|
||||
\\ assert(b.* == 42);
|
||||
\\
|
||||
\\ exit();
|
||||
\\}
|
||||
\\fn assert(b: bool) void {
|
||||
\\ if (!b) unreachable; // assertion failure
|
||||
\\}
|
||||
\\fn exit() noreturn {
|
||||
\\ asm volatile ("syscall"
|
||||
\\ :
|
||||
\\ : [number] "{rax}" (231),
|
||||
\\ [arg1] "{rdi}" (0)
|
||||
\\ : "rcx", "r11", "memory"
|
||||
\\ );
|
||||
\\ unreachable;
|
||||
\\}
|
||||
, "");
|
||||
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() noreturn {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user