Bug 525411 - lirasm: fix CallInfo problems, r=graydon.

--HG--
extra : convert_revision : 18149ad4f58ed4f0cdc2034aeaa0acf269c1a205
This commit is contained in:
Nicholas Nethercote 2009-11-02 12:14:45 -08:00
parent f73327e2bb
commit 324726905d

View File

@ -144,15 +144,7 @@ enum ReturnType {
const int I32 = nanojit::ARGSIZE_LO; const int I32 = nanojit::ARGSIZE_LO;
const int I64 = nanojit::ARGSIZE_Q; const int I64 = nanojit::ARGSIZE_Q;
const int F64 = nanojit::ARGSIZE_F; const int F64 = nanojit::ARGSIZE_F;
const int PTRARG = nanojit::ARGSIZE_LO; const int PTR = nanojit::ARGSIZE_P;
const int PTRRET =
#if defined AVMPLUS_64BIT
nanojit::ARGSIZE_Q
#else
nanojit::ARGSIZE_LO
#endif
;
enum LirTokenType { enum LirTokenType {
NAME, NUMBER, PUNCT, NEWLINE NAME, NUMBER, PUNCT, NEWLINE
@ -257,7 +249,7 @@ public:
void assemble(istream &in); void assemble(istream &in);
void assembleRandom(int nIns); void assembleRandom(int nIns);
void lookupFunction(const string &name, CallInfo *&ci); bool lookupFunction(const string &name, CallInfo *&ci);
LirBuffer *mLirbuf; LirBuffer *mLirbuf;
verbose_only( LabelMap *mLabelMap; ) verbose_only( LabelMap *mLabelMap; )
@ -326,6 +318,7 @@ private:
LIns *assemble_jump(); LIns *assemble_jump();
LIns *assemble_load(); LIns *assemble_load();
void bad(const string &msg); void bad(const string &msg);
void nyi(const string &opname);
void extract_any_label(string &lab, char lab_delim); void extract_any_label(string &lab, char lab_delim);
void endFragment(); void endFragment();
}; };
@ -357,10 +350,10 @@ double sinFn(double d) {
#define sin sinFn #define sin sinFn
Function functions[] = { Function functions[] = {
FN(puts, argMask(PTRARG, 1, 1) | retMask(I32)), FN(puts, argMask(PTR, 1, 1) | retMask(I32)),
FN(sin, argMask(F64, 1, 1) | retMask(F64)), FN(sin, argMask(F64, 1, 1) | retMask(F64)),
FN(malloc, argMask(PTRARG, 1, 1) | retMask(PTRRET)), FN(malloc, argMask(PTR, 1, 1) | retMask(PTR)),
FN(free, argMask(PTRARG, 1, 1) | retMask(I32)) FN(free, argMask(PTR, 1, 1) | retMask(I32))
}; };
template<typename out, typename in> out template<typename out, typename in> out
@ -535,6 +528,13 @@ FragmentAssembler::bad(const string &msg)
exit(1); exit(1);
} }
void
FragmentAssembler::nyi(const string &opname)
{
cerr << "line " << mLineno << ": '" << opname << "' not yet implemented, sorry" << endl;
exit(1);
}
void void
FragmentAssembler::need(size_t n) FragmentAssembler::need(size_t n)
{ {
@ -629,44 +629,50 @@ FragmentAssembler::assemble_call(const string &op)
_abi = ABI_CDECL; _abi = ABI_CDECL;
else else
bad("call abi name '" + abi + "'"); bad("call abi name '" + abi + "'");
ci->_abi = _abi;
if (mTokens.size() > MAXARGS) if (mTokens.size() > MAXARGS)
bad("too many args to " + op); bad("too many args to " + op);
if (func.find("0x") == 0) { bool isBuiltin = mParent.lookupFunction(func, ci);
ci->_address = imm(func); if (isBuiltin) {
// Built-in: use its CallInfo. Also check (some) CallInfo details
ci->_cse = 0; // against those from the call site.
ci->_fold = 0;
#ifdef DEBUG
ci->_name = "fn";
#endif
} else {
mParent.lookupFunction(func, ci);
if (ci == NULL)
bad("invalid function reference " + func);
if (_abi != ci->_abi) if (_abi != ci->_abi)
bad("invalid calling convention for " + func); bad("invalid calling convention for " + func);
size_t i;
for (i = 0; i < mTokens.size(); ++i) {
args[i] = ref(mTokens[mTokens.size() - (i+1)]);
}
if (i != ci->count_args())
bad("wrong number of arguments for " + func);
} else {
// User-defined function: infer CallInfo details (ABI, arg types, ret
// type) from the call site.
int ty;
ci->_abi = _abi;
ci->_argtypes = 0;
size_t argc = mTokens.size();
for (size_t i = 0; i < argc; ++i) {
args[argc - (i+1)] = ref(mTokens[i]); // args[] is in reverse order!
if (args[i]->isFloat()) ty = ARGSIZE_F;
else if (args[i]->isQuad()) ty = ARGSIZE_Q;
else ty = ARGSIZE_I;
// Nb: i+1 because argMask() uses 1-based arg counting.
ci->_argtypes |= argMask(ty, i+1, argc);
}
// Select return type from opcode.
if (mOpcode == LIR_icall) ty = ARGSIZE_LO;
else if (mOpcode == LIR_fcall) ty = ARGSIZE_F;
else if (mOpcode == LIR_qcall) ty = ARGSIZE_Q;
else nyi("callh");
ci->_argtypes |= retMask(ty);
} }
ci->_argtypes = 0;
for (size_t i = 0; i < mTokens.size(); ++i) {
args[i] = ref(mTokens[mTokens.size() - (i+1)]);
ci->_argtypes |= args[i]->isQuad() ? ARGSIZE_F : ARGSIZE_LO;
ci->_argtypes <<= ARGSIZE_SHIFT;
}
// Select return type from opcode.
// FIXME: callh needs special treatment currently
// missing from here.
if (mOpcode == LIR_icall)
ci->_argtypes |= ARGSIZE_LO;
else
ci->_argtypes |= ARGSIZE_F;
return mLir->insCall(ci, args); return mLir->insCall(ci, args);
} }
@ -1671,35 +1677,37 @@ Lirasm::~Lirasm()
} }
void bool
Lirasm::lookupFunction(const string &name, CallInfo *&ci) Lirasm::lookupFunction(const string &name, CallInfo *&ci)
{ {
const size_t nfuns = sizeof(functions) / sizeof(functions[0]); const size_t nfuns = sizeof(functions) / sizeof(functions[0]);
for (size_t i = 0; i < nfuns; i++) { for (size_t i = 0; i < nfuns; i++) {
if (name == functions[i].name) { if (name == functions[i].name) {
*ci = functions[i].callInfo; *ci = functions[i].callInfo;
return; return true;
} }
} }
Fragments::const_iterator func = mFragments.find(name); Fragments::const_iterator func = mFragments.find(name);
if (func != mFragments.end()) { if (func != mFragments.end()) {
// The ABI, arg types and ret type will be overridden by the caller.
if (func->second.mReturnType == RT_FLOAT) { if (func->second.mReturnType == RT_FLOAT) {
CallInfo target = {(uintptr_t) func->second.rfloat, CallInfo target = {(uintptr_t) func->second.rfloat,
ARGSIZE_F, 0, 0, 0, 0, 0, ABI_FASTCALL
nanojit::ABI_FASTCALL
verbose_only(, func->first.c_str()) }; verbose_only(, func->first.c_str()) };
*ci = target; *ci = target;
} else { } else {
CallInfo target = {(uintptr_t) func->second.rint, CallInfo target = {(uintptr_t) func->second.rint,
ARGSIZE_LO, 0, 0, 0, 0, 0, ABI_FASTCALL
nanojit::ABI_FASTCALL
verbose_only(, func->first.c_str()) }; verbose_only(, func->first.c_str()) };
*ci = target; *ci = target;
} }
return false;
} else { } else {
ci = NULL; bad("invalid function reference " + name);
return false;
} }
} }