Commit 9568248450
Changed files (5)
src-self-hosted
src-self-hosted/astgen.zig
@@ -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);
src-self-hosted/Module.zig
@@ -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: {
src-self-hosted/type.zig
@@ -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,
+ };
};
};
src-self-hosted/zir.zig
@@ -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,
src-self-hosted/zir_sema.zig
@@ -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);
}