Bug 595728 - nanojit: clarify semantics of shift operations. r=edwsmith.

--HG--
extra : convert_revision : 2a75fed5283f0efb625b10d20db007ad6bfe849a
This commit is contained in:
Nicholas Nethercote 2010-09-13 10:59:56 -07:00
parent 9e20f0f9b8
commit ced06e86bf
3 changed files with 71 additions and 33 deletions

View File

@ -150,7 +150,8 @@ void ValidateWriter::checkAccSet(LOpcode op, LIns* base, int32_t disp, AccSet ac
#endif
typedef int32_t (FASTCALL *RetInt)();
typedef double (FASTCALL *RetFloat)();
typedef int64_t (FASTCALL *RetQuad)();
typedef double (FASTCALL *RetDouble)();
typedef GuardRecord* (FASTCALL *RetGuard)();
struct Function {
@ -159,9 +160,12 @@ struct Function {
};
enum ReturnType {
RT_INT32 = 1,
RT_FLOAT = 2,
RT_GUARD = 4
RT_INT = 1,
#ifdef NANOJIT_64BIT
RT_QUAD = 2,
#endif
RT_DOUBLE = 4,
RT_GUARD = 8
};
#ifdef DEBUG
@ -262,8 +266,11 @@ private:
class LirasmFragment {
public:
union {
RetFloat rfloat;
RetInt rint;
#ifdef NANOJIT_64BIT
RetQuad rquad;
#endif
RetDouble rdouble;
RetGuard rguard;
};
ReturnType mReturnType;
@ -817,9 +824,14 @@ FragmentAssembler::endFragment()
if (mReturnTypeBits == 0) {
cerr << "warning: no return type in fragment '"
<< mFragName << "'" << endl;
}
if (mReturnTypeBits != RT_INT32 && mReturnTypeBits != RT_FLOAT &&
mReturnTypeBits != RT_GUARD) {
} else if (mReturnTypeBits != RT_INT &&
#ifdef NANOJIT_64BIT
mReturnTypeBits != RT_QUAD &&
#endif
mReturnTypeBits != RT_DOUBLE &&
mReturnTypeBits != RT_GUARD)
{
cerr << "warning: multiple return types in fragment '"
<< mFragName << "'" << endl;
}
@ -847,17 +859,26 @@ FragmentAssembler::endFragment()
f = &mParent.mFragments[mFragName];
switch (mReturnTypeBits) {
case RT_INT:
f->rint = (RetInt)((uintptr_t)mFragment->code());
f->mReturnType = RT_INT;
break;
#ifdef NANOJIT_64BIT
case RT_QUAD:
f->rquad = (RetQuad)((uintptr_t)mFragment->code());
f->mReturnType = RT_QUAD;
break;
#endif
case RT_DOUBLE:
f->rdouble = (RetDouble)((uintptr_t)mFragment->code());
f->mReturnType = RT_DOUBLE;
break;
case RT_GUARD:
f->rguard = (RetGuard)((uintptr_t)mFragment->code());
f->mReturnType = RT_GUARD;
break;
case RT_FLOAT:
f->rfloat = (RetFloat)((uintptr_t)mFragment->code());
f->mReturnType = RT_FLOAT;
break;
default:
f->rint = (RetInt)((uintptr_t)mFragment->code());
f->mReturnType = RT_INT32;
NanoAssert(0);
break;
}
@ -1158,11 +1179,17 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
break;
case LIR_reti:
ins = assemble_ret(RT_INT32);
ins = assemble_ret(RT_INT);
break;
#ifdef NANOJIT_64BIT
case LIR_retq:
ins = assemble_ret(RT_QUAD);
break;
#endif
case LIR_retd:
ins = assemble_ret(RT_FLOAT);
ins = assemble_ret(RT_DOUBLE);
break;
case LIR_label:
@ -1176,7 +1203,6 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
case LIR_line:
case LIR_xtbl:
case LIR_jtbl:
CASE64(LIR_retq:)
nyi(op);
break;
@ -2019,7 +2045,7 @@ FragmentAssembler::assembleRandomFragment(int nIns)
delete[] classGenerator;
// Return 0.
mReturnTypeBits |= RT_INT32;
mReturnTypeBits |= RT_INT;
mLir->ins1(LIR_reti, mLir->insImmI(0));
endFragment();
@ -2072,8 +2098,8 @@ Lirasm::lookupFunction(const string &name, CallInfo *&ci)
Fragments::const_iterator func = mFragments.find(name);
if (func != mFragments.end()) {
// The ABI, arg types and ret type will be overridden by the caller.
if (func->second.mReturnType == RT_FLOAT) {
CallInfo target = {(uintptr_t) func->second.rfloat,
if (func->second.mReturnType == RT_DOUBLE) {
CallInfo target = {(uintptr_t) func->second.rdouble,
0, ABI_FASTCALL, /*isPure*/0, ACCSET_STORE_ANY
verbose_only(, func->first.c_str()) };
*ci = target;
@ -2339,20 +2365,24 @@ main(int argc, char **argv)
if (i == lasm.mFragments.end())
errMsgAndQuit(opts.progname, "error: at least one fragment must be named 'main'");
switch (i->second.mReturnType) {
case RT_FLOAT:
{
double res = i->second.rfloat();
cout << "Output is: " << res << endl;
break;
}
case RT_INT32:
{
case RT_INT: {
int res = i->second.rint();
cout << "Output is: " << res << endl;
break;
}
case RT_GUARD:
{
#ifdef NANOJIT_64BIT
case RT_QUAD: {
int res = i->second.rquad();
cout << "Output is: " << res << endl;
break;
}
#endif
case RT_DOUBLE: {
double res = i->second.rdouble();
cout << "Output is: " << res << endl;
break;
}
case RT_GUARD: {
LasmSideExit *ls = (LasmSideExit*) i->second.rguard()->exit;
cout << "Exited block on line: " << ls->line << endl;
break;

View File

@ -42,9 +42,6 @@ do
runtest $infile
done
runtest "--random 1000000"
runtest "--random 1000000 --optimize"
# ---- Platform-specific tests and configurations. ----
# 64-bit platforms
@ -102,5 +99,10 @@ then
runtest "--random 10000 --optimize --arch 5 --novfp"
fi
# ---- Randomized tests, they are run last because they are slow ----
runtest "--random 1000000"
runtest "--random 1000000 --optimize"
rm testoutput.txt

View File

@ -263,6 +263,9 @@ OP___(andi, 85, Op2, I, 1) // bitwise-AND int
OP___(ori, 86, Op2, I, 1) // bitwise-OR int
OP___(xori, 87, Op2, I, 1) // bitwise-XOR int
// For all three integer shift operations, only the bottom five bits of the
// second operand are used, and they are treated as unsigned. This matches
// x86 semantics.
OP___(lshi, 88, Op2, I, 1) // left shift int
OP___(rshi, 89, Op2, I, 1) // right shift int (>>)
OP___(rshui, 90, Op2, I, 1) // right shift unsigned int (>>>)
@ -274,6 +277,9 @@ OP_64(andq, 93, Op2, Q, 1) // bitwise-AND quad
OP_64(orq, 94, Op2, Q, 1) // bitwise-OR quad
OP_64(xorq, 95, Op2, Q, 1) // bitwise-XOR quad
// For all three quad shift operations, only the bottom six bits of the
// second operand are used, and they are treated as unsigned. This matches
// x86-64 semantics.
OP_64(lshq, 96, Op2, Q, 1) // left shift quad; 2nd operand is an int
OP_64(rshq, 97, Op2, Q, 1) // right shift quad; 2nd operand is an int
OP_64(rshuq, 98, Op2, Q, 1) // right shift unsigned quad; 2nd operand is an int