| author | |
| committer | |
| log | 25e3851fe0f7fe254b48c2242ab8d4ef89165fd5 |
| tree | c7991ec10945496de6dcb8f8aae32d12c077ecd6 |
| parent | fbcf1c0006dc6656deb3f04e2f52d1da4a599952 |
| parent | abc1e52e0885c8e46d743d5e48ba260b35ae2769 |
| signature |
wasm: Implement `@tagName` instruction4 files changed, 248 insertions(+), 7 deletions(-)
src/arch/wasm/CodeGen.zig+192-1| ... | @@ -1944,6 +1944,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -1944,6 +1944,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1944 | .memcpy => func.airMemcpy(inst), | 1944 | .memcpy => func.airMemcpy(inst), |
| 1945 | 1945 | ||
| 1946 | .ret_addr => func.airRetAddr(inst), | 1946 | .ret_addr => func.airRetAddr(inst), |
| 1947 | .tag_name => func.airTagName(inst), | ||
| 1947 | 1948 | ||
| 1948 | .mul_sat, | 1949 | .mul_sat, |
| 1949 | .mod, | 1950 | .mod, |
| ... | @@ -1962,7 +1963,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -1962,7 +1963,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1962 | .atomic_store_release, | 1963 | .atomic_store_release, |
| 1963 | .atomic_store_seq_cst, | 1964 | .atomic_store_seq_cst, |
| 1964 | .atomic_rmw, | 1965 | .atomic_rmw, |
| 1965 | .tag_name, | ||
| 1966 | .err_return_trace, | 1966 | .err_return_trace, |
| 1967 | .set_err_return_trace, | 1967 | .set_err_return_trace, |
| 1968 | .save_err_return_trace_index, | 1968 | .save_err_return_trace_index, |
| ... | @@ -6396,3 +6396,194 @@ fn callIntrinsic( | ... | @@ -6396,3 +6396,194 @@ fn callIntrinsic( |
| 6396 | return WValue{ .stack = {} }; | 6396 | return WValue{ .stack = {} }; |
| 6397 | } | 6397 | } |
| 6398 | } | 6398 | } |
| 6399 | |||
| 6400 | fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ||
| 6401 | const un_op = func.air.instructions.items(.data)[inst].un_op; | ||
| 6402 | if (func.liveness.isUnused(inst)) return func.finishAir(inst, .none, &.{un_op}); | ||
| 6403 | const operand = try func.resolveInst(un_op); | ||
| 6404 | const enum_ty = func.air.typeOf(un_op); | ||
| 6405 | |||
| 6406 | const func_sym_index = try func.getTagNameFunction(enum_ty); | ||
| 6407 | |||
| 6408 | const result_ptr = try func.allocStack(func.air.typeOfIndex(inst)); | ||
| 6409 | try func.lowerToStack(result_ptr); | ||
| 6410 | try func.emitWValue(operand); | ||
| 6411 | try func.addLabel(.call, func_sym_index); | ||
| 6412 | |||
| 6413 | return func.finishAir(inst, result_ptr, &.{un_op}); | ||
| 6414 | } | ||
| 6415 | |||
| 6416 | fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { | ||
| 6417 | const enum_decl_index = enum_ty.getOwnerDecl(); | ||
| 6418 | const module = func.bin_file.base.options.module.?; | ||
| 6419 | |||
| 6420 | var arena_allocator = std.heap.ArenaAllocator.init(func.gpa); | ||
| 6421 | defer arena_allocator.deinit(); | ||
| 6422 | const arena = arena_allocator.allocator(); | ||
| 6423 | |||
| 6424 | const fqn = try module.declPtr(enum_decl_index).getFullyQualifiedName(module); | ||
| 6425 | defer module.gpa.free(fqn); | ||
| 6426 | const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn}); | ||
| 6427 | |||
| 6428 | // check if we already generated code for this. | ||
| 6429 | if (func.bin_file.findGlobalSymbol(func_name)) |loc| { | ||
| 6430 | return loc.index; | ||
| 6431 | } | ||
| 6432 | |||
| 6433 | var int_tag_type_buffer: Type.Payload.Bits = undefined; | ||
| 6434 | const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer); | ||
| 6435 | |||
| 6436 | if (int_tag_ty.bitSize(func.target) > 64) { | ||
| 6437 | return func.fail("TODO: Implement @tagName for enums with tag size larger than 64 bits", .{}); | ||
| 6438 | } | ||
| 6439 | |||
| 6440 | var relocs = std.ArrayList(link.File.Wasm.Relocation).init(func.gpa); | ||
| 6441 | defer relocs.deinit(); | ||
| 6442 | |||
| 6443 | var body_list = std.ArrayList(u8).init(func.gpa); | ||
| 6444 | defer body_list.deinit(); | ||
| 6445 | var writer = body_list.writer(); | ||
| 6446 | |||
| 6447 | // The locals of the function body (always 0) | ||
| 6448 | try leb.writeULEB128(writer, @as(u32, 0)); | ||
| 6449 | |||
| 6450 | // outer block | ||
| 6451 | try writer.writeByte(std.wasm.opcode(.block)); | ||
| 6452 | try writer.writeByte(std.wasm.block_empty); | ||
| 6453 | |||
| 6454 | // TODO: Make switch implementation generic so we can use a jump table for this when the tags are not sparse. | ||
| 6455 | // generate an if-else chain for each tag value as well as constant. | ||
| 6456 | for (enum_ty.enumFields().keys(), 0..) |tag_name, field_index| { | ||
| 6457 | // for each tag name, create an unnamed const, | ||
| 6458 | // and then get a pointer to its value. | ||
| 6459 | var name_ty_payload: Type.Payload.Len = .{ | ||
| 6460 | .base = .{ .tag = .array_u8_sentinel_0 }, | ||
| 6461 | .data = @intCast(u64, tag_name.len), | ||
| 6462 | }; | ||
| 6463 | const name_ty = Type.initPayload(&name_ty_payload.base); | ||
| 6464 | const string_bytes = &module.string_literal_bytes; | ||
| 6465 | try string_bytes.ensureUnusedCapacity(module.gpa, tag_name.len); | ||
| 6466 | const gop = try module.string_literal_table.getOrPutContextAdapted(module.gpa, tag_name, Module.StringLiteralAdapter{ | ||
| 6467 | .bytes = string_bytes, | ||
| 6468 | }, Module.StringLiteralContext{ | ||
| 6469 | .bytes = string_bytes, | ||
| 6470 | }); | ||
| 6471 | if (!gop.found_existing) { | ||
| 6472 | gop.key_ptr.* = .{ | ||
| 6473 | .index = @intCast(u32, string_bytes.items.len), | ||
| 6474 | .len = @intCast(u32, tag_name.len), | ||
| 6475 | }; | ||
| 6476 | string_bytes.appendSliceAssumeCapacity(tag_name); | ||
| 6477 | gop.value_ptr.* = .none; | ||
| 6478 | } | ||
| 6479 | var name_val_payload: Value.Payload.StrLit = .{ | ||
| 6480 | .base = .{ .tag = .str_lit }, | ||
| 6481 | .data = gop.key_ptr.*, | ||
| 6482 | }; | ||
| 6483 | const name_val = Value.initPayload(&name_val_payload.base); | ||
| 6484 | const tag_sym_index = try func.bin_file.lowerUnnamedConst( | ||
| 6485 | .{ .ty = name_ty, .val = name_val }, | ||
| 6486 | enum_decl_index, | ||
| 6487 | ); | ||
| 6488 | |||
| 6489 | // block for this if case | ||
| 6490 | try writer.writeByte(std.wasm.opcode(.block)); | ||
| 6491 | try writer.writeByte(std.wasm.block_empty); | ||
| 6492 | |||
| 6493 | // get actual tag value (stored in 2nd parameter); | ||
| 6494 | try writer.writeByte(std.wasm.opcode(.local_get)); | ||
| 6495 | try leb.writeULEB128(writer, @as(u32, 1)); | ||
| 6496 | |||
| 6497 | var tag_val_payload: Value.Payload.U32 = .{ | ||
| 6498 | .base = .{ .tag = .enum_field_index }, | ||
| 6499 | .data = @intCast(u32, field_index), | ||
| 6500 | }; | ||
| 6501 | const tag_value = try func.lowerConstant(Value.initPayload(&tag_val_payload.base), enum_ty); | ||
| 6502 | |||
| 6503 | switch (tag_value) { | ||
| 6504 | .imm32 => |value| { | ||
| 6505 | try writer.writeByte(std.wasm.opcode(.i32_const)); | ||
| 6506 | try leb.writeULEB128(writer, value); | ||
| 6507 | try writer.writeByte(std.wasm.opcode(.i32_ne)); | ||
| 6508 | }, | ||
| 6509 | .imm64 => |value| { | ||
| 6510 | try writer.writeByte(std.wasm.opcode(.i64_const)); | ||
| 6511 | try leb.writeULEB128(writer, value); | ||
| 6512 | try writer.writeByte(std.wasm.opcode(.i64_ne)); | ||
| 6513 | }, | ||
| 6514 | else => unreachable, | ||
| 6515 | } | ||
| 6516 | // if they're not equal, break out of current branch | ||
| 6517 | try writer.writeByte(std.wasm.opcode(.br_if)); | ||
| 6518 | try leb.writeULEB128(writer, @as(u32, 0)); | ||
| 6519 | |||
| 6520 | // store the address of the tagname in the pointer field of the slice | ||
| 6521 | // get the address twice so we can also store the length. | ||
| 6522 | try writer.writeByte(std.wasm.opcode(.local_get)); | ||
| 6523 | try leb.writeULEB128(writer, @as(u32, 0)); | ||
| 6524 | try writer.writeByte(std.wasm.opcode(.local_get)); | ||
| 6525 | try leb.writeULEB128(writer, @as(u32, 0)); | ||
| 6526 | |||
| 6527 | // get address of tagname and emit a relocation to it | ||
| 6528 | if (func.arch() == .wasm32) { | ||
| 6529 | const encoded_alignment = @ctz(@as(u32, 4)); | ||
| 6530 | try writer.writeByte(std.wasm.opcode(.i32_const)); | ||
| 6531 | try relocs.append(.{ | ||
| 6532 | .relocation_type = .R_WASM_MEMORY_ADDR_LEB, | ||
| 6533 | .offset = @intCast(u32, body_list.items.len), | ||
| 6534 | .index = tag_sym_index, | ||
| 6535 | }); | ||
| 6536 | try writer.writeAll(&[_]u8{0} ** 5); // will be relocated | ||
| 6537 | |||
| 6538 | // store pointer | ||
| 6539 | try writer.writeByte(std.wasm.opcode(.i32_store)); | ||
| 6540 | try leb.writeULEB128(writer, encoded_alignment); | ||
| 6541 | try leb.writeULEB128(writer, @as(u32, 0)); | ||
| 6542 | |||
| 6543 | // store length | ||
| 6544 | try writer.writeByte(std.wasm.opcode(.i32_const)); | ||
| 6545 | try leb.writeULEB128(writer, @intCast(u32, tag_name.len)); | ||
| 6546 | try writer.writeByte(std.wasm.opcode(.i32_store)); | ||
| 6547 | try leb.writeULEB128(writer, encoded_alignment); | ||
| 6548 | try leb.writeULEB128(writer, @as(u32, 4)); | ||
| 6549 | } else { | ||
| 6550 | const encoded_alignment = @ctz(@as(u32, 8)); | ||
| 6551 | try writer.writeByte(std.wasm.opcode(.i64_const)); | ||
| 6552 | try relocs.append(.{ | ||
| 6553 | .relocation_type = .R_WASM_MEMORY_ADDR_LEB64, | ||
| 6554 | .offset = @intCast(u32, body_list.items.len), | ||
| 6555 | .index = tag_sym_index, | ||
| 6556 | }); | ||
| 6557 | try writer.writeAll(&[_]u8{0} ** 10); // will be relocated | ||
| 6558 | |||
| 6559 | // store pointer | ||
| 6560 | try writer.writeByte(std.wasm.opcode(.i64_store)); | ||
| 6561 | try leb.writeULEB128(writer, encoded_alignment); | ||
| 6562 | try leb.writeULEB128(writer, @as(u32, 0)); | ||
| 6563 | |||
| 6564 | // store length | ||
| 6565 | try writer.writeByte(std.wasm.opcode(.i64_const)); | ||
| 6566 | try leb.writeULEB128(writer, @intCast(u64, tag_name.len)); | ||
| 6567 | try writer.writeByte(std.wasm.opcode(.i64_store)); | ||
| 6568 | try leb.writeULEB128(writer, encoded_alignment); | ||
| 6569 | try leb.writeULEB128(writer, @as(u32, 8)); | ||
| 6570 | } | ||
| 6571 | |||
| 6572 | // break outside blocks | ||
| 6573 | try writer.writeByte(std.wasm.opcode(.br)); | ||
| 6574 | try leb.writeULEB128(writer, @as(u32, 1)); | ||
| 6575 | |||
| 6576 | // end the block for this case | ||
| 6577 | try writer.writeByte(std.wasm.opcode(.end)); | ||
| 6578 | } | ||
| 6579 | |||
| 6580 | try writer.writeByte(std.wasm.opcode(.@"unreachable")); // tag value does not have a name | ||
| 6581 | // finish outer block | ||
| 6582 | try writer.writeByte(std.wasm.opcode(.end)); | ||
| 6583 | // finish function body | ||
| 6584 | try writer.writeByte(std.wasm.opcode(.end)); | ||
| 6585 | |||
| 6586 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); | ||
| 6587 | const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty}, slice_ty, func.target); | ||
| 6588 | return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs); | ||
| 6589 | } |
src/link/Wasm.zig+55-1| ... | @@ -30,6 +30,7 @@ const Symbol = @import("Wasm/Symbol.zig"); | ... | @@ -30,6 +30,7 @@ const Symbol = @import("Wasm/Symbol.zig"); |
| 30 | const Object = @import("Wasm/Object.zig"); | 30 | const Object = @import("Wasm/Object.zig"); |
| 31 | const Archive = @import("Wasm/Archive.zig"); | 31 | const Archive = @import("Wasm/Archive.zig"); |
| 32 | const types = @import("Wasm/types.zig"); | 32 | const types = @import("Wasm/types.zig"); |
| 33 | pub const Relocation = types.Relocation; | ||
| 33 | 34 | ||
| 34 | pub const base_tag: link.File.Tag = .wasm; | 35 | pub const base_tag: link.File.Tag = .wasm; |
| 35 | 36 | ||
| ... | @@ -178,6 +179,10 @@ debug_str_atom: ?Atom.Index = null, | ... | @@ -178,6 +179,10 @@ debug_str_atom: ?Atom.Index = null, |
| 178 | debug_pubnames_atom: ?Atom.Index = null, | 179 | debug_pubnames_atom: ?Atom.Index = null, |
| 179 | debug_pubtypes_atom: ?Atom.Index = null, | 180 | debug_pubtypes_atom: ?Atom.Index = null, |
| 180 | 181 | ||
| 182 | /// List of atom indexes of functions that are generated by the backend, | ||
| 183 | /// rather than by the linker. | ||
| 184 | synthetic_functions: std.ArrayListUnmanaged(Atom.Index) = .{}, | ||
| 185 | |||
| 181 | pub const Segment = struct { | 186 | pub const Segment = struct { |
| 182 | alignment: u32, | 187 | alignment: u32, |
| 183 | size: u32, | 188 | size: u32, |
| ... | @@ -1208,7 +1213,7 @@ fn resolveLazySymbols(wasm: *Wasm) !void { | ... | @@ -1208,7 +1213,7 @@ fn resolveLazySymbols(wasm: *Wasm) !void { |
| 1208 | 1213 | ||
| 1209 | // Tries to find a global symbol by its name. Returns null when not found, | 1214 | // Tries to find a global symbol by its name. Returns null when not found, |
| 1210 | /// and its location when it is found. | 1215 | /// and its location when it is found. |
| 1211 | fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc { | 1216 | pub fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc { |
| 1212 | const offset = wasm.string_table.getOffset(name) orelse return null; | 1217 | const offset = wasm.string_table.getOffset(name) orelse return null; |
| 1213 | return wasm.globals.get(offset); | 1218 | return wasm.globals.get(offset); |
| 1214 | } | 1219 | } |
| ... | @@ -1287,6 +1292,7 @@ pub fn deinit(wasm: *Wasm) void { | ... | @@ -1287,6 +1292,7 @@ pub fn deinit(wasm: *Wasm) void { |
| 1287 | wasm.exports.deinit(gpa); | 1292 | wasm.exports.deinit(gpa); |
| 1288 | 1293 | ||
| 1289 | wasm.string_table.deinit(gpa); | 1294 | wasm.string_table.deinit(gpa); |
| 1295 | wasm.synthetic_functions.deinit(gpa); | ||
| 1290 | 1296 | ||
| 1291 | if (wasm.dwarf) |*dwarf| { | 1297 | if (wasm.dwarf) |*dwarf| { |
| 1292 | dwarf.deinit(); | 1298 | dwarf.deinit(); |
| ... | @@ -2272,6 +2278,49 @@ fn createSyntheticFunction( | ... | @@ -2272,6 +2278,49 @@ fn createSyntheticFunction( |
| 2272 | atom.offset = prev_atom.offset + prev_atom.size; | 2278 | atom.offset = prev_atom.offset + prev_atom.size; |
| 2273 | } | 2279 | } |
| 2274 | 2280 | ||
| 2281 | /// Unlike `createSyntheticFunction` this function is to be called by | ||
| 2282 | /// the codegeneration backend. This will not allocate the created Atom yet, | ||
| 2283 | /// but will instead be appended to `synthetic_functions` list and will be | ||
| 2284 | /// parsed at the end of code generation. | ||
| 2285 | /// Returns the index of the symbol. | ||
| 2286 | pub fn createFunction( | ||
| 2287 | wasm: *Wasm, | ||
| 2288 | symbol_name: []const u8, | ||
| 2289 | func_ty: std.wasm.Type, | ||
| 2290 | function_body: *std.ArrayList(u8), | ||
| 2291 | relocations: *std.ArrayList(Relocation), | ||
| 2292 | ) !u32 { | ||
| 2293 | const loc = try wasm.createSyntheticSymbol(symbol_name, .function); | ||
| 2294 | |||
| 2295 | const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len); | ||
| 2296 | const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); | ||
| 2297 | atom.* = .{ | ||
| 2298 | .size = @intCast(u32, function_body.items.len), | ||
| 2299 | .offset = 0, | ||
| 2300 | .sym_index = loc.index, | ||
| 2301 | .file = null, | ||
| 2302 | .alignment = 1, | ||
| 2303 | .next = null, | ||
| 2304 | .prev = null, | ||
| 2305 | .code = function_body.moveToUnmanaged(), | ||
| 2306 | .relocs = relocations.moveToUnmanaged(), | ||
| 2307 | }; | ||
| 2308 | const symbol = loc.getSymbol(wasm); | ||
| 2309 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); // ensure function does not get exported | ||
| 2310 | |||
| 2311 | const section_index = wasm.code_section_index orelse idx: { | ||
| 2312 | const index = @intCast(u32, wasm.segments.items.len); | ||
| 2313 | try wasm.appendDummySegment(); | ||
| 2314 | break :idx index; | ||
| 2315 | }; | ||
| 2316 | try wasm.appendAtomAtIndex(section_index, atom_index); | ||
| 2317 | try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index); | ||
| 2318 | try wasm.atom_types.put(wasm.base.allocator, atom_index, try wasm.putOrGetFuncType(func_ty)); | ||
| 2319 | try wasm.synthetic_functions.append(wasm.base.allocator, atom_index); | ||
| 2320 | |||
| 2321 | return loc.index; | ||
| 2322 | } | ||
| 2323 | |||
| 2275 | fn initializeTLSFunction(wasm: *Wasm) !void { | 2324 | fn initializeTLSFunction(wasm: *Wasm) !void { |
| 2276 | if (!wasm.base.options.shared_memory) return; | 2325 | if (!wasm.base.options.shared_memory) return; |
| 2277 | 2326 | ||
| ... | @@ -3306,6 +3355,11 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -3306,6 +3355,11 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 3306 | } | 3355 | } |
| 3307 | } | 3356 | } |
| 3308 | 3357 | ||
| 3358 | // also parse any backend-generated functions | ||
| 3359 | for (wasm.synthetic_functions.items) |atom_index| { | ||
| 3360 | try wasm.parseAtom(atom_index, .function); | ||
| 3361 | } | ||
| 3362 | |||
| 3309 | if (wasm.dwarf) |*dwarf| { | 3363 | if (wasm.dwarf) |*dwarf| { |
| 3310 | try dwarf.flushModule(wasm.base.options.module.?); | 3364 | try dwarf.flushModule(wasm.base.options.module.?); |
| 3311 | } | 3365 | } |
src/link/Wasm/Atom.zig+1-1| ... | @@ -43,7 +43,7 @@ pub const Index = u32; | ... | @@ -43,7 +43,7 @@ pub const Index = u32; |
| 43 | 43 | ||
| 44 | /// Represents a default empty wasm `Atom` | 44 | /// Represents a default empty wasm `Atom` |
| 45 | pub const empty: Atom = .{ | 45 | pub const empty: Atom = .{ |
| 46 | .alignment = 0, | 46 | .alignment = 1, |
| 47 | .file = null, | 47 | .file = null, |
| 48 | .next = null, | 48 | .next = null, |
| 49 | .offset = 0, | 49 | .offset = 0, |
test/behavior/enum.zig-4| ... | @@ -979,7 +979,6 @@ fn test3_2(f: Test3Foo) !void { | ... | @@ -979,7 +979,6 @@ fn test3_2(f: Test3Foo) !void { |
| 979 | } | 979 | } |
| 980 | 980 | ||
| 981 | test "@tagName" { | 981 | test "@tagName" { |
| 982 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 983 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 982 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 984 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 983 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 985 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 984 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| ... | @@ -996,7 +995,6 @@ fn testEnumTagNameBare(n: anytype) []const u8 { | ... | @@ -996,7 +995,6 @@ fn testEnumTagNameBare(n: anytype) []const u8 { |
| 996 | const BareNumber = enum { One, Two, Three }; | 995 | const BareNumber = enum { One, Two, Three }; |
| 997 | 996 | ||
| 998 | test "@tagName non-exhaustive enum" { | 997 | test "@tagName non-exhaustive enum" { |
| 999 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1000 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 998 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 1001 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 999 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 1002 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1000 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| ... | @@ -1008,7 +1006,6 @@ test "@tagName non-exhaustive enum" { | ... | @@ -1008,7 +1006,6 @@ test "@tagName non-exhaustive enum" { |
| 1008 | const NonExhaustive = enum(u8) { A, B, _ }; | 1006 | const NonExhaustive = enum(u8) { A, B, _ }; |
| 1009 | 1007 | ||
| 1010 | test "@tagName is null-terminated" { | 1008 | test "@tagName is null-terminated" { |
| 1011 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1012 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 1009 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 1013 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 1010 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 1014 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1011 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| ... | @@ -1024,7 +1021,6 @@ test "@tagName is null-terminated" { | ... | @@ -1024,7 +1021,6 @@ test "@tagName is null-terminated" { |
| 1024 | } | 1021 | } |
| 1025 | 1022 | ||
| 1026 | test "tag name with assigned enum values" { | 1023 | test "tag name with assigned enum values" { |
| 1027 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1028 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 1024 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 1029 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 1025 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 1030 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1026 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |