mirror of
https://github.com/ziglang/zig.git
synced 2025-12-21 13:43:10 +00:00
stage2 ARM: generate correct variants of ldr instruction
When loading an i16 for example, generate ldrsh instead of ldrh
This commit is contained in:
parent
8ef80cfaab
commit
f48f4baf67
@ -1575,7 +1575,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
|
|||||||
.compare_flags_signed, .compare_flags_unsigned => unreachable,
|
.compare_flags_signed, .compare_flags_unsigned => unreachable,
|
||||||
.embedded_in_code => unreachable,
|
.embedded_in_code => unreachable,
|
||||||
.register => |dst_reg| {
|
.register => |dst_reg| {
|
||||||
try self.genLdrRegister(dst_reg, reg, elem_size);
|
try self.genLdrRegister(dst_reg, reg, elem_ty);
|
||||||
},
|
},
|
||||||
.stack_offset => |off| {
|
.stack_offset => |off| {
|
||||||
if (elem_size <= 4) {
|
if (elem_size <= 4) {
|
||||||
@ -1676,7 +1676,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
|
|||||||
|
|
||||||
switch (value) {
|
switch (value) {
|
||||||
.register => |value_reg| {
|
.register => |value_reg| {
|
||||||
try self.genStrRegister(value_reg, addr_reg, @intCast(u32, value_ty.abiSize(self.target.*)));
|
try self.genStrRegister(value_reg, addr_reg, value_ty);
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
if (value_ty.abiSize(self.target.*) <= 4) {
|
if (value_ty.abiSize(self.target.*) <= 4) {
|
||||||
@ -2241,68 +2241,71 @@ fn binOp(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, abi_size: u32) !void {
|
fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void {
|
||||||
switch (abi_size) {
|
const abi_size = ty.abiSize(self.target.*);
|
||||||
1, 3, 4 => {
|
|
||||||
const tag: Mir.Inst.Tag = switch (abi_size) {
|
const tag: Mir.Inst.Tag = switch (abi_size) {
|
||||||
1 => .ldrb,
|
1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb,
|
||||||
|
2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh,
|
||||||
3, 4 => .ldr,
|
3, 4 => .ldr,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = try self.addInst(.{
|
const rr_offset: Mir.Inst.Data = .{ .rr_offset = .{
|
||||||
.tag = tag,
|
|
||||||
.data = .{ .rr_offset = .{
|
|
||||||
.rt = dest_reg,
|
.rt = dest_reg,
|
||||||
.rn = addr_reg,
|
.rn = addr_reg,
|
||||||
.offset = .{ .offset = Instruction.Offset.none },
|
.offset = .{ .offset = Instruction.Offset.none },
|
||||||
} },
|
} };
|
||||||
});
|
const rr_extra_offset: Mir.Inst.Data = .{ .rr_extra_offset = .{
|
||||||
},
|
|
||||||
2 => {
|
|
||||||
_ = try self.addInst(.{
|
|
||||||
.tag = .ldrh,
|
|
||||||
.data = .{ .rr_extra_offset = .{
|
|
||||||
.rt = dest_reg,
|
.rt = dest_reg,
|
||||||
.rn = addr_reg,
|
.rn = addr_reg,
|
||||||
.offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none },
|
.offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none },
|
||||||
} },
|
} };
|
||||||
});
|
|
||||||
},
|
|
||||||
else => unreachable, // invalid abi_size for a register
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, abi_size: u32) !void {
|
const data: Mir.Inst.Data = switch (abi_size) {
|
||||||
switch (abi_size) {
|
1 => if (ty.isSignedInt()) rr_extra_offset else rr_offset,
|
||||||
1, 3, 4 => {
|
2 => rr_extra_offset,
|
||||||
const tag: Mir.Inst.Tag = switch (abi_size) {
|
3, 4 => rr_offset,
|
||||||
1 => .strb,
|
|
||||||
3, 4 => .str,
|
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = tag,
|
.tag = tag,
|
||||||
.data = .{ .rr_offset = .{
|
.data = data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Type) !void {
|
||||||
|
const abi_size = ty.abiSize(self.target.*);
|
||||||
|
|
||||||
|
const tag: Mir.Inst.Tag = switch (abi_size) {
|
||||||
|
1 => .strb,
|
||||||
|
2 => .strh,
|
||||||
|
3, 4 => .str,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
const rr_offset: Mir.Inst.Data = .{ .rr_offset = .{
|
||||||
.rt = source_reg,
|
.rt = source_reg,
|
||||||
.rn = addr_reg,
|
.rn = addr_reg,
|
||||||
.offset = .{ .offset = Instruction.Offset.none },
|
.offset = .{ .offset = Instruction.Offset.none },
|
||||||
} },
|
} };
|
||||||
});
|
const rr_extra_offset: Mir.Inst.Data = .{ .rr_extra_offset = .{
|
||||||
},
|
|
||||||
2 => {
|
|
||||||
_ = try self.addInst(.{
|
|
||||||
.tag = .strh,
|
|
||||||
.data = .{ .rr_extra_offset = .{
|
|
||||||
.rt = source_reg,
|
.rt = source_reg,
|
||||||
.rn = addr_reg,
|
.rn = addr_reg,
|
||||||
.offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none },
|
.offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none },
|
||||||
} },
|
} };
|
||||||
|
|
||||||
|
const data: Mir.Inst.Data = switch (abi_size) {
|
||||||
|
1, 3, 4 => rr_offset,
|
||||||
|
2 => rr_extra_offset,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
_ = try self.addInst(.{
|
||||||
|
.tag = tag,
|
||||||
|
.data = data,
|
||||||
});
|
});
|
||||||
},
|
|
||||||
else => unreachable, // invalid abi_size for a register
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genInlineMemcpy(
|
fn genInlineMemcpy(
|
||||||
@ -2895,8 +2898,6 @@ fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
|
fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
|
||||||
_ = operand;
|
|
||||||
|
|
||||||
const error_type = ty.errorUnionSet();
|
const error_type = ty.errorUnionSet();
|
||||||
const payload_type = ty.errorUnionPayload();
|
const payload_type = ty.errorUnionPayload();
|
||||||
|
|
||||||
@ -3630,25 +3631,48 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
|||||||
// The value is in memory at a hard-coded address.
|
// The value is in memory at a hard-coded address.
|
||||||
// If the type is a pointer, it means the pointer address is at this memory location.
|
// If the type is a pointer, it means the pointer address is at this memory location.
|
||||||
try self.genSetReg(ty, reg, .{ .immediate = @intCast(u32, addr) });
|
try self.genSetReg(ty, reg, .{ .immediate = @intCast(u32, addr) });
|
||||||
try self.genLdrRegister(reg, reg, @intCast(u32, ty.abiSize(self.target.*)));
|
try self.genLdrRegister(reg, reg, ty);
|
||||||
},
|
},
|
||||||
.stack_offset => |unadjusted_off| {
|
.stack_offset => |unadjusted_off| {
|
||||||
// TODO: maybe addressing from sp instead of fp
|
// TODO: maybe addressing from sp instead of fp
|
||||||
const abi_size = @intCast(u32, ty.abiSize(self.target.*));
|
const abi_size = @intCast(u32, ty.abiSize(self.target.*));
|
||||||
const adj_off = unadjusted_off + abi_size;
|
const adj_off = unadjusted_off + abi_size;
|
||||||
|
|
||||||
switch (abi_size) {
|
const tag: Mir.Inst.Tag = switch (abi_size) {
|
||||||
1, 4 => {
|
1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb,
|
||||||
|
2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh,
|
||||||
|
3, 4 => .ldr,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
const extra_offset = switch (abi_size) {
|
||||||
|
1 => ty.isSignedInt(),
|
||||||
|
2 => true,
|
||||||
|
3, 4 => false,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (extra_offset) {
|
||||||
|
const offset = if (adj_off <= math.maxInt(u8)) blk: {
|
||||||
|
break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, adj_off));
|
||||||
|
} else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off }));
|
||||||
|
|
||||||
|
_ = try self.addInst(.{
|
||||||
|
.tag = tag,
|
||||||
|
.data = .{ .rr_extra_offset = .{
|
||||||
|
.rt = reg,
|
||||||
|
.rn = .fp,
|
||||||
|
.offset = .{
|
||||||
|
.offset = offset,
|
||||||
|
.positive = false,
|
||||||
|
},
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
const offset = if (adj_off <= math.maxInt(u12)) blk: {
|
const offset = if (adj_off <= math.maxInt(u12)) blk: {
|
||||||
break :blk Instruction.Offset.imm(@intCast(u12, adj_off));
|
break :blk Instruction.Offset.imm(@intCast(u12, adj_off));
|
||||||
} else Instruction.Offset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off }), .none);
|
} else Instruction.Offset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off }), .none);
|
||||||
|
|
||||||
const tag: Mir.Inst.Tag = switch (abi_size) {
|
|
||||||
1 => .ldrb,
|
|
||||||
4 => .ldr,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
|
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = tag,
|
.tag = tag,
|
||||||
.data = .{ .rr_offset = .{
|
.data = .{ .rr_offset = .{
|
||||||
@ -3660,25 +3684,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
|||||||
},
|
},
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
},
|
|
||||||
2 => {
|
|
||||||
const offset = if (adj_off <= math.maxInt(u8)) blk: {
|
|
||||||
break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, adj_off));
|
|
||||||
} else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off }));
|
|
||||||
|
|
||||||
_ = try self.addInst(.{
|
|
||||||
.tag = .ldrh,
|
|
||||||
.data = .{ .rr_extra_offset = .{
|
|
||||||
.rt = reg,
|
|
||||||
.rn = .fp,
|
|
||||||
.offset = .{
|
|
||||||
.offset = offset,
|
|
||||||
.positive = false,
|
|
||||||
},
|
|
||||||
} },
|
|
||||||
});
|
|
||||||
},
|
|
||||||
else => return self.fail("TODO a type of size {} is not allowed in a register", .{abi_size}),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.stack_argument_offset => |unadjusted_off| {
|
.stack_argument_offset => |unadjusted_off| {
|
||||||
@ -3686,9 +3691,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
|||||||
const adj_off = unadjusted_off + abi_size;
|
const adj_off = unadjusted_off + abi_size;
|
||||||
|
|
||||||
const tag: Mir.Inst.Tag = switch (abi_size) {
|
const tag: Mir.Inst.Tag = switch (abi_size) {
|
||||||
1 => .ldrb_stack_argument,
|
1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument,
|
||||||
2 => .ldrh_stack_argument,
|
2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument,
|
||||||
4 => .ldr_stack_argument,
|
3, 4 => .ldr_stack_argument,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -115,8 +115,12 @@ pub fn emitMir(
|
|||||||
.ldr_stack_argument => try emit.mirLoadStackArgument(inst),
|
.ldr_stack_argument => try emit.mirLoadStackArgument(inst),
|
||||||
.ldrb_stack_argument => try emit.mirLoadStackArgument(inst),
|
.ldrb_stack_argument => try emit.mirLoadStackArgument(inst),
|
||||||
.ldrh_stack_argument => try emit.mirLoadStackArgument(inst),
|
.ldrh_stack_argument => try emit.mirLoadStackArgument(inst),
|
||||||
|
.ldrsb_stack_argument => try emit.mirLoadStackArgument(inst),
|
||||||
|
.ldrsh_stack_argument => try emit.mirLoadStackArgument(inst),
|
||||||
|
|
||||||
.ldrh => try emit.mirLoadStoreExtra(inst),
|
.ldrh => try emit.mirLoadStoreExtra(inst),
|
||||||
|
.ldrsb => try emit.mirLoadStore(inst),
|
||||||
|
.ldrsh => try emit.mirLoadStoreExtra(inst),
|
||||||
.strh => try emit.mirLoadStoreExtra(inst),
|
.strh => try emit.mirLoadStoreExtra(inst),
|
||||||
|
|
||||||
.movw => try emit.mirSpecialMove(inst),
|
.movw => try emit.mirSpecialMove(inst),
|
||||||
@ -593,36 +597,42 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
|
|||||||
|
|
||||||
const raw_offset = emit.prologue_stack_space - r_stack_offset.stack_offset;
|
const raw_offset = emit.prologue_stack_space - r_stack_offset.stack_offset;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
.ldr_stack_argument => {
|
.ldr_stack_argument,
|
||||||
|
.ldrb_stack_argument,
|
||||||
|
=> {
|
||||||
const offset = if (raw_offset <= math.maxInt(u12)) blk: {
|
const offset = if (raw_offset <= math.maxInt(u12)) blk: {
|
||||||
break :blk Instruction.Offset.imm(@intCast(u12, raw_offset));
|
break :blk Instruction.Offset.imm(@intCast(u12, raw_offset));
|
||||||
} else return emit.fail("TODO mirLoadStack larger offsets", .{});
|
} else return emit.fail("TODO mirLoadStack larger offsets", .{});
|
||||||
|
|
||||||
try emit.writeInstruction(Instruction.ldr(
|
const ldr = switch (tag) {
|
||||||
|
.ldr_stack_argument => Instruction.ldr,
|
||||||
|
.ldrb_stack_argument => Instruction.ldrb,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
try emit.writeInstruction(ldr(
|
||||||
cond,
|
cond,
|
||||||
r_stack_offset.rt,
|
r_stack_offset.rt,
|
||||||
.fp,
|
.fp,
|
||||||
.{ .offset = offset },
|
.{ .offset = offset },
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
.ldrb_stack_argument => {
|
.ldrh_stack_argument,
|
||||||
const offset = if (raw_offset <= math.maxInt(u12)) blk: {
|
.ldrsb_stack_argument,
|
||||||
break :blk Instruction.Offset.imm(@intCast(u12, raw_offset));
|
.ldrsh_stack_argument,
|
||||||
} else return emit.fail("TODO mirLoadStack larger offsets", .{});
|
=> {
|
||||||
|
|
||||||
try emit.writeInstruction(Instruction.ldrb(
|
|
||||||
cond,
|
|
||||||
r_stack_offset.rt,
|
|
||||||
.fp,
|
|
||||||
.{ .offset = offset },
|
|
||||||
));
|
|
||||||
},
|
|
||||||
.ldrh_stack_argument => {
|
|
||||||
const offset = if (raw_offset <= math.maxInt(u8)) blk: {
|
const offset = if (raw_offset <= math.maxInt(u8)) blk: {
|
||||||
break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, raw_offset));
|
break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, raw_offset));
|
||||||
} else return emit.fail("TODO mirLoadStack larger offsets", .{});
|
} else return emit.fail("TODO mirLoadStack larger offsets", .{});
|
||||||
|
|
||||||
try emit.writeInstruction(Instruction.ldrh(
|
const ldr = switch (tag) {
|
||||||
|
.ldrh_stack_argument => Instruction.ldrh,
|
||||||
|
.ldrsb_stack_argument => Instruction.ldrsb,
|
||||||
|
.ldrsh_stack_argument => Instruction.ldrsh,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
try emit.writeInstruction(ldr(
|
||||||
cond,
|
cond,
|
||||||
r_stack_offset.rt,
|
r_stack_offset.rt,
|
||||||
.fp,
|
.fp,
|
||||||
@ -640,6 +650,8 @@ fn mirLoadStoreExtra(emit: *Emit, inst: Mir.Inst.Index) !void {
|
|||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
.ldrh => try emit.writeInstruction(Instruction.ldrh(cond, rr_extra_offset.rt, rr_extra_offset.rn, rr_extra_offset.offset)),
|
.ldrh => try emit.writeInstruction(Instruction.ldrh(cond, rr_extra_offset.rt, rr_extra_offset.rn, rr_extra_offset.offset)),
|
||||||
|
.ldrsb => try emit.writeInstruction(Instruction.ldrsb(cond, rr_extra_offset.rt, rr_extra_offset.rn, rr_extra_offset.offset)),
|
||||||
|
.ldrsh => try emit.writeInstruction(Instruction.ldrsh(cond, rr_extra_offset.rt, rr_extra_offset.rn, rr_extra_offset.offset)),
|
||||||
.strh => try emit.writeInstruction(Instruction.strh(cond, rr_extra_offset.rt, rr_extra_offset.rn, rr_extra_offset.offset)),
|
.strh => try emit.writeInstruction(Instruction.strh(cond, rr_extra_offset.rt, rr_extra_offset.rn, rr_extra_offset.offset)),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,6 +64,14 @@ pub const Inst = struct {
|
|||||||
ldrh,
|
ldrh,
|
||||||
/// Load Register Halfword
|
/// Load Register Halfword
|
||||||
ldrh_stack_argument,
|
ldrh_stack_argument,
|
||||||
|
/// Load Register Signed Byte
|
||||||
|
ldrsb,
|
||||||
|
/// Load Register Signed Byte
|
||||||
|
ldrsb_stack_argument,
|
||||||
|
/// Load Register Signed Halfword
|
||||||
|
ldrsh,
|
||||||
|
/// Load Register Signed Halfword
|
||||||
|
ldrsh_stack_argument,
|
||||||
/// Logical Shift Left
|
/// Logical Shift Left
|
||||||
lsl,
|
lsl,
|
||||||
/// Logical Shift Right
|
/// Logical Shift Right
|
||||||
|
|||||||
@ -1123,11 +1123,19 @@ pub const Instruction = union(enum) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn strh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
pub fn strh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
||||||
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0, 0b01, rn, rt, args.offset);
|
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b0, 0b01, rn, rt, args.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ldrh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
pub fn ldrh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
||||||
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 1, 0b01, rn, rt, args.offset);
|
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b1, 0b01, rn, rt, args.offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ldrsh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
||||||
|
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b1, 0b11, rn, rt, args.offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ldrsb(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
|
||||||
|
return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b1, 0b10, rn, rt, args.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block data transfer
|
// Block data transfer
|
||||||
|
|||||||
@ -26,7 +26,6 @@ fn testTruncate(x: u32) u8 {
|
|||||||
|
|
||||||
test "truncate to non-power-of-two integers" {
|
test "truncate to non-power-of-two integers" {
|
||||||
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;
|
|
||||||
|
|
||||||
try testTrunc(u32, u1, 0b10101, 0b1);
|
try testTrunc(u32, u1, 0b10101, 0b1);
|
||||||
try testTrunc(u32, u1, 0b10110, 0b0);
|
try testTrunc(u32, u1, 0b10110, 0b0);
|
||||||
|
|||||||
@ -66,7 +66,6 @@ test "truncate.i0.var" {
|
|||||||
|
|
||||||
test "truncate on comptime integer" {
|
test "truncate on comptime integer" {
|
||||||
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;
|
|
||||||
|
|
||||||
var x = @truncate(u16, 9999);
|
var x = @truncate(u16, 9999);
|
||||||
try expect(x == 9999);
|
try expect(x == 9999);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user