aboutsummaryrefslogtreecommitdiff
path: root/src/arch/wasm/CodeGen.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-08-21 14:27:34 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-08-22 13:54:14 -0700
commitada0010471163a3accca8976185fbb6bb59c914f (patch)
treed5035071ea3cb73677e381c0052e137fded064ac /src/arch/wasm/CodeGen.zig
parent6a5463951f0aa11cbdd5575cc78e85cd2ed10b46 (diff)
downloadzig-ada0010471163a3accca8976185fbb6bb59c914f.tar.gz
zig-ada0010471163a3accca8976185fbb6bb59c914f.zip
compiler: move unions into InternPool
There are a couple concepts here worth understanding: Key.UnionType - This type is available *before* resolving the union's fields. The enum tag type, number of fields, and field names, field types, and field alignments are not available with this. InternPool.UnionType - This one can be obtained from the above type with `InternPool.loadUnionType` which asserts that the union's enum tag type has been resolved. This one has all the information available. Additionally: * ZIR: Turn an unused bit into `any_aligned_fields` flag to help semantic analysis know whether a union has explicit alignment on any fields (usually not). * Sema: delete `resolveTypeRequiresComptime` which had the same type signature and near-duplicate logic to `typeRequiresComptime`. - Make opaque types not report comptime-only (this was inconsistent between the two implementations of this function). * Implement accepted proposal #12556 which is a breaking change.
Diffstat (limited to 'src/arch/wasm/CodeGen.zig')
-rw-r--r--src/arch/wasm/CodeGen.zig62
1 files changed, 33 insertions, 29 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 98fe8c8b7c..2fd5a50d0b 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -1717,6 +1717,7 @@ fn arch(func: *const CodeGen) std.Target.Cpu.Arch {
/// For a given `Type`, will return true when the type will be passed
/// by reference, rather than by value
fn isByRef(ty: Type, mod: *Module) bool {
+ const ip = &mod.intern_pool;
const target = mod.getTarget();
switch (ty.zigTypeTag(mod)) {
.Type,
@@ -1742,7 +1743,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
=> return ty.hasRuntimeBitsIgnoreComptime(mod),
.Union => {
if (mod.typeToUnion(ty)) |union_obj| {
- if (union_obj.layout == .Packed) {
+ if (union_obj.getLayout(ip) == .Packed) {
return ty.abiSize(mod) > 8;
}
}
@@ -2974,7 +2975,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
.Union => switch (parent_ty.containerLayout(mod)) {
.Packed => 0,
else => blk: {
- const layout: Module.Union.Layout = parent_ty.unionGetLayout(mod);
+ const layout: Module.UnionLayout = parent_ty.unionGetLayout(mod);
if (layout.payload_size == 0) break :blk 0;
if (layout.payload_align > layout.tag_align) break :blk 0;
@@ -3058,8 +3059,9 @@ fn toTwosComplement(value: anytype, bits: u7) std.meta.Int(.unsigned, @typeInfo(
fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
const mod = func.bin_file.base.options.module.?;
+ const ip = &mod.intern_pool;
var val = arg_val;
- switch (mod.intern_pool.indexToKey(val.ip_index)) {
+ switch (ip.indexToKey(val.ip_index)) {
.runtime_value => |rt| val = rt.val.toValue(),
else => {},
}
@@ -3110,7 +3112,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
=> unreachable, // comptime-only types
};
- switch (mod.intern_pool.indexToKey(val.ip_index)) {
+ switch (ip.indexToKey(val.ip_index)) {
.int_type,
.ptr_type,
.array_type,
@@ -3198,7 +3200,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});
},
.enum_tag => |enum_tag| {
- const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
+ const int_tag_ty = ip.typeOf(enum_tag.int);
return func.lowerConstant(enum_tag.int.toValue(), int_tag_ty.toType());
},
.float => |float| switch (float.storage) {
@@ -3210,7 +3212,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
.ptr => |ptr| switch (ptr.addr) {
.decl => |decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl, 0),
.mut_decl => |mut_decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, mut_decl.decl, 0),
- .int => |int| return func.lowerConstant(int.toValue(), mod.intern_pool.typeOf(int).toType()),
+ .int => |int| return func.lowerConstant(int.toValue(), ip.typeOf(int).toType()),
.opt_payload, .elem, .field => return func.lowerParentPtr(val, 0),
else => return func.fail("Wasm TODO: lowerConstant for other const addr tag {}", .{ptr.addr}),
},
@@ -3224,7 +3226,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
} else {
return WValue{ .imm32 = @intFromBool(!val.isNull(mod)) };
},
- .aggregate => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
+ .aggregate => switch (ip.indexToKey(ty.ip_index)) {
.array_type => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(mod)}),
.vector_type => {
assert(determineSimdStoreStrategy(ty, mod) == .direct);
@@ -3245,11 +3247,12 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
},
else => unreachable,
},
- .un => |union_obj| {
+ .un => |un| {
// in this case we have a packed union which will not be passed by reference.
- const field_index = ty.unionTagFieldIndex(union_obj.tag.toValue(), func.bin_file.base.options.module.?).?;
- const field_ty = ty.unionFields(mod).values()[field_index].ty;
- return func.lowerConstant(union_obj.val.toValue(), field_ty);
+ const union_obj = mod.typeToUnion(ty).?;
+ const field_index = mod.unionTagFieldIndex(union_obj, un.tag.toValue()).?;
+ const field_ty = union_obj.field_types.get(ip)[field_index].toType();
+ return func.lowerConstant(un.val.toValue(), field_ty);
},
.memoized_call => unreachable,
}
@@ -5163,6 +5166,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const mod = func.bin_file.base.options.module.?;
+ const ip = &mod.intern_pool;
const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
const extra = func.air.extraData(Air.UnionInit, ty_pl.payload).data;
@@ -5170,8 +5174,8 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const union_ty = func.typeOfIndex(inst);
const layout = union_ty.unionGetLayout(mod);
const union_obj = mod.typeToUnion(union_ty).?;
- const field = union_obj.fields.values()[extra.field_index];
- const field_name = union_obj.fields.keys()[extra.field_index];
+ const field_ty = union_obj.field_types.get(ip)[extra.field_index].toType();
+ const field_name = union_obj.field_names.get(ip)[extra.field_index];
const tag_int = blk: {
const tag_ty = union_ty.unionTagTypeHypothetical(mod);
@@ -5191,24 +5195,24 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const result_ptr = try func.allocStack(union_ty);
const payload = try func.resolveInst(extra.init);
if (layout.tag_align >= layout.payload_align) {
- if (isByRef(field.ty, mod)) {
+ if (isByRef(field_ty, mod)) {
const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new);
- try func.store(payload_ptr, payload, field.ty, 0);
+ try func.store(payload_ptr, payload, field_ty, 0);
} else {
- try func.store(result_ptr, payload, field.ty, @as(u32, @intCast(layout.tag_size)));
+ try func.store(result_ptr, payload, field_ty, @intCast(layout.tag_size));
}
if (layout.tag_size > 0) {
- try func.store(result_ptr, tag_int, union_obj.tag_ty, 0);
+ try func.store(result_ptr, tag_int, union_obj.enum_tag_ty.toType(), 0);
}
} else {
- try func.store(result_ptr, payload, field.ty, 0);
+ try func.store(result_ptr, payload, field_ty, 0);
if (layout.tag_size > 0) {
try func.store(
result_ptr,
tag_int,
- union_obj.tag_ty,
- @as(u32, @intCast(layout.payload_size)),
+ union_obj.enum_tag_ty.toType(),
+ @intCast(layout.payload_size),
);
}
}
@@ -5216,18 +5220,18 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
} else {
const operand = try func.resolveInst(extra.init);
const union_int_type = try mod.intType(.unsigned, @as(u16, @intCast(union_ty.bitSize(mod))));
- if (field.ty.zigTypeTag(mod) == .Float) {
- const int_type = try mod.intType(.unsigned, @as(u16, @intCast(field.ty.bitSize(mod))));
- const bitcasted = try func.bitcast(field.ty, int_type, operand);
+ if (field_ty.zigTypeTag(mod) == .Float) {
+ const int_type = try mod.intType(.unsigned, @intCast(field_ty.bitSize(mod)));
+ const bitcasted = try func.bitcast(field_ty, int_type, operand);
const casted = try func.trunc(bitcasted, int_type, union_int_type);
- break :result try casted.toLocal(func, field.ty);
- } else if (field.ty.isPtrAtRuntime(mod)) {
- const int_type = try mod.intType(.unsigned, @as(u16, @intCast(field.ty.bitSize(mod))));
+ break :result try casted.toLocal(func, field_ty);
+ } else if (field_ty.isPtrAtRuntime(mod)) {
+ const int_type = try mod.intType(.unsigned, @intCast(field_ty.bitSize(mod)));
const casted = try func.intcast(operand, int_type, union_int_type);
- break :result try casted.toLocal(func, field.ty);
+ break :result try casted.toLocal(func, field_ty);
}
- const casted = try func.intcast(operand, field.ty, union_int_type);
- break :result try casted.toLocal(func, field.ty);
+ const casted = try func.intcast(operand, field_ty, union_int_type);
+ break :result try casted.toLocal(func, field_ty);
}
};