aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-07-27 14:06:42 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-07-27 14:19:53 -0700
commita8e964eadd3496330043985cacaaee7db92886c6 (patch)
tree57768a2f87b76b9f80231ab924d2bdb481a22d2a /src/value.zig
parentba71b96fe6c0e01b8445a2f7bd49541a07c360db (diff)
downloadzig-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.zig73
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,