mirror of
https://github.com/ziglang/zig.git
synced 2025-12-17 11:43:16 +00:00
Merge pull request #11036 from ziglang/x64-optionals
x64: handle more optional types
This commit is contained in:
commit
aa867c7dbe
@ -472,10 +472,14 @@ fn gen(self: *Self) InnerError!void {
|
|||||||
.regs = 0,
|
.regs = 0,
|
||||||
.disp = mem.alignForwardGeneric(u32, self.next_stack_offset, 8),
|
.disp = mem.alignForwardGeneric(u32, self.next_stack_offset, 8),
|
||||||
};
|
};
|
||||||
|
var disp = data.disp + 8;
|
||||||
inline for (callee_preserved_regs) |reg, i| {
|
inline for (callee_preserved_regs) |reg, i| {
|
||||||
if (self.register_manager.isRegAllocated(reg)) {
|
if (self.register_manager.isRegAllocated(reg)) {
|
||||||
if (reg.to64() == .rdi) {
|
if (reg.to64() == .rdi) {
|
||||||
for (self.ret_backpatches.items) |inst| {
|
for (self.ret_backpatches.items) |inst| {
|
||||||
|
log.debug(".rdi was spilled, backpatching with mov from stack at offset {}", .{
|
||||||
|
-@intCast(i32, disp),
|
||||||
|
});
|
||||||
const ops = Mir.Ops.decode(self.mir_instructions.items(.ops)[inst]);
|
const ops = Mir.Ops.decode(self.mir_instructions.items(.ops)[inst]);
|
||||||
self.mir_instructions.set(inst, Mir.Inst{
|
self.mir_instructions.set(inst, Mir.Inst{
|
||||||
.tag = .mov,
|
.tag = .mov,
|
||||||
@ -484,12 +488,13 @@ fn gen(self: *Self) InnerError!void {
|
|||||||
.reg2 = .rbp,
|
.reg2 = .rbp,
|
||||||
.flags = 0b01,
|
.flags = 0b01,
|
||||||
}).encode(),
|
}).encode(),
|
||||||
.data = .{ .imm = @bitCast(u32, -@intCast(i32, self.max_end_stack + 8)) },
|
.data = .{ .imm = @bitCast(u32, -@intCast(i32, disp)) },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.regs |= 1 << @intCast(u5, i);
|
data.regs |= 1 << @intCast(u5, i);
|
||||||
self.max_end_stack += 8;
|
self.max_end_stack += 8;
|
||||||
|
disp += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break :blk try self.addExtra(data);
|
break :blk try self.addExtra(data);
|
||||||
@ -981,7 +986,10 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
operand.freezeIfRegister(&self.register_manager);
|
operand.freezeIfRegister(&self.register_manager);
|
||||||
defer operand.unfreezeIfRegister(&self.register_manager);
|
defer operand.unfreezeIfRegister(&self.register_manager);
|
||||||
|
|
||||||
break :blk try self.copyToRegisterWithInstTracking(inst, dest_ty, operand);
|
const reg = try self.register_manager.allocReg(inst);
|
||||||
|
try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
|
||||||
|
try self.genSetReg(operand_ty, reg, operand);
|
||||||
|
break :blk MCValue{ .register = reg };
|
||||||
};
|
};
|
||||||
|
|
||||||
return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
|
return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
|
||||||
@ -1704,12 +1712,36 @@ fn airShr(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
|
|
||||||
fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
|
fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
if (self.liveness.isUnused(inst)) {
|
||||||
|
return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload_ty = self.air.typeOfIndex(inst);
|
||||||
|
const optional_ty = self.air.typeOf(ty_op.operand);
|
||||||
const operand = try self.resolveInst(ty_op.operand);
|
const operand = try self.resolveInst(ty_op.operand);
|
||||||
|
const result: MCValue = result: {
|
||||||
|
if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
|
||||||
|
if (optional_ty.isPtrLikeOptional()) {
|
||||||
if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
|
if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
|
||||||
break :result operand;
|
break :result operand;
|
||||||
}
|
}
|
||||||
break :result try self.copyToRegisterWithInstTracking(inst, self.air.typeOfIndex(inst), operand);
|
break :result try self.copyToRegisterWithInstTracking(inst, payload_ty, operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
const offset = optional_ty.abiSize(self.target.*) - payload_ty.abiSize(self.target.*);
|
||||||
|
switch (operand) {
|
||||||
|
.stack_offset => |off| {
|
||||||
|
break :result MCValue{ .stack_offset = off - @intCast(i32, offset) };
|
||||||
|
},
|
||||||
|
.register => {
|
||||||
|
// TODO reuse the operand
|
||||||
|
const result = try self.copyToRegisterWithInstTracking(inst, optional_ty, operand);
|
||||||
|
const shift = @intCast(u8, offset * 8);
|
||||||
|
try self.shiftRegister(result.register, @intCast(u8, shift));
|
||||||
|
break :result result;
|
||||||
|
},
|
||||||
|
else => return self.fail("TODO implement optional_payload when operand is {}", .{operand}),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||||
}
|
}
|
||||||
@ -1827,14 +1859,38 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
|
|
||||||
fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
|
fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
if (self.liveness.isUnused(inst)) {
|
||||||
const optional_ty = self.air.typeOfIndex(inst);
|
return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
|
||||||
|
}
|
||||||
|
|
||||||
// Optional with a zero-bit payload type is just a boolean true
|
const payload_ty = self.air.typeOf(ty_op.operand);
|
||||||
if (optional_ty.abiSize(self.target.*) == 1)
|
const result: MCValue = result: {
|
||||||
|
if (!payload_ty.hasRuntimeBits()) {
|
||||||
break :result MCValue{ .immediate = 1 };
|
break :result MCValue{ .immediate = 1 };
|
||||||
|
}
|
||||||
|
|
||||||
return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});
|
const optional_ty = self.air.typeOfIndex(inst);
|
||||||
|
const operand = try self.resolveInst(ty_op.operand);
|
||||||
|
operand.freezeIfRegister(&self.register_manager);
|
||||||
|
defer operand.unfreezeIfRegister(&self.register_manager);
|
||||||
|
|
||||||
|
if (optional_ty.isPtrLikeOptional()) {
|
||||||
|
// TODO should we check if we can reuse the operand?
|
||||||
|
if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
|
||||||
|
break :result operand;
|
||||||
|
}
|
||||||
|
break :result try self.copyToRegisterWithInstTracking(inst, payload_ty, operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
const optional_abi_size = @intCast(u32, optional_ty.abiSize(self.target.*));
|
||||||
|
const optional_abi_align = optional_ty.abiAlignment(self.target.*);
|
||||||
|
const payload_abi_size = @intCast(u32, payload_ty.abiSize(self.target.*));
|
||||||
|
const offset = optional_abi_size - payload_abi_size;
|
||||||
|
|
||||||
|
const stack_offset = @intCast(i32, try self.allocMem(inst, optional_abi_size, optional_abi_align));
|
||||||
|
try self.genSetStack(Type.bool, stack_offset, .{ .immediate = 1 }, .{});
|
||||||
|
try self.genSetStack(payload_ty, stack_offset - @intCast(i32, offset), operand, .{});
|
||||||
|
break :result MCValue{ .stack_offset = stack_offset };
|
||||||
};
|
};
|
||||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||||
}
|
}
|
||||||
@ -3761,7 +3817,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValu
|
|||||||
try self.spillCompareFlagsIfOccupied();
|
try self.spillCompareFlagsIfOccupied();
|
||||||
self.compare_flags_inst = inst;
|
self.compare_flags_inst = inst;
|
||||||
|
|
||||||
try self.genBinMathOpMir(.cmp, ty, operand, MCValue{ .immediate = 0 });
|
const cmp_ty: Type = if (!ty.isPtrLikeOptional()) blk: {
|
||||||
|
var buf: Type.Payload.ElemType = undefined;
|
||||||
|
const payload_ty = ty.optionalChild(&buf);
|
||||||
|
break :blk if (payload_ty.hasRuntimeBits()) Type.bool else ty;
|
||||||
|
} else ty;
|
||||||
|
|
||||||
|
try self.genBinMathOpMir(.cmp, cmp_ty, operand, MCValue{ .immediate = 0 });
|
||||||
|
|
||||||
return MCValue{ .compare_flags_unsigned = .eq };
|
return MCValue{ .compare_flags_unsigned = .eq };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5625,7 +5688,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
|
|||||||
.val = typed_value.val,
|
.val = typed_value.val,
|
||||||
});
|
});
|
||||||
} else if (typed_value.ty.abiSize(self.target.*) == 1) {
|
} else if (typed_value.ty.abiSize(self.target.*) == 1) {
|
||||||
return MCValue{ .immediate = @boolToInt(typed_value.val.isNull()) };
|
return MCValue{ .immediate = @boolToInt(!typed_value.val.isNull()) };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Enum => {
|
.Enum => {
|
||||||
|
|||||||
100
src/codegen.zig
100
src/codegen.zig
@ -140,6 +140,16 @@ pub fn generateFunction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian, code: []u8) void {
|
||||||
|
_ = target;
|
||||||
|
const Int = @Type(.{ .Int = .{
|
||||||
|
.signedness = .unsigned,
|
||||||
|
.bits = @typeInfo(F).Float.bits,
|
||||||
|
} });
|
||||||
|
const int = @bitCast(Int, f);
|
||||||
|
mem.writeInt(Int, code[0..@sizeOf(Int)], int, endian);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generateSymbol(
|
pub fn generateSymbol(
|
||||||
bin_file: *link.File,
|
bin_file: *link.File,
|
||||||
src_loc: Module.SrcLoc,
|
src_loc: Module.SrcLoc,
|
||||||
@ -151,10 +161,12 @@ pub fn generateSymbol(
|
|||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
|
const target = bin_file.options.target;
|
||||||
|
const endian = target.cpu.arch.endian();
|
||||||
|
|
||||||
log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val });
|
log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val });
|
||||||
|
|
||||||
if (typed_value.val.isUndefDeep()) {
|
if (typed_value.val.isUndefDeep()) {
|
||||||
const target = bin_file.options.target;
|
|
||||||
const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
|
const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
|
||||||
try code.appendNTimes(0xaa, abi_size);
|
try code.appendNTimes(0xaa, abi_size);
|
||||||
return Result{ .appended = {} };
|
return Result{ .appended = {} };
|
||||||
@ -171,6 +183,25 @@ pub fn generateSymbol(
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
.Float => {
|
||||||
|
const float_bits = typed_value.ty.floatBits(target);
|
||||||
|
switch (float_bits) {
|
||||||
|
16 => writeFloat(f16, typed_value.val.toFloat(f16), target, endian, try code.addManyAsArray(2)),
|
||||||
|
32 => writeFloat(f32, typed_value.val.toFloat(f32), target, endian, try code.addManyAsArray(4)),
|
||||||
|
64 => writeFloat(f64, typed_value.val.toFloat(f64), target, endian, try code.addManyAsArray(8)),
|
||||||
|
80 => return Result{
|
||||||
|
.fail = try ErrorMsg.create(
|
||||||
|
bin_file.allocator,
|
||||||
|
src_loc,
|
||||||
|
"TODO handle f80 in generateSymbol",
|
||||||
|
.{},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
128 => writeFloat(f128, typed_value.val.toFloat(f128), target, endian, try code.addManyAsArray(16)),
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
return Result{ .appended = {} };
|
||||||
|
},
|
||||||
.Array => switch (typed_value.val.tag()) {
|
.Array => switch (typed_value.val.tag()) {
|
||||||
.bytes => {
|
.bytes => {
|
||||||
// TODO populate .debug_info for the array
|
// TODO populate .debug_info for the array
|
||||||
@ -311,7 +342,6 @@ pub fn generateSymbol(
|
|||||||
return Result{ .appended = {} };
|
return Result{ .appended = {} };
|
||||||
},
|
},
|
||||||
.field_ptr => {
|
.field_ptr => {
|
||||||
const target = bin_file.options.target;
|
|
||||||
const field_ptr = typed_value.val.castTag(.field_ptr).?.data;
|
const field_ptr = typed_value.val.castTag(.field_ptr).?.data;
|
||||||
const container_ptr = field_ptr.container_ptr;
|
const container_ptr = field_ptr.container_ptr;
|
||||||
|
|
||||||
@ -373,7 +403,6 @@ pub fn generateSymbol(
|
|||||||
},
|
},
|
||||||
.Int => {
|
.Int => {
|
||||||
// TODO populate .debug_info for the integer
|
// TODO populate .debug_info for the integer
|
||||||
const endian = bin_file.options.target.cpu.arch.endian();
|
|
||||||
const info = typed_value.ty.intInfo(bin_file.options.target);
|
const info = typed_value.ty.intInfo(bin_file.options.target);
|
||||||
if (info.bits <= 8) {
|
if (info.bits <= 8) {
|
||||||
const x = @intCast(u8, typed_value.val.toUnsignedInt());
|
const x = @intCast(u8, typed_value.val.toUnsignedInt());
|
||||||
@ -423,7 +452,6 @@ pub fn generateSymbol(
|
|||||||
var int_buffer: Value.Payload.U64 = undefined;
|
var int_buffer: Value.Payload.U64 = undefined;
|
||||||
const int_val = typed_value.enumToInt(&int_buffer);
|
const int_val = typed_value.enumToInt(&int_buffer);
|
||||||
|
|
||||||
const target = bin_file.options.target;
|
|
||||||
const info = typed_value.ty.intInfo(target);
|
const info = typed_value.ty.intInfo(target);
|
||||||
if (info.bits <= 8) {
|
if (info.bits <= 8) {
|
||||||
const x = @intCast(u8, int_val.toUnsignedInt());
|
const x = @intCast(u8, int_val.toUnsignedInt());
|
||||||
@ -440,7 +468,6 @@ pub fn generateSymbol(
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const endian = target.cpu.arch.endian();
|
|
||||||
switch (info.signedness) {
|
switch (info.signedness) {
|
||||||
.unsigned => {
|
.unsigned => {
|
||||||
if (info.bits <= 16) {
|
if (info.bits <= 16) {
|
||||||
@ -506,7 +533,6 @@ pub fn generateSymbol(
|
|||||||
const unpadded_field_end = code.items.len - struct_begin;
|
const unpadded_field_end = code.items.len - struct_begin;
|
||||||
|
|
||||||
// Pad struct members if required
|
// Pad struct members if required
|
||||||
const target = bin_file.options.target;
|
|
||||||
const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target);
|
const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target);
|
||||||
const padding = try math.cast(usize, padded_field_end - unpadded_field_end);
|
const padding = try math.cast(usize, padded_field_end - unpadded_field_end);
|
||||||
|
|
||||||
@ -519,7 +545,6 @@ pub fn generateSymbol(
|
|||||||
},
|
},
|
||||||
.Union => {
|
.Union => {
|
||||||
// TODO generate debug info for unions
|
// TODO generate debug info for unions
|
||||||
const target = bin_file.options.target;
|
|
||||||
const union_obj = typed_value.val.castTag(.@"union").?.data;
|
const union_obj = typed_value.val.castTag(.@"union").?.data;
|
||||||
const layout = typed_value.ty.unionGetLayout(target);
|
const layout = typed_value.ty.unionGetLayout(target);
|
||||||
|
|
||||||
@ -590,19 +615,69 @@ pub fn generateSymbol(
|
|||||||
return Result{ .appended = {} };
|
return Result{ .appended = {} };
|
||||||
},
|
},
|
||||||
.Optional => {
|
.Optional => {
|
||||||
// TODO generateSymbol for optionals
|
// TODO generate debug info for optionals
|
||||||
const target = bin_file.options.target;
|
var opt_buf: Type.Payload.ElemType = undefined;
|
||||||
|
const payload_type = typed_value.ty.optionalChild(&opt_buf);
|
||||||
|
const is_pl = !typed_value.val.isNull();
|
||||||
const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
|
const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
|
||||||
try code.writer().writeByteNTimes(0xaa, abi_size);
|
const offset = abi_size - try math.cast(usize, payload_type.abiSize(target));
|
||||||
|
|
||||||
|
if (!payload_type.hasRuntimeBits()) {
|
||||||
|
try code.writer().writeByteNTimes(@boolToInt(is_pl), abi_size);
|
||||||
|
return Result{ .appended = {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typed_value.ty.isPtrLikeOptional()) {
|
||||||
|
if (typed_value.val.castTag(.opt_payload)) |payload| {
|
||||||
|
switch (try generateSymbol(bin_file, src_loc, .{
|
||||||
|
.ty = payload_type,
|
||||||
|
.val = payload.data,
|
||||||
|
}, code, debug_output, reloc_info)) {
|
||||||
|
.appended => {},
|
||||||
|
.externally_managed => |external_slice| {
|
||||||
|
code.appendSliceAssumeCapacity(external_slice);
|
||||||
|
},
|
||||||
|
.fail => |em| return Result{ .fail = em },
|
||||||
|
}
|
||||||
|
} else if (!typed_value.val.isNull()) {
|
||||||
|
switch (try generateSymbol(bin_file, src_loc, .{
|
||||||
|
.ty = payload_type,
|
||||||
|
.val = typed_value.val,
|
||||||
|
}, code, debug_output, reloc_info)) {
|
||||||
|
.appended => {},
|
||||||
|
.externally_managed => |external_slice| {
|
||||||
|
code.appendSliceAssumeCapacity(external_slice);
|
||||||
|
},
|
||||||
|
.fail => |em| return Result{ .fail = em },
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try code.writer().writeByteNTimes(0, abi_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result{ .appended = {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef);
|
||||||
|
try code.writer().writeByteNTimes(@boolToInt(is_pl), offset);
|
||||||
|
switch (try generateSymbol(bin_file, src_loc, .{
|
||||||
|
.ty = payload_type,
|
||||||
|
.val = value,
|
||||||
|
}, code, debug_output, reloc_info)) {
|
||||||
|
.appended => {},
|
||||||
|
.externally_managed => |external_slice| {
|
||||||
|
code.appendSliceAssumeCapacity(external_slice);
|
||||||
|
},
|
||||||
|
.fail => |em| return Result{ .fail = em },
|
||||||
|
}
|
||||||
|
|
||||||
return Result{ .appended = {} };
|
return Result{ .appended = {} };
|
||||||
},
|
},
|
||||||
.ErrorUnion => {
|
.ErrorUnion => {
|
||||||
|
// TODO generate debug info for error unions
|
||||||
const error_ty = typed_value.ty.errorUnionSet();
|
const error_ty = typed_value.ty.errorUnionSet();
|
||||||
const payload_ty = typed_value.ty.errorUnionPayload();
|
const payload_ty = typed_value.ty.errorUnionPayload();
|
||||||
const is_payload = typed_value.val.errorUnionIsPayload();
|
const is_payload = typed_value.val.errorUnionIsPayload();
|
||||||
|
|
||||||
const target = bin_file.options.target;
|
|
||||||
const abi_align = typed_value.ty.abiAlignment(target);
|
const abi_align = typed_value.ty.abiAlignment(target);
|
||||||
|
|
||||||
const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
|
const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
|
||||||
@ -643,12 +718,11 @@ pub fn generateSymbol(
|
|||||||
return Result{ .appended = {} };
|
return Result{ .appended = {} };
|
||||||
},
|
},
|
||||||
.ErrorSet => {
|
.ErrorSet => {
|
||||||
const target = bin_file.options.target;
|
// TODO generate debug info for error sets
|
||||||
switch (typed_value.val.tag()) {
|
switch (typed_value.val.tag()) {
|
||||||
.@"error" => {
|
.@"error" => {
|
||||||
const name = typed_value.val.getError().?;
|
const name = typed_value.val.getError().?;
|
||||||
const kv = try bin_file.options.module.?.getErrorValue(name);
|
const kv = try bin_file.options.module.?.getErrorValue(name);
|
||||||
const endian = target.cpu.arch.endian();
|
|
||||||
try code.writer().writeInt(u32, kv.value, endian);
|
try code.writer().writeInt(u32, kv.value, endian);
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
|||||||
@ -728,7 +728,6 @@ test "thread local variable" {
|
|||||||
test "result location is optional inside error union" {
|
test "result location is optional inside error union" {
|
||||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
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_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_aarch64) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,6 @@ fn parseNote() ?i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "fixed" {
|
test "fixed" {
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,6 @@ test "zig test crash" {
|
|||||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_c) 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_arm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
||||||
var global: State = undefined;
|
var global: State = undefined;
|
||||||
global.enter = prev;
|
global.enter = prev;
|
||||||
global.enter(null);
|
global.enter(null);
|
||||||
|
|||||||
@ -19,7 +19,7 @@ test "integer literal to pointer cast" {
|
|||||||
|
|
||||||
test "peer type resolution: ?T and T" {
|
test "peer type resolution: ?T and T" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
|
|
||||||
try expect(peerTypeTAndOptionalT(true, false).? == 0);
|
try expect(peerTypeTAndOptionalT(true, false).? == 0);
|
||||||
try expect(peerTypeTAndOptionalT(false, false).? == 3);
|
try expect(peerTypeTAndOptionalT(false, false).? == 3);
|
||||||
@ -179,7 +179,7 @@ test "@floatCast comptime_int and comptime_float" {
|
|||||||
|
|
||||||
test "coerce undefined to optional" {
|
test "coerce undefined to optional" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
|
|
||||||
try expect(MakeType(void).getNull() == null);
|
try expect(MakeType(void).getNull() == null);
|
||||||
try expect(MakeType(void).getNonNull() != null);
|
try expect(MakeType(void).getNonNull() != null);
|
||||||
@ -237,7 +237,7 @@ test "@intCast to u0 and use the result" {
|
|||||||
|
|
||||||
test "peer result null and comptime_int" {
|
test "peer result null and comptime_int" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn blah(n: i32) ?i32 {
|
fn blah(n: i32) ?i32 {
|
||||||
@ -302,7 +302,7 @@ fn implicitIntLitToOptional() void {
|
|||||||
|
|
||||||
test "return u8 coercing into ?u32 return type" {
|
test "return u8 coercing into ?u32 return type" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn doTheTest() !void {
|
fn doTheTest() !void {
|
||||||
@ -373,7 +373,6 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {
|
|||||||
test "implicitly cast from T to anyerror!?T" {
|
test "implicitly cast from T to anyerror!?T" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
||||||
|
|
||||||
try castToOptionalTypeError(1);
|
try castToOptionalTypeError(1);
|
||||||
comptime try castToOptionalTypeError(1);
|
comptime try castToOptionalTypeError(1);
|
||||||
@ -1036,7 +1035,6 @@ test "implicit cast from [*]T to ?*anyopaque" {
|
|||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
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_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
var a = [_]u8{ 3, 2, 1 };
|
var a = [_]u8{ 3, 2, 1 };
|
||||||
var runtime_zero: usize = 0;
|
var runtime_zero: usize = 0;
|
||||||
@ -1073,7 +1071,6 @@ test "implicit ptr to *anyopaque" {
|
|||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
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_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
var a: u32 = 1;
|
var a: u32 = 1;
|
||||||
var ptr: *align(@alignOf(u32)) anyopaque = &a;
|
var ptr: *align(@alignOf(u32)) anyopaque = &a;
|
||||||
@ -1087,7 +1084,6 @@ test "implicit ptr to *anyopaque" {
|
|||||||
test "return null from fn() anyerror!?&T" {
|
test "return null from fn() anyerror!?&T" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
const a = returnNullFromOptionalTypeErrorRef();
|
const a = returnNullFromOptionalTypeErrorRef();
|
||||||
const b = returnNullLitFromOptionalTypeErrorRef();
|
const b = returnNullLitFromOptionalTypeErrorRef();
|
||||||
@ -1125,7 +1121,6 @@ test "implicitly cast from [N]T to ?[]const T" {
|
|||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
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_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
||||||
comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
||||||
@ -1177,7 +1172,6 @@ test "implicit cast from *T to ?*anyopaque" {
|
|||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
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_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
var a: u8 = 1;
|
var a: u8 = 1;
|
||||||
incrementVoidPtrValue(&a);
|
incrementVoidPtrValue(&a);
|
||||||
@ -1213,7 +1207,6 @@ test "*const [N]null u8 to ?[]const u8" {
|
|||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
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_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn doTheTest() !void {
|
fn doTheTest() !void {
|
||||||
@ -1249,7 +1242,6 @@ test "assignment to optional pointer result loc" {
|
|||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
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_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };
|
var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };
|
||||||
try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct));
|
try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct));
|
||||||
|
|||||||
@ -1083,7 +1083,6 @@ test "@tagName on enum literals" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "enum literal casting to optional" {
|
test "enum literal casting to optional" {
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@ const expectEqual = testing.expectEqual;
|
|||||||
test "passing an optional integer as a parameter" {
|
test "passing an optional integer as a parameter" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn entry() bool {
|
fn entry() bool {
|
||||||
@ -60,7 +59,6 @@ fn testNullPtrsEql() !void {
|
|||||||
test "optional with void type" {
|
test "optional with void type" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
const Foo = struct {
|
const Foo = struct {
|
||||||
x: ?void,
|
x: ?void,
|
||||||
@ -171,7 +169,6 @@ test "unwrap function call with optional pointer return value" {
|
|||||||
test "nested orelse" {
|
test "nested orelse" {
|
||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn entry() !void {
|
fn entry() !void {
|
||||||
@ -199,7 +196,6 @@ test "self-referential struct through a slice of optional" {
|
|||||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
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_arm) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
const Node = struct {
|
const Node = struct {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user