aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-09-15 14:46:31 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-09-15 14:51:08 -0700
commitf3ebfcae3882c03da84821abed40167ea07a8c78 (patch)
treef1b759c94cba5b020a9ffb141fc62cb686fc5f04 /src/value.zig
parent111a2dcf3ad53c0c8ad2c9e7c9bd042b81e90c82 (diff)
parent0395b35cee8d4082cc40b0dcd0298f797f42309d (diff)
downloadzig-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.zig133
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 {