mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 15:13:08 +00:00
wasm: union_init support packed unions
This commit is contained in:
parent
128814f9bf
commit
e36cc0ce8f
@ -1014,6 +1014,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {
|
||||
.direct => wasm.Valtype.v128,
|
||||
.unrolled => wasm.Valtype.i32,
|
||||
},
|
||||
.Union => switch (ty.containerLayout()) {
|
||||
.Packed => {
|
||||
var int_ty_payload: Type.Payload.Bits = .{
|
||||
.base = .{ .tag = .int_unsigned },
|
||||
.data = @intCast(u16, ty.bitSize(target)),
|
||||
};
|
||||
const int_ty = Type.initPayload(&int_ty_payload.base);
|
||||
return typeToValtype(int_ty, target);
|
||||
},
|
||||
else => wasm.Valtype.i32,
|
||||
},
|
||||
else => wasm.Valtype.i32, // all represented as reference/immediate
|
||||
};
|
||||
}
|
||||
@ -5074,33 +5085,61 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
assert(!isByRef(union_ty, func.target));
|
||||
break :result tag_int;
|
||||
}
|
||||
assert(isByRef(union_ty, func.target));
|
||||
|
||||
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, func.target)) {
|
||||
const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new);
|
||||
try func.store(payload_ptr, payload, field.ty, 0);
|
||||
if (isByRef(union_ty, func.target)) {
|
||||
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, func.target)) {
|
||||
const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new);
|
||||
try func.store(payload_ptr, payload, field.ty, 0);
|
||||
} else {
|
||||
try func.store(result_ptr, payload, field.ty, @intCast(u32, layout.tag_size));
|
||||
}
|
||||
|
||||
if (layout.tag_size > 0) {
|
||||
try func.store(result_ptr, tag_int, union_obj.tag_ty, 0);
|
||||
}
|
||||
} else {
|
||||
try func.store(result_ptr, payload, field.ty, @intCast(u32, 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, payload, field.ty, 0);
|
||||
if (layout.tag_size > 0) {
|
||||
try func.store(
|
||||
result_ptr,
|
||||
tag_int,
|
||||
union_obj.tag_ty,
|
||||
@intCast(u32, layout.payload_size),
|
||||
);
|
||||
}
|
||||
}
|
||||
break :result result_ptr;
|
||||
} else {
|
||||
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,
|
||||
@intCast(u32, layout.payload_size),
|
||||
);
|
||||
const operand = try func.resolveInst(extra.init);
|
||||
var payload: Type.Payload.Bits = .{
|
||||
.base = .{ .tag = .int_unsigned },
|
||||
.data = @intCast(u16, union_ty.bitSize(func.target)),
|
||||
};
|
||||
const union_int_type = Type.initPayload(&payload.base);
|
||||
if (field.ty.zigTypeTag() == .Float) {
|
||||
var int_payload: Type.Payload.Bits = .{
|
||||
.base = .{ .tag = .int_unsigned },
|
||||
.data = @intCast(u16, field.ty.bitSize(func.target)),
|
||||
};
|
||||
const int_type = Type.initPayload(&int_payload.base);
|
||||
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()) {
|
||||
var int_payload: Type.Payload.Bits = .{
|
||||
.base = .{ .tag = .int_unsigned },
|
||||
.data = @intCast(u16, field.ty.bitSize(func.target)),
|
||||
};
|
||||
const int_type = Type.initPayload(&int_payload.base);
|
||||
const casted = try func.intcast(operand, int_type, 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);
|
||||
}
|
||||
break :result result_ptr;
|
||||
};
|
||||
|
||||
return func.finishAir(inst, result, &.{extra.init});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user