| ... | ... | @@ -1871,13 +1871,21 @@ fn emitTagNameFunction( |
| 1871 | 1871 | const enum_type = ip.loadEnumType(enum_type_ip); |
| 1872 | 1872 | const tag_values = enum_type.values.get(ip); |
| 1873 | 1873 | |
| 1874 | | try code.ensureUnusedCapacity(gpa, 7 * 5 + 6 + 1 * 6); |
| 1875 | | appendReservedUleb32(code, 0); // no locals |
| 1876 | | |
| 1877 | 1874 | const slice_abi_size = 8; |
| 1878 | 1875 | const encoded_alignment = @ctz(@as(u32, 4)); |
| 1876 | |
| 1879 | 1877 | if (tag_values.len == 0) { |
| 1880 | | // Then it's auto-numbered and therefore a direct table lookup. |
| 1878 | // Auto-numbered, therefore a direct table lookup. |
| 1879 | |
| 1880 | try code.ensureUnusedCapacity( |
| 1881 | gpa, |
| 1882 | 6 * @sizeOf(std.wasm.Opcode) + |
| 1883 | 7 * 5 + // appendReservedUleb32 |
| 1884 | 1 * 6, // appendReservedI32Const |
| 1885 | ); |
| 1886 | |
| 1887 | appendReservedUleb32(code, 0); // no locals |
| 1888 | |
| 1881 | 1889 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); |
| 1882 | 1890 | appendReservedUleb32(code, 0); |
| 1883 | 1891 | |
| ... | ... | @@ -1894,78 +1902,91 @@ fn emitTagNameFunction( |
| 1894 | 1902 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store)); |
| 1895 | 1903 | appendReservedUleb32(code, encoded_alignment); |
| 1896 | 1904 | appendReservedUleb32(code, 0); |
| 1897 | | } else { |
| 1898 | | const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu); |
| 1899 | | const outer_block_type: std.wasm.BlockType = switch (int_info.bits) { |
| 1900 | | 0...32 => .i32, |
| 1901 | | 33...64 => .i64, |
| 1902 | | else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}), |
| 1903 | | }; |
| 1904 | 1905 | |
| 1905 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); |
| 1906 | | appendReservedUleb32(code, 0); |
| 1906 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1907 | 1907 | |
| 1908 | | // Outer block that computes table offset. |
| 1909 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); |
| 1910 | | code.appendAssumeCapacity(@intFromEnum(outer_block_type)); |
| 1911 | | |
| 1912 | | for (tag_values, 0..) |tag_value, tag_index| { |
| 1913 | | // block for this if case |
| 1914 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); |
| 1915 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty)); |
| 1916 | | |
| 1917 | | // Tag value whose name should be returned. |
| 1918 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); |
| 1919 | | appendReservedUleb32(code, 1); |
| 1920 | | |
| 1921 | | const val: Zcu.Value = .fromInterned(tag_value); |
| 1922 | | switch (outer_block_type) { |
| 1923 | | .i32 => { |
| 1924 | | const x: u32 = switch (int_info.signedness) { |
| 1925 | | .signed => @bitCast(@as(i32, @intCast(val.toSignedInt(zcu)))), |
| 1926 | | .unsigned => @intCast(val.toUnsignedInt(zcu)), |
| 1927 | | }; |
| 1928 | | appendReservedI32Const(code, x); |
| 1929 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_ne)); |
| 1930 | | }, |
| 1931 | | .i64 => { |
| 1932 | | const x: u64 = switch (int_info.signedness) { |
| 1933 | | .signed => @bitCast(val.toSignedInt(zcu)), |
| 1934 | | .unsigned => val.toUnsignedInt(zcu), |
| 1935 | | }; |
| 1936 | | appendReservedI64Const(code, x); |
| 1937 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_ne)); |
| 1938 | | }, |
| 1939 | | else => unreachable, |
| 1940 | | } |
| 1908 | return; |
| 1909 | } |
| 1941 | 1910 | |
| 1942 | | // if they're not equal, break out of current branch |
| 1943 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_if)); |
| 1944 | | appendReservedUleb32(code, 0); |
| 1911 | const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu); |
| 1912 | const outer_block_type: std.wasm.BlockType = switch (int_info.bits) { |
| 1913 | 0...32 => .i32, |
| 1914 | 33...64 => .i64, |
| 1915 | else => return diags.fail("wasm linker does not yet implement @tagName for sparse enums with more than 64 bit integer tag types", .{}), |
| 1916 | }; |
| 1945 | 1917 | |
| 1946 | | // Put the table offset of the result on the stack. |
| 1947 | | appendReservedI32Const(code, @intCast(tag_index * slice_abi_size)); |
| 1918 | try code.ensureUnusedCapacity( |
| 1919 | gpa, |
| 1920 | (7 + tag_values.len * 6) * @sizeOf(std.wasm.Opcode) + |
| 1921 | (1 + tag_values.len * 1) * @sizeOf(std.wasm.BlockType) + |
| 1922 | (6 + tag_values.len * 3) * 5 + // appendReservedUleb32 |
| 1923 | (tag_values.len * 2) * 11, // appendReservedI32Const / appendReservedI64Const |
| 1924 | ); |
| 1948 | 1925 | |
| 1949 | | // break outside blocks |
| 1950 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br)); |
| 1951 | | appendReservedUleb32(code, 1); |
| 1926 | appendReservedUleb32(code, 0); // no locals |
| 1952 | 1927 | |
| 1953 | | // end the block for this case |
| 1954 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1955 | | } |
| 1956 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.@"unreachable")); |
| 1957 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1928 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); |
| 1929 | appendReservedUleb32(code, 0); |
| 1958 | 1930 | |
| 1959 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_load)); |
| 1960 | | appendReservedUleb32(code, encoded_alignment); |
| 1961 | | appendReservedUleb32(code, table_base_addr + table_index * 8); |
| 1931 | // Outer block that computes table offset. |
| 1932 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); |
| 1933 | code.appendAssumeCapacity(@intFromEnum(outer_block_type)); |
| 1962 | 1934 | |
| 1963 | | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store)); |
| 1964 | | appendReservedUleb32(code, encoded_alignment); |
| 1935 | for (tag_values, 0..) |tag_value, tag_index| { |
| 1936 | // block for this if case |
| 1937 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); |
| 1938 | code.appendAssumeCapacity(@intFromEnum(std.wasm.BlockType.empty)); |
| 1939 | |
| 1940 | // Tag value whose name should be returned. |
| 1941 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); |
| 1942 | appendReservedUleb32(code, 1); |
| 1943 | |
| 1944 | const val: Zcu.Value = .fromInterned(tag_value); |
| 1945 | switch (outer_block_type) { |
| 1946 | .i32 => { |
| 1947 | const x: u32 = switch (int_info.signedness) { |
| 1948 | .signed => @bitCast(@as(i32, @intCast(val.toSignedInt(zcu)))), |
| 1949 | .unsigned => @intCast(val.toUnsignedInt(zcu)), |
| 1950 | }; |
| 1951 | appendReservedI32Const(code, x); |
| 1952 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i32_ne)); |
| 1953 | }, |
| 1954 | .i64 => { |
| 1955 | const x: u64 = switch (int_info.signedness) { |
| 1956 | .signed => @bitCast(val.toSignedInt(zcu)), |
| 1957 | .unsigned => val.toUnsignedInt(zcu), |
| 1958 | }; |
| 1959 | appendReservedI64Const(code, x); |
| 1960 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_ne)); |
| 1961 | }, |
| 1962 | else => unreachable, |
| 1963 | } |
| 1964 | |
| 1965 | // if they're not equal, break out of current branch |
| 1966 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_if)); |
| 1965 | 1967 | appendReservedUleb32(code, 0); |
| 1968 | |
| 1969 | // Put the table offset of the result on the stack. |
| 1970 | appendReservedI32Const(code, @intCast(tag_index * slice_abi_size)); |
| 1971 | |
| 1972 | // break outside blocks |
| 1973 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br)); |
| 1974 | appendReservedUleb32(code, 1); |
| 1975 | |
| 1976 | // end the block for this case |
| 1977 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1966 | 1978 | } |
| 1979 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.@"unreachable")); |
| 1980 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1981 | |
| 1982 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_load)); |
| 1983 | appendReservedUleb32(code, encoded_alignment); |
| 1984 | appendReservedUleb32(code, table_base_addr + table_index * 8); |
| 1985 | |
| 1986 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store)); |
| 1987 | appendReservedUleb32(code, encoded_alignment); |
| 1988 | appendReservedUleb32(code, 0); |
| 1967 | 1989 | |
| 1968 | | // End of the function body |
| 1969 | 1990 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1970 | 1991 | } |
| 1971 | 1992 | |