diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-07-27 14:06:42 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-07-27 14:19:53 -0700 |
| commit | a8e964eadd3496330043985cacaaee7db92886c6 (patch) | |
| tree | 57768a2f87b76b9f80231ab924d2bdb481a22d2a /src/value.zig | |
| parent | ba71b96fe6c0e01b8445a2f7bd49541a07c360db (diff) | |
| download | zig-a8e964eadd3496330043985cacaaee7db92886c6.tar.gz zig-a8e964eadd3496330043985cacaaee7db92886c6.zip | |
stage2: `zig test` now works with the LLVM backend
Frontend improvements:
* When compiling in `zig test` mode, put a task on the work queue to
analyze the main package root file. Normally, start code does
`_ = import("root");` to make Zig analyze the user's code, however in
the case of `zig test`, the root source file is the test runner.
Without this change, no tests are picked up.
* In the main pipeline, once semantic analysis is finished, if there
are no compile errors, populate the `test_functions` Decl with the
set of test functions picked up from semantic analysis.
* Value: add `array` and `slice` Tags.
LLVM backend improvements:
* Fix incremental updates of globals. Previously the
value of a global would not get replaced with a new value.
* Fix LLVM type of arrays. They were incorrectly sending
the ABI size as the element count.
* Remove the FuncGen parameter from genTypedValue. This function is for
generating global constants and there is no function available when
it is being called.
- The `ref_val` case is now commented out. I'd like to eliminate
`ref_val` as one of the possible Value Tags. Instead it should
always be done via `decl_ref`.
* Implement constant value generation for slices, arrays, and structs.
* Constant value generation for functions supports the `decl_ref` tag.
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 73 |
1 files changed, 68 insertions, 5 deletions
diff --git a/src/value.zig b/src/value.zig index abb2ea7b1e..fc34473921 100644 --- a/src/value.zig +++ b/src/value.zig @@ -112,6 +112,10 @@ pub const Value = extern union { /// This value is repeated some number of times. The amount of times to repeat /// is stored externally. repeated, + /// Each element stored as a `Value`. + array, + /// Pointer and length as sub `Value` objects. + slice, float_16, float_32, float_64, @@ -217,6 +221,9 @@ pub const Value = extern union { .enum_literal, => Payload.Bytes, + .array => Payload.Array, + .slice => Payload.Slice, + .enum_field_index => Payload.U32, .ty => Payload.Ty, @@ -442,6 +449,28 @@ pub const Value = extern union { }; return Value{ .ptr_otherwise = &new_payload.base }; }, + .array => { + const payload = self.castTag(.array).?; + const new_payload = try allocator.create(Payload.Array); + new_payload.* = .{ + .base = payload.base, + .data = try allocator.alloc(Value, payload.data.len), + }; + std.mem.copy(Value, new_payload.data, payload.data); + return Value{ .ptr_otherwise = &new_payload.base }; + }, + .slice => { + const payload = self.castTag(.slice).?; + const new_payload = try allocator.create(Payload.Slice); + new_payload.* = .{ + .base = payload.base, + .data = .{ + .ptr = try payload.data.ptr.copy(allocator), + .len = try payload.data.len.copy(allocator), + }, + }; + return Value{ .ptr_otherwise = &new_payload.base }; + }, .float_16 => return self.copyPayloadShallow(allocator, Payload.Float_16), .float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32), .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64), @@ -605,6 +634,8 @@ pub const Value = extern union { try out_stream.writeAll("(repeated) "); val = val.castTag(.repeated).?.data; }, + .array => return out_stream.writeAll("(array)"), + .slice => return out_stream.writeAll("(slice)"), .float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}), .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}), .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}), @@ -729,6 +760,8 @@ pub const Value = extern union { .field_ptr, .bytes, .repeated, + .array, + .slice, .float_16, .float_32, .float_64, @@ -1075,6 +1108,8 @@ pub const Value = extern union { return orderAgainstZero(lhs).compare(op); } + /// TODO we can't compare value equality without also knowing the type to treat + /// the values as pub fn eql(a: Value, b: Value) bool { const a_tag = a.tag(); const b_tag = b.tag(); @@ -1109,6 +1144,8 @@ pub const Value = extern union { return @truncate(u32, self.hash()); } + /// TODO we can't hash without also knowing the type of the value. + /// we have to hash as if there were a canonical value memory layout. pub fn hash(self: Value) u64 { var hasher = std.hash.Wyhash.init(0); @@ -1203,6 +1240,15 @@ pub const Value = extern union { const payload = self.castTag(.bytes).?; hasher.update(payload.data); }, + .repeated => { + @panic("TODO Value.hash for repeated"); + }, + .array => { + @panic("TODO Value.hash for array"); + }, + .slice => { + @panic("TODO Value.hash for slice"); + }, .int_u64 => { const payload = self.castTag(.int_u64).?; std.hash.autoHash(&hasher, payload.data); @@ -1211,10 +1257,6 @@ pub const Value = extern union { const payload = self.castTag(.int_i64).?; std.hash.autoHash(&hasher, payload.data); }, - .repeated => { - const payload = self.castTag(.repeated).?; - std.hash.autoHash(&hasher, payload.data.hash()); - }, .ref_val => { const payload = self.castTag(.ref_val).?; std.hash.autoHash(&hasher, payload.data.hash()); @@ -1340,6 +1382,8 @@ pub const Value = extern union { return switch (val.tag()) { .empty_array => 0, .bytes => val.castTag(.bytes).?.data.len, + .array => val.castTag(.array).?.data.len, + .slice => val.castTag(.slice).?.data.len.toUnsignedInt(), .ref_val => sliceLen(val.castTag(.ref_val).?.data), .decl_ref => { const decl = val.castTag(.decl_ref).?.data; @@ -1364,6 +1408,9 @@ pub const Value = extern union { // No matter the index; all the elements are the same! .repeated => return self.castTag(.repeated).?.data, + .array => return self.castTag(.array).?.data[index], + .slice => return self.castTag(.slice).?.data.ptr.elemValue(allocator, index), + else => unreachable, } } @@ -1450,7 +1497,8 @@ pub const Value = extern union { } /// Valid for all types. Asserts the value is not undefined. - pub fn isType(self: Value) bool { + /// TODO this function is a code smell and should be deleted + fn isType(self: Value) bool { return switch (self.tag()) { .ty, .int_type, @@ -1528,6 +1576,8 @@ pub const Value = extern union { .field_ptr, .bytes, .repeated, + .array, + .slice, .float_16, .float_32, .float_64, @@ -1638,6 +1688,19 @@ pub const Value = extern union { data: []const u8, }; + pub const Array = struct { + base: Payload, + data: []Value, + }; + + pub const Slice = struct { + base: Payload, + data: struct { + ptr: Value, + len: Value, + }, + }; + pub const Ty = struct { base: Payload, data: Type, |
