mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
stage2: complex pointer types
This commit is contained in:
parent
ebfe723f3c
commit
9568248450
@ -3153,7 +3153,7 @@ pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mu
|
||||
type_payload.* = .{
|
||||
.base = .{
|
||||
.tag = switch (size) {
|
||||
.One => if (mutable) .single_mut_pointer else T.many_const_pointer,
|
||||
.One => if (mutable) T.single_mut_pointer else T.single_const_pointer,
|
||||
.Many => if (mutable) T.many_mut_pointer else T.many_const_pointer,
|
||||
.C => if (mutable) T.c_mut_pointer else T.c_const_pointer,
|
||||
else => unreachable,
|
||||
@ -3164,6 +3164,38 @@ pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mu
|
||||
return Type.initPayload(&type_payload.base);
|
||||
}
|
||||
|
||||
pub fn ptrType(
|
||||
self: *Module,
|
||||
scope: *Scope,
|
||||
src: usize,
|
||||
elem_ty: Type,
|
||||
sentinel: ?Value,
|
||||
@"align": u32,
|
||||
bit_offset: u16,
|
||||
host_size: u16,
|
||||
mutable: bool,
|
||||
@"allowzero": bool,
|
||||
@"volatile": bool,
|
||||
size: std.builtin.TypeInfo.Pointer.Size,
|
||||
) Allocator.Error!Type {
|
||||
assert(host_size == 0 or bit_offset < host_size * 8);
|
||||
|
||||
// TODO check if type can be represented by simplePtrType
|
||||
const type_payload = try scope.arena().create(Type.Payload.Pointer);
|
||||
type_payload.* = .{
|
||||
.pointee_type = elem_ty,
|
||||
.sentinel = sentinel,
|
||||
.@"align" = @"align",
|
||||
.bit_offset = bit_offset,
|
||||
.host_size = host_size,
|
||||
.@"allowzero" = @"allowzero",
|
||||
.mutable = mutable,
|
||||
.@"volatile" = @"volatile",
|
||||
.size = size,
|
||||
};
|
||||
return Type.initPayload(&type_payload.base);
|
||||
}
|
||||
|
||||
pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type {
|
||||
return Type.initPayload(switch (child_type.tag()) {
|
||||
.single_const_pointer => blk: {
|
||||
|
||||
@ -582,8 +582,7 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir
|
||||
// TODO stage1 type inference bug
|
||||
.LBracket => @as(std.builtin.TypeInfo.Pointer.Size, switch (tree.token_ids[node.op_token + 2]) {
|
||||
.Identifier => .C,
|
||||
.RBracket => .Many,
|
||||
else => unreachable,
|
||||
else => .Many,
|
||||
}),
|
||||
else => unreachable,
|
||||
};
|
||||
@ -616,7 +615,7 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir
|
||||
kw_args.align_bit_end = try expr(mod, scope, .none, bit_range.end);
|
||||
}
|
||||
}
|
||||
kw_args.@"const" = node.ptr_info.const_token != null;
|
||||
kw_args.mutable = node.ptr_info.const_token == null;
|
||||
kw_args.@"volatile" = node.ptr_info.volatile_token != null;
|
||||
if (node.ptr_info.sentinel) |some| {
|
||||
kw_args.sentinel = try expr(mod, scope, .none, some);
|
||||
|
||||
@ -74,6 +74,7 @@ pub const Type = extern union {
|
||||
.many_mut_pointer,
|
||||
.c_const_pointer,
|
||||
.c_mut_pointer,
|
||||
.pointer,
|
||||
=> return .Pointer,
|
||||
|
||||
.optional,
|
||||
@ -390,6 +391,25 @@ pub const Type = extern union {
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> return self.copyPayloadSingleField(allocator, Payload.PointerSimple, "pointee_type"),
|
||||
|
||||
.pointer => {
|
||||
const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
|
||||
const new_payload = try allocator.create(Payload.Pointer);
|
||||
new_payload.* = .{
|
||||
.base = payload.base,
|
||||
|
||||
.pointee_type = try payload.pointee_type.copy(allocator),
|
||||
.sentinel = if (payload.sentinel) |some| try some.copy(allocator) else null,
|
||||
.@"align" = payload.@"align",
|
||||
.bit_offset = payload.bit_offset,
|
||||
.host_size = payload.host_size,
|
||||
.@"allowzero" = payload.@"allowzero",
|
||||
.mutable = payload.mutable,
|
||||
.@"volatile" = payload.@"volatile",
|
||||
.size = payload.size,
|
||||
};
|
||||
return Type{ .ptr_otherwise = &new_payload.base };
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,6 +576,34 @@ pub const Type = extern union {
|
||||
ty = payload.pointee_type;
|
||||
continue;
|
||||
},
|
||||
|
||||
.pointer => {
|
||||
const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise);
|
||||
if (payload.sentinel) |some| switch (payload.size) {
|
||||
.One, .C => unreachable,
|
||||
.Many => try out_stream.writeAll("[*:{}]"),
|
||||
.Slice => try out_stream.writeAll("[:{}]"),
|
||||
} else switch (payload.size) {
|
||||
.One => try out_stream.writeAll("*"),
|
||||
.Many => try out_stream.writeAll("[*]"),
|
||||
.C => try out_stream.writeAll("[*c]"),
|
||||
.Slice => try out_stream.writeAll("[]"),
|
||||
}
|
||||
if (payload.@"align" != 0) {
|
||||
try out_stream.print("align({}", .{payload.@"align"});
|
||||
|
||||
if (payload.bit_offset != 0) {
|
||||
try out_stream.print(":{}:{}", .{ payload.bit_offset, payload.host_size });
|
||||
}
|
||||
try out_stream.writeAll(") ");
|
||||
}
|
||||
if (!payload.mutable) try out_stream.writeAll("const ");
|
||||
if (payload.@"volatile") try out_stream.writeAll("volatile ");
|
||||
if (payload.@"allowzero") try out_stream.writeAll("allowzero ");
|
||||
|
||||
ty = payload.pointee_type;
|
||||
continue;
|
||||
},
|
||||
}
|
||||
unreachable;
|
||||
}
|
||||
@ -660,6 +708,7 @@ pub const Type = extern union {
|
||||
.many_mut_pointer => self.elemType().hasCodeGenBits(),
|
||||
.c_const_pointer => self.elemType().hasCodeGenBits(),
|
||||
.c_mut_pointer => self.elemType().hasCodeGenBits(),
|
||||
.pointer => self.elemType().hasCodeGenBits(),
|
||||
.int_signed => self.cast(Payload.IntSigned).?.bits == 0,
|
||||
.int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0,
|
||||
|
||||
@ -718,6 +767,13 @@ pub const Type = extern union {
|
||||
.optional_single_mut_pointer,
|
||||
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
|
||||
.pointer => {
|
||||
const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
|
||||
|
||||
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),
|
||||
@ -789,6 +845,7 @@ pub const Type = extern union {
|
||||
.@"null" => unreachable,
|
||||
.@"undefined" => unreachable,
|
||||
.enum_literal => unreachable,
|
||||
.single_const_pointer_to_comptime_int => unreachable,
|
||||
|
||||
.u8,
|
||||
.i8,
|
||||
@ -812,18 +869,28 @@ pub const Type = extern union {
|
||||
.i64, .u64 => return 8,
|
||||
|
||||
.isize,
|
||||
.usize,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.const_slice_u8,
|
||||
.usize
|
||||
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
.const_slice_u8 => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2,
|
||||
|
||||
.optional_single_const_pointer,
|
||||
.optional_single_mut_pointer,
|
||||
=> {
|
||||
if (self.elemType().hasCodeGenBits()) return 1;
|
||||
return @divExact(target.cpu.arch.ptrBitWidth(), 8);
|
||||
},
|
||||
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
.many_mut_pointer,
|
||||
.c_const_pointer,
|
||||
.c_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
.optional_single_mut_pointer,
|
||||
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
.pointer,
|
||||
=> {
|
||||
if (self.elemType().hasCodeGenBits()) return 0;
|
||||
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),
|
||||
@ -931,6 +998,8 @@ pub const Type = extern union {
|
||||
.single_mut_pointer,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
=> true,
|
||||
|
||||
.pointer => self.cast(Payload.Pointer).?.size == .One,
|
||||
};
|
||||
}
|
||||
|
||||
@ -994,6 +1063,8 @@ pub const Type = extern union {
|
||||
=> false,
|
||||
|
||||
.const_slice_u8 => true,
|
||||
|
||||
.pointer => self.cast(Payload.Pointer).?.size == .Slice,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1058,6 +1129,8 @@ pub const Type = extern union {
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.const_slice_u8,
|
||||
=> true,
|
||||
|
||||
.pointer => !self.cast(Payload.Pointer).?.mutable,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1120,6 +1193,11 @@ pub const Type = extern union {
|
||||
.optional_single_const_pointer,
|
||||
.enum_literal,
|
||||
=> false,
|
||||
|
||||
.pointer => {
|
||||
const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise);
|
||||
return payload.@"volatile";
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -1237,6 +1315,7 @@ pub const Type = extern union {
|
||||
.c_mut_pointer => self.castPointer().?.pointee_type,
|
||||
.array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
|
||||
.single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
|
||||
.pointer => self.cast(Payload.Pointer).?.pointee_type,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1325,6 +1404,7 @@ pub const Type = extern union {
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.function,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1389,6 +1469,7 @@ pub const Type = extern union {
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.function,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1443,6 +1524,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1508,6 +1590,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1573,6 +1656,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1636,6 +1720,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1728,6 +1813,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1796,6 +1882,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1863,6 +1950,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1930,6 +2018,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -1994,6 +2083,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -2058,6 +2148,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -2142,6 +2233,7 @@ pub const Type = extern union {
|
||||
.array_sentinel,
|
||||
.array_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.pointer,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.many_const_pointer,
|
||||
@ -2241,6 +2333,10 @@ pub const Type = extern union {
|
||||
ty = ptr.pointee_type;
|
||||
continue;
|
||||
},
|
||||
.pointer => {
|
||||
ty = ty.cast(Payload.Pointer).?.pointee_type;
|
||||
continue;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -2305,6 +2401,8 @@ pub const Type = extern union {
|
||||
.c_const_pointer,
|
||||
.c_mut_pointer,
|
||||
=> return true,
|
||||
|
||||
.pointer => self.cast(Payload.Pointer).?.size == .C,
|
||||
};
|
||||
}
|
||||
|
||||
@ -2362,6 +2460,7 @@ pub const Type = extern union {
|
||||
array_u8_sentinel_0,
|
||||
array,
|
||||
array_sentinel,
|
||||
pointer,
|
||||
single_const_pointer,
|
||||
single_mut_pointer,
|
||||
many_const_pointer,
|
||||
@ -2440,6 +2539,21 @@ pub const Type = extern union {
|
||||
|
||||
child_type: Type,
|
||||
};
|
||||
|
||||
pub const Pointer = struct {
|
||||
base: Payload = .{ .tag = .pointer },
|
||||
|
||||
pointee_type: Type,
|
||||
sentinel: ?Value,
|
||||
/// If zero use pointee_type.AbiAlign()
|
||||
@"align": u32,
|
||||
bit_offset: u16,
|
||||
host_size: u16,
|
||||
@"allowzero": bool,
|
||||
mutable: bool,
|
||||
@"volatile": bool,
|
||||
size: std.builtin.TypeInfo.Pointer.Size,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -872,7 +872,7 @@ pub const Inst = struct {
|
||||
@"align": ?*Inst = null,
|
||||
align_bit_start: ?*Inst = null,
|
||||
align_bit_end: ?*Inst = null,
|
||||
@"const": bool = true,
|
||||
mutable: bool = true,
|
||||
@"volatile": bool = false,
|
||||
sentinel: ?*Inst = null,
|
||||
size: std.builtin.TypeInfo.Pointer.Size = .One,
|
||||
|
||||
@ -271,6 +271,14 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type {
|
||||
return val.toType();
|
||||
}
|
||||
|
||||
fn resolveInt(mod: *Module, scope: *Scope, old_inst: *zir.Inst, dest_type: Type) !u64 {
|
||||
const new_inst = try resolveInst(mod, scope, old_inst);
|
||||
const coerced = try mod.coerce(scope, dest_type, new_inst);
|
||||
const val = try mod.resolveConstValue(scope, coerced);
|
||||
|
||||
return val.toUnsignedInt();
|
||||
}
|
||||
|
||||
pub fn resolveInstConst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!TypedValue {
|
||||
const new_inst = try resolveInst(mod, scope, old_inst);
|
||||
const val = try mod.resolveConstValue(scope, new_inst);
|
||||
@ -1322,5 +1330,42 @@ fn analyzeInstSimplePtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, m
|
||||
}
|
||||
|
||||
fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) InnerError!*Inst {
|
||||
return mod.fail(scope, inst.base.src, "TODO implement ptr_type", .{});
|
||||
// TODO lazy values
|
||||
const @"align" = if (inst.kw_args.@"align") |some|
|
||||
@truncate(u32, try resolveInt(mod, scope, some, Type.initTag(.u32)))
|
||||
else
|
||||
0;
|
||||
const bit_offset = if (inst.kw_args.align_bit_start) |some|
|
||||
@truncate(u16, try resolveInt(mod, scope, some, Type.initTag(.u16)))
|
||||
else
|
||||
0;
|
||||
const host_size = if (inst.kw_args.align_bit_end) |some|
|
||||
@truncate(u16, try resolveInt(mod, scope, some, Type.initTag(.u16)))
|
||||
else
|
||||
0;
|
||||
|
||||
if (host_size != 0 and bit_offset >= host_size * 8)
|
||||
return mod.fail(scope, inst.base.src, "bit offset starts after end of host integer", .{});
|
||||
|
||||
const sentinel = if (inst.kw_args.sentinel) |some|
|
||||
(try resolveInstConst(mod, scope, some)).val
|
||||
else
|
||||
null;
|
||||
|
||||
const elem_type = try resolveType(mod, scope, inst.positionals.child_type);
|
||||
|
||||
const ty = try mod.ptrType(
|
||||
scope,
|
||||
inst.base.src,
|
||||
elem_type,
|
||||
sentinel,
|
||||
@"align",
|
||||
bit_offset,
|
||||
host_size,
|
||||
inst.kw_args.mutable,
|
||||
inst.kw_args.@"allowzero",
|
||||
inst.kw_args.@"volatile",
|
||||
inst.kw_args.size,
|
||||
);
|
||||
return mod.constType(scope, inst.base.src, ty);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user