| ... | @@ -1871,13 +1871,21 @@ fn emitTagNameFunction( | ... | @@ -1871,13 +1871,21 @@ fn emitTagNameFunction( |
| 1871 | const enum_type = ip.loadEnumType(enum_type_ip); | 1871 | const enum_type = ip.loadEnumType(enum_type_ip); |
| 1872 | const tag_values = enum_type.values.get(ip); | 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 | const slice_abi_size = 8; | 1874 | const slice_abi_size = 8; |
| 1878 | const encoded_alignment = @ctz(@as(u32, 4)); | 1875 | const encoded_alignment = @ctz(@as(u32, 4)); |
| | 1876 | |
| 1879 | if (tag_values.len == 0) { | 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 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); | 1889 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); |
| 1882 | appendReservedUleb32(code, 0); | 1890 | appendReservedUleb32(code, 0); |
| 1883 | | 1891 | |
| ... | @@ -1894,78 +1902,91 @@ fn emitTagNameFunction( | ... | @@ -1894,78 +1902,91 @@ fn emitTagNameFunction( |
| 1894 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store)); | 1902 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store)); |
| 1895 | appendReservedUleb32(code, encoded_alignment); | 1903 | appendReservedUleb32(code, encoded_alignment); |
| 1896 | appendReservedUleb32(code, 0); | 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 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1906 | appendReservedUleb32(code, 0); | | |
| 1907 | | 1907 | |
| 1908 | // Outer block that computes table offset. | 1908 | return; |
| 1909 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); | 1909 | } |
| 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 | } | | |
| 1941 | | 1910 | |
| 1942 | // if they're not equal, break out of current branch | 1911 | const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu); |
| 1943 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br_if)); | 1912 | const outer_block_type: std.wasm.BlockType = switch (int_info.bits) { |
| 1944 | appendReservedUleb32(code, 0); | 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. | 1918 | try code.ensureUnusedCapacity( |
| 1947 | appendReservedI32Const(code, @intCast(tag_index * slice_abi_size)); | 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 | 1926 | appendReservedUleb32(code, 0); // no locals |
| 1950 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.br)); | | |
| 1951 | appendReservedUleb32(code, 1); | | |
| 1952 | | 1927 | |
| 1953 | // end the block for this case | 1928 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.local_get)); |
| 1954 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); | 1929 | appendReservedUleb32(code, 0); |
| 1955 | } | | |
| 1956 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.@"unreachable")); | | |
| 1957 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); | | |
| 1958 | | 1930 | |
| 1959 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_load)); | 1931 | // Outer block that computes table offset. |
| 1960 | appendReservedUleb32(code, encoded_alignment); | 1932 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.block)); |
| 1961 | appendReservedUleb32(code, table_base_addr + table_index * 8); | 1933 | code.appendAssumeCapacity(@intFromEnum(outer_block_type)); |
| 1962 | | 1934 | |
| 1963 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.i64_store)); | 1935 | for (tag_values, 0..) |tag_value, tag_index| { |
| 1964 | appendReservedUleb32(code, encoded_alignment); | 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 | appendReservedUleb32(code, 0); | 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 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); | 1990 | code.appendAssumeCapacity(@intFromEnum(std.wasm.Opcode.end)); |
| 1970 | } | 1991 | } |
| 1971 | | 1992 | |