aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-12 21:26:59 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-12 21:38:46 -0700
commita3104a4a78089f3260c0dd3f4a96012c6d73a63b (patch)
tree63d73840d9d48d09cd27c3fef5e52f051a2dc4bd /src/type.zig
parent7f006287ae89b97ff0ca977f64744ea344ec94fd (diff)
downloadzig-a3104a4a78089f3260c0dd3f4a96012c6d73a63b.tar.gz
zig-a3104a4a78089f3260c0dd3f4a96012c6d73a63b.zip
stage2: fix comptime stores and sentinel-terminated arrays
* ZIR: the `array_type_sentinel` now has a source node attached to it for proper error reporting. * Refactor: move `Module.arrayType` to `Type.array` * Value: the `bytes` and `array` tags now include the sentinel, if the type has one. This simplifies comptime evaluation logic. * Sema: fix `zirStructInitEmpty` to properly handle when the type is void or a sentinel-terminated array. This handles the syntax `void{}` and `[0:X]T{}`. * Sema: fix the logic for reporting "cannot store runtime value in compile time variable" as well as for emitting a runtime store when a pointer value is comptime known but it is a global variable. * Sema: implement elemVal for double pointer to array. This can happen with this code for example: `var a: *[1]u8 = undefined; _ = a[0];` * Sema: Rework the `storePtrVal` function to properly handle nested structs and arrays. - Also it now handles comptime stores through a bitcasted pointer. When the pointer element type and the type according to the Decl don't match, the element value is bitcasted before storage.
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig64
1 files changed, 56 insertions, 8 deletions
diff --git a/src/type.zig b/src/type.zig
index 2abf7e9baf..814878c747 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -1468,7 +1468,19 @@ pub const Type = extern union {
// TODO lazy types
.array, .vector => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
.array_u8 => self.arrayLen() != 0,
- .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(),
+
+ .array_sentinel,
+ .single_const_pointer,
+ .single_mut_pointer,
+ .many_const_pointer,
+ .many_mut_pointer,
+ .c_const_pointer,
+ .c_mut_pointer,
+ .const_slice,
+ .mut_slice,
+ .pointer,
+ => self.childType().hasCodeGenBits(),
+
.int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0,
.error_union => {
@@ -2560,18 +2572,22 @@ pub const Type = extern union {
}
/// Asserts the type is an array or vector.
- pub fn arrayLen(self: Type) u64 {
- return switch (self.tag()) {
- .vector => self.castTag(.vector).?.data.len,
- .array => self.castTag(.array).?.data.len,
- .array_sentinel => self.castTag(.array_sentinel).?.data.len,
- .array_u8 => self.castTag(.array_u8).?.data,
- .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data,
+ pub fn arrayLen(ty: Type) u64 {
+ return switch (ty.tag()) {
+ .vector => ty.castTag(.vector).?.data.len,
+ .array => ty.castTag(.array).?.data.len,
+ .array_sentinel => ty.castTag(.array_sentinel).?.data.len,
+ .array_u8 => ty.castTag(.array_u8).?.data,
+ .array_u8_sentinel_0 => ty.castTag(.array_u8_sentinel_0).?.data,
else => unreachable,
};
}
+ pub fn arrayLenIncludingSentinel(ty: Type) u64 {
+ return ty.arrayLen() + @boolToInt(ty.sentinel() != null);
+ }
+
/// Asserts the type is an array, pointer or vector.
pub fn sentinel(self: Type) ?Value {
return switch (self.tag()) {
@@ -3882,9 +3898,11 @@ pub const Type = extern union {
};
};
+ pub const @"u8" = initTag(.u8);
pub const @"bool" = initTag(.bool);
pub const @"usize" = initTag(.usize);
pub const @"comptime_int" = initTag(.comptime_int);
+ pub const @"void" = initTag(.void);
pub fn ptr(arena: *Allocator, d: Payload.Pointer.Data) !Type {
assert(d.host_size == 0 or d.bit_offset < d.host_size * 8);
@@ -3917,6 +3935,36 @@ pub const Type = extern union {
return Type.initPayload(&type_payload.base);
}
+ pub fn array(
+ arena: *Allocator,
+ len: u64,
+ sent: ?Value,
+ elem_type: Type,
+ ) Allocator.Error!Type {
+ if (elem_type.eql(Type.u8)) {
+ if (sent) |some| {
+ if (some.eql(Value.initTag(.zero), elem_type)) {
+ return Tag.array_u8_sentinel_0.create(arena, len);
+ }
+ } else {
+ return Tag.array_u8.create(arena, len);
+ }
+ }
+
+ if (sent) |some| {
+ return Tag.array_sentinel.create(arena, .{
+ .len = len,
+ .sentinel = some,
+ .elem_type = elem_type,
+ });
+ }
+
+ return Tag.array.create(arena, .{
+ .len = len,
+ .elem_type = elem_type,
+ });
+ }
+
pub fn smallestUnsignedBits(max: u64) u16 {
if (max == 0) return 0;
const base = std.math.log2(max);