mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
link.Wasm: reserve sufficient capacity for @tagName function code
Resolves: https://codeberg.org/ziglang/zig/issues/30748
This commit is contained in:
@@ -48,7 +48,6 @@ stage3-debug/bin/zig build test docs \
|
||||
--maxrss ${ZSF_MAX_RSS:-0} \
|
||||
-Dstatic-llvm \
|
||||
-Dskip-non-native \
|
||||
-Dskip-test-incremental \
|
||||
-Dtarget=native-native-musl \
|
||||
--search-prefix "$PREFIX" \
|
||||
--zig-lib-dir "$PWD/../lib" \
|
||||
|
||||
@@ -48,7 +48,6 @@ stage3-release/bin/zig build test docs \
|
||||
--maxrss ${ZSF_MAX_RSS:-0} \
|
||||
-Dstatic-llvm \
|
||||
-Dskip-non-native \
|
||||
-Dskip-test-incremental \
|
||||
-Dtarget=native-native-musl \
|
||||
--search-prefix "$PREFIX" \
|
||||
--zig-lib-dir "$PWD/../lib" \
|
||||
|
||||
+92
-71
@@ -1871,13 +1871,21 @@ fn emitTagNameFunction(
|
||||
const enum_type = ip.loadEnumType(enum_type_ip);
|
||||
const tag_values = enum_type.values.get(ip);
|
||||
|
||||
try code.ensureUnusedCapacity(gpa, 7 * 5 + 6 + 1 * 6);
|
||||
appendReservedUleb32(code, 0); // no locals
|
||||
|
||||
const slice_abi_size = 8;
|
||||
const encoded_alignment = @ctz(@as(u32, 4));
|
||||
|
||||
if (tag_values.len == 0) {
|
||||
// Then it's auto-numbered and therefore a direct table lookup.
|
||||
// Auto-numbered, therefore a direct table lookup.
|
||||
|
||||
try code.ensureUnusedCapacity(
|
||||
gpa,
|
||||
6 * @sizeOf(std.wasm.Opcode) +
|
||||
7 * 5 + // appendReservedUleb32
|
||||
1 * 6, // appendReservedI32Const
|
||||
);
|
||||
|
||||
appendReservedUleb32(code, 0); // no locals
|
||||
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));
|
||||
appendReservedUleb32(code, 0);
|
||||
|
||||
@@ -1894,78 +1902,91 @@ fn emitTagNameFunction(
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store));
|
||||
appendReservedUleb32(code, encoded_alignment);
|
||||
appendReservedUleb32(code, 0);
|
||||
} else {
|
||||
const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu);
|
||||
const outer_block_type: std.wasm.BlockType = switch (int_info.bits) {
|
||||
0...32 => .i32,
|
||||
33...64 => .i64,
|
||||
else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}),
|
||||
};
|
||||
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));
|
||||
appendReservedUleb32(code, 0);
|
||||
|
||||
// Outer block that computes table offset.
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block));
|
||||
code.appendAssumeCapacity(@intFromEnum(outer_block_type));
|
||||
|
||||
for (tag_values, 0..) |tag_value, tag_index| {
|
||||
// block for this if case
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block));
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty));
|
||||
|
||||
// Tag value whose name should be returned.
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));
|
||||
appendReservedUleb32(code, 1);
|
||||
|
||||
const val: Zcu.Value = .fromInterned(tag_value);
|
||||
switch (outer_block_type) {
|
||||
.i32 => {
|
||||
const x: u32 = switch (int_info.signedness) {
|
||||
.signed => @bitCast(@as(i32, @intCast(val.toSignedInt(zcu)))),
|
||||
.unsigned => @intCast(val.toUnsignedInt(zcu)),
|
||||
};
|
||||
appendReservedI32Const(code, x);
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_ne));
|
||||
},
|
||||
.i64 => {
|
||||
const x: u64 = switch (int_info.signedness) {
|
||||
.signed => @bitCast(val.toSignedInt(zcu)),
|
||||
.unsigned => val.toUnsignedInt(zcu),
|
||||
};
|
||||
appendReservedI64Const(code, x);
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_ne));
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
// if they're not equal, break out of current branch
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_if));
|
||||
appendReservedUleb32(code, 0);
|
||||
|
||||
// Put the table offset of the result on the stack.
|
||||
appendReservedI32Const(code, @intCast(tag_index * slice_abi_size));
|
||||
|
||||
// break outside blocks
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br));
|
||||
appendReservedUleb32(code, 1);
|
||||
|
||||
// end the block for this case
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));
|
||||
}
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.@"unreachable"));
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));
|
||||
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_load));
|
||||
appendReservedUleb32(code, encoded_alignment);
|
||||
appendReservedUleb32(code, table_base_addr + table_index * 8);
|
||||
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store));
|
||||
appendReservedUleb32(code, encoded_alignment);
|
||||
appendReservedUleb32(code, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// End of the function body
|
||||
const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu);
|
||||
const outer_block_type: std.wasm.BlockType = switch (int_info.bits) {
|
||||
0...32 => .i32,
|
||||
33...64 => .i64,
|
||||
else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}),
|
||||
};
|
||||
|
||||
try code.ensureUnusedCapacity(
|
||||
gpa,
|
||||
(7 + tag_values.len * 6) * @sizeOf(std.wasm.Opcode) +
|
||||
(1 + tag_values.len * 1) * @sizeOf(std.wasm.BlockType) +
|
||||
(6 + tag_values.len * 3) * 5 + // appendReservedUleb32
|
||||
(tag_values.len * 2) * 11, // appendReservedI32Const / appendReservedI64Const
|
||||
);
|
||||
|
||||
appendReservedUleb32(code, 0); // no locals
|
||||
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));
|
||||
appendReservedUleb32(code, 0);
|
||||
|
||||
// Outer block that computes table offset.
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block));
|
||||
code.appendAssumeCapacity(@intFromEnum(outer_block_type));
|
||||
|
||||
for (tag_values, 0..) |tag_value, tag_index| {
|
||||
// block for this if case
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block));
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty));
|
||||
|
||||
// Tag value whose name should be returned.
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get));
|
||||
appendReservedUleb32(code, 1);
|
||||
|
||||
const val: Zcu.Value = .fromInterned(tag_value);
|
||||
switch (outer_block_type) {
|
||||
.i32 => {
|
||||
const x: u32 = switch (int_info.signedness) {
|
||||
.signed => @bitCast(@as(i32, @intCast(val.toSignedInt(zcu)))),
|
||||
.unsigned => @intCast(val.toUnsignedInt(zcu)),
|
||||
};
|
||||
appendReservedI32Const(code, x);
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_ne));
|
||||
},
|
||||
.i64 => {
|
||||
const x: u64 = switch (int_info.signedness) {
|
||||
.signed => @bitCast(val.toSignedInt(zcu)),
|
||||
.unsigned => val.toUnsignedInt(zcu),
|
||||
};
|
||||
appendReservedI64Const(code, x);
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_ne));
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
// if they're not equal, break out of current branch
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_if));
|
||||
appendReservedUleb32(code, 0);
|
||||
|
||||
// Put the table offset of the result on the stack.
|
||||
appendReservedI32Const(code, @intCast(tag_index * slice_abi_size));
|
||||
|
||||
// break outside blocks
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br));
|
||||
appendReservedUleb32(code, 1);
|
||||
|
||||
// end the block for this case
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));
|
||||
}
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.@"unreachable"));
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));
|
||||
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_load));
|
||||
appendReservedUleb32(code, encoded_alignment);
|
||||
appendReservedUleb32(code, table_base_addr + table_index * 8);
|
||||
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store));
|
||||
appendReservedUleb32(code, encoded_alignment);
|
||||
appendReservedUleb32(code, 0);
|
||||
|
||||
code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user