Compare commits

...

5 Commits

Author SHA1 Message Date
Andy Wingo
0b900e1ac8
Merge 1dab08b1ab into eec7a8016c 2025-04-14 22:07:40 +08:00
Mike Pall
eec7a8016c Prevent Clang UB 'optimization' which breaks integerness checks.
Thanks to Kacper Michajłow. #1351 #1355
2025-04-10 22:53:50 +02:00
Mike Pall
51d4c26ec7 ARM: Fix soft-float math.min()/math.max().
Reported by Dong Jianqiang. #1356
2025-04-10 22:45:38 +02:00
Mike Pall
c262976486 ARM64: Fix pass-by-value struct calling conventions.
Reported by AnthonyK213. #1357
2025-04-10 22:06:47 +02:00
Andy Wingo
1dab08b1ab Fix x86-64 JIT conversion of negative floats to unsigned ints
Thanks to Peter Cawley for advice, help on the test case, an initial
patch, and suggested assembly.
2018-04-30 16:16:36 +02:00
8 changed files with 56 additions and 42 deletions

View File

@ -302,6 +302,9 @@ endif
ifneq (,$(INSTALL_LJLIBD))
TARGET_XCFLAGS+= -DLUA_LJDIR=\"$(INSTALL_LJLIBD)\"
endif
ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-strict-float-cast-overflow 2>/dev/null || echo 1))
TARGET_XCFLAGS+= -fno-strict-float-cast-overflow
endif
##############################################################################
# Target system detection.

View File

@ -1927,7 +1927,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
} else if ((ir-1)->o == IR_MIN || (ir-1)->o == IR_MAX) {
as->curins--; /* Always skip the loword min/max. */
if (uselo || usehi)
asm_sfpmin_max(as, ir-1, (ir-1)->o == IR_MIN ? CC_PL : CC_LE);
asm_sfpmin_max(as, ir-1, (ir-1)->o == IR_MIN ? CC_HS : CC_LS);
return;
#elif LJ_HASFFI
} else if ((ir-1)->o == IR_CONV) {

View File

@ -886,32 +886,38 @@ static void asm_conv(ASMState *as, IRIns *ir)
asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
} else {
Reg dest = ra_dest(as, ir, RSET_GPR);
Reg tmp = ra_noreg(IR(lref)->r) ? ra_alloc1(as, lref, RSET_FPR) :
ra_scratch(as, RSET_FPR);
x86Op op = st == IRT_NUM ? XO_CVTTSD2SI : XO_CVTTSS2SI;
if (LJ_64 ? irt_isu64(ir->t) : irt_isu32(ir->t)) {
/* LJ_64: For inputs >= 2^63 add -2^64, convert again. */
/* LJ_32: For inputs >= 2^31 add -2^31, convert again and add 2^31. */
Reg tmp = ra_noreg(IR(lref)->r) ? ra_alloc1(as, lref, RSET_FPR) :
ra_scratch(as, RSET_FPR);
MCLabel l_end = emit_label(as);
if (LJ_32)
emit_gri(as, XG_ARITHi(XOg_ADD), dest, (int32_t)0x80000000);
emit_rr(as, op, dest|REX_64, tmp);
if (st == IRT_NUM)
emit_rma(as, XO_ADDSD, tmp, &as->J->k64[LJ_K64_M2P64_31]);
else
emit_rma(as, XO_ADDSS, tmp, &as->J->k32[LJ_K32_M2P64_31]);
emit_sjcc(as, CC_NS, l_end);
emit_rr(as, XO_TEST, dest|REX_64, dest); /* Check if dest negative. */
emit_rr(as, op, dest|REX_64, tmp);
ra_left(as, tmp, lref);
} else {
if (LJ_64 && irt_isu32(ir->t))
emit_rr(as, XO_MOV, dest, dest); /* Zero hiword. */
emit_mrm(as, op,
dest|((LJ_64 &&
(irt_is64(ir->t) || irt_isu32(ir->t))) ? REX_64 : 0),
asm_fuseload(as, lref, RSET_FPR));
Reg r64 = (LJ_64 && irt_is64 (ir->t)) ? REX_64 : 0;
if (LJ_64 && (irt_isu32(ir->t) || irt_isint(ir->t)))
emit_rr(as, XO_MOV, dest, dest); /* Zero hiword. */
if (irt_isu64(ir->t) || irt_isu32(ir->t)) {
/* The cvtsd2si family of instructions operates on the signed integers,
producing INT_MIN on error. However we're converting to an unsigned
integer, so we want to accept the whole unsigned integer range.
Convert both the number and the number minus INT_MIN, choosing the
first result if successful and the second otherwise. */
Reg dest2 = ra_scratch(as, rset_exclude(RSET_GPR, dest));
Reg tmp2 = ra_scratch(as, rset_exclude(RSET_FPR, tmp));
x86Op sub_op;
void *krange;
if (st == IRT_NUM) {
sub_op = XO_SUBSD;
krange = &as->J->k64[irt_isu64(ir->t) ? LJ_K64_2P64 : LJ_K64_2P32];
} else {
sub_op = XO_SUBSS;
krange = &as->J->k32[irt_isu64(ir->t) ? LJ_K32_2P64 : LJ_K32_2P32];
}
emit_rr(as, XO_CMOV + (CC_O<<24), dest|r64, dest2|r64);
emit_i8(as, 1);
emit_rr(as, XO_ARITHi8, XOg_CMP|r64, dest);
emit_rr(as, op, dest2|r64, tmp2);
emit_rma(as, sub_op, tmp2, krange);
emit_rr(as, XO_MOVAPS, tmp2, tmp);
}
emit_rr(as, op, dest|r64, tmp);
ra_left(as, tmp, lref);
}
} else if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */
Reg left, dest = ra_dest(as, ir, RSET_GPR);

View File

@ -781,17 +781,24 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct)
{
CTSize sz = ct->size;
unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION);
while (ct->sib) {
while (ct->sib && n <= 4) {
unsigned int m = 1;
CType *sct;
ct = ctype_get(cts, ct->sib);
if (ctype_isfield(ct->info)) {
sct = ctype_rawchild(cts, ct);
if (ctype_isarray(sct->info)) {
CType *cct = ctype_rawchild(cts, sct);
if (!cct->size) continue;
m = sct->size / cct->size;
sct = cct;
}
if (ctype_isfp(sct->info)) {
r |= sct->size;
if (!isu) n++; else if (n == 0) n = 1;
if (!isu) n += m; else if (n < m) n = m;
} else if (ctype_iscomplex(sct->info)) {
r |= (sct->size >> 1);
if (!isu) n += 2; else if (n < 2) n = 2;
if (!isu) n += 2*m; else if (n < 2*m) n = 2*m;
} else if (ctype_isstruct(sct->info)) {
goto substruct;
} else {
@ -803,10 +810,11 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct)
sct = ctype_rawchild(cts, ct);
substruct:
if (sct->size > 0) {
unsigned int s = ccall_classify_struct(cts, sct);
unsigned int s = ccall_classify_struct(cts, sct), sn;
if (s <= 1) goto noth;
r |= (s & 255);
if (!isu) n += (s >> 8); else if (n < (s >>8)) n = (s >> 8);
sn = (s >> 8) * m;
if (!isu) n += sn; else if (n < sn) n = sn;
}
}
}

View File

@ -359,14 +359,10 @@ enum {
enum {
#if LJ_TARGET_X86ORX64
LJ_K64_2P32, /* 2^32 */
LJ_K64_TOBIT, /* 2^52 + 2^51 */
LJ_K64_2P64, /* 2^64 */
LJ_K64_M2P64, /* -2^64 */
#if LJ_32
LJ_K64_M2P64_31, /* -2^64 or -2^31 */
#else
LJ_K64_M2P64_31 = LJ_K64_M2P64,
#endif
#endif
#if LJ_TARGET_MIPS
LJ_K64_2P31, /* 2^31 */
@ -381,7 +377,8 @@ enum {
enum {
#if LJ_TARGET_X86ORX64
LJ_K32_M2P64_31, /* -2^64 or -2^31 */
LJ_K32_2P32, /* 2^32 */
LJ_K32_2P64, /* 2^64 */
#endif
#if LJ_TARGET_PPC
LJ_K32_2P52_2P31, /* 2^52 + 2^31 */

View File

@ -300,6 +300,7 @@ typedef enum {
XO_CVTSS2SD = XO_f30f(5a),
XO_CVTSD2SS = XO_f20f(5a),
XO_ADDSS = XO_f30f(58),
XO_SUBSS = XO_f30f(5c),
XO_MOVD = XO_660f(6e),
XO_MOVDto = XO_660f(7e),

View File

@ -318,12 +318,11 @@ void lj_trace_initstate(global_State *g)
/* Initialize 32/64 bit constants. */
#if LJ_TARGET_X86ORX64
J->k64[LJ_K64_2P32].u64 = U64x(41f00000,00000000);
J->k64[LJ_K64_TOBIT].u64 = U64x(43380000,00000000);
#if LJ_32
J->k64[LJ_K64_M2P64_31].u64 = U64x(c1e00000,00000000);
#endif
J->k64[LJ_K64_2P64].u64 = U64x(43f00000,00000000);
J->k32[LJ_K32_M2P64_31] = LJ_64 ? 0xdf800000 : 0xcf000000;
J->k32[LJ_K32_2P64] = 0x5f800000;
J->k32[LJ_K32_2P32] = 0x4f800000;
#endif
#if LJ_TARGET_X86ORX64 || LJ_TARGET_MIPS64
J->k64[LJ_K64_M2P64].u64 = U64x(c3f00000,00000000);

View File

@ -1717,8 +1717,8 @@ static void build_subroutines(BuildCtx *ctx)
|.endif
|.endmacro
|
| math_minmax math_min, gt, pl
| math_minmax math_max, lt, le
| math_minmax math_min, gt, hs
| math_minmax math_max, lt, ls
|
|//-- String library -----------------------------------------------------
|