diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-12 21:26:59 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-12 21:38:46 -0700 |
| commit | a3104a4a78089f3260c0dd3f4a96012c6d73a63b (patch) | |
| tree | 63d73840d9d48d09cd27c3fef5e52f051a2dc4bd /src/type.zig | |
| parent | 7f006287ae89b97ff0ca977f64744ea344ec94fd (diff) | |
| download | zig-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.zig | 64 |
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); |
