diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-09-15 14:46:31 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-09-15 14:51:08 -0700 |
| commit | f3ebfcae3882c03da84821abed40167ea07a8c78 (patch) | |
| tree | f1b759c94cba5b020a9ffb141fc62cb686fc5f04 /src/value.zig | |
| parent | 111a2dcf3ad53c0c8ad2c9e7c9bd042b81e90c82 (diff) | |
| parent | 0395b35cee8d4082cc40b0dcd0298f797f42309d (diff) | |
| download | zig-f3ebfcae3882c03da84821abed40167ea07a8c78.tar.gz zig-f3ebfcae3882c03da84821abed40167ea07a8c78.zip | |
Merge remote-tracking branch 'origin/master' into llvm13
Conflicts:
* cmake/Findclang.cmake
* cmake/Findlld.cmake
* cmake/Findllvm.cmake
In master branch, more search paths were added to these files with "12"
in the path. In this commit I updated them to "13".
* src/stage1/codegen.cpp
* src/zig_llvm.cpp
* src/zig_llvm.h
In master branch, ZigLLVMBuildCmpXchg is improved to add
`is_single_threaded`. However, the LLVM 13 C API has this already, and
in the llvm13 branch, ZigLLVMBuildCmpXchg is deleted in favor of the C
API. In this commit I updated stage2 to use the LLVM 13 C API rather
than depending on an improved ZigLLVMBuildCmpXchg.
Additionally, src/target.zig largestAtomicBits needed to be updated to
include the new m68k ISA.
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 133 |
1 files changed, 80 insertions, 53 deletions
diff --git a/src/value.zig b/src/value.zig index 5ac9f142c4..88d0d04086 100644 --- a/src/value.zig +++ b/src/value.zig @@ -17,10 +17,10 @@ const Air = @import("Air.zig"); pub const Value = extern union { /// If the tag value is less than Tag.no_payload_count, then no pointer /// dereference is needed. - tag_if_small_enough: usize, + tag_if_small_enough: Tag, ptr_otherwise: *Payload, - pub const Tag = enum { + pub const Tag = enum(usize) { // The first section of this enum are tags that require no payload. u1_type, u8_type, @@ -60,7 +60,7 @@ pub const Value = extern union { null_type, undefined_type, enum_literal_type, - atomic_ordering_type, + atomic_order_type, atomic_rmw_op_type, calling_convention_type, float_mode_type, @@ -223,7 +223,7 @@ pub const Value = extern union { .abi_align_default, .manyptr_u8_type, .manyptr_const_u8_type, - .atomic_ordering_type, + .atomic_order_type, .atomic_rmw_op_type, .calling_convention_type, .float_mode_type, @@ -296,7 +296,7 @@ pub const Value = extern union { pub fn initTag(small_tag: Tag) Value { assert(@enumToInt(small_tag) < Tag.no_payload_count); - return .{ .tag_if_small_enough = @enumToInt(small_tag) }; + return .{ .tag_if_small_enough = small_tag }; } pub fn initPayload(payload: *Payload) Value { @@ -305,8 +305,8 @@ pub const Value = extern union { } pub fn tag(self: Value) Tag { - if (self.tag_if_small_enough < Tag.no_payload_count) { - return @intToEnum(Tag, @intCast(std.meta.Tag(Tag), self.tag_if_small_enough)); + if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) { + return self.tag_if_small_enough; } else { return self.ptr_otherwise.tag; } @@ -315,9 +315,9 @@ pub const Value = extern union { /// Prefer `castTag` to this. pub fn cast(self: Value, comptime T: type) ?*T { if (@hasField(T, "base_tag")) { - return base.castTag(T.base_tag); + return self.castTag(T.base_tag); } - if (self.tag_if_small_enough < Tag.no_payload_count) { + if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) { return null; } inline for (@typeInfo(Tag).Enum.fields) |field| { @@ -335,7 +335,7 @@ pub const Value = extern union { } pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() { - if (self.tag_if_small_enough < Tag.no_payload_count) + if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) return null; if (self.ptr_otherwise.tag == t) @@ -344,8 +344,10 @@ pub const Value = extern union { return null; } - pub fn copy(self: Value, allocator: *Allocator) error{OutOfMemory}!Value { - if (self.tag_if_small_enough < Tag.no_payload_count) { + /// It's intentional that this function is not passed a corresponding Type, so that + /// a Value can be copied from a Sema to a Decl prior to resolving struct/union field types. + pub fn copy(self: Value, arena: *Allocator) error{OutOfMemory}!Value { + if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) { return Value{ .tag_if_small_enough = self.tag_if_small_enough }; } else switch (self.ptr_otherwise.tag) { .u1_type, @@ -407,7 +409,7 @@ pub const Value = extern union { .abi_align_default, .manyptr_u8_type, .manyptr_const_u8_type, - .atomic_ordering_type, + .atomic_order_type, .atomic_rmw_op_type, .calling_convention_type, .float_mode_type, @@ -421,37 +423,37 @@ pub const Value = extern union { .ty => { const payload = self.castTag(.ty).?; - const new_payload = try allocator.create(Payload.Ty); + const new_payload = try arena.create(Payload.Ty); new_payload.* = .{ .base = payload.base, - .data = try payload.data.copy(allocator), + .data = try payload.data.copy(arena), }; return Value{ .ptr_otherwise = &new_payload.base }; }, - .int_type => return self.copyPayloadShallow(allocator, Payload.IntType), - .int_u64 => return self.copyPayloadShallow(allocator, Payload.U64), - .int_i64 => return self.copyPayloadShallow(allocator, Payload.I64), + .int_type => return self.copyPayloadShallow(arena, Payload.IntType), + .int_u64 => return self.copyPayloadShallow(arena, Payload.U64), + .int_i64 => return self.copyPayloadShallow(arena, Payload.I64), .int_big_positive, .int_big_negative => { const old_payload = self.cast(Payload.BigInt).?; - const new_payload = try allocator.create(Payload.BigInt); + const new_payload = try arena.create(Payload.BigInt); new_payload.* = .{ .base = .{ .tag = self.ptr_otherwise.tag }, - .data = try allocator.dupe(std.math.big.Limb, old_payload.data), + .data = try arena.dupe(std.math.big.Limb, old_payload.data), }; return Value{ .ptr_otherwise = &new_payload.base }; }, - .function => return self.copyPayloadShallow(allocator, Payload.Function), - .extern_fn => return self.copyPayloadShallow(allocator, Payload.Decl), - .variable => return self.copyPayloadShallow(allocator, Payload.Variable), - .decl_ref => return self.copyPayloadShallow(allocator, Payload.Decl), - .decl_ref_mut => return self.copyPayloadShallow(allocator, Payload.DeclRefMut), + .function => return self.copyPayloadShallow(arena, Payload.Function), + .extern_fn => return self.copyPayloadShallow(arena, Payload.Decl), + .variable => return self.copyPayloadShallow(arena, Payload.Variable), + .decl_ref => return self.copyPayloadShallow(arena, Payload.Decl), + .decl_ref_mut => return self.copyPayloadShallow(arena, Payload.DeclRefMut), .elem_ptr => { const payload = self.castTag(.elem_ptr).?; - const new_payload = try allocator.create(Payload.ElemPtr); + const new_payload = try arena.create(Payload.ElemPtr); new_payload.* = .{ .base = payload.base, .data = .{ - .array_ptr = try payload.data.array_ptr.copy(allocator), + .array_ptr = try payload.data.array_ptr.copy(arena), .index = payload.data.index, }, }; @@ -459,17 +461,17 @@ pub const Value = extern union { }, .field_ptr => { const payload = self.castTag(.field_ptr).?; - const new_payload = try allocator.create(Payload.FieldPtr); + const new_payload = try arena.create(Payload.FieldPtr); new_payload.* = .{ .base = payload.base, .data = .{ - .container_ptr = try payload.data.container_ptr.copy(allocator), + .container_ptr = try payload.data.container_ptr.copy(arena), .field_index = payload.data.field_index, }, }; return Value{ .ptr_otherwise = &new_payload.base }; }, - .bytes => return self.copyPayloadShallow(allocator, Payload.Bytes), + .bytes => return self.copyPayloadShallow(arena, Payload.Bytes), .repeated, .eu_payload, .eu_payload_ptr, @@ -477,61 +479,85 @@ pub const Value = extern union { .opt_payload_ptr, => { const payload = self.cast(Payload.SubValue).?; - const new_payload = try allocator.create(Payload.SubValue); + const new_payload = try arena.create(Payload.SubValue); new_payload.* = .{ .base = payload.base, - .data = try payload.data.copy(allocator), + .data = try payload.data.copy(arena), }; return Value{ .ptr_otherwise = &new_payload.base }; }, .array => { const payload = self.castTag(.array).?; - const new_payload = try allocator.create(Payload.Array); + const new_payload = try arena.create(Payload.Array); new_payload.* = .{ .base = payload.base, - .data = try allocator.alloc(Value, payload.data.len), + .data = try arena.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); + const new_payload = try arena.create(Payload.Slice); new_payload.* = .{ .base = payload.base, .data = .{ - .ptr = try payload.data.ptr.copy(allocator), - .len = try payload.data.len.copy(allocator), + .ptr = try payload.data.ptr.copy(arena), + .len = try payload.data.len.copy(arena), }, }; 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), - .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128), + .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16), + .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32), + .float_64 => return self.copyPayloadShallow(arena, Payload.Float_64), + .float_128 => return self.copyPayloadShallow(arena, Payload.Float_128), .enum_literal => { const payload = self.castTag(.enum_literal).?; - const new_payload = try allocator.create(Payload.Bytes); + const new_payload = try arena.create(Payload.Bytes); new_payload.* = .{ .base = payload.base, - .data = try allocator.dupe(u8, payload.data), + .data = try arena.dupe(u8, payload.data), + }; + return Value{ .ptr_otherwise = &new_payload.base }; + }, + .enum_field_index => return self.copyPayloadShallow(arena, Payload.U32), + .@"error" => return self.copyPayloadShallow(arena, Payload.Error), + + .@"struct" => { + const old_field_values = self.castTag(.@"struct").?.data; + const new_payload = try arena.create(Payload.Struct); + new_payload.* = .{ + .base = .{ .tag = .@"struct" }, + .data = try arena.alloc(Value, old_field_values.len), + }; + for (old_field_values) |old_field_val, i| { + new_payload.data[i] = try old_field_val.copy(arena); + } + return Value{ .ptr_otherwise = &new_payload.base }; + }, + + .@"union" => { + const tag_and_val = self.castTag(.@"union").?.data; + const new_payload = try arena.create(Payload.Union); + new_payload.* = .{ + .base = .{ .tag = .@"union" }, + .data = .{ + .tag = try tag_and_val.tag.copy(arena), + .val = try tag_and_val.val.copy(arena), + }, }; return Value{ .ptr_otherwise = &new_payload.base }; }, - .enum_field_index => return self.copyPayloadShallow(allocator, Payload.U32), - .@"error" => return self.copyPayloadShallow(allocator, Payload.Error), - .@"struct" => @panic("TODO can't copy struct value without knowing the type"), - .@"union" => @panic("TODO can't copy union value without knowing the type"), .inferred_alloc => unreachable, .inferred_alloc_comptime => unreachable, } } - fn copyPayloadShallow(self: Value, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Value { + fn copyPayloadShallow(self: Value, arena: *Allocator, comptime T: type) error{OutOfMemory}!Value { const payload = self.cast(T).?; - const new_payload = try allocator.create(T); + const new_payload = try arena.create(T); new_payload.* = payload.*; return Value{ .ptr_otherwise = &new_payload.base }; } @@ -596,7 +622,7 @@ pub const Value = extern union { .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), .manyptr_u8_type => return out_stream.writeAll("[*]u8"), .manyptr_const_u8_type => return out_stream.writeAll("[*]const u8"), - .atomic_ordering_type => return out_stream.writeAll("std.builtin.AtomicOrdering"), + .atomic_order_type => return out_stream.writeAll("std.builtin.AtomicOrder"), .atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"), .calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"), .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"), @@ -763,7 +789,7 @@ pub const Value = extern union { .enum_literal_type => Type.initTag(.enum_literal), .manyptr_u8_type => Type.initTag(.manyptr_u8), .manyptr_const_u8_type => Type.initTag(.manyptr_const_u8), - .atomic_ordering_type => Type.initTag(.atomic_ordering), + .atomic_order_type => Type.initTag(.atomic_order), .atomic_rmw_op_type => Type.initTag(.atomic_rmw_op), .calling_convention_type => Type.initTag(.calling_convention), .float_mode_type => Type.initTag(.float_mode), @@ -1932,8 +1958,9 @@ pub const Value = extern union { pub const base_tag = Tag.@"struct"; base: Payload = .{ .tag = base_tag }, - /// Field values. The number and type are according to the struct type. - data: [*]Value, + /// Field values. The types are according to the struct type. + /// The length is provided here so that copying a Value does not depend on the Type. + data: []Value, }; pub const Union = struct { |
