Bug 525413 - lirasm: avoid operandCount, r=graydon.

--HG--
extra : convert_revision : f35c3aab85189126ca884e976372050c3278324f
This commit is contained in:
Nicholas Nethercote 2009-11-02 12:15:37 -08:00
Родитель 425771a170
Коммит f867541f61
4 изменённых файлов: 182 добавлений и 87 удалений

Просмотреть файл

@ -200,7 +200,7 @@ public:
token.data.clear(); token.data.clear();
mLine.clear(); mLine.clear();
} else { } else {
cerr << mLineno << ": error: Unrecognized character in file." << endl; cerr << "line " << mLineno << ": error: Unrecognized character in file." << endl;
return false; return false;
} }
@ -260,7 +260,7 @@ public:
bool mVerbose; bool mVerbose;
Fragments mFragments; Fragments mFragments;
Assembler mAssm; Assembler mAssm;
map<string, pair<LOpcode, size_t> > mOpMap; map<string, LOpcode> mOpMap;
void bad(const string &msg) { void bad(const string &msg) {
cerr << "error: " << msg << endl; cerr << "error: " << msg << endl;
@ -312,11 +312,11 @@ private:
void tokenizeLine(LirTokenStream &in, LirToken &token); void tokenizeLine(LirTokenStream &in, LirToken &token);
void need(size_t); void need(size_t);
LIns *ref(const string &); LIns *ref(const string &);
LIns *assemble_call(const string &); LIns *assemble_jump(bool isCond);
LIns *assemble_general();
LIns *assemble_guard();
LIns *assemble_jump();
LIns *assemble_load(); LIns *assemble_load();
LIns *assemble_call(const string &);
LIns *assemble_ret(ReturnType rt);
LIns *assemble_guard(bool isCond);
void bad(const string &msg); void bad(const string &msg);
void nyi(const string &opname); void nyi(const string &opname);
void extract_any_label(string &lab, char lab_delim); void extract_any_label(string &lab, char lab_delim);
@ -382,20 +382,21 @@ imm(const string &s)
uint64_t uint64_t
quad(const string &s) quad(const string &s)
{ {
stringstream tmp1(s), tmp2(s); stringstream tmp(s);
union { uint64_t ret;
uint64_t u64;
double d;
} pun;
if ((s.find("0x") == 0 || s.find("0X") == 0) && if ((s.find("0x") == 0 || s.find("0X") == 0) &&
(tmp1 >> hex >> pun.u64 && tmp1.eof())) (tmp >> hex >> ret && tmp.eof())) {
return pun.u64; return ret;
if ((s.find(".") != string::npos) && }
(tmp2 >> pun.d && tmp2.eof()))
return pun.u64;
return lexical_cast<uint64_t>(s); return lexical_cast<uint64_t>(s);
} }
double
immf(const string &s)
{
return lexical_cast<double>(s);
}
template<typename t> t template<typename t> t
pop_front(vector<t> &vec) pop_front(vector<t> &vec)
{ {
@ -524,7 +525,8 @@ FragmentAssembler::~FragmentAssembler()
void void
FragmentAssembler::bad(const string &msg) FragmentAssembler::bad(const string &msg)
{ {
cerr << "instruction " << mLineno << ": " << msg << endl; cerr << "line " << mLineno << ": " << msg << endl;
exit(1);
exit(1); exit(1);
} }
@ -553,24 +555,24 @@ FragmentAssembler::ref(const string &lab)
} }
LIns * LIns *
FragmentAssembler::assemble_jump() FragmentAssembler::assemble_jump(bool isCond)
{ {
LIns *target = NULL; LIns *condition;
LIns *condition = NULL;
if (mOpcode == LIR_j) { if (isCond) {
need(1);
} else {
need(2); need(2);
string cond = pop_front(mTokens); string cond = pop_front(mTokens);
condition = ref(cond); condition = ref(cond);
} else {
need(1);
condition = NULL;
} }
string name = pop_front(mTokens); string name = pop_front(mTokens);
if (mLabels.find(name) != mLabels.end()) { if (mLabels.find(name) != mLabels.end()) {
target = ref(name); LIns *target = ref(name);
return mLir->insBranch(mOpcode, condition, target); return mLir->insBranch(mOpcode, condition, target);
} else { } else {
LIns *ins = mLir->insBranch(mOpcode, condition, target); LIns *ins = mLir->insBranch(mOpcode, condition, NULL);
mFwdJumps.insert(make_pair(name, ins)); mFwdJumps.insert(make_pair(name, ins));
return ins; return ins;
} }
@ -676,6 +678,14 @@ FragmentAssembler::assemble_call(const string &op)
return mLir->insCall(ci, args); return mLir->insCall(ci, args);
} }
LIns *
FragmentAssembler::assemble_ret(ReturnType rt)
{
need(1);
mReturnTypeBits |= rt;
return mLir->ins1(mOpcode, ref(mTokens[0]));
}
LasmSideExit* LasmSideExit*
FragmentAssembler::createSideExit() FragmentAssembler::createSideExit()
{ {
@ -699,61 +709,27 @@ FragmentAssembler::createGuardRecord(LasmSideExit *exit)
LIns * LIns *
FragmentAssembler::assemble_guard() FragmentAssembler::assemble_guard(bool isCond)
{ {
GuardRecord* guard = createGuardRecord(createSideExit()); GuardRecord* guard = createGuardRecord(createSideExit());
need(mOpcount); LIns *ins_cond;
if (isCond) {
need(1);
ins_cond = ref(pop_front(mTokens));
} else {
need(0);
ins_cond = NULL;
}
mReturnTypeBits |= RT_GUARD; mReturnTypeBits |= RT_GUARD;
LIns *ins_cond;
if (mOpcode == LIR_xt || mOpcode == LIR_xf)
ins_cond = ref(pop_front(mTokens));
else
ins_cond = NULL;
if (!mTokens.empty()) if (!mTokens.empty())
bad("too many arguments"); bad("too many arguments");
return mLir->insGuard(mOpcode, ins_cond, guard); return mLir->insGuard(mOpcode, ins_cond, guard);
} }
LIns *
FragmentAssembler::assemble_general()
{
if (mOpcount == 0) {
// 0-ary ops may, or may not, have an immediate
// thing wedged in them; depends on the op. We
// are lax and set it if it's provided.
LIns *ins = mLir->ins0(mOpcode);
if (mTokens.size() > 0) {
assert(mTokens.size() == 1);
ins->initLInsI(mOpcode, imm(mTokens[0]));
}
return ins;
} else {
need(mOpcount);
if (mOpcount == 1) {
if (mOpcode == LIR_ret)
mReturnTypeBits |= RT_INT32;
if (mOpcode == LIR_fret)
mReturnTypeBits |= RT_FLOAT;
return mLir->ins1(mOpcode,
ref(mTokens[0]));
} else if (mOpcount == 2) {
return mLir->ins2(mOpcode,
ref(mTokens[0]),
ref(mTokens[1]));
} else {
bad("too many operands");
}
}
// Never get here.
return NULL;
}
void void
FragmentAssembler::endFragment() FragmentAssembler::endFragment()
{ {
@ -885,18 +861,106 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
if (mParent.mOpMap.find(op) == mParent.mOpMap.end()) if (mParent.mOpMap.find(op) == mParent.mOpMap.end())
bad("unknown instruction '" + op + "'"); bad("unknown instruction '" + op + "'");
pair<LOpcode, size_t> entry = mParent.mOpMap[op]; mOpcode = mParent.mOpMap[op];
mOpcode = entry.first;
mOpcount = entry.second;
switch (mOpcode) { switch (mOpcode) {
// A few special opcode cases. case LIR_start:
bad("start instructions cannot be specified explicitly");
break;
case LIR_regfence:
need(0);
ins = mLir->ins0(mOpcode);
break;
case LIR_live:
case LIR_flive:
case LIR_neg:
case LIR_fneg:
case LIR_qlo:
case LIR_qhi:
case LIR_ov:
case LIR_i2q:
case LIR_u2q:
case LIR_i2f:
case LIR_u2f:
need(1);
ins = mLir->ins1(mOpcode,
ref(mTokens[0]));
break;
case LIR_iaddp:
case LIR_qaddp:
case LIR_add:
case LIR_sub:
case LIR_mul:
case LIR_div:
case LIR_mod:
case LIR_fadd:
case LIR_fsub:
case LIR_fmul:
case LIR_fdiv:
case LIR_fmod:
case LIR_qiadd:
case LIR_and:
case LIR_or:
case LIR_xor:
case LIR_qiand:
case LIR_qior:
case LIR_qxor:
case LIR_not:
case LIR_lsh:
case LIR_rsh:
case LIR_ush:
case LIR_qilsh:
case LIR_qirsh:
case LIR_qursh:
case LIR_eq:
case LIR_lt:
case LIR_gt:
case LIR_le:
case LIR_ge:
case LIR_ult:
case LIR_ugt:
case LIR_ule:
case LIR_uge:
case LIR_feq:
case LIR_flt:
case LIR_fgt:
case LIR_fle:
case LIR_fge:
case LIR_qeq:
case LIR_qlt:
case LIR_qgt:
case LIR_qle:
case LIR_qge:
case LIR_qult:
case LIR_qugt:
case LIR_qule:
case LIR_quge:
case LIR_qjoin:
need(2);
ins = mLir->ins2(mOpcode,
ref(mTokens[0]),
ref(mTokens[1]));
break;
case LIR_cmov:
case LIR_qcmov:
need(3);
ins = mLir->ins3(mOpcode,
ref(mTokens[0]),
ref(mTokens[1]),
ref(mTokens[2]));
break;
case LIR_j: case LIR_j:
ins = assemble_jump(/*isCond*/false);
break;
case LIR_jt: case LIR_jt:
case LIR_jf: case LIR_jf:
case LIR_ji: ins = assemble_jump(/*isCond*/true);
ins = assemble_jump();
break; break;
case LIR_int: case LIR_int:
@ -909,6 +973,11 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
ins = mLir->insImmq(quad(mTokens[0])); ins = mLir->insImmq(quad(mTokens[0]));
break; break;
case LIR_float:
need(1);
ins = mLir->insImmf(immf(mTokens[0]));
break;
case LIR_sti: case LIR_sti:
case LIR_stqi: case LIR_stqi:
need(3); need(3);
@ -926,13 +995,19 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
ins = assemble_load(); ins = assemble_load();
break; break;
// XXX: insParam gives the one appropriate for the platform. Eg. if
// you specify qparam on x86 you'll end up with iparam anyway. Fix
// this.
case LIR_iparam: case LIR_iparam:
case LIR_qparam:
need(2); need(2);
ins = mLir->insParam(imm(mTokens[0]), ins = mLir->insParam(imm(mTokens[0]),
imm(mTokens[1])); imm(mTokens[1]));
break; break;
// XXX: similar to iparam/qparam above.
case LIR_ialloc: case LIR_ialloc:
case LIR_qalloc:
need(1); need(1);
ins = mLir->insAlloc(imm(mTokens[0])); ins = mLir->insAlloc(imm(mTokens[0]));
break; break;
@ -941,21 +1016,41 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
bad("skip instruction is deprecated"); bad("skip instruction is deprecated");
break; break;
case LIR_xt:
case LIR_xf:
case LIR_x: case LIR_x:
case LIR_xbarrier: case LIR_xbarrier:
ins = assemble_guard(); ins = assemble_guard(/*isCond*/false);
break;
case LIR_xt:
case LIR_xf:
ins = assemble_guard(/*isCond*/true);
break; break;
case LIR_icall: case LIR_icall:
case LIR_callh: case LIR_callh:
case LIR_fcall: case LIR_fcall:
case LIR_qcall:
ins = assemble_call(op); ins = assemble_call(op);
break; break;
case LIR_ret:
ins = assemble_ret(RT_INT32);
break;
case LIR_fret:
ins = assemble_ret(RT_FLOAT);
break;
case LIR_label:
case LIR_file:
case LIR_line:
case LIR_xtbl:
case LIR_ji:
nyi(op);
break;
default: default:
ins = assemble_general(); nyi(op);
break; break;
} }
@ -1656,9 +1751,9 @@ Lirasm::Lirasm(bool verbose) :
// Populate the mOpMap table. // Populate the mOpMap table.
#define OPDEF(op, number, args, repkind) \ #define OPDEF(op, number, args, repkind) \
mOpMap[#op] = make_pair(LIR_##op, args); mOpMap[#op] = LIR_##op;
#define OPDEF64(op, number, args, repkind) \ #define OPDEF64(op, number, args, repkind) \
mOpMap[#op] = make_pair(LIR_##op, args); mOpMap[#op] = LIR_##op;
#include "nanojit/LIRopcode.tbl" #include "nanojit/LIRopcode.tbl"
#undef OPDEF #undef OPDEF
#undef OPDEF64 #undef OPDEF64

Просмотреть файл

@ -1,5 +1,5 @@
pi = quad 3.14 pi = float 3.14
half = quad 0.5 half = float 0.5
halfpi = fmul pi half halfpi = fmul pi half
res = fcall sin cdecl halfpi res = fcall sin cdecl halfpi
fret res fret res

Просмотреть файл

@ -1,4 +1,4 @@
pi = quad 3.14 pi = float 3.14
two = quad 2.0 two = float 2.0
TwoPi = fmul pi two TwoPi = fmul pi two
fret two fret two

Просмотреть файл

@ -1,6 +1,6 @@
.begin sinpibytwo .begin sinpibytwo
pi = quad 3.14 pi = float 3.14
half = quad 0.5 half = float 0.5
halfpi = fmul pi half halfpi = fmul pi half
res = fcall sin cdecl halfpi res = fcall sin cdecl halfpi
fret res fret res
@ -8,7 +8,7 @@ fret res
.begin main .begin main
aa = fcall sinpibytwo fastcall aa = fcall sinpibytwo fastcall
bb = quad 5.53 bb = float 5.53
res = fadd aa bb res = fadd aa bb
fret res fret res
.end .end