mirror of
https://github.com/ziglang/zig.git
synced 2025-12-30 18:13:19 +00:00
Merge pull request #10679 from Luukdegram/wasm-unions
Stage2: wasm - Implement unions
This commit is contained in:
commit
f2835c6a28
@ -722,9 +722,9 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {
|
||||
if (info.bits > 32 and info.bits <= 64) break :blk wasm.Valtype.i64;
|
||||
break :blk wasm.Valtype.i32; // represented as pointer to stack
|
||||
},
|
||||
.Enum => switch (ty.tag()) {
|
||||
.enum_simple => wasm.Valtype.i32,
|
||||
else => typeToValtype(ty.cast(Type.Payload.EnumFull).?.data.tag_ty, target),
|
||||
.Enum => {
|
||||
var buf: Type.Payload.Bits = undefined;
|
||||
return typeToValtype(ty.intTagType(&buf), target);
|
||||
},
|
||||
else => wasm.Valtype.i32, // all represented as reference/immediate
|
||||
};
|
||||
@ -1033,14 +1033,21 @@ pub const DeclGen = struct {
|
||||
return Result{ .appended = {} };
|
||||
},
|
||||
.Enum => {
|
||||
try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target())));
|
||||
return Result{ .appended = {} };
|
||||
var int_buffer: Value.Payload.U64 = undefined;
|
||||
const int_val = val.enumToInt(ty, &int_buffer);
|
||||
var buf: Type.Payload.Bits = undefined;
|
||||
const int_ty = ty.intTagType(&buf);
|
||||
return self.genTypedValue(int_ty, int_val, writer);
|
||||
},
|
||||
.Bool => {
|
||||
try writer.writeByte(@boolToInt(val.toBool()));
|
||||
return Result{ .appended = {} };
|
||||
},
|
||||
.Struct => {
|
||||
const struct_ty = ty.castTag(.@"struct").?.data;
|
||||
if (struct_ty.layout == .Packed) {
|
||||
return self.fail("TODO: Packed structs for wasm", .{});
|
||||
}
|
||||
const field_vals = val.castTag(.@"struct").?.data;
|
||||
for (field_vals) |field_val, index| {
|
||||
const field_ty = ty.structFieldType(index);
|
||||
@ -1053,9 +1060,45 @@ pub const DeclGen = struct {
|
||||
return Result{ .appended = {} };
|
||||
},
|
||||
.Union => {
|
||||
// TODO: Implement Union declarations
|
||||
try writer.writeByteNTimes(0xaa, @intCast(usize, ty.abiSize(self.target())));
|
||||
return Result{ .appended = {} };
|
||||
const union_val = val.castTag(.@"union").?.data;
|
||||
const layout = ty.unionGetLayout(self.target());
|
||||
|
||||
if (layout.payload_size == 0) {
|
||||
return self.genTypedValue(ty.unionTagType().?, union_val.tag, writer);
|
||||
}
|
||||
|
||||
// Check if we should store the tag first, in which case, do so now:
|
||||
if (layout.tag_align >= layout.payload_align) {
|
||||
switch (try self.genTypedValue(ty.unionTagType().?, union_val.tag, writer)) {
|
||||
.appended => {},
|
||||
.externally_managed => |payload| try writer.writeAll(payload),
|
||||
}
|
||||
}
|
||||
|
||||
const union_ty = ty.cast(Type.Payload.Union).?.data;
|
||||
const field_index = union_ty.tag_ty.enumTagFieldIndex(union_val.tag).?;
|
||||
assert(union_ty.haveFieldTypes());
|
||||
const field_ty = union_ty.fields.values()[field_index].ty;
|
||||
if (!field_ty.hasRuntimeBits()) {
|
||||
try writer.writeByteNTimes(0xaa, @intCast(usize, layout.payload_size));
|
||||
} else {
|
||||
switch (try self.genTypedValue(field_ty, union_val.val, writer)) {
|
||||
.appended => {},
|
||||
.externally_managed => |payload| try writer.writeAll(payload),
|
||||
}
|
||||
|
||||
// Unions have the size of the largest field, so we must pad
|
||||
// whenever the active field has a smaller size.
|
||||
const diff = layout.payload_size - field_ty.abiSize(self.target());
|
||||
if (diff > 0) {
|
||||
try writer.writeByteNTimes(0xaa, @intCast(usize, diff));
|
||||
}
|
||||
}
|
||||
|
||||
if (layout.tag_size == 0) {
|
||||
return Result{ .appended = {} };
|
||||
}
|
||||
return self.genTypedValue(union_ty.tag_ty, union_val.tag, writer);
|
||||
},
|
||||
.Pointer => switch (val.tag()) {
|
||||
.variable => {
|
||||
@ -1080,6 +1123,10 @@ pub const DeclGen = struct {
|
||||
}
|
||||
return Result{ .appended = {} };
|
||||
},
|
||||
.zero => {
|
||||
try writer.writeByteNTimes(0, @divExact(self.target().cpu.arch.ptrBitWidth(), 8));
|
||||
return Result{ .appended = {} };
|
||||
},
|
||||
else => return self.fail("TODO: Implement zig decl gen for pointer type value: '{s}'", .{@tagName(val.tag())}),
|
||||
},
|
||||
.ErrorUnion => {
|
||||
@ -1334,7 +1381,7 @@ fn isByRef(ty: Type, target: std.Target) bool {
|
||||
},
|
||||
.Pointer => {
|
||||
// Slices act like struct and will be passed by reference
|
||||
if (ty.isSlice()) return ty.hasRuntimeBits();
|
||||
if (ty.isSlice()) return true;
|
||||
return false;
|
||||
},
|
||||
}
|
||||
@ -1394,6 +1441,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.bit_or => self.airBinOp(inst, .@"or"),
|
||||
.bool_and => self.airBinOp(inst, .@"and"),
|
||||
.bool_or => self.airBinOp(inst, .@"or"),
|
||||
.rem => self.airBinOp(inst, .rem),
|
||||
.shl => self.airBinOp(inst, .shl),
|
||||
.shr => self.airBinOp(inst, .shr),
|
||||
.xor => self.airBinOp(inst, .xor),
|
||||
@ -1419,6 +1467,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.dbg_stmt => WValue.none,
|
||||
.intcast => self.airIntcast(inst),
|
||||
.float_to_int => self.airFloatToInt(inst),
|
||||
.get_union_tag => self.airGetUnionTag(inst),
|
||||
|
||||
.is_err => self.airIsErr(inst, .i32_ne),
|
||||
.is_non_err => self.airIsErr(inst, .i32_eq),
|
||||
@ -1454,6 +1503,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.slice_ptr => self.airSlicePtr(inst),
|
||||
.store => self.airStore(inst),
|
||||
|
||||
.set_union_tag => self.airSetUnionTag(inst),
|
||||
.struct_field_ptr => self.airStructFieldPtr(inst),
|
||||
.struct_field_ptr_index_0 => self.airStructFieldPtrIndex(inst, 0),
|
||||
.struct_field_ptr_index_1 => self.airStructFieldPtrIndex(inst, 1),
|
||||
@ -1477,7 +1527,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.div_float,
|
||||
.div_floor,
|
||||
.div_exact,
|
||||
.rem,
|
||||
.mod,
|
||||
.max,
|
||||
.min,
|
||||
@ -1494,8 +1543,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.fpext,
|
||||
.unwrap_errunion_payload_ptr,
|
||||
.unwrap_errunion_err_ptr,
|
||||
.set_union_tag,
|
||||
.get_union_tag,
|
||||
|
||||
.ptr_slice_len_ptr,
|
||||
.ptr_slice_ptr_ptr,
|
||||
.int_to_float,
|
||||
@ -1518,7 +1566,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.sub_with_overflow,
|
||||
.mul_with_overflow,
|
||||
.shl_with_overflow,
|
||||
=> |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
|
||||
=> |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1596,6 +1644,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
break :blk func.data.owner_decl;
|
||||
} else if (func_val.castTag(.extern_fn)) |ext_fn| {
|
||||
break :blk ext_fn.data;
|
||||
} else if (func_val.castTag(.decl_ref)) |decl_ref| {
|
||||
break :blk decl_ref.data;
|
||||
}
|
||||
return self.fail("Expected a function, but instead found type '{s}'", .{func_val.tag()});
|
||||
};
|
||||
@ -1697,7 +1747,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
|
||||
|
||||
return self.memCopy(ty, lhs, rhs);
|
||||
},
|
||||
.Struct, .Array => {
|
||||
.Struct, .Array, .Union => {
|
||||
return try self.memCopy(ty, lhs, rhs);
|
||||
},
|
||||
.Pointer => {
|
||||
@ -1720,18 +1770,8 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
|
||||
try self.emitWValue(lhs);
|
||||
try self.emitWValue(rhs);
|
||||
const valtype = typeToValtype(ty, self.target);
|
||||
// check if we should pass by pointer or value based on ABI size
|
||||
// TODO: Implement a way to get ABI values from a given type,
|
||||
// that is portable across the backend, rather than copying logic.
|
||||
const abi_size = switch (ty.zigTypeTag()) {
|
||||
.Int,
|
||||
.Float,
|
||||
.ErrorSet,
|
||||
.Enum,
|
||||
.Bool,
|
||||
=> @intCast(u8, ty.abiSize(self.target)),
|
||||
else => @as(u8, 4),
|
||||
};
|
||||
const abi_size = @intCast(u8, ty.abiSize(self.target));
|
||||
|
||||
const opcode = buildOpcode(.{
|
||||
.valtype1 = valtype,
|
||||
.width = abi_size * 8, // use bitsize instead of byte size
|
||||
@ -1771,22 +1811,9 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
|
||||
.unsigned
|
||||
else
|
||||
.signed;
|
||||
// TODO: Implement a way to get ABI values from a given type,
|
||||
// that is portable across the backend, rather than copying logic.
|
||||
const abi_size = switch (ty.zigTypeTag()) {
|
||||
.Int,
|
||||
.Float,
|
||||
.ErrorSet,
|
||||
.Enum,
|
||||
.Bool,
|
||||
.ErrorUnion,
|
||||
=> @intCast(u8, ty.abiSize(self.target)),
|
||||
.Optional => blk: {
|
||||
if (ty.isPtrLikeOptional()) break :blk @intCast(u8, self.ptrSize());
|
||||
break :blk @intCast(u8, ty.abiSize(self.target));
|
||||
},
|
||||
else => @as(u8, 4),
|
||||
};
|
||||
|
||||
// TODO: Revisit below to determine if optional zero-sized pointers should still have abi-size 4.
|
||||
const abi_size = if (ty.isPtrLikeOptional()) @as(u8, 4) else @intCast(u8, ty.abiSize(self.target));
|
||||
|
||||
const opcode = buildOpcode(.{
|
||||
.valtype1 = typeToValtype(ty, self.target),
|
||||
@ -1952,7 +1979,13 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
|
||||
return WValue{ .imm32 = field_index.data };
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
.enum_numbered => {
|
||||
const index = field_index.data;
|
||||
const enum_data = ty.castTag(.enum_numbered).?.data;
|
||||
const enum_val = enum_data.values.keys()[index];
|
||||
return self.lowerConstant(enum_val, enum_data.tag_ty);
|
||||
},
|
||||
else => return self.fail("TODO: lowerConstant for enum tag: {}", .{ty.tag()}),
|
||||
}
|
||||
} else {
|
||||
var int_tag_buffer: Type.Payload.Bits = undefined;
|
||||
@ -2724,7 +2757,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
const elem_size = elem_ty.abiSize(self.target);
|
||||
|
||||
// load pointer onto stack
|
||||
const slice_ptr = try self.load(slice, slice_ty, 0);
|
||||
const slice_ptr = try self.load(slice, Type.usize, 0);
|
||||
try self.addLabel(.local_get, slice_ptr.local);
|
||||
|
||||
// calculate index into slice
|
||||
@ -2746,14 +2779,13 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
if (self.liveness.isUnused(inst)) return WValue.none;
|
||||
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
|
||||
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
|
||||
const slice_ty = self.air.typeOf(bin_op.lhs);
|
||||
const elem_ty = self.air.getRefType(ty_pl.ty).childType();
|
||||
const elem_size = elem_ty.abiSize(self.target);
|
||||
|
||||
const slice = try self.resolveInst(bin_op.lhs);
|
||||
const index = try self.resolveInst(bin_op.rhs);
|
||||
|
||||
const slice_ptr = try self.load(slice, slice_ty, 0);
|
||||
const slice_ptr = try self.load(slice, Type.usize, 0);
|
||||
try self.addLabel(.local_get, slice_ptr.local);
|
||||
|
||||
// calculate index into slice
|
||||
@ -3177,3 +3209,43 @@ fn cmpBigInt(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.ma
|
||||
try self.addLabel(.local_set, result.local);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
const un_ty = self.air.typeOf(bin_op.lhs).childType();
|
||||
const tag_ty = self.air.typeOf(bin_op.rhs);
|
||||
const layout = un_ty.unionGetLayout(self.target);
|
||||
if (layout.tag_size == 0) return WValue{ .none = {} };
|
||||
const union_ptr = try self.resolveInst(bin_op.lhs);
|
||||
const new_tag = try self.resolveInst(bin_op.rhs);
|
||||
if (layout.payload_size == 0) {
|
||||
try self.store(union_ptr, new_tag, tag_ty, 0);
|
||||
return WValue{ .none = {} };
|
||||
}
|
||||
|
||||
// when the tag alignment is smaller than the payload, the field will be stored
|
||||
// after the payload.
|
||||
const offset = if (layout.tag_align < layout.payload_align) blk: {
|
||||
break :blk @intCast(u32, layout.payload_size);
|
||||
} else @as(u32, 0);
|
||||
try self.store(union_ptr, new_tag, tag_ty, offset);
|
||||
return WValue{ .none = {} };
|
||||
}
|
||||
|
||||
fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
|
||||
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const un_ty = self.air.typeOf(ty_op.operand);
|
||||
const tag_ty = self.air.typeOfIndex(inst);
|
||||
const layout = un_ty.unionGetLayout(self.target);
|
||||
if (layout.tag_size == 0) return WValue{ .none = {} };
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
|
||||
// when the tag alignment is smaller than the payload, the field will be stored
|
||||
// after the payload.
|
||||
const offset = if (layout.tag_align < layout.payload_align) blk: {
|
||||
break :blk @intCast(u32, layout.payload_size);
|
||||
} else @as(u32, 0);
|
||||
return self.load(operand, tag_ty, offset);
|
||||
}
|
||||
|
||||
@ -173,6 +173,10 @@ pub fn emitMir(emit: *Emit) InnerError!void {
|
||||
.i64_trunc_f32_u => try emit.emitTag(tag),
|
||||
.i64_trunc_f64_s => try emit.emitTag(tag),
|
||||
.i64_trunc_f64_u => try emit.emitTag(tag),
|
||||
.i32_rem_s => try emit.emitTag(tag),
|
||||
.i32_rem_u => try emit.emitTag(tag),
|
||||
.i64_rem_s => try emit.emitTag(tag),
|
||||
.i64_rem_u => try emit.emitTag(tag),
|
||||
|
||||
.extended => try emit.emitExtended(inst),
|
||||
}
|
||||
|
||||
@ -327,6 +327,10 @@ pub const Inst = struct {
|
||||
/// Uses `tag`
|
||||
i32_div_u = 0x6E,
|
||||
/// Uses `tag`
|
||||
i32_rem_s = 0x6F,
|
||||
/// Uses `tag`
|
||||
i32_rem_u = 0x70,
|
||||
/// Uses `tag`
|
||||
i32_and = 0x71,
|
||||
/// Uses `tag`
|
||||
i32_or = 0x72,
|
||||
@ -349,6 +353,10 @@ pub const Inst = struct {
|
||||
/// Uses `tag`
|
||||
i64_div_u = 0x80,
|
||||
/// Uses `tag`
|
||||
i64_rem_s = 0x81,
|
||||
/// Uses `tag`
|
||||
i64_rem_u = 0x82,
|
||||
/// Uses `tag`
|
||||
i64_and = 0x83,
|
||||
/// Uses `tag`
|
||||
i64_or = 0x84,
|
||||
|
||||
@ -3,18 +3,34 @@ const builtin = @import("builtin");
|
||||
test {
|
||||
// Tests that pass for stage1, llvm backend, C backend, wasm backend, arm backend and x86_64 backend.
|
||||
_ = @import("behavior/align.zig");
|
||||
_ = @import("behavior/alignof.zig");
|
||||
_ = @import("behavior/array.zig");
|
||||
_ = @import("behavior/bit_shifting.zig");
|
||||
_ = @import("behavior/bool.zig");
|
||||
_ = @import("behavior/bugs/394.zig");
|
||||
_ = @import("behavior/bugs/655.zig");
|
||||
_ = @import("behavior/bugs/656.zig");
|
||||
_ = @import("behavior/bugs/679.zig");
|
||||
_ = @import("behavior/bugs/1111.zig");
|
||||
_ = @import("behavior/bugs/1277.zig");
|
||||
_ = @import("behavior/bugs/1310.zig");
|
||||
_ = @import("behavior/bugs/1381.zig");
|
||||
_ = @import("behavior/bugs/1500.zig");
|
||||
_ = @import("behavior/bugs/1735.zig");
|
||||
_ = @import("behavior/bugs/2006.zig");
|
||||
_ = @import("behavior/bugs/2346.zig");
|
||||
_ = @import("behavior/bugs/3112.zig");
|
||||
_ = @import("behavior/bugs/3367.zig");
|
||||
_ = @import("behavior/bugs/6850.zig");
|
||||
_ = @import("behavior/bugs/7250.zig");
|
||||
_ = @import("behavior/cast.zig");
|
||||
_ = @import("behavior/comptime_memory.zig");
|
||||
_ = @import("behavior/fn_in_struct_in_comptime.zig");
|
||||
_ = @import("behavior/generics_llvm.zig");
|
||||
_ = @import("behavior/hasdecl.zig");
|
||||
_ = @import("behavior/hasfield.zig");
|
||||
_ = @import("behavior/namespace_depends_on_compile_var.zig");
|
||||
_ = @import("behavior/optional_llvm.zig");
|
||||
_ = @import("behavior/prefetch.zig");
|
||||
_ = @import("behavior/pub_enum.zig");
|
||||
_ = @import("behavior/slice_sentinel_comptime.zig");
|
||||
@ -60,6 +76,7 @@ test {
|
||||
_ = @import("behavior/type_info.zig");
|
||||
_ = @import("behavior/undefined.zig");
|
||||
_ = @import("behavior/underscore.zig");
|
||||
_ = @import("behavior/union.zig");
|
||||
_ = @import("behavior/usingnamespace.zig");
|
||||
_ = @import("behavior/void.zig");
|
||||
_ = @import("behavior/while.zig");
|
||||
@ -68,30 +85,16 @@ test {
|
||||
// Tests that pass for stage1, llvm backend, C backend
|
||||
_ = @import("behavior/cast_int.zig");
|
||||
_ = @import("behavior/int128.zig");
|
||||
_ = @import("behavior/union.zig");
|
||||
_ = @import("behavior/translate_c_macros.zig");
|
||||
|
||||
if (builtin.zig_backend != .stage2_c) {
|
||||
// Tests that pass for stage1 and the llvm backend.
|
||||
_ = @import("behavior/alignof.zig");
|
||||
_ = @import("behavior/array_llvm.zig");
|
||||
_ = @import("behavior/atomics.zig");
|
||||
_ = @import("behavior/basic_llvm.zig");
|
||||
_ = @import("behavior/bit_shifting.zig");
|
||||
_ = @import("behavior/bugs/394.zig");
|
||||
_ = @import("behavior/bugs/656.zig");
|
||||
_ = @import("behavior/bugs/1277.zig");
|
||||
_ = @import("behavior/bugs/1310.zig");
|
||||
_ = @import("behavior/bugs/1381.zig");
|
||||
_ = @import("behavior/bugs/1500.zig");
|
||||
_ = @import("behavior/bugs/1735.zig");
|
||||
_ = @import("behavior/bugs/1741.zig");
|
||||
_ = @import("behavior/bugs/2006.zig");
|
||||
_ = @import("behavior/bugs/2578.zig");
|
||||
_ = @import("behavior/bugs/3007.zig");
|
||||
_ = @import("behavior/bugs/3112.zig");
|
||||
_ = @import("behavior/bugs/3367.zig");
|
||||
_ = @import("behavior/bugs/7250.zig");
|
||||
_ = @import("behavior/bugs/9584.zig");
|
||||
_ = @import("behavior/cast_llvm.zig");
|
||||
_ = @import("behavior/enum_llvm.zig");
|
||||
@ -99,13 +102,10 @@ test {
|
||||
_ = @import("behavior/eval.zig");
|
||||
_ = @import("behavior/floatop.zig");
|
||||
_ = @import("behavior/fn.zig");
|
||||
_ = @import("behavior/generics_llvm.zig");
|
||||
_ = @import("behavior/math.zig");
|
||||
_ = @import("behavior/maximum_minimum.zig");
|
||||
_ = @import("behavior/merge_error_sets.zig");
|
||||
_ = @import("behavior/namespace_depends_on_compile_var.zig");
|
||||
_ = @import("behavior/null_llvm.zig");
|
||||
_ = @import("behavior/optional_llvm.zig");
|
||||
_ = @import("behavior/popcount.zig");
|
||||
_ = @import("behavior/saturating_arithmetic.zig");
|
||||
_ = @import("behavior/sizeof_and_typeof.zig");
|
||||
|
||||
@ -11,6 +11,9 @@ const Foo = struct {
|
||||
};
|
||||
|
||||
test "@alignOf(T) before referencing T" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
comptime try expect(@alignOf(Foo) != maxInt(usize));
|
||||
if (native_arch == .x86_64) {
|
||||
comptime try expect(@alignOf(Foo) == 4);
|
||||
@ -18,6 +21,9 @@ test "@alignOf(T) before referencing T" {
|
||||
}
|
||||
|
||||
test "comparison of @alignOf(T) against zero" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
{
|
||||
const T = struct { x: u32 };
|
||||
try expect(!(@alignOf(T) == 0));
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
|
||||
const key_bits = @typeInfo(Key).Int.bits;
|
||||
@ -60,6 +61,9 @@ fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, compt
|
||||
}
|
||||
|
||||
test "sharded table" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
// realistic 16-way sharding
|
||||
try testShardedTable(u32, 4, 8);
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const S = struct {
|
||||
f: ?fn () i32,
|
||||
@ -11,5 +12,7 @@ fn f() i32 {
|
||||
}
|
||||
|
||||
test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
try std.testing.expect(s.f.?() == 1234);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub const VM = ?[*]const struct_InvocationTable_;
|
||||
pub const struct_InvocationTable_ = extern struct {
|
||||
@ -22,5 +23,7 @@ fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 {
|
||||
}
|
||||
|
||||
test "fixed" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
try expect(agent_callback(undefined, undefined) == 11);
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const B = union(enum) {
|
||||
D: u8,
|
||||
@ -11,6 +12,8 @@ const A = union(enum) {
|
||||
};
|
||||
|
||||
test "union that needs padding bytes inside an array" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
var as = [_]A{
|
||||
A{ .B = B{ .D = 1 } },
|
||||
A{ .B = B{ .D = 1 } },
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const A = struct {
|
||||
b: B,
|
||||
};
|
||||
@ -5,6 +6,9 @@ const A = struct {
|
||||
const B = *const fn (A) void;
|
||||
|
||||
test "allow these dependencies" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
var a: A = undefined;
|
||||
var b: B = undefined;
|
||||
if (false) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const mystruct = struct {
|
||||
pending: ?listofstructs,
|
||||
@ -41,6 +42,9 @@ const a = struct {
|
||||
};
|
||||
|
||||
test "initialization" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
var t = a.init();
|
||||
try std.testing.expect(t.foo.len == 0);
|
||||
}
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const S = struct {
|
||||
p: *S,
|
||||
};
|
||||
test "bug 2006" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
var a: S = undefined;
|
||||
a = S{ .p = undefined };
|
||||
try expect(@sizeOf(S) != 0);
|
||||
|
||||
@ -13,7 +13,9 @@ fn prev(p: ?State) void {
|
||||
|
||||
test "zig test crash" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
var global: State = undefined;
|
||||
global.enter = prev;
|
||||
global.enter(null);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const Foo = struct {
|
||||
usingnamespace Mixin;
|
||||
};
|
||||
@ -9,6 +10,9 @@ const Mixin = struct {
|
||||
};
|
||||
|
||||
test "container member access usingnamespace decls" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
var foo = Foo{};
|
||||
foo.two();
|
||||
}
|
||||
|
||||
@ -8,8 +8,11 @@ const S = struct {
|
||||
};
|
||||
|
||||
const expect = @import("std").testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
test "bug 394 fixed" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
const x = S{
|
||||
.x = 3,
|
||||
.y = E{ .B = 1 },
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
const expect = @import("std").testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const PrefixOp = union(enum) {
|
||||
Return,
|
||||
@ -10,6 +11,8 @@ const Value = struct {
|
||||
};
|
||||
|
||||
test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
try foo(false, true);
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
const builtin = @import("builtin");
|
||||
const nrfx_uart_t = extern struct {
|
||||
p_reg: [*c]u32,
|
||||
drv_inst_idx: u8,
|
||||
@ -13,5 +14,8 @@ threadlocal var g_uart0 = nrfx_uart_t{
|
||||
};
|
||||
|
||||
test "reference a global threadlocal variable" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
_ = nrfx_uart_rx(&g_uart0);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const foos = [_]fn (anytype) bool{
|
||||
foo1,
|
||||
@ -14,11 +15,17 @@ fn foo2(arg: anytype) bool {
|
||||
}
|
||||
|
||||
test "array of generic fns" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
try expect(foos[0](true));
|
||||
try expect(!foos[1](true));
|
||||
}
|
||||
|
||||
test "generic struct" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
var a1 = GenNode(i32){
|
||||
.value = 13,
|
||||
.next = null,
|
||||
|
||||
@ -3,6 +3,9 @@ const builtin = @import("builtin");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
test "namespace depends on compile var" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (some_namespace.a_bool) {
|
||||
try expect(some_namespace.a_bool);
|
||||
} else {
|
||||
|
||||
@ -2,8 +2,12 @@ const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const expect = testing.expect;
|
||||
const expectEqual = testing.expectEqual;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
test "self-referential struct through a slice of optional" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
const S = struct {
|
||||
const Node = struct {
|
||||
children: []?Node,
|
||||
|
||||
@ -362,6 +362,8 @@ pub const FooUnion = union(enum) {
|
||||
var glbl_array: [2]FooUnion = undefined;
|
||||
|
||||
test "initialize global array of union" {
|
||||
if (@import("builtin").zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
|
||||
glbl_array[1] = FooUnion{ .U1 = 2 };
|
||||
glbl_array[0] = FooUnion{ .U0 = 1 };
|
||||
try expect(glbl_array[0].U0 == 1);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user