Turn HPHP::Op into an enum class

Because stronger types are better types, and this will make
future refactoring easier. I considered trying to purge the Opcode
type from the codebase too but that would be a much bigger project.
Esse commit está contido em:
bsimmers
2013-06-21 16:39:19 -07:00
commit de Sara Golemon
commit 6d91f8195a
28 arquivos alterados com 329 adições e 294 exclusões
+2 -2
Ver Arquivo
@@ -265,7 +265,7 @@ static int32_t countStackValues(const std::vector<uchar>& immVec) {
#define O(name, imm, pop, push, flags) \
void Emitter::name(imm) { \
const Opcode opcode = Op##name; \
auto const opcode = Op::name; \
Offset curPos UNUSED = getUnitEmitter().bcPos(); \
getEmitterVisitor().prepareEvalStack(); \
POP_##pop; \
@@ -1227,7 +1227,7 @@ void EmitterVisitor::popEvalStack(char expected, int arg, int pos) {
}
}
void EmitterVisitor::popSymbolicLocal(Opcode op, int arg, int pos) {
void EmitterVisitor::popSymbolicLocal(Op op, int arg, int pos) {
// Special case for instructions that consume the loc below the
// top.
int belowTop = -1;
+4 -4
Ver Arquivo
@@ -340,7 +340,7 @@ public:
}
bool evalStackIsUnknown() { return m_evalStackIsUnknown; }
void popEvalStack(char symFlavor, int arg = -1, int pos = -1);
void popSymbolicLocal(Opcode opcode, int arg = -1, int pos = -1);
void popSymbolicLocal(Op opcode, int arg = -1, int pos = -1);
void popEvalStackLMany();
void popEvalStackMany(int len, char symFlavor);
void popEvalStackCVMany(int len);
@@ -355,8 +355,8 @@ public:
void restoreJumpTargetEvalStack();
void recordCall();
bool isJumpTarget(Offset target);
void setPrevOpcode(Opcode op) { m_prevOpcode = op; }
Opcode getPrevOpcode() const { return m_prevOpcode; }
void setPrevOpcode(Op op) { m_prevOpcode = op; }
Op getPrevOpcode() const { return m_prevOpcode; }
bool currentPositionIsReachable() {
return (m_ue.bcPos() == m_curFunc->base()
|| isJumpTarget(m_ue.bcPos())
@@ -519,7 +519,7 @@ private:
FuncEmitter* m_curFunc;
FileScopePtr m_file;
Opcode m_prevOpcode;
Op m_prevOpcode;
std::deque<PostponedMeth> m_postponedMeths;
std::deque<PostponedCtor> m_postponedCtors;
+9 -9
Ver Arquivo
@@ -20,9 +20,9 @@
namespace HPHP { namespace Compiler {
static void collapseJmp(Offset* offsetPtr, Opcode* instr, Opcode* start) {
static void collapseJmp(Offset* offsetPtr, Op* instr, Op* start) {
if (offsetPtr) {
Opcode* dest = instr + *offsetPtr;
Op* dest = instr + *offsetPtr;
while (*dest == OpJmp && dest != instr) {
dest = start + instrJumpTarget(start, dest - start);
}
@@ -42,10 +42,10 @@ Peephole::Peephole(UnitEmitter &ue, MetaInfoBuilder& metaInfo)
buildJumpTargets();
// Scan the bytecode linearly.
Opcode* start = ue.m_bc;
Opcode* prev = start;
Opcode* cur = prev + instrLen(prev);
Opcode* end = start + ue.m_bclen;
Op* start = (Op*)ue.m_bc;
Op* prev = start;
Op* cur = prev + instrLen(prev);
Op* end = start + ue.m_bclen;
/*
* TODO(1086005): we should try to minimize use of CGetL2/CGetL3.
@@ -161,14 +161,14 @@ void Peephole::buildJumpTargets() {
}
// all jump targets are targets
for (Offset pos = 0; pos < (Offset)m_ue.m_bclen;
pos += instrLen(&m_ue.m_bc[pos])) {
Opcode* instr = &m_ue.m_bc[pos];
pos += instrLen((Op*)&m_ue.m_bc[pos])) {
Op* instr = (Op*)&m_ue.m_bc[pos];
if (isSwitch(*instr)) {
foreachSwitchTarget(instr, [&](Offset& o) {
m_jumpTargets.insert(pos + o);
});
} else {
Offset target = instrJumpTarget(m_ue.m_bc, pos);
Offset target = instrJumpTarget((Op*)m_ue.m_bc, pos);
if (target != InvalidAbsoluteOffset) {
m_jumpTargets.insert(target);
}
+4 -2
Ver Arquivo
@@ -13,10 +13,12 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/base/stats.h"
#include "hphp/util/base.h"
#include "hphp/runtime/vm/jit/x64-util.h"
#include "hphp/runtime/vm/jit/translator-x64.h"
#include "hphp/runtime/base/stats.h"
namespace HPHP {
namespace Stats {
@@ -68,7 +70,7 @@ emitInc(X64Assembler& a, uint64_t* tl_table, uint index, int n,
}
}
void emitIncTranslOp(X64Assembler& a, Opcode opc, bool force) {
void emitIncTranslOp(X64Assembler& a, Op opc, bool force) {
if (!force && !enableInstrCount()) return;
emitInc(a, &tl_counters[0], opcodeToTranslStatCounter(opc), 1,
CC_None, force);
+14 -10
Ver Arquivo
@@ -217,28 +217,32 @@ inline void inc(StatCounter stat, int n = 1) {
}
}
inline StatCounter opcodeToStatCounter(Opcode opc) {
inline StatCounter opcodeToStatCounter(Op opc) {
assert(OpLowInvalid == 0);
return StatCounter(Instr_InterpBBLowInvalid + STATS_PER_OPCODE * opc);
return StatCounter(Instr_InterpBBLowInvalid +
STATS_PER_OPCODE * uint8_t(opc));
}
inline void incOp(Opcode opc) {
inline void incOp(Op opc) {
inc(opcodeToStatCounter(opc));
}
inline StatCounter opcodeToTranslStatCounter(Opcode opc) {
inline StatCounter opcodeToTranslStatCounter(Op opc) {
assert(OpLowInvalid == 0);
return StatCounter(Instr_TranslLowInvalid + STATS_PER_OPCODE * opc);
return StatCounter(Instr_TranslLowInvalid +
STATS_PER_OPCODE * uint8_t(opc));
}
inline StatCounter opcodeToIRPreStatCounter(Opcode opc) {
inline StatCounter opcodeToIRPreStatCounter(Op opc) {
assert(OpLowInvalid == 0);
return StatCounter(Instr_TranslIRPreLowInvalid + STATS_PER_OPCODE * opc);
return StatCounter(Instr_TranslIRPreLowInvalid +
STATS_PER_OPCODE * uint8_t(opc));
}
inline StatCounter opcodeToIRPostStatCounter(Opcode opc) {
inline StatCounter opcodeToIRPostStatCounter(Op opc) {
assert(OpLowInvalid == 0);
return StatCounter(Instr_TranslIRPostLowInvalid + STATS_PER_OPCODE * opc);
return StatCounter(Instr_TranslIRPostLowInvalid +
STATS_PER_OPCODE * uint8_t(opc));
}
// Both emitIncs use r10.
@@ -254,7 +258,7 @@ inline void emitInc(Transl::X64Assembler& a, StatCounter stat, int n = 1,
emitInc(a, &tl_counters[0], stat, n, cc, force);
}
extern void emitIncTranslOp(Transl::X64Assembler& a, Opcode opc,
extern void emitIncTranslOp(Transl::X64Assembler& a, Op opc,
bool force = false);
extern void init();
extern void dump();
+7 -7
Ver Arquivo
@@ -106,7 +106,7 @@ void CmdFlowControl::installLocationFilterForLine(InterruptSite *site) {
ranges.clear();
}
}
auto excludeContinuationReturns = [] (Opcode op) {
auto excludeContinuationReturns = [] (Op op) {
return (op != OpContExit) && (op != OpContRetC);
};
g_vmContext->m_lastLocFilter->addRanges(unit, ranges,
@@ -153,26 +153,26 @@ void CmdFlowControl::setupStepOuts() {
PC returnPC = returnUnit->at(returnOffset);
TRACE(2, "CmdFlowControl::setupStepOuts: at '%s' offset %d opcode %s\n",
fp->m_func->fullName()->data(), returnOffset,
opcodeToName(*returnPC));
opcodeToName(toOp(*returnPC)));
// Don't step out to generated functions, keep looking.
if (fp->m_func->line1() == 0) continue;
if (fromVMEntry) {
TRACE(2, "CmdFlowControl::setupStepOuts: VM entry\n");
// We only execute this for opcodes which invoke more PHP, and that does
// not include switches. Thus, we'll have at most two destinations.
assert(!isSwitch(*returnPC) && (numSuccs(returnPC) <= 2));
assert(!isSwitch(*returnPC) && (numSuccs((Op*)returnPC) <= 2));
// Set an internal breakpoint after the instruction if it can fall thru.
if (instrAllowsFallThru(*returnPC)) {
if (instrAllowsFallThru(toOp(*returnPC))) {
m_stepOutUnit = returnUnit;
m_stepOutOffset1 = returnOffset + instrLen(returnPC);
m_stepOutOffset1 = returnOffset + instrLen((Op*)returnPC);
TRACE(2, "CmdFlowControl: step out to '%s' offset %d (fall-thru)\n",
fp->m_func->fullName()->data(), m_stepOutOffset1);
phpAddBreakPoint(m_stepOutUnit, m_stepOutOffset1);
}
// Set an internal breakpoint at the target of a control flow instruction.
// A good example of a control flow op that invokes PHP is IterNext.
if (instrIsControlFlow(*returnPC)) {
Offset target = instrJumpTarget(returnPC, 0);
if (instrIsControlFlow(toOp(*returnPC))) {
Offset target = instrJumpTarget((Op*)returnPC, 0);
if (target != InvalidAbsoluteOffset) {
m_stepOutUnit = returnUnit;
m_stepOutOffset2 = returnOffset + target;
+1 -1
Ver Arquivo
@@ -62,7 +62,7 @@ void CmdNext::onBeginInterrupt(DebuggerProxy& proxy, CmdInterrupt& interrupt) {
Unit* unit = fp->m_func->unit();
Offset offset = unit->offsetOf(pc);
TRACE(2, "CmdNext: pc %p, opcode %s at '%s' offset %d\n",
pc, opcodeToName(*pc), fp->m_func->fullName()->data(), offset);
pc, opcodeToName(toOp(*pc)), fp->m_func->fullName()->data(), offset);
int currentVMDepth = g_vmContext->m_nesting;
int currentStackDepth = proxy.getStackDepth();
+1 -1
Ver Arquivo
@@ -1028,7 +1028,7 @@ OpcodeParserMap opcode_parsers;
#define O(name, imm, pop, push, flags) \
void parse_opcode_##name(AsmState& as) { \
UNUSED int64_t immIVA = -1; \
UNUSED const Opcode thisOpcode = Op##name; \
UNUSED auto const thisOpcode = Op::name; \
UNUSED const Offset curOpcodeOff = as.ue->bcPos(); \
std::vector<std::pair<std::string, Offset> > labelJumps; \
\
+19 -19
Ver Arquivo
@@ -4466,7 +4466,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopCGetM(PC& pc) {
if (tvRet->m_type == KindOfRef) {
tvUnbox(tvRet);
}
assert(hasImmVector(*oldPC));
assert(hasImmVector(toOp(*oldPC)));
const ImmVector& immVec = ImmVector::createFromStream(oldPC + 1);
StringData* name;
MemberCode mc;
@@ -5657,13 +5657,13 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFPushCufSafe(PC& pc) {
doFPushCuf(pc, false, true);
}
static inline ActRec* arFromInstr(TypedValue* sp, const Opcode* pc) {
static inline ActRec* arFromInstr(TypedValue* sp, const Op* pc) {
return arFromSpOffset((ActRec*)sp, instrSpToArDelta(pc));
}
inline void OPTBLD_INLINE VMExecutionContext::iopFPassC(PC& pc) {
#ifdef DEBUG
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc);
#endif
NEXT();
DECODE_IVA(paramId);
@@ -5673,7 +5673,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFPassC(PC& pc) {
}
#define FPASSC_CHECKED_PRELUDE \
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc); \
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc); \
NEXT(); \
DECODE_IVA(paramId); \
assert(paramId < ar->numArgs()); \
@@ -5704,7 +5704,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFPassCE(PC& pc) {
#undef FPASSC_CHECKED_PRELUDE
inline void OPTBLD_INLINE VMExecutionContext::iopFPassV(PC& pc) {
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc);
NEXT();
DECODE_IVA(paramId);
assert(paramId < ar->numArgs());
@@ -5715,7 +5715,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFPassV(PC& pc) {
}
inline void OPTBLD_INLINE VMExecutionContext::iopFPassR(PC& pc) {
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc);
NEXT();
DECODE_IVA(paramId);
assert(paramId < ar->numArgs());
@@ -5733,7 +5733,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFPassR(PC& pc) {
}
inline void OPTBLD_INLINE VMExecutionContext::iopFPassL(PC& pc) {
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc);
NEXT();
DECODE_IVA(paramId);
DECODE_HA(local);
@@ -5748,7 +5748,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFPassL(PC& pc) {
}
inline void OPTBLD_INLINE VMExecutionContext::iopFPassN(PC& pc) {
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc);
PC origPc = pc;
NEXT();
DECODE_IVA(paramId);
@@ -5761,7 +5761,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFPassN(PC& pc) {
}
inline void OPTBLD_INLINE VMExecutionContext::iopFPassG(PC& pc) {
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc);
PC origPc = pc;
NEXT();
DECODE_IVA(paramId);
@@ -5774,7 +5774,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFPassG(PC& pc) {
}
inline void OPTBLD_INLINE VMExecutionContext::iopFPassS(PC& pc) {
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc);
PC origPc = pc;
NEXT();
DECODE_IVA(paramId);
@@ -5787,7 +5787,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFPassS(PC& pc) {
}
void VMExecutionContext::iopFPassM(PC& pc) {
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc);
NEXT();
DECODE_IVA(paramId);
assert(paramId < ar->numArgs());
@@ -5834,7 +5834,7 @@ bool VMExecutionContext::doFCall(ActRec* ar, PC& pc) {
}
inline void OPTBLD_INLINE VMExecutionContext::iopFCall(PC& pc) {
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
ActRec* ar = arFromInstr(m_stack.top(), (Op*)pc);
NEXT();
DECODE_IVA(numArgs);
assert(numArgs == ar->numArgs());
@@ -7187,15 +7187,15 @@ inline void VMExecutionContext::dispatchImpl(int numInstrs) {
m_fp)); \
return; \
} \
Op op = (Op)*pc; \
Op op = toOp(*pc); \
COND_STACKTRACE("dispatch: "); \
ONTRACE(1, \
Trace::trace("dispatch: %d: %s\n", pcOff(), nametab[op])); \
assert(op < Op_count); \
Trace::trace("dispatch: %d: %s\n", pcOff(), \
nametab[uint8_t(op)])); \
if (profile && (op == OpRetC || op == OpRetV)) { \
profileReturnValue(m_stack.top()->m_type); \
} \
goto *optab[op]; \
goto *optab[uint8_t(op)]; \
} while (0)
ONTRACE(1, Trace::trace("dispatch: Enter ExecutionContext::dispatch(%p)\n",
@@ -7214,10 +7214,10 @@ inline void VMExecutionContext::dispatchImpl(int numInstrs) {
iop##name(pc); \
SYNC(); \
if (breakOnCtlFlow) { \
isCtlFlow = instrIsControlFlow(Op##name); \
Stats::incOp(Op##name); \
isCtlFlow = instrIsControlFlow(Op::name); \
Stats::incOp(Op::name); \
} \
const Op op = Op##name; \
const Op op = Op::name; \
if (op == OpRetC || op == OpRetV || op == OpNativeImpl) { \
if (UNLIKELY(!pc)) { m_fp = 0; return; } \
} \
+3 -3
Ver Arquivo
@@ -111,7 +111,7 @@ static void blacklistRangesInJit(const Unit* unit,
for (OffsetRangeVec::const_iterator it = offsets.begin();
it != offsets.end(); ++it) {
for (PC pc = unit->at(it->m_base); pc < unit->at(it->m_past);
pc += instrLen((Opcode*)pc)) {
pc += instrLen((Op*)pc)) {
transl()->addDbgBLPC(pc);
}
}
@@ -445,8 +445,8 @@ void PCFilter::addRanges(const Unit* unit, const OffsetRangeVec& offsets,
for (auto range = offsets.cbegin(); range != offsets.cend(); ++range) {
TRACE(3, "\toffsets [%d, %d)\n", range->m_base, range->m_past);
for (PC pc = unit->at(range->m_base); pc < unit->at(range->m_past);
pc += instrLen(pc)) {
if (isOpcodeAllowed(*pc)) {
pc += instrLen((Op*)pc)) {
if (isOpcodeAllowed(toOp(*pc))) {
TRACE(3, "\t\tpc %p\n", pc);
addPC(pc);
} else {
+2 -2
Ver Arquivo
@@ -111,12 +111,12 @@ public:
PCFilter() {}
// Filter function to exclude opcodes when adding ranges.
typedef std::function<bool(Opcode)> OpcodeFilter;
typedef std::function<bool(Op)> OpcodeFilter;
// Add/remove offsets, either individually or by range. By default allow all
// opcodes.
void addRanges(const Unit* unit, const OffsetRangeVec& offsets,
OpcodeFilter isOpcodeAllowed = [] (Opcode) { return true; });
OpcodeFilter isOpcodeAllowed = [] (Op) { return true; });
void removeOffset(const Unit* unit, Offset offset);
// Add/remove/check explicit PCs.
+56 -58
Ver Arquivo
@@ -23,11 +23,7 @@
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
bool isValidOpcode(Opcode op) {
return op > OpLowInvalid && op < OpHighInvalid;
}
int numImmediates(Opcode opcode) {
int numImmediates(Op opcode) {
assert(isValidOpcode(opcode));
static const int8_t values[] = {
#define NA 0
@@ -44,10 +40,10 @@ int numImmediates(Opcode opcode) {
#undef THREE
#undef FOUR
};
return values[opcode];
return values[uint8_t(opcode)];
}
ArgType immType(const Opcode opcode, int idx) {
ArgType immType(const Op opcode, int idx) {
assert(isValidOpcode(opcode));
assert(idx >= 0 && idx < numImmediates(opcode));
always_assert(idx < 4); // No opcodes have more than four immediates
@@ -107,16 +103,17 @@ ArgType immType(const Opcode opcode, int idx) {
#undef THREE
#undef FOUR
};
auto opInt = uint8_t(opcode);
switch (idx) {
case 0: return (ArgType)arg0Types[opcode];
case 1: return (ArgType)arg1Types[opcode];
case 2: return (ArgType)arg2Types[opcode];
case 3: return (ArgType)arg3Types[opcode];
case 0: return (ArgType)arg0Types[opInt];
case 1: return (ArgType)arg1Types[opInt];
case 2: return (ArgType)arg2Types[opInt];
case 3: return (ArgType)arg3Types[opInt];
default: assert(false); return (ArgType)-1;
}
}
int immSize(const Opcode* opcode, int idx) {
int immSize(const Op* opcode, int idx) {
assert(idx >= 0 && idx < numImmediates(*opcode));
always_assert(idx < 4); // No opcodes have more than four immediates
static const int8_t argTypeToSizes[] = {
@@ -162,12 +159,12 @@ int immSize(const Opcode* opcode, int idx) {
}
}
bool immIsVector(Opcode opcode, int idx) {
bool immIsVector(Op opcode, int idx) {
ArgType type = immType(opcode, idx);
return (type == MA || type == BLA || type == SLA);
}
bool hasImmVector(Opcode opcode) {
bool hasImmVector(Op opcode) {
const int num = numImmediates(opcode);
for (int i = 0; i < num; ++i) {
if (immIsVector(opcode, i)) return true;
@@ -175,8 +172,8 @@ bool hasImmVector(Opcode opcode) {
return false;
}
ArgUnion getImm(const Opcode* opcode, int idx) {
const Opcode* p = opcode + 1;
ArgUnion getImm(const Op* opcode, int idx) {
const Op* p = opcode + 1;
assert(idx >= 0 && idx < numImmediates(*opcode));
ArgUnion retval;
retval.u_NA = 0;
@@ -188,7 +185,7 @@ ArgUnion getImm(const Opcode* opcode, int idx) {
always_assert(cursor == idx);
ArgType type = immType(*opcode, idx);
if (type == IVA || type == HA || type == IA) {
retval.u_IVA = decodeVariableSizeImm(&p);
retval.u_IVA = decodeVariableSizeImm((const uint8_t**)&p);
} else if (!immIsVector(*opcode, cursor)) {
memcpy(&retval.bytes, p, immSize(opcode, idx));
}
@@ -196,11 +193,11 @@ ArgUnion getImm(const Opcode* opcode, int idx) {
return retval;
}
ArgUnion* getImmPtr(const Opcode* opcode, int idx) {
ArgUnion* getImmPtr(const Op* opcode, int idx) {
assert(immType(*opcode, idx) != IVA);
assert(immType(*opcode, idx) != HA);
assert(immType(*opcode, idx) != IA);
const Opcode* ptr = opcode + 1;
const Op* ptr = opcode + 1;
for (int i = 0; i < idx; i++) {
ptr += immSize(opcode, i);
}
@@ -249,25 +246,26 @@ void encodeIvaToVector(std::vector<uchar>& out, int32_t val) {
out.resize(currentLen + encodeVariableSizeImm(val, &out[currentLen]));
}
int instrLen(const Opcode* opcode) {
int instrLen(const Op* opcode) {
auto op = *opcode;
int len = 1;
int nImm = numImmediates(*opcode);
int nImm = numImmediates(op);
for (int i = 0; i < nImm; i++) {
len += immSize(opcode, i);
}
return len;
}
InstrFlags instrFlags(Opcode opcode) {
InstrFlags instrFlags(Op opcode) {
static const InstrFlags instrFlagsData[] = {
#define O(unusedName, unusedImm, unusedPop, unusedPush, flags) flags,
OPCODES
#undef O
};
return instrFlagsData[opcode];
return instrFlagsData[uint8_t(opcode)];
}
Offset* instrJumpOffset(Opcode* instr) {
Offset* instrJumpOffset(Op* instr) {
static const int8_t jumpMask[] = {
#define NA 0
#define MA 0
@@ -305,7 +303,7 @@ Offset* instrJumpOffset(Opcode* instr) {
};
assert(!isSwitch(*instr));
int mask = jumpMask[*instr];
int mask = jumpMask[uint8_t(*instr)];
if (mask == 0) {
return nullptr;
}
@@ -322,8 +320,8 @@ Offset* instrJumpOffset(Opcode* instr) {
return &getImmPtr(instr, immNum)->u_BA;
}
Offset instrJumpTarget(const Opcode* instrs, Offset pos) {
Offset* offset = instrJumpOffset(const_cast<Opcode*>(instrs + pos));
Offset instrJumpTarget(const Op* instrs, Offset pos) {
Offset* offset = instrJumpOffset(const_cast<Op*>(instrs + pos));
if (!offset) {
return InvalidAbsoluteOffset;
@@ -336,16 +334,16 @@ Offset instrJumpTarget(const Opcode* instrs, Offset pos) {
* Return the number of successor-edges including fall-through paths but not
* implicit exception paths.
*/
int numSuccs(const Opcode* instr) {
int numSuccs(const Op* instr) {
if (!instrIsControlFlow(*instr)) return 1;
if ((instrFlags(*instr) & TF) != 0) {
if (isSwitch(*instr)) {
return *(int*)(instr + 1);
}
if (Op(*instr) == OpJmp) return 1;
if (*instr == OpJmp) return 1;
return 0;
}
if (instrJumpOffset(const_cast<Opcode*>(instr))) return 2;
if (instrJumpOffset(const_cast<Op*>(instr))) return 2;
return 1;
}
@@ -354,7 +352,7 @@ int numSuccs(const Opcode* instr) {
* for a given push/pop instruction. For peek/poke instructions, this
* function returns 0.
*/
int instrNumPops(const Opcode* opcode) {
int instrNumPops(const Op* opcode) {
static const int8_t numberOfPops[] = {
#define NOV 0
#define ONE(...) 1
@@ -384,7 +382,7 @@ int instrNumPops(const Opcode* opcode) {
#undef CMANY
#undef O
};
int n = numberOfPops[*opcode];
int n = numberOfPops[uint8_t(*opcode)];
// For most instructions, we know how many values are popped based
// solely on the opcode
if (n >= 0) return n;
@@ -409,7 +407,7 @@ int instrNumPops(const Opcode* opcode) {
* for a given push/pop instruction. For peek/poke instructions or
* InsertMid instructions, this function returns 0.
*/
int instrNumPushes(const Opcode* opcode) {
int instrNumPushes(const Op* opcode) {
static const int8_t numberOfPushes[] = {
#define NOV 0
#define ONE(...) 1
@@ -429,10 +427,10 @@ int instrNumPushes(const Opcode* opcode) {
#undef INS_2
#undef O
};
return numberOfPushes[*opcode];
return numberOfPushes[uint8_t(*opcode)];
}
StackTransInfo instrStackTransInfo(const Opcode* opcode) {
StackTransInfo instrStackTransInfo(const Op* opcode) {
static const StackTransInfo::Kind transKind[] = {
#define NOV StackTransInfo::Kind::PushPop
#define ONE(...) StackTransInfo::Kind::PushPop
@@ -472,7 +470,7 @@ StackTransInfo instrStackTransInfo(const Opcode* opcode) {
#undef O
};
StackTransInfo ret;
ret.kind = transKind[*opcode];
ret.kind = transKind[uint8_t(*opcode)];
switch (ret.kind) {
case StackTransInfo::Kind::PushPop:
ret.pos = 0;
@@ -482,14 +480,14 @@ StackTransInfo instrStackTransInfo(const Opcode* opcode) {
case StackTransInfo::Kind::InsertMid:
ret.numPops = 0;
ret.numPushes = 0;
ret.pos = peekPokeType[*opcode];
ret.pos = peekPokeType[uint8_t(*opcode)];
return ret;
default:
NOT_REACHED();
}
}
bool pushesActRec(Opcode opcode) {
bool pushesActRec(Op opcode) {
switch (opcode) {
case OpFPushFunc:
case OpFPushFuncD:
@@ -674,7 +672,7 @@ MemberCode parseMemberCode(const char* s) {
}
}
std::string instrToString(const Opcode* it, const Unit* u /* = NULL */) {
std::string instrToString(const Op* it, const Unit* u /* = NULL */) {
// IncDec names
static const char* incdecNames[] = {
"PreInc", "PostInc", "PreDec", "PostDec"
@@ -691,8 +689,8 @@ std::string instrToString(const Opcode* it, const Unit* u /* = NULL */) {
(int)(sizeof(setopNames)/sizeof(const char*));
std::stringstream out;
const Opcode* iStart = it;
Op op = (Op)*it;
const Op* iStart = it;
Op op = *it;
++it;
switch (op) {
@@ -707,11 +705,11 @@ std::string instrToString(const Opcode* it, const Unit* u /* = NULL */) {
it += sizeof(Offset); \
} while (false)
#define READV() out << " " << decodeVariableSizeImm(&it);
#define READV() out << " " << decodeVariableSizeImm((const uint8_t**)&it);
#define READIVA() do { \
out << " "; \
auto imm = decodeVariableSizeImm(&it); \
auto imm = decodeVariableSizeImm((const uint8_t**)&it); \
if (op == OpIncStat && immIdx == 0) { \
out << Stats::g_counterNames[imm]; \
} else { \
@@ -744,16 +742,16 @@ std::string instrToString(const Opcode* it, const Unit* u /* = NULL */) {
#define READVEC() do { \
int sz = *((int*)&*it); \
it += sizeof(int) * 2; \
const uint8_t* const start = it; \
const uint8_t* const start = (uint8_t*)it; \
out << " <"; \
if (sz > 0) { \
int immVal = (int)*((uchar*)&*it); \
out << ((immVal >=0 && size_t(immVal) < locationNamesCount) ? \
out << ((immVal >= 0 && size_t(immVal) < locationNamesCount) ? \
locationCodeString(LocationCode(immVal)) : "?"); \
it += sizeof(uchar); \
int numLocImms = numLocationCodeImms(LocationCode(immVal)); \
for (int i = 0; i < numLocImms; ++i) { \
out << ':' << decodeVariableSizeImm(&it); \
out << ':' << decodeVariableSizeImm((const uint8_t**)&it); \
} \
while (reinterpret_cast<const uint8_t*>(it) - start < sz) { \
immVal = (int)*((uchar*)&*it); \
@@ -761,7 +759,8 @@ std::string instrToString(const Opcode* it, const Unit* u /* = NULL */) {
memberCodeString(MemberCode(immVal)) : "?"); \
it += sizeof(uchar); \
if (memberCodeHasImm(MemberCode(immVal))) { \
int64_t imm = decodeMemberCodeImm(&it, MemberCode(immVal)); \
int64_t imm = decodeMemberCodeImm((const uint8_t**)&it, \
MemberCode(immVal)); \
out << ':'; \
if (memberCodeImmIsString(MemberCode(immVal)) && u) { \
const StringData* str = u->lookupLitstrId(imm); \
@@ -805,7 +804,7 @@ std::string instrToString(const Opcode* it, const Unit* u /* = NULL */) {
} \
Offset o = readData<Offset>(it); \
if (u != nullptr) { \
if (iStart + o == u->entry() - 1) { \
if (iStart + o == (Op*)u->entry() - 1) { \
out << "Invalid"; \
} else { \
out << u->offsetOf(iStart + o); \
@@ -874,26 +873,25 @@ OPCODES
return out.str();
}
const char* opcodeToName(Opcode op) {
const char* opcodeToName(Op op) {
const char* namesArr[] = {
#define O(name, imm, inputs, outputs, flags) \
#name ,
OPCODES
#undef O
"Invalid"
};
if (op >= 0 && op < sizeof namesArr / sizeof *namesArr) {
return namesArr[op];
if (op >= Op::LowInvalid && op <= Op::HighInvalid) {
return namesArr[uint8_t(op)];
}
return "Invalid";
}
bool instrIsControlFlow(Opcode opcode) {
bool instrIsControlFlow(Op opcode) {
InstrFlags opFlags = instrFlags(opcode);
return (opFlags & CF) != 0;
}
bool instrIsNonCallControlFlow(Opcode opcode) {
bool instrIsNonCallControlFlow(Op opcode) {
return
instrIsControlFlow(opcode) &&
!isFCallStar(opcode) &&
@@ -901,17 +899,17 @@ bool instrIsNonCallControlFlow(Opcode opcode) {
opcode != OpFCallBuiltin;
}
bool instrAllowsFallThru(Opcode opcode) {
bool instrAllowsFallThru(Op opcode) {
InstrFlags opFlags = instrFlags(opcode);
return (opFlags & TF) == 0;
}
bool instrReadsCurrentFpi(Opcode opcode) {
bool instrReadsCurrentFpi(Op opcode) {
InstrFlags opFlags = instrFlags(opcode);
return (opFlags & FF) != 0;
}
ImmVector getImmVector(const Opcode* opcode) {
ImmVector getImmVector(const Op* opcode) {
int numImm = numImmediates(*opcode);
for (int k = 0; k < numImm; ++k) {
ArgType t = immType(*opcode, k);
@@ -972,7 +970,7 @@ bool ImmVector::decodeLastMember(const Unit* u,
}
int instrSpToArDelta(const Opcode* opcode) {
int instrSpToArDelta(const Op* opcode) {
// This function should only be called for instructions that read
// the current FPI
assert(instrReadsCurrentFpi(*opcode));
+74 -34
Ver Arquivo
@@ -564,12 +564,42 @@ enum SetOpOp {
O(ArrayIdx, NA, THREE(CV,CV,CV), ONE(CV), NF) \
O(HighInvalid, NA, NOV, NOV, NF) \
enum Op {
#define O(name, imm, pop, push, flags) Op##name,
enum class Op : uint8_t {
#define O(name, ...) name,
OPCODES
#undef O
Op_count
};
auto constexpr Op_count = uint8_t(Op::HighInvalid) + 1;
/* Also put Op* in the enclosing namespace, to avoid having to change
* every existing usage site of the enum values. */
#define O(name, ...) UNUSED auto constexpr Op##name = Op::name;
OPCODES
#undef O
inline constexpr bool operator<(Op a, Op b) { return uint8_t(a) < uint8_t(b); }
inline constexpr bool operator>(Op a, Op b) { return uint8_t(a) > uint8_t(b); }
inline constexpr bool operator<=(Op a, Op b) {
return uint8_t(a) <= uint8_t(b);
}
inline constexpr bool operator>=(Op a, Op b) {
return uint8_t(a) >= uint8_t(b);
}
inline bool isValidOpcode(Op op) {
return op > OpLowInvalid && op < OpHighInvalid;
}
inline Op toOp(Opcode o) {
Op op = Op(o);
assert(isValidOpcode(op));
return op;
}
inline bool operator==(Op a, Opcode b) { return a == toOp(b); }
inline bool operator==(Opcode a, Op b) { return b == a; }
inline bool operator!=(Op a, Opcode b) { return !(a == b); }
inline bool operator!=(Opcode a, Op b) { return b != a; }
const MInstrInfo& getMInstrInfo(Op op);
@@ -684,26 +714,26 @@ private:
};
// Must be an opcode that actually has an ImmVector.
ImmVector getImmVector(const Opcode* opcode);
ImmVector getImmVector(const Op* opcode);
/* Some decoding helper functions. */
int numImmediates(Opcode opcode);
ArgType immType(Opcode opcode, int idx);
int immSize(const Opcode* opcode, int idx);
bool immIsVector(Opcode opcode, int idx);
bool hasImmVector(Opcode opcode);
inline bool isTypePred(const Opcode op) {
int numImmediates(Op opcode);
ArgType immType(Op opcode, int idx);
int immSize(const Op* opcode, int idx);
bool immIsVector(Op opcode, int idx);
bool hasImmVector(Op opcode);
inline bool isTypePred(const Op op) {
return op >= OpIsNullC && op <= OpIsObjectL;
}
int instrLen(const Opcode* opcode);
InstrFlags instrFlags(Opcode opcode);
int numSuccs(const Opcode* opcode);
bool pushesActRec(Opcode opcode);
int instrLen(const Op* opcode);
InstrFlags instrFlags(Op opcode);
int numSuccs(const Op* opcode);
bool pushesActRec(Op opcode);
// The returned struct has normalized variable-sized immediates
ArgUnion getImm(const Opcode* opcode, int idx);
ArgUnion getImm(const Op* opcode, int idx);
// Don't use this with variable-sized immediates!
ArgUnion* getImmPtr(const Opcode* opcode, int idx);
ArgUnion* getImmPtr(const Op* opcode, int idx);
// Pass a pointer to the pointer to the immediate; this function will advance
// the pointer past the immediate
@@ -737,17 +767,17 @@ void encodeToVector(std::vector<uchar>& vec, T val) {
void staticStreamer(const TypedValue* tv, std::stringstream& out);
std::string instrToString(const Opcode* it, const Unit* u = nullptr);
const char* opcodeToName(Opcode op);
std::string instrToString(const Op* it, const Unit* u = nullptr);
const char* opcodeToName(Op op);
// returns a pointer to the location within the bytecode containing the jump
// Offset, or NULL if the instruction cannot jump. Note that this offset is
// relative to the current instruction.
Offset* instrJumpOffset(Opcode* instr);
Offset* instrJumpOffset(Op* instr);
// returns absolute address of target, or InvalidAbsoluteOffset if instruction
// cannot jump
Offset instrJumpTarget(const Opcode* instrs, Offset pos);
Offset instrJumpTarget(const Op* instrs, Offset pos);
struct StackTransInfo {
enum class Kind {
@@ -760,26 +790,28 @@ struct StackTransInfo {
int pos;
};
bool isValidOpcode(Opcode opcode);
bool instrIsControlFlow(Opcode opcode);
bool instrIsNonCallControlFlow(Opcode opcode);
bool instrAllowsFallThru(Opcode opcode);
bool instrReadsCurrentFpi(Opcode opcode);
bool instrIsControlFlow(Op opcode);
bool instrIsNonCallControlFlow(Op opcode);
bool instrAllowsFallThru(Op opcode);
bool instrReadsCurrentFpi(Op opcode);
inline bool isFPush(Opcode opcode) {
inline bool isFPush(Op opcode) {
return opcode >= OpFPushFunc && opcode <= OpFPushCufSafe;
}
inline bool isFCallStar(Opcode opcode) {
inline bool isFCallStar(Op opcode) {
return opcode == OpFCall || opcode == OpFCallArray;
}
inline bool isSwitch(Opcode op) {
inline bool isSwitch(Op op) {
return op == OpSwitch || op == OpSSwitch;
}
inline bool isSwitch(Opcode op) {
return isSwitch(toOp(op));
}
template<typename L>
void foreachSwitchTarget(Opcode* op, L func) {
void foreachSwitchTarget(Op* op, L func) {
assert(isSwitch(*op));
bool isStr = readData<Opcode>(op) == OpSSwitch;
int32_t size = readData<int32_t>(op);
@@ -800,10 +832,10 @@ void foreachSwitchString(Opcode* op, L func) {
}
}
int instrNumPops(const Opcode* opcode);
int instrNumPushes(const Opcode* opcode);
StackTransInfo instrStackTransInfo(const Opcode* opcode);
int instrSpToArDelta(const Opcode* opcode);
int instrNumPops(const Op* opcode);
int instrNumPushes(const Op* opcode);
StackTransInfo instrStackTransInfo(const Op* opcode);
int instrSpToArDelta(const Op* opcode);
inline bool
mcodeIsLiteral(MemberCode mcode) {
@@ -835,7 +867,15 @@ mcodeMaybeVectorKey(MemberCode mcode) {
return mcode == MEC || mcode == MEL || mcode == MEI;
}
}
namespace std { namespace tr1 {
template<>
struct hash<HPHP::Op> {
size_t operator()(HPHP::Op op) const {
return HPHP::hash_int64(uint8_t(op));
}
};
} }
#endif
+2 -2
Ver Arquivo
@@ -107,7 +107,7 @@ static void recordActRecPush(NormalizedInstruction& i,
assert(name->isStatic());
assert(sk.offset() == fpi->m_fpushOff);
auto const fcall = SrcKey { curFunc(), fpi->m_fcallOff };
assert(isFCallStar(*unit->at(fcall.offset())));
assert(isFCallStar(toOp(*unit->at(fcall.offset()))));
if (clsName) {
const Class* cls = Unit::lookupUniqueClass(clsName);
bool magic = false;
@@ -126,7 +126,7 @@ static void recordActRecPush(NormalizedInstruction& i,
} else {
// It's not enough to remember the function name; we also need to encode
// the number of arguments and current flag disposition.
int numArgs = getImm(unit->at(sk.offset()), 0).u_IVA;
int numArgs = getImm((Op*)unit->at(sk.offset()), 0).u_IVA;
recordNameAndArgs(fcall, name, numArgs);
}
}
+19 -19
Ver Arquivo
@@ -136,7 +136,7 @@ Translator::translateMod(const NormalizedInstruction& i) {
void
Translator::translateBinaryArithOp(const NormalizedInstruction& i) {
const Opcode op = i.op();
auto const op = i.op();
switch (op) {
#define CASE(OpBc) \
case Op ## OpBc: HHIR_EMIT(OpBc);
@@ -156,7 +156,7 @@ Translator::translateBinaryArithOp(const NormalizedInstruction& i) {
void
Translator::translateSameOp(const NormalizedInstruction& i) {
const Opcode op = i.op();
auto const op = i.op();
assert(op == OpSame || op == OpNSame);
if (op == OpSame) {
HHIR_EMIT(Same);
@@ -167,7 +167,7 @@ Translator::translateSameOp(const NormalizedInstruction& i) {
void
Translator::translateEqOp(const NormalizedInstruction& i) {
const Opcode op = i.op();
auto const op = i.op();
assert(op == OpEq || op == OpNeq);
if (op == OpEq) {
HHIR_EMIT(Eq);
@@ -178,7 +178,7 @@ Translator::translateEqOp(const NormalizedInstruction& i) {
void
Translator::translateLtGtOp(const NormalizedInstruction& i) {
const Opcode op = i.op();
auto const op = i.op();
assert(op == OpLt || op == OpLte || op == OpGt || op == OpGte);
assert(i.inputs.size() == 2);
assert(i.inputs[0]->outerType() != KindOfRef);
@@ -203,7 +203,7 @@ Translator::translateLtGtOp(const NormalizedInstruction& i) {
void
Translator::translateUnaryBooleanOp(const NormalizedInstruction& i) {
const Opcode op = i.op();
auto const op = i.op();
assert(op == OpCastBool || op == OpEmptyL);
if (op == OpCastBool) {
HHIR_EMIT(CastBool);
@@ -214,7 +214,7 @@ Translator::translateUnaryBooleanOp(const NormalizedInstruction& i) {
void
Translator::translateBranchOp(const NormalizedInstruction& i) {
const Opcode op = i.op();
auto const op = i.op();
assert(op == OpJmpZ || op == OpJmpNZ);
assert(!i.next);
@@ -227,8 +227,8 @@ Translator::translateBranchOp(const NormalizedInstruction& i) {
void
Translator::translateCGetL(const NormalizedInstruction& i) {
const DEBUG_ONLY Opcode op = i.op();
assert(op == OpFPassL || OpCGetL);
DEBUG_ONLY auto const op = i.op();
assert(op == OpFPassL || op == OpCGetL);
const vector<DynLocation*>& inputs = i.inputs;
assert(inputs.size() == 1);
assert(inputs[0]->isLocal());
@@ -252,7 +252,7 @@ void
Translator::translateAssignToLocalOp(const NormalizedInstruction& ni) {
DEBUG_ONLY const int rhsIdx = 0;
const int locIdx = 1;
const Opcode op = ni.op();
auto const op = ni.op();
assert(op == OpSetL || op == OpBindL);
assert(ni.inputs.size() == 2);
assert((op == OpBindL) ==
@@ -735,7 +735,7 @@ void
Translator::translateCheckTypeOp(const NormalizedInstruction& ni) {
assert(ni.inputs.size() == 1);
const Opcode op = ni.op();
auto const op = ni.op();
const int off = ni.inputs[0]->location.offset;
switch (op) {
case OpIssetL: HHIR_EMIT(IssetL, off);
@@ -755,8 +755,8 @@ Translator::translateCheckTypeOp(const NormalizedInstruction& ni) {
case OpIsObjectC: HHIR_EMIT(IsObjectC);
// Note: for IsObject*, we need to emit some kind of
// call to ObjectData::isResource or something.
default: not_reached();
}
NOT_REACHED();
}
void
@@ -915,7 +915,7 @@ Translator::translateFPushFuncD(const NormalizedInstruction& i) {
void
Translator::translateFPassCOp(const NormalizedInstruction& i) {
const Opcode op = i.op();
auto const op = i.op();
if (i.preppedByRef && (op == OpFPassCW || op == OpFPassCE)) {
// These cases might have to raise a warning or an error
HHIR_UNIMPLEMENTED(FPassCW_FPassCE_byref);
@@ -1081,18 +1081,18 @@ bool shouldIRInline(const Func* curFunc,
// Little pattern recognition helpers:
const NormalizedInstruction* cursor;
Opcode current;
Op current;
auto resetCursor = [&] {
cursor = callee.m_instrStream.first;
current = cursor->op();
};
auto next = [&]() -> Opcode {
auto next = [&]() -> Op {
auto op = cursor->op();
cursor = cursor->next;
current = cursor->op();
return op;
};
auto nextIf = [&](Opcode op) -> bool {
auto nextIf = [&](Op op) -> bool {
if (current != op) return false;
next();
return true;
@@ -1485,15 +1485,15 @@ Translator::translateInstrDefault(const NormalizedInstruction& i) {
OPCODES
#undef O
};
const Opcode op = i.op();
auto const op = i.op();
HHIR_UNIMPLEMENTED_OP(opNames[op]);
HHIR_UNIMPLEMENTED_OP(opNames[uint8_t(op)]);
assert(false);
}
void
Translator::translateInstrWork(const NormalizedInstruction& i) {
const Opcode op = i.op();
auto const op = i.op();
switch (op) {
#define CASE(iNm) \
@@ -1510,7 +1510,7 @@ Translator::translateInstrWork(const NormalizedInstruction& i) {
}
}
static bool isPop(Opcode opc) {
static bool isPop(Op opc) {
return opc == OpPopC || opc == OpPopR;
}
+1 -1
Ver Arquivo
@@ -33,7 +33,7 @@ bool isFuncEntry(const Func* func, Offset off) {
int numInstrs(PC start, PC end) {
int ret{};
for (; start != end; ++ret) {
start += instrLen(start);
start += instrLen((Op*)start);
}
return ret;
}
+3 -3
Ver Arquivo
@@ -93,12 +93,12 @@ void RegionDesc::Block::checkInvariants() const {
for (int i = 1; i < length(); ++i) {
if (i != length() - 1) {
auto const pc = unit()->at(keysInRange.back().offset());
if (instrFlags(*pc) & TF) {
if (instrFlags(toOp(*pc)) & TF) {
FTRACE(1, "Bad block: {}\n", show(*this));
assert(!"Block may not contain non-fallthrough instruction unless "
"they are last");
}
if (instrIsNonCallControlFlow(*pc)) {
if (instrIsNonCallControlFlow(toOp(*pc))) {
FTRACE(1, "Bad block: {}\n", show(*this));
assert(!"Block may not contain control flow instructions unless "
"they are last");
@@ -324,7 +324,7 @@ std::string show(const RegionDesc::Block& b) {
" ",
skIter.offset(),
" ",
instrToString(b.unit()->at(skIter.offset()), b.unit()),
instrToString((Op*)b.unit()->at(skIter.offset()), b.unit()),
'\n',
&ret
);
+8 -24
Ver Arquivo
@@ -1782,7 +1782,7 @@ int32_t TranslatorX64::emitNativeImpl(const Func* func,
assert(func->numIterators() == 0 && func->isBuiltin());
assert(func->numLocals() == func->numParams());
assert(*func->getEntry() == OpNativeImpl);
assert(instrLen(func->getEntry()) == func->past() - func->base());
assert(instrLen((Op*)func->getEntry()) == func->past() - func->base());
Offset pcOffset = 0; // NativeImpl is the only instruction in the func
Offset stackOff = func->numLocals(); // Builtin stubs have no
// non-arg locals
@@ -2496,7 +2496,7 @@ bool TranslatorX64::handleServiceRequest(TReqInfo& info,
const FPIEnt* fe = curFunc()->findPrecedingFPI(
curUnit()->offsetOf(vmpc()));
vmpc() = curUnit()->at(fe->m_fcallOff);
assert(isFCallStar(*vmpc()));
assert(isFCallStar(toOp(*vmpc())));
raise_error("Stack overflow");
NOT_REACHED();
}
@@ -2711,24 +2711,6 @@ TranslatorX64::getInputsIntoXMMRegs(const NormalizedInstruction& ni,
intoXmm(r, rr, rxmm);
}
void
TranslatorX64::binaryMixedArith(const NormalizedInstruction& i,
Opcode op,
PhysReg srcReg,
PhysReg srcDestReg) {
getInputsIntoXMMRegs(i, srcReg, srcDestReg, xmm1, xmm0);
switch(op) {
#define CASEIMM(OpBc, x64op) \
case OpBc: a. x64op ##sd_xmm_xmm(xmm1, xmm0); break
CASEIMM(OpAdd, add);
CASEIMM(OpSub, sub);
CASEIMM(OpMul, mul);
#undef CASEIMM
default: not_reached();
}
a. mov_xmm_reg64(xmm0, srcDestReg);
}
#define O(opcode, imm, pusph, pop, flags) \
/**
* The interpOne methods saves m_pc, m_fp, and m_sp ExecutionContext,
@@ -2741,7 +2723,7 @@ interpOne##opcode(ActRec* ar, Cell* sp, Offset pcOff) { \
SKTRACE(5, SrcKey(curFunc(), vmpc()), "%40s %p %p\n", \
"interpOne" #opcode " before (fp,sp)", \
vmfp(), vmsp()); \
assert(*vmpc() == Op ## opcode); \
assert(toOp(*vmpc()) == Op::opcode); \
VMExecutionContext* ec = g_vmContext; \
Stats::inc(Stats::Instr_InterpOne ## opcode); \
INC_TPC(interp_one) \
@@ -3090,15 +3072,17 @@ int64_t switchObjHelper(ObjectData* o, int64_t base, int64_t nTargets) {
func(CheckTypeOp, t, i)
bool
TranslatorX64::dontGuardAnyInputs(Opcode op) {
TranslatorX64::dontGuardAnyInputs(Op op) {
switch (op) {
#define CASE(iNm) case Op ## iNm:
#define NOOP(a, b, c)
INSTRS
PSEUDOINSTR_DISPATCH(NOOP)
return false;
default:
return true;
}
return true;
#undef NOOP
#undef CASE
}
@@ -3206,7 +3190,7 @@ void dumpTranslationInfo(const Tracelet& t, TCA postGuards) {
}
for (auto ni = t.m_instrStream.first; ni; ni = ni->next) {
TRACE(3, " %6d: %s\n", ni->source.offset(),
instrToString(ni->pc()).c_str());
instrToString((Op*)ni->pc()).c_str());
if (ni->breaksTracelet) break;
}
TRACE(3, "----------------------------------------------\n");
+1 -3
Ver Arquivo
@@ -253,8 +253,6 @@ private:
void getInputsIntoXMMRegs(const NormalizedInstruction& ni,
PhysReg lr, PhysReg rr,
RegXMM lxmm, RegXMM rxmm);
void binaryMixedArith(const NormalizedInstruction &i,
Opcode op, PhysReg srcReg, PhysReg srcDestReg);
void fpEq(const NormalizedInstruction& i, PhysReg lr, PhysReg rr);
void emitRB(Asm& a, Trace::RingBufferType t, SrcKey sk,
RegSet toSave = RegSet());
@@ -274,7 +272,7 @@ private:
static uint64_t toStringHelper(ObjectData *obj);
void invalidateSrcKey(SrcKey sk);
bool dontGuardAnyInputs(Opcode op);
bool dontGuardAnyInputs(Op op);
public:
template<typename T>
void invalidateSrcKeys(const T& keys) {
+26 -23
Ver Arquivo
@@ -184,7 +184,7 @@ void sktrace(SrcKey sk, const char *fmt, ...) {
return;
}
// We don't want to print string literals, so don't pass the unit
string s = instrToString(curUnit()->at(sk.offset()));
string s = instrToString((Op*)curUnit()->at(sk.offset()));
const char *filepath = "*anonFile*";
if (curUnit()->filepath()->data() &&
strlen(curUnit()->filepath()->data()) > 0)
@@ -784,7 +784,7 @@ static RuntimeType setOpOutputType(NormalizedInstruction* ni,
static RuntimeType
getDynLocType(const vector<DynLocation*>& inputs,
const Tracelet& t,
Opcode opcode,
Op opcode,
NormalizedInstruction* ni,
Operands op,
OutTypeConstraints constraint,
@@ -889,7 +889,7 @@ getDynLocType(const vector<DynLocation*>& inputs,
* consumers, stack elements before M-vectors and locals, etc.)
*/
assert(inputs.size() >= 1);
Opcode op = ni->op();
auto op = ni->op();
ASSERT_NOT_IMPLEMENTED(
// Sets and binds that take multiple arguments have the rhs
// pushed first. In the case of the M-vector versions, the
@@ -1031,7 +1031,7 @@ struct InstrInfo {
};
static const struct {
Opcode op;
Op op;
InstrInfo info;
} instrInfoSparse [] = {
@@ -1362,7 +1362,7 @@ static const struct {
{ OpContHandle, {Stack1, None, OutNone, -1 }},
};
static hphp_hash_map<Opcode, InstrInfo> instrInfo;
static hphp_hash_map<Op, InstrInfo> instrInfo;
static bool instrInfoInited;
static void initInstrInfo() {
if (!instrInfoInited) {
@@ -1383,7 +1383,7 @@ static int numHiddenStackInputs(const NormalizedInstruction& ni) {
int getStackDelta(const NormalizedInstruction& ni) {
int hiddenStackInputs = 0;
initInstrInfo();
Opcode op = ni.op();
auto op = ni.op();
switch (op) {
case OpFCall: {
int numArgs = ni.imm[0].u_IVA;
@@ -1394,6 +1394,9 @@ int getStackDelta(const NormalizedInstruction& ni) {
case OpNewTuple:
case OpCreateCl:
return 1 - ni.imm[0].u_IVA;
default:
break;
}
const InstrInfo& info = instrInfo[op];
if (info.in & MVector) {
@@ -1919,7 +1922,7 @@ void Translator::getInputs(SrcKey startSk,
}
}
bool outputDependsOnInput(const Opcode instr) {
bool outputDependsOnInput(const Op instr) {
switch (instrInfo[instr].type) {
case OutNull:
case OutNullUninit:
@@ -2220,7 +2223,7 @@ void Translator::getOutputs(/*inout*/ Tracelet& t,
op == OpWIterInitK || op == OpWIterNextK ||
op == OpMIterInitK || op == OpMIterNextK) {
DynLocation* outKey = t.newDynLocation();
int keyOff = getImm(ni->pc(), kKeyImmIdx).u_IVA;
int keyOff = getImm((Op*)ni->pc(), kKeyImmIdx).u_IVA;
outKey->location = Location(Location::Local, keyOff);
outKey->rtt = RuntimeType(KindOfInvalid);
ni->outLocal2 = outKey;
@@ -2423,7 +2426,7 @@ void TraceletContext::recordJmp() {
* Helpers for recovering context of this instruction.
*/
Op NormalizedInstruction::op() const {
uchar op = *pc();
auto op = toOp(*pc());
assert(isValidOpcode(op));
return (Op)op;
}
@@ -2454,7 +2457,7 @@ Offset NormalizedInstruction::offset() const {
}
std::string NormalizedInstruction::toString() const {
return instrToString(pc(), unit());
return instrToString((Op*)pc(), unit());
}
void Translator::postAnalyze(NormalizedInstruction* ni, SrcKey& sk,
@@ -2473,7 +2476,7 @@ void Translator::postAnalyze(NormalizedInstruction* ni, SrcKey& sk,
}
static bool isPop(const NormalizedInstruction* instr) {
Opcode opc = instr->op();
auto opc = instr->op();
return (opc == OpPopC ||
opc == OpPopV ||
opc == OpPopR);
@@ -2644,7 +2647,7 @@ bool isPopped(DynLocation* loc, NormalizedInstruction* instr) {
DataTypeCategory
Translator::getOperandConstraintCategory(NormalizedInstruction* instr,
size_t opndIdx) {
Opcode opc = instr->op();
auto opc = instr->op();
switch (opc) {
case OpSetS:
@@ -2754,7 +2757,7 @@ void Translator::constrainDep(const DynLocation* loc,
for (NormalizedInstruction* instr = firstInstr; instr; instr = instr->next) {
if (instr->noOp) continue;
Opcode opc = instr->op();
auto opc = instr->op();
size_t nInputs = instr->inputs.size();
for (size_t i = 0; i < nInputs; i++) {
DynLocation* usedLoc = instr->inputs[i];
@@ -2826,7 +2829,7 @@ void Translator::propagateRelaxedType(Tracelet& tclet,
for (NormalizedInstruction* instr = firstInstr; instr; instr = instr->next) {
if (instr->noOp) continue;
Opcode opc = instr->op();
auto opc = instr->op();
size_t nInputs = instr->inputs.size();
for (size_t i = 0; i < nInputs; i++) {
DynLocation* usedLoc = instr->inputs[i];
@@ -2967,7 +2970,7 @@ static bool checkTaintFuncs(StringData* name) {
*/
static bool shouldAnalyzeCallee(const NormalizedInstruction* fcall,
const FPIEnt* fpi,
const Opcode pushOp) {
const Op pushOp) {
auto const numArgs = fcall->imm[0].u_IVA;
auto const target = fcall->funcd;
@@ -3315,7 +3318,7 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
// beginning of the instruction, but getReffiness() wants the delta
// relative to the sp at the beginning of the tracelet, so we adjust
// by subtracting ni->stackOff
int entryArDelta = instrSpToArDelta(ni->pc()) - ni->stackOffset;
int entryArDelta = instrSpToArDelta((Op*)ni->pc()) - ni->stackOffset;
ni->preppedByRef = t.m_arState.getReffiness(argNum,
entryArDelta,
&t.m_refDeps);
@@ -3390,11 +3393,11 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
doVarEnvTaint = true;
} else if (*fpushPc == OpFPushFuncD) {
StringData *funcName =
curUnit()->lookupLitstrId(getImm(fpushPc, 1).u_SA);
curUnit()->lookupLitstrId(getImm((Op*)fpushPc, 1).u_SA);
doVarEnvTaint = checkTaintFuncs(funcName);
} else if (*fpushPc == OpFPushFuncU) {
StringData *fallbackName =
curUnit()->lookupLitstrId(getImm(fpushPc, 2).u_SA);
curUnit()->lookupLitstrId(getImm((Op*)fpushPc, 2).u_SA);
doVarEnvTaint = checkTaintFuncs(fallbackName);
}
}
@@ -3566,8 +3569,8 @@ Translator::isSrcKeyInBL(const Unit* unit, const SrcKey& sk) {
if (m_dbgBLSrcKey.find(sk) != m_dbgBLSrcKey.end()) {
return true;
}
for (PC pc = unit->at(sk.offset()); !opcodeBreaksBB(*pc);
pc += instrLen(pc)) {
for (PC pc = unit->at(sk.offset()); !opcodeBreaksBB(toOp(*pc));
pc += instrLen((Op*)pc)) {
if (m_dbgBLPC.checkPC(pc)) {
m_dbgBLSrcKey.insert(sk);
return true;
@@ -3602,10 +3605,10 @@ SrcKey Translator::nextSrcKey(const NormalizedInstruction& i) {
void Translator::populateImmediates(NormalizedInstruction& inst) {
for (int i = 0; i < numImmediates(inst.op()); i++) {
inst.imm[i] = getImm(inst.pc(), i);
inst.imm[i] = getImm((Op*)inst.pc(), i);
}
if (hasImmVector(*inst.pc())) {
inst.immVec = getImmVector(inst.pc());
if (hasImmVector(toOp(*inst.pc()))) {
inst.immVec = getImmVector((Op*)inst.pc());
}
if (inst.op() == OpFCallArray) {
inst.imm[0].u_IVA = 1;
+5 -5
Ver Arquivo
@@ -1074,7 +1074,7 @@ public:
* inputs to this instruction (this is essentially to avoid
* generating guards on behalf of interpreted instructions).
*/
virtual bool dontGuardAnyInputs(Opcode op) { return false; }
virtual bool dontGuardAnyInputs(Op op) { return false; }
protected:
PCFilter m_dbgBLPC;
@@ -1121,7 +1121,7 @@ enum class ControlFlowInfo {
};
static inline ControlFlowInfo
opcodeControlFlowInfo(const Opcode instr) {
opcodeControlFlowInfo(const Op instr) {
switch (instr) {
case OpJmp:
case OpJmpZ:
@@ -1174,7 +1174,7 @@ opcodeControlFlowInfo(const Opcode instr) {
* to something other than the next instruction in the bytecode
*/
static inline bool
opcodeChangesPC(const Opcode instr) {
opcodeChangesPC(const Op instr) {
return opcodeControlFlowInfo(instr) >= ControlFlowInfo::ChangesPC;
}
@@ -1186,11 +1186,11 @@ opcodeChangesPC(const Opcode instr) {
* do not (ex. FCall).
*/
static inline bool
opcodeBreaksBB(const Opcode instr) {
opcodeBreaksBB(const Op instr) {
return opcodeControlFlowInfo(instr) == ControlFlowInfo::BreaksBB;
}
bool outputDependsOnInput(const Opcode instr);
bool outputDependsOnInput(const Op instr);
extern bool tc_dump();
const Func* lookupImmutableMethod(const Class* cls, const StringData* name,
+1 -1
Ver Arquivo
@@ -89,7 +89,7 @@ struct SrcKey : private boost::totally_ordered<SrcKey> {
* contain an invalid bytecode offset.
*/
void advance(const Unit* u) {
m_offset += instrLen(u->at(offset()));
m_offset += instrLen((Op*)u->at(offset()));
}
/*
+2 -2
Ver Arquivo
@@ -1577,7 +1577,7 @@ void Unit::prettyPrint(std::ostream& out, PrintOpts opts) const {
out << std::string(opts.indentSize, ' ')
<< std::setw(4) << (it - m_bc) << ": ";
out << instrToString((Opcode*)it, (Unit*)this);
out << instrToString((Op*)it, (Unit*)this);
if (metaHand.findMeta(this, offsetOf(it))) {
out << " #";
Unit::MetaInfo info;
@@ -1633,7 +1633,7 @@ void Unit::prettyPrint(std::ostream& out, PrintOpts opts) const {
}
}
out << std::endl;
it += instrLen((Opcode*)it);
it += instrLen((Op*)it);
}
}
+5 -2
Ver Arquivo
@@ -412,6 +412,9 @@ struct Unit {
assert(op >= m_bc && op <= (m_bc + m_bclen));
return op - m_bc;
}
Offset offsetOf(const Op* op) const {
return offsetOf(reinterpret_cast<const Opcode*>(op));
}
const StringData* filepath() const {
assert(m_filepath);
@@ -607,9 +610,9 @@ public:
bool getOffsetRanges(int line, OffsetRangeVec& offsets) const;
bool getOffsetRange(Offset pc, OffsetRange& range) const;
Opcode getOpcode(size_t instrOffset) const {
Op getOpcode(size_t instrOffset) const {
assert(instrOffset < m_bclen);
return (Opcode)m_bc[instrOffset];
return toOp(m_bc[instrOffset]);
}
/*
+4 -4
Ver Arquivo
@@ -58,11 +58,11 @@ void GraphBuilder::createBlocks() {
PC pc = i.popFront();
if (isCF(pc) && !i.empty()) createBlock(i.front());
if (isSwitch(*pc)) {
foreachSwitchTarget((Opcode*)pc, [&](Offset& o) {
foreachSwitchTarget((Op*)pc, [&](Offset& o) {
createBlock(pc + o);
});
} else {
Offset target = instrJumpTarget(bc, pc - bc);
Offset target = instrJumpTarget((Op*)bc, pc - bc);
if (target != InvalidAbsoluteOffset) createBlock(target);
}
}
@@ -82,11 +82,11 @@ void GraphBuilder::linkBlocks() {
if (isCF(pc)) {
if (isSwitch(*pc)) {
int i = 0;
foreachSwitchTarget((Opcode*)pc, [&](Offset& o) {
foreachSwitchTarget((Op*)pc, [&](Offset& o) {
succs(block)[i++] = at(pc + o);
});
} else {
Offset target = instrJumpTarget(bc, pc - bc);
Offset target = instrJumpTarget((Op*)bc, pc - bc);
if (target != InvalidAbsoluteOffset) {
assert(numSuccBlocks(block) > 0);
succs(block)[numSuccBlocks(block) - 1] = at(target);
+10 -10
Ver Arquivo
@@ -81,31 +81,31 @@ struct Graph {
};
inline bool isTF(PC pc) {
return (instrFlags(*pc) & TF) != 0;
return (instrFlags(toOp(*pc)) & TF) != 0;
}
inline bool isCF(PC pc) {
return instrIsNonCallControlFlow(*pc);
return instrIsNonCallControlFlow(toOp(*pc));
}
inline bool isFF(PC pc) {
return instrReadsCurrentFpi(*pc);
return instrReadsCurrentFpi(toOp(*pc));
}
inline bool isRet(PC pc) {
return isTF(pc) && Op(*pc) >= OpRetC && Op(*pc) <= OpRetV;
return isTF(pc) && toOp(*pc) >= OpRetC && toOp(*pc) <= OpRetV;
}
inline bool isIter(PC pc) {
return Op(*pc) >= OpIterInit && Op(*pc) <= OpCIterFree;
return toOp(*pc) >= OpIterInit && toOp(*pc) <= OpCIterFree;
}
inline int getImmIva(PC pc) {
return getImm((Opcode*)pc, 0).u_IVA;
return getImm((Op*)pc, 0).u_IVA;
}
inline int numSuccBlocks(const Block* b) {
return numSuccs(b->last);
return numSuccs((Op*)b->last);
}
/**
@@ -203,7 +203,7 @@ class InstrRange {
}
PC popFront() {
PC i = front();
pc += instrLen((Opcode*)i);
pc += instrLen((Op*)i);
return i;
}
private:
@@ -251,12 +251,12 @@ typedef std::pair<Id, Offset> CatchEnt;
inline Offset fpiBase(const FPIEnt& fpi, PC bc) {
PC fpush = bc + fpi.m_fpushOff;
return fpush + instrLen((Opcode*)fpush) - bc;
return fpush + instrLen((Op*)fpush) - bc;
}
inline Offset fpiPast(const FPIEnt& fpi, PC bc) {
PC fcall = bc + fpi.m_fcallOff;
return fcall + instrLen((Opcode*)fcall) - bc;
return fcall + instrLen((Op*)fcall) - bc;
}
}} // HPHP::Verifier
+44 -41
Ver Arquivo
@@ -76,7 +76,7 @@ class FuncChecker {
const char* regionName, Offset base, Offset past,
bool check_instrs = true);
bool checkSection(bool main, const char* name, Offset base, Offset past);
bool checkImmediates(const char* name, const Opcode* instr);
bool checkImmediates(const char* name, const Op* instr);
bool checkInputs(State* cur, PC, Block* b);
bool checkOutputs(State* cur, PC, Block* b);
bool checkSig(PC pc, int len, const FlavorDesc* args, const FlavorDesc* sig);
@@ -246,14 +246,14 @@ bool FuncChecker::checkSection(bool is_main, const char* name, Offset base,
PC bc = unit()->entry();
// Find instruction boundaries and branch instructions.
for (InstrRange i(at(base), at(past)); !i.empty();) {
if (!checkImmediates(name, i.front())) return false;
if (!checkImmediates(name, (Op*)i.front())) return false;
PC pc = i.popFront();
m_instrs.set(offset(pc) - m_func->base());
if (isSwitch(*pc) ||
instrJumpTarget(bc, offset(pc)) != InvalidAbsoluteOffset) {
if (*pc == OpSwitch && getImm(pc, 2).u_IVA != 0) {
int64_t switchBase = getImm(pc, 1).u_I64A;
int32_t len = getImmVector(pc).size();
if (isSwitch(toOp(*pc)) ||
instrJumpTarget((Op*)bc, offset(pc)) != InvalidAbsoluteOffset) {
if (*pc == OpSwitch && getImm((Op*)pc, 2).u_IVA != 0) {
int64_t switchBase = getImm((Op*)pc, 1).u_I64A;
int32_t len = getImmVector((Op*)pc).size();
if (len <= 2) {
error("Bounded switch must have a vector of length > 2 [%d:%d]\n",
base, past);
@@ -269,14 +269,14 @@ bool FuncChecker::checkSection(bool is_main, const char* name, Offset base,
branches.push_back(pc);
}
if (i.empty()) {
if (offset(pc + instrLen(pc)) != past) {
if (offset(pc + instrLen((Op*)pc)) != past) {
error("Last instruction in %s at %d overflows [%d:%d]\n",
name, offset(pc), base, past);
ok = false;
}
if (!isTF(pc)) {
error("Last instruction in %s is not teriminal %d:%s\n",
name, offset(pc), instrToString(pc, unit()).c_str());
name, offset(pc), instrToString((Op*)pc, unit()).c_str());
ok = false;
} else {
if (isRet(pc) && !is_main) {
@@ -294,12 +294,12 @@ bool FuncChecker::checkSection(bool is_main, const char* name, Offset base,
for (Range<BranchList> i(branches); !i.empty();) {
PC branch = i.popFront();
if (isSwitch(*branch)) {
foreachSwitchTarget((Opcode*)branch, [&](Offset& o) {
foreachSwitchTarget((Op*)branch, [&](Offset& o) {
ok &= checkOffset("switch target", offset(branch + o),
name, base, past);
});
} else {
Offset target = instrJumpTarget(bc, offset(branch));
Offset target = instrJumpTarget((Op*)bc, offset(branch));
ok &= checkOffset("branch target", target, name, base, past);
}
}
@@ -323,7 +323,7 @@ Offset decodeOffset(PC* ppc) {
*/
class ImmVecRange {
public:
explicit ImmVecRange(const Opcode* instr) : v(getImmVector(instr)),
explicit ImmVecRange(const Op* instr) : v(getImmVector(instr)),
vecp(v.vec() + 1), // skip location code
loc(v.locationCode()),
loc_local(numLocationCodeImms(loc) ? decodeVariableSizeImm(&vecp) : -1) {
@@ -392,10 +392,10 @@ bool FuncChecker::checkString(PC pc, Id id) {
* Check instruction and its immediates, return false if we can't continue
* because we don't know the length of this instruction
*/
bool FuncChecker::checkImmediates(const char* name, const Opcode* instr) {
bool FuncChecker::checkImmediates(const char* name, const Op* instr) {
if (!isValidOpcode(*instr)) {
error("Invalid opcode %d in section %s at offset %d\n",
*instr, name, offset(instr));
uint8_t(*instr), name, offset(PC(instr)));
return false;
}
bool ok = true;
@@ -409,12 +409,12 @@ bool FuncChecker::checkImmediates(const char* name, const Opcode* instr) {
if (vr.size() < 2) {
// vector must at least have a LocationCode and 1+ MemberCodes
error("invalid vector size %d at %d\n",
vr.size(), offset(instr));
vr.size(), offset((PC)instr));
return false;
} else {
if (vr.loc < 0 || vr.loc >= NumLocationCodes) {
error("invalid location code %d in vector at %d\n",
(int)vr.loc, offset(instr));
(int)vr.loc, offset((PC)instr));
ok = false;
}
if (vr.loc_local != -1) checkLocal(pc, vr.loc_local);
@@ -464,6 +464,8 @@ bool FuncChecker::checkImmediates(const char* name, const Opcode* instr) {
k, offset((PC)instr));
ok = false;
}
default:
break;
}
break;
}
@@ -498,7 +500,7 @@ bool FuncChecker::checkImmediates(const char* name, const Opcode* instr) {
}
case BA: // bytecode address
// we check branch offsets in checkSection(). ignore here.
assert(instrJumpTarget(unit()->entry(), offset((PC)instr)) !=
assert(instrJumpTarget((Op*)unit()->entry(), offset((PC)instr)) !=
InvalidAbsoluteOffset);
break;
case OA: { // secondary opcode
@@ -558,7 +560,7 @@ bool FuncChecker::checkSig(PC pc, int len, const FlavorDesc* args,
* [uint8 MemberCode; [IVA imm for member]]
*/
const FlavorDesc* FuncChecker::vectorSig(PC pc, FlavorDesc rhs_flavor) {
ImmVecRange vr(pc);
ImmVecRange vr((Op*)pc);
int n = 0;
if (vr.loc_local != -1 ||
vr.loc == LH ||
@@ -579,7 +581,7 @@ const FlavorDesc* FuncChecker::vectorSig(PC pc, FlavorDesc rhs_flavor) {
}
if (vr.loc == LSC || vr.loc == LSL) m_tmp_sig[n++] = AV; // extra classref
if (rhs_flavor != NOV) m_tmp_sig[n++] = rhs_flavor; // extra rhs value for Set
assert(n == instrNumPops(pc));
assert(n == instrNumPops((Op*)pc));
return m_tmp_sig;
}
@@ -613,7 +615,7 @@ const FlavorDesc* FuncChecker::sig(PC pc) {
#undef ONE
#undef NOV
};
switch (Op(*pc)) {
switch (toOp(*pc)) {
case OpCGetM: // ONE(LA), LMANY(), ONE(CV)
case OpVGetM: // ONE(LA), LMANY(), ONE(VV)
case OpIssetM: // ONE(LA), LMANY(), ONE(CV)
@@ -633,28 +635,28 @@ const FlavorDesc* FuncChecker::sig(PC pc) {
return vectorSig(pc, RV);
case OpFCall: // ONE(IVA), FMANY, ONE(RV)
case OpFCallArray:// NA, ONE(FV), ONE(RV)
for (int i = 0, n = instrNumPops(pc); i < n; ++i) {
for (int i = 0, n = instrNumPops((Op*)pc); i < n; ++i) {
m_tmp_sig[i] = FV;
}
return m_tmp_sig;
case OpFCallBuiltin: //TWO(IVA, SA) CVMANY, ONE(RV)
case OpCreateCl: // TWO(IVA,SA), CVMANY, ONE(CV)
for (int i = 0, n = instrNumPops(pc); i < n; ++i) {
for (int i = 0, n = instrNumPops((Op*)pc); i < n; ++i) {
m_tmp_sig[i] = CVV;
}
return m_tmp_sig;
case OpNewTuple: // ONE(IVA), CMANY, ONE(CV)
for (int i = 0, n = instrNumPops(pc); i < n; ++i) {
for (int i = 0, n = instrNumPops((Op*)pc); i < n; ++i) {
m_tmp_sig[i] = CV;
}
return m_tmp_sig;
default:
return &inputSigs[*pc][0];
return &inputSigs[uint8_t(toOp(*pc))][0];
}
}
bool FuncChecker::checkInputs(State* cur, PC pc, Block* b) {
StackTransInfo info = instrStackTransInfo(pc);
StackTransInfo info = instrStackTransInfo((Op*)pc);
int min = cur->fpilen > 0 ? cur->fpi[cur->fpilen - 1].stkmin : 0;
if (info.numPops > 0 && cur->stklen - info.numPops < min) {
reportStkUnderflow(b, *cur, pc);
@@ -666,7 +668,7 @@ bool FuncChecker::checkInputs(State* cur, PC pc, Block* b) {
}
bool FuncChecker::checkTerminal(State* cur, PC pc) {
if (isRet(pc) || Op(*pc) == OpUnwind) {
if (isRet(pc) || toOp(*pc) == OpUnwind) {
if (cur->stklen != 0) {
error("stack depth must equal 0 after Ret* and Unwind; got %d\n",
cur->stklen);
@@ -683,9 +685,9 @@ bool FuncChecker::checkFpi(State* cur, PC pc, Block* b) {
}
bool ok = true;
FpiState& fpi = cur->fpi[cur->fpilen - 1];
if (isFCallStar(Op(*pc))) {
if (isFCallStar(toOp(*pc))) {
--cur->fpilen;
int call_params = Op(*pc) == OpFCall ? getImmIva(pc) : 1;
int call_params = toOp(*pc) == OpFCall ? getImmIva(pc) : 1;
int push_params = getImmIva(at(fpi.fpush));
if (call_params != push_params) {
error("FCall* param_count (%d) doesn't match FPush* (%d)\n",
@@ -728,14 +730,15 @@ bool FuncChecker::checkFpi(State* cur, PC pc, Block* b) {
return ok;
}
bool FuncChecker::checkIter(State* cur, PC pc) {
bool FuncChecker::checkIter(State* cur, PC const pc) {
assert(isIter(pc));
int id = getImmIva(pc);
bool ok = true;
if (Op(*pc) == OpIterInit || Op(*pc) == OpIterInitK ||
Op(*pc) == OpWIterInit || Op(*pc) == OpWIterInitK ||
Op(*pc) == OpMIterInit || Op(*pc) == OpMIterInitK ||
Op(*pc) == OpDecodeCufIter) {
auto op = toOp(*pc);
if (op == OpIterInit || op == OpIterInitK ||
op == OpWIterInit || op == OpWIterInitK ||
op == OpMIterInit || op == OpMIterInitK ||
op == OpDecodeCufIter) {
if (cur->iters[id]) {
error(
"IterInit* or MIterInit* <%d> trying to double-initialize\n", id);
@@ -746,9 +749,9 @@ bool FuncChecker::checkIter(State* cur, PC pc) {
error("Cannot access un-initialized iter %d\n", id);
ok = false;
}
if (Op(*pc) == OpIterFree ||
Op(*pc) == OpMIterFree ||
Op(*pc) == OpCIterFree) {
if (op == OpIterFree ||
op == OpMIterFree ||
op == OpCIterFree) {
cur->iters[id] = false;
}
}
@@ -788,7 +791,7 @@ bool FuncChecker::checkOutputs(State* cur, PC pc, Block* b) {
#undef NOV
};
bool ok = true;
StackTransInfo info = instrStackTransInfo(pc);
StackTransInfo info = instrStackTransInfo((Op*)pc);
if (info.kind == StackTransInfo::Kind::InsertMid) {
int index = cur->stklen - info.pos - 1;
if (index < 0) {
@@ -797,7 +800,7 @@ bool FuncChecker::checkOutputs(State* cur, PC pc, Block* b) {
}
memmove(&cur->stk[index + 1], &cur->stk[index],
(info.pos + 1) * sizeof(*cur->stk));
cur->stk[index] = outputSigs[*pc][0];
cur->stk[index] = outputSigs[uint8_t(toOp(*pc))][0];
cur->stklen++;
} else {
int pushes = info.numPushes;
@@ -805,8 +808,8 @@ bool FuncChecker::checkOutputs(State* cur, PC pc, Block* b) {
FlavorDesc *outs = &cur->stk[cur->stklen];
cur->stklen += pushes;
for (int i = 0; i < pushes; ++i)
outs[i] = outputSigs[*pc][i];
if (isFPush(Op(*pc))) {
outs[i] = outputSigs[uint8_t(toOp(*pc))][i];
if (isFPush(toOp(*pc))) {
if (cur->fpilen >= maxFpi()) {
error("%s", "more FPush* instructions than FPI regions\n");
return false;
@@ -909,7 +912,7 @@ bool FuncChecker::checkFlow() {
if (m_verbose) {
std::cout << " " << std::setw(5) << offset(pc) << ":" <<
stateToString(cur) << " " <<
instrToString(pc, unit()) << std::endl;
instrToString((Op*)pc, unit()) << std::endl;
}
ok &= checkInputs(&cur, pc, b);
if (isTF(pc)) ok &= checkTerminal(&cur, pc);
+2 -2
Ver Arquivo
@@ -29,13 +29,13 @@ namespace HPHP {
namespace Verifier {
void printInstr(const Unit* unit, PC pc) {
Opcode* op = (Opcode*)pc;
auto* op = (Op*)pc;
std::cout << " " << std::setw(4) << (pc - unit->entry()) << ":" <<
(isCF(pc) ? "C":" ") <<
(isTF(pc) ? "T":" ") <<
(isFF(pc) ? "F":" ") <<
std::setw(3) << instrLen(op) <<
" " << instrToString(op, unit) << std::endl;
" " << instrToString(op, unit) << std::endl;
}
std::string blockToString(const Block* b, const Graph* g, const Unit* u) {