stage2 CBE: Improve support for unions and error sets
This includes various fixes/improvements to the C backend to improve error/union support. It also fixes up our handling of decls, where some decls were not correctly marked alive.
This commit is contained in:
committed by
Andrew Kelley
parent
2f9264d8dc
commit
a9a91a5d49
@@ -375,8 +375,6 @@ pub const DeclGen = struct {
|
||||
val: Value,
|
||||
decl: *Decl,
|
||||
) error{ OutOfMemory, AnalysisFail }!void {
|
||||
decl.markAlive();
|
||||
|
||||
const target = dg.module.getTarget();
|
||||
|
||||
if (ty.isSlice()) {
|
||||
@@ -461,12 +459,14 @@ pub const DeclGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
// Renders a "child" pointer (e.g. ElemPtr, FieldPtr) by recursing
|
||||
// to the root decl/variable that acts as its parent
|
||||
// Renders a "parent" pointer by recursing to the root decl/variable
|
||||
// that its contents are defined with respect to.
|
||||
//
|
||||
// Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr, since
|
||||
// the Type of their container cannot be retrieved from their own Type
|
||||
fn renderChildPtr(dg: *DeclGen, writer: anytype, ptr_val: Value) error{ OutOfMemory, AnalysisFail }!Type {
|
||||
// Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr
|
||||
fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type) error{ OutOfMemory, AnalysisFail }!void {
|
||||
try writer.writeByte('(');
|
||||
try dg.renderTypecast(writer, ptr_ty);
|
||||
try writer.writeByte(')');
|
||||
switch (ptr_val.tag()) {
|
||||
.decl_ref_mut, .decl_ref, .variable => {
|
||||
const decl = switch (ptr_val.tag()) {
|
||||
@@ -475,16 +475,12 @@ pub const DeclGen = struct {
|
||||
.variable => ptr_val.castTag(.variable).?.data.owner_decl,
|
||||
else => unreachable,
|
||||
};
|
||||
try dg.renderDeclName(writer, decl);
|
||||
return decl.ty;
|
||||
try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl);
|
||||
},
|
||||
.field_ptr => {
|
||||
const field_ptr = ptr_val.castTag(.field_ptr).?.data;
|
||||
const container_ty = field_ptr.container_ty;
|
||||
const index = field_ptr.field_index;
|
||||
|
||||
try writer.writeAll("&(");
|
||||
const container_ty = try dg.renderChildPtr(writer, field_ptr.container_ptr);
|
||||
|
||||
const field_name = switch (container_ty.zigTypeTag()) {
|
||||
.Struct => container_ty.structFields().keys()[index],
|
||||
.Union => container_ty.unionFields().keys()[index],
|
||||
@@ -495,19 +491,48 @@ pub const DeclGen = struct {
|
||||
.Union => container_ty.unionFields().values()[index].ty,
|
||||
else => unreachable,
|
||||
};
|
||||
try writer.print(").{ }", .{fmtIdent(field_name)});
|
||||
var container_ptr_ty_pl: Type.Payload.ElemType = .{
|
||||
.base = .{ .tag = .c_mut_pointer },
|
||||
.data = field_ptr.container_ty,
|
||||
};
|
||||
const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base);
|
||||
|
||||
return field_ty;
|
||||
if (field_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
try writer.writeAll("&(");
|
||||
try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
|
||||
if (field_ptr.container_ty.tag() == .union_tagged) {
|
||||
try writer.print(")->payload.{ }", .{fmtIdent(field_name)});
|
||||
} else {
|
||||
try writer.print(")->{ }", .{fmtIdent(field_name)});
|
||||
}
|
||||
} else {
|
||||
try dg.renderParentPtr(writer, field_ptr.container_ptr, field_ty);
|
||||
}
|
||||
},
|
||||
.elem_ptr => {
|
||||
const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
|
||||
var elem_ptr_ty_pl: Type.Payload.ElemType = .{
|
||||
.base = .{ .tag = .c_mut_pointer },
|
||||
.data = elem_ptr.elem_ty,
|
||||
};
|
||||
const elem_ptr_ty = Type.initPayload(&elem_ptr_ty_pl.base);
|
||||
|
||||
try writer.writeAll("&(");
|
||||
const container_ty = try dg.renderChildPtr(writer, elem_ptr.array_ptr);
|
||||
try dg.renderParentPtr(writer, elem_ptr.array_ptr, elem_ptr_ty);
|
||||
try writer.print(")[{d}]", .{elem_ptr.index});
|
||||
return container_ty.childType();
|
||||
},
|
||||
.opt_payload_ptr => return dg.fail("implement renderChildPtr for optional payload", .{}),
|
||||
.eu_payload_ptr => return dg.fail("implement renderChildPtr for error union payload", .{}),
|
||||
.opt_payload_ptr, .eu_payload_ptr => {
|
||||
const payload_ptr = ptr_val.cast(Value.Payload.PayloadPtr).?.data;
|
||||
var container_ptr_ty_pl: Type.Payload.ElemType = .{
|
||||
.base = .{ .tag = .c_mut_pointer },
|
||||
.data = payload_ptr.container_ty,
|
||||
};
|
||||
const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base);
|
||||
|
||||
try writer.writeAll("&(");
|
||||
try dg.renderParentPtr(writer, payload_ptr.container_ptr, container_ptr_ty);
|
||||
try writer.writeAll(")->payload");
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@@ -559,6 +584,13 @@ pub const DeclGen = struct {
|
||||
.Int => switch (val.tag()) {
|
||||
.int_big_positive => try dg.renderBigIntConst(writer, val.castTag(.int_big_positive).?.asBigInt(), ty.isSignedInt()),
|
||||
.int_big_negative => try dg.renderBigIntConst(writer, val.castTag(.int_big_negative).?.asBigInt(), true),
|
||||
.field_ptr,
|
||||
.elem_ptr,
|
||||
.opt_payload_ptr,
|
||||
.eu_payload_ptr,
|
||||
.decl_ref_mut,
|
||||
.decl_ref,
|
||||
=> try dg.renderParentPtr(writer, val, ty),
|
||||
else => {
|
||||
if (ty.isSignedInt())
|
||||
return writer.print("{d}", .{val.toSignedInt()});
|
||||
@@ -586,10 +618,6 @@ pub const DeclGen = struct {
|
||||
// to the assigned pointer type. Note this is just a hack to fix warnings from ordered comparisons (<, >, etc)
|
||||
// between pointers and 0, which is an extension to begin with.
|
||||
.zero => try writer.writeByte('0'),
|
||||
.decl_ref => {
|
||||
const decl = val.castTag(.decl_ref).?.data;
|
||||
return dg.renderDeclValue(writer, ty, val, decl);
|
||||
},
|
||||
.variable => {
|
||||
const decl = val.castTag(.variable).?.data.owner_decl;
|
||||
return dg.renderDeclValue(writer, ty, val, decl);
|
||||
@@ -606,9 +634,6 @@ pub const DeclGen = struct {
|
||||
try dg.renderValue(writer, Type.usize, slice.len);
|
||||
try writer.writeAll("}");
|
||||
},
|
||||
.field_ptr, .elem_ptr, .opt_payload_ptr, .eu_payload_ptr => {
|
||||
_ = try dg.renderChildPtr(writer, val);
|
||||
},
|
||||
.function => {
|
||||
const func = val.castTag(.function).?.data;
|
||||
try dg.renderDeclName(writer, func.owner_decl);
|
||||
@@ -622,6 +647,13 @@ pub const DeclGen = struct {
|
||||
try dg.renderTypecast(writer, ty);
|
||||
try writer.print(")0x{x}u)", .{val.toUnsignedInt(target)});
|
||||
},
|
||||
.field_ptr,
|
||||
.elem_ptr,
|
||||
.opt_payload_ptr,
|
||||
.eu_payload_ptr,
|
||||
.decl_ref_mut,
|
||||
.decl_ref,
|
||||
=> try dg.renderParentPtr(writer, val, ty),
|
||||
else => unreachable,
|
||||
},
|
||||
.Array => {
|
||||
@@ -1326,7 +1358,7 @@ pub const DeclGen = struct {
|
||||
return w.writeAll(name);
|
||||
},
|
||||
.Struct => {
|
||||
const name = dg.getTypedefName(t) orelse if (t.isTuple())
|
||||
const name = dg.getTypedefName(t) orelse if (t.isTuple() or t.tag() == .anon_struct)
|
||||
try dg.renderTupleTypedef(t)
|
||||
else
|
||||
try dg.renderStructTypedef(t);
|
||||
@@ -1346,11 +1378,11 @@ pub const DeclGen = struct {
|
||||
|
||||
try dg.renderType(w, int_tag_ty);
|
||||
},
|
||||
.Opaque => return w.writeAll("void"),
|
||||
|
||||
.Frame,
|
||||
.AnyFrame,
|
||||
.Vector,
|
||||
.Opaque,
|
||||
=> |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
|
||||
@tagName(tag),
|
||||
}),
|
||||
@@ -1497,6 +1529,8 @@ pub const DeclGen = struct {
|
||||
}
|
||||
|
||||
fn renderDeclName(dg: DeclGen, writer: anytype, decl: *Decl) !void {
|
||||
decl.markAlive();
|
||||
|
||||
if (dg.module.decl_exports.get(decl)) |exports| {
|
||||
return writer.writeAll(exports[0].options.name);
|
||||
} else if (decl.val.tag() == .extern_fn) {
|
||||
@@ -3188,7 +3222,7 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
|
||||
field_name = fields.keys()[index];
|
||||
field_val_ty = fields.values()[index].ty;
|
||||
},
|
||||
.tuple => {
|
||||
.tuple, .anon_struct => {
|
||||
const tuple = struct_ty.tupleFields();
|
||||
if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
|
||||
|
||||
@@ -3203,9 +3237,17 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
|
||||
const inst_ty = f.air.typeOfIndex(inst);
|
||||
const local = try f.allocLocal(inst_ty, .Const);
|
||||
|
||||
try writer.print(" = &", .{});
|
||||
try f.writeCValueDeref(writer, struct_ptr);
|
||||
try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) });
|
||||
if (field_val_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
try writer.writeAll(" = &");
|
||||
try f.writeCValueDeref(writer, struct_ptr);
|
||||
try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) });
|
||||
} else {
|
||||
try writer.writeAll(" = (");
|
||||
try f.renderTypecast(writer, inst_ty);
|
||||
try writer.writeByte(')');
|
||||
try f.writeCValue(writer, struct_ptr);
|
||||
try writer.writeAll(";\n");
|
||||
}
|
||||
return local;
|
||||
}
|
||||
|
||||
@@ -3223,7 +3265,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const field_name = switch (struct_ty.tag()) {
|
||||
.@"struct" => struct_ty.structFields().keys()[extra.field_index],
|
||||
.@"union", .union_tagged => struct_ty.unionFields().keys()[extra.field_index],
|
||||
.tuple => blk: {
|
||||
.tuple, .anon_struct => blk: {
|
||||
const tuple = struct_ty.tupleFields();
|
||||
if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none;
|
||||
|
||||
@@ -3348,8 +3390,36 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
}
|
||||
|
||||
fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
_ = inst;
|
||||
return f.fail("TODO: C backend: implement airErrUnionPayloadPtrSet", .{});
|
||||
const writer = f.object.writer();
|
||||
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
|
||||
const operand = try f.resolveInst(ty_op.operand);
|
||||
const error_union_ty = f.air.typeOf(ty_op.operand).childType();
|
||||
|
||||
const error_ty = error_union_ty.errorUnionSet();
|
||||
const payload_ty = error_union_ty.errorUnionPayload();
|
||||
|
||||
// First, set the non-error value.
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
try f.writeCValueDeref(writer, operand);
|
||||
try writer.writeAll(" = ");
|
||||
try f.object.dg.renderValue(writer, error_ty, Value.zero);
|
||||
try writer.writeAll(";\n ");
|
||||
|
||||
return operand;
|
||||
}
|
||||
try f.writeCValueDeref(writer, operand);
|
||||
try writer.writeAll(".error = ");
|
||||
try f.object.dg.renderValue(writer, error_ty, Value.zero);
|
||||
try writer.writeAll(";\n");
|
||||
|
||||
// Then return the payload pointer (only if it is used)
|
||||
if (f.liveness.isUnused(inst)) return CValue.none;
|
||||
|
||||
const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);
|
||||
try writer.writeAll(" = &(");
|
||||
try f.writeCValueDeref(writer, operand);
|
||||
try writer.writeAll(").payload;\n");
|
||||
return local;
|
||||
}
|
||||
|
||||
fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectError = std.testing.expectError;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const mem = std.mem;
|
||||
|
||||
/// A more basic implementation of std.testing.expectError which
|
||||
/// does not require formatter/printing support
|
||||
fn expectError(expected_err: anyerror, observed_err_union: anytype) !void {
|
||||
if (observed_err_union) {
|
||||
return error.TestExpectedError;
|
||||
} else |err| if (err == expected_err) {
|
||||
return; // Success
|
||||
}
|
||||
return error.TestExpectedError;
|
||||
}
|
||||
|
||||
test "error values" {
|
||||
const a = @errorToInt(error.err1);
|
||||
const b = @errorToInt(error.err2);
|
||||
@@ -329,7 +339,6 @@ fn intLiteral(str: []const u8) !?i64 {
|
||||
|
||||
test "nested error union function call in optional unwrap" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
@@ -377,7 +386,6 @@ test "nested error union function call in optional unwrap" {
|
||||
}
|
||||
|
||||
test "return function call to error set from error union function" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
@@ -410,7 +418,6 @@ test "optional error set is the same size as error set" {
|
||||
}
|
||||
|
||||
test "nested catch" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
@@ -471,7 +478,6 @@ test "function pointer with return type that is error union with payload which i
|
||||
|
||||
test "return result loc as peer result loc in inferred error set function" {
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
@@ -503,7 +509,6 @@ test "return result loc as peer result loc in inferred error set function" {
|
||||
}
|
||||
|
||||
test "error payload type is correctly resolved" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
@@ -519,7 +524,7 @@ test "error payload type is correctly resolved" {
|
||||
}
|
||||
};
|
||||
|
||||
try expectEqual(MyIntWrapper{ .x = 42 }, try MyIntWrapper.create());
|
||||
try expect(std.meta.eql(MyIntWrapper{ .x = 42 }, try MyIntWrapper.create()));
|
||||
}
|
||||
|
||||
test "error union comptime caching" {
|
||||
|
||||
@@ -39,7 +39,6 @@ fn testReinterpretWithOffsetAndNoWellDefinedLayout() !void {
|
||||
}
|
||||
|
||||
test "reinterpret bytes inside auto-layout struct as integer with nonzero offset" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
@@ -80,9 +79,9 @@ fn testReinterpretBytesAsExternStruct() !void {
|
||||
try expect(val == 5);
|
||||
}
|
||||
|
||||
test "reinterpret bytes of an extern struct into another" {
|
||||
test "reinterpret bytes of an extern struct (with under-aligned fields) into another" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO: Under-aligned fields are not yet supported in the CBE
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
try testReinterpretExternStructAsExternStruct();
|
||||
@@ -106,12 +105,39 @@ fn testReinterpretExternStructAsExternStruct() !void {
|
||||
try expect(val == 5);
|
||||
}
|
||||
|
||||
test "lower reinterpreted comptime field ptr" {
|
||||
test "reinterpret bytes of an extern struct into another" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
try testReinterpretOverAlignedExternStructAsExternStruct();
|
||||
comptime try testReinterpretOverAlignedExternStructAsExternStruct();
|
||||
}
|
||||
|
||||
fn testReinterpretOverAlignedExternStructAsExternStruct() !void {
|
||||
const S1 = extern struct {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: u8,
|
||||
};
|
||||
comptime var bytes: S1 = .{ .a = 0, .b = 0, .c = 5 };
|
||||
|
||||
const S2 = extern struct {
|
||||
a0: u32,
|
||||
a1: u16,
|
||||
a2: u16,
|
||||
c: u8,
|
||||
};
|
||||
var ptr = @ptrCast(*const S2, &bytes);
|
||||
var val = ptr.c;
|
||||
try expect(val == 5);
|
||||
}
|
||||
|
||||
test "lower reinterpreted comptime field ptr (with under-aligned fields)" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO: CBE does not yet support under-aligned fields
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
// Test lowering a field ptr
|
||||
@@ -131,8 +157,31 @@ test "lower reinterpreted comptime field ptr" {
|
||||
try expect(val2.* == 5);
|
||||
}
|
||||
|
||||
test "lower reinterpreted comptime field ptr" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
// Test lowering a field ptr
|
||||
comptime var bytes align(4) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
const S = extern struct {
|
||||
a: u32,
|
||||
c: u8,
|
||||
};
|
||||
comptime var ptr = @ptrCast(*const S, &bytes);
|
||||
var val = &ptr.c;
|
||||
try expect(val.* == 5);
|
||||
|
||||
// Test lowering an elem ptr
|
||||
comptime var src_value = S{ .a = 15, .c = 5 };
|
||||
comptime var ptr2 = @ptrCast(*[@sizeOf(S)]u8, &src_value);
|
||||
var val2 = &ptr2[4];
|
||||
try expect(val2.* == 5);
|
||||
}
|
||||
|
||||
test "reinterpret struct field at comptime" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
@@ -164,7 +213,6 @@ test "comptime ptrcast keeps larger alignment" {
|
||||
}
|
||||
|
||||
test "implicit optional pointer to optional anyopaque pointer" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
|
||||
@@ -436,8 +436,6 @@ test "global union with single field is correctly initialized" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
|
||||
glbl = Foo1{
|
||||
.f = @typeInfo(Foo1).Union.fields[0].field_type{ .x = 123 },
|
||||
};
|
||||
@@ -456,8 +454,6 @@ test "initialize global array of union" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
|
||||
glbl_array[1] = FooUnion{ .U1 = 2 };
|
||||
glbl_array[0] = FooUnion{ .U0 = 1 };
|
||||
try expect(glbl_array[0].U0 == 1);
|
||||
@@ -1033,7 +1029,6 @@ test "switching on non exhaustive union" {
|
||||
}
|
||||
|
||||
test "containers with single-field enums" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
@@ -1113,7 +1108,6 @@ test "union enum type gets a separate scope" {
|
||||
}
|
||||
|
||||
test "global variable struct contains union initialized to non-most-aligned field" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
Reference in New Issue
Block a user