diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-05-07 14:18:14 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-05-07 14:18:14 -0700 |
| commit | 47531b7d9389c45af3e46b623235792f14a40ff2 (patch) | |
| tree | 9412cb8c20a690381e58d607e6348028e19ab3d2 /src/value.zig | |
| parent | a7221ef4e902e63e72524559a067afcf6c1dfd17 (diff) | |
| download | zig-47531b7d9389c45af3e46b623235792f14a40ff2.tar.gz zig-47531b7d9389c45af3e46b623235792f14a40ff2.zip | |
Sema: support enough to check main calling convention via `@typeInfo`
After this commit, `pub export fn main() c_int { ... }` will be
correctly detected as the intended entry point, and therefore start code
will not try to export its own conflicting `main` function.
* Implement basic union support
- lots of stuff is still TODO, including runtime field access
- also TODO: resolving the union tag type
- comptime field access is implemented
* DRY up some code by using the `Zir.DeclIterator` for skipping over
decls in structs and unions.
* Start to clean up Sema with regards to calling `.value()` to find out
a const value. Instead, Sema code should call one of these two:
- `resolvePossiblyUndefinedValue` (followed by logic dealing with
undefined values)
- `resolveDefinedValue` (a compile error will be emitted if the value
is undefined)
* An exported function with an unspecified calling convention gets the
C calling convention.
* Implement comptime field access for structs.
* Add another implementation of "type has one possible value" in Sema.
This is a bit unfortunate since the logic is duplicated, but the one
in Type asserts that the types are resolved already, and is
appropriate to call from codegen, while the one in Sema performs
type resolution if necessary, reporting any compile errors that occur
in the process.
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/value.zig b/src/value.zig index 2c7002402b..65d8a8f6fa 100644 --- a/src/value.zig +++ b/src/value.zig @@ -104,6 +104,7 @@ pub const Value = extern union { /// Represents a pointer to a decl, not the value of the decl. decl_ref, elem_ptr, + field_ptr, /// A slice of u8 whose memory is managed externally. bytes, /// This value is repeated some number of times. The amount of times to repeat @@ -223,6 +224,7 @@ pub const Value = extern union { .function => Payload.Function, .variable => Payload.Variable, .elem_ptr => Payload.ElemPtr, + .field_ptr => Payload.FieldPtr, .float_16 => Payload.Float_16, .float_32 => Payload.Float_32, .float_64 => Payload.Float_64, @@ -414,6 +416,18 @@ pub const Value = extern union { }; return Value{ .ptr_otherwise = &new_payload.base }; }, + .field_ptr => { + const payload = self.castTag(.field_ptr).?; + const new_payload = try allocator.create(Payload.FieldPtr); + new_payload.* = .{ + .base = payload.base, + .data = .{ + .container_ptr = try payload.data.container_ptr.copy(allocator), + .field_index = payload.data.field_index, + }, + }; + return Value{ .ptr_otherwise = &new_payload.base }; + }, .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes), .repeated => { const payload = self.castTag(.repeated).?; @@ -569,6 +583,11 @@ pub const Value = extern union { try out_stream.print("&[{}] ", .{elem_ptr.index}); val = elem_ptr.array_ptr; }, + .field_ptr => { + const field_ptr = val.castTag(.field_ptr).?.data; + try out_stream.print("fieldptr({d}) ", .{field_ptr.field_index}); + val = field_ptr.container_ptr; + }, .empty_array => return out_stream.writeAll(".{}"), .enum_literal => return out_stream.print(".{}", .{std.zig.fmtId(self.castTag(.enum_literal).?.data)}), .enum_field_index => return out_stream.print("(enum field {d})", .{self.castTag(.enum_field_index).?.data}), @@ -704,6 +723,7 @@ pub const Value = extern union { .ref_val, .decl_ref, .elem_ptr, + .field_ptr, .bytes, .repeated, .float_16, @@ -1196,6 +1216,11 @@ pub const Value = extern union { std.hash.autoHash(&hasher, payload.array_ptr.hash()); std.hash.autoHash(&hasher, payload.index); }, + .field_ptr => { + const payload = self.castTag(.field_ptr).?.data; + std.hash.autoHash(&hasher, payload.container_ptr.hash()); + std.hash.autoHash(&hasher, payload.field_index); + }, .decl_ref => { const decl = self.castTag(.decl_ref).?.data; std.hash.autoHash(&hasher, decl); @@ -1250,6 +1275,11 @@ pub const Value = extern union { const array_val = try elem_ptr.array_ptr.pointerDeref(allocator); return array_val.elemValue(allocator, elem_ptr.index); }, + .field_ptr => { + const field_ptr = self.castTag(.field_ptr).?.data; + const container_val = try field_ptr.container_ptr.pointerDeref(allocator); + return container_val.fieldValue(allocator, field_ptr.field_index); + }, else => unreachable, }; @@ -1270,6 +1300,22 @@ pub const Value = extern union { } } + pub fn fieldValue(val: Value, allocator: *Allocator, index: usize) error{OutOfMemory}!Value { + switch (val.tag()) { + .@"struct" => { + const field_values = val.castTag(.@"struct").?.data; + return field_values[index]; + }, + .@"union" => { + const payload = val.castTag(.@"union").?.data; + // TODO assert the tag is correct + return payload.val; + }, + + else => unreachable, + } + } + /// Returns a pointer to the element value at the index. pub fn elemPtr(self: Value, allocator: *Allocator, index: usize) !Value { if (self.castTag(.elem_ptr)) |elem_ptr| { @@ -1409,6 +1455,7 @@ pub const Value = extern union { .ref_val, .decl_ref, .elem_ptr, + .field_ptr, .bytes, .repeated, .float_16, @@ -1496,6 +1543,16 @@ pub const Value = extern union { }, }; + pub const FieldPtr = struct { + pub const base_tag = Tag.field_ptr; + + base: Payload = Payload{ .tag = base_tag }, + data: struct { + container_ptr: Value, + field_index: usize, + }, + }; + pub const Bytes = struct { base: Payload, data: []const u8, |
