diff --git a/hphp/compiler/analysis/emitter.cpp b/hphp/compiler/analysis/emitter.cpp index e95f09054..f78f09bfe 100644 --- a/hphp/compiler/analysis/emitter.cpp +++ b/hphp/compiler/analysis/emitter.cpp @@ -265,7 +265,7 @@ static int32_t countStackValues(const std::vector& 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; diff --git a/hphp/compiler/analysis/emitter.h b/hphp/compiler/analysis/emitter.h index 517ee0f81..f60870740 100644 --- a/hphp/compiler/analysis/emitter.h +++ b/hphp/compiler/analysis/emitter.h @@ -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 m_postponedMeths; std::deque m_postponedCtors; diff --git a/hphp/compiler/analysis/peephole.cpp b/hphp/compiler/analysis/peephole.cpp index 1cd921963..c0af8bcf2 100644 --- a/hphp/compiler/analysis/peephole.cpp +++ b/hphp/compiler/analysis/peephole.cpp @@ -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); } diff --git a/hphp/runtime/base/stats.cpp b/hphp/runtime/base/stats.cpp index 428a7dd3c..b6c9a64a0 100644 --- a/hphp/runtime/base/stats.cpp +++ b/hphp/runtime/base/stats.cpp @@ -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); diff --git a/hphp/runtime/base/stats.h b/hphp/runtime/base/stats.h index 8e8279cad..5822b322d 100644 --- a/hphp/runtime/base/stats.h +++ b/hphp/runtime/base/stats.h @@ -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(); diff --git a/hphp/runtime/debugger/cmd/cmd_flow_control.cpp b/hphp/runtime/debugger/cmd/cmd_flow_control.cpp index cc939720f..3643afe3e 100644 --- a/hphp/runtime/debugger/cmd/cmd_flow_control.cpp +++ b/hphp/runtime/debugger/cmd/cmd_flow_control.cpp @@ -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; diff --git a/hphp/runtime/debugger/cmd/cmd_next.cpp b/hphp/runtime/debugger/cmd/cmd_next.cpp index 724018ea2..1ebfc1412 100644 --- a/hphp/runtime/debugger/cmd/cmd_next.cpp +++ b/hphp/runtime/debugger/cmd/cmd_next.cpp @@ -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(); diff --git a/hphp/runtime/vm/as.cpp b/hphp/runtime/vm/as.cpp index caf4502c3..c5b5eaf60 100644 --- a/hphp/runtime/vm/as.cpp +++ b/hphp/runtime/vm/as.cpp @@ -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 > labelJumps; \ \ diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index 46dfe1b23..e419d84b4 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -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; } \ } \ diff --git a/hphp/runtime/vm/debugger_hook.cpp b/hphp/runtime/vm/debugger_hook.cpp index ef5dce350..d07f78f44 100644 --- a/hphp/runtime/vm/debugger_hook.cpp +++ b/hphp/runtime/vm/debugger_hook.cpp @@ -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 { diff --git a/hphp/runtime/vm/debugger_hook.h b/hphp/runtime/vm/debugger_hook.h index 28ac00da1..898e6c414 100644 --- a/hphp/runtime/vm/debugger_hook.h +++ b/hphp/runtime/vm/debugger_hook.h @@ -111,12 +111,12 @@ public: PCFilter() {} // Filter function to exclude opcodes when adding ranges. - typedef std::function OpcodeFilter; + typedef std::function 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. diff --git a/hphp/runtime/vm/hhbc.cpp b/hphp/runtime/vm/hhbc.cpp index 67ce00cb7..3170779e4 100644 --- a/hphp/runtime/vm/hhbc.cpp +++ b/hphp/runtime/vm/hhbc.cpp @@ -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& 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(instrs + pos)); +Offset instrJumpTarget(const Op* instrs, Offset pos) { + Offset* offset = instrJumpOffset(const_cast(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(instr))) return 2; + if (instrJumpOffset(const_cast(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(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(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)); diff --git a/hphp/runtime/vm/hhbc.h b/hphp/runtime/vm/hhbc.h index d635b7d54..2c1efed0b 100644 --- a/hphp/runtime/vm/hhbc.h +++ b/hphp/runtime/vm/hhbc.h @@ -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& 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 -void foreachSwitchTarget(Opcode* op, L func) { +void foreachSwitchTarget(Op* op, L func) { assert(isSwitch(*op)); bool isStr = readData(op) == OpSSwitch; int32_t size = readData(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 { + size_t operator()(HPHP::Op op) const { + return HPHP::hash_int64(uint8_t(op)); + } +}; +} } + #endif diff --git a/hphp/runtime/vm/jit/annotation.cpp b/hphp/runtime/vm/jit/annotation.cpp index 3652251ed..2d01014b5 100644 --- a/hphp/runtime/vm/jit/annotation.cpp +++ b/hphp/runtime/vm/jit/annotation.cpp @@ -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); } } diff --git a/hphp/runtime/vm/jit/irtranslator.cpp b/hphp/runtime/vm/jit/irtranslator.cpp index 70b30776a..560f9012f 100644 --- a/hphp/runtime/vm/jit/irtranslator.cpp +++ b/hphp/runtime/vm/jit/irtranslator.cpp @@ -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& 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; } diff --git a/hphp/runtime/vm/jit/region_method.cpp b/hphp/runtime/vm/jit/region_method.cpp index 6668b0be9..a54fd493e 100644 --- a/hphp/runtime/vm/jit/region_method.cpp +++ b/hphp/runtime/vm/jit/region_method.cpp @@ -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; } diff --git a/hphp/runtime/vm/jit/region_selection.cpp b/hphp/runtime/vm/jit/region_selection.cpp index 6802c43de..413834cfe 100644 --- a/hphp/runtime/vm/jit/region_selection.cpp +++ b/hphp/runtime/vm/jit/region_selection.cpp @@ -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 ); diff --git a/hphp/runtime/vm/jit/translator-x64.cpp b/hphp/runtime/vm/jit/translator-x64.cpp index 16fac8767..196fc25ab 100644 --- a/hphp/runtime/vm/jit/translator-x64.cpp +++ b/hphp/runtime/vm/jit/translator-x64.cpp @@ -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"); diff --git a/hphp/runtime/vm/jit/translator-x64.h b/hphp/runtime/vm/jit/translator-x64.h index fbe8d1042..e3f486c55 100644 --- a/hphp/runtime/vm/jit/translator-x64.h +++ b/hphp/runtime/vm/jit/translator-x64.h @@ -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 void invalidateSrcKeys(const T& keys) { diff --git a/hphp/runtime/vm/jit/translator.cpp b/hphp/runtime/vm/jit/translator.cpp index 4a083342b..40a73df76 100644 --- a/hphp/runtime/vm/jit/translator.cpp +++ b/hphp/runtime/vm/jit/translator.cpp @@ -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& inputs, const Tracelet& t, - Opcode opcode, + Op opcode, NormalizedInstruction* ni, Operands op, OutTypeConstraints constraint, @@ -889,7 +889,7 @@ getDynLocType(const vector& 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 instrInfo; +static hphp_hash_map 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 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 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; diff --git a/hphp/runtime/vm/jit/translator.h b/hphp/runtime/vm/jit/translator.h index 72ff8f88c..a22d5d505 100644 --- a/hphp/runtime/vm/jit/translator.h +++ b/hphp/runtime/vm/jit/translator.h @@ -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, diff --git a/hphp/runtime/vm/srckey.h b/hphp/runtime/vm/srckey.h index 0bdbc43e7..a6da615fd 100644 --- a/hphp/runtime/vm/srckey.h +++ b/hphp/runtime/vm/srckey.h @@ -89,7 +89,7 @@ struct SrcKey : private boost::totally_ordered { * contain an invalid bytecode offset. */ void advance(const Unit* u) { - m_offset += instrLen(u->at(offset())); + m_offset += instrLen((Op*)u->at(offset())); } /* diff --git a/hphp/runtime/vm/unit.cpp b/hphp/runtime/vm/unit.cpp index 25284fc3a..729ae7d9e 100644 --- a/hphp/runtime/vm/unit.cpp +++ b/hphp/runtime/vm/unit.cpp @@ -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); } } diff --git a/hphp/runtime/vm/unit.h b/hphp/runtime/vm/unit.h index 91dc56d23..9d227b5b9 100644 --- a/hphp/runtime/vm/unit.h +++ b/hphp/runtime/vm/unit.h @@ -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(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]); } /* diff --git a/hphp/runtime/vm/verifier/cfg.cpp b/hphp/runtime/vm/verifier/cfg.cpp index 6ceff0df4..f574dd07c 100644 --- a/hphp/runtime/vm/verifier/cfg.cpp +++ b/hphp/runtime/vm/verifier/cfg.cpp @@ -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); diff --git a/hphp/runtime/vm/verifier/cfg.h b/hphp/runtime/vm/verifier/cfg.h index 34b972d9f..dc72e23bc 100644 --- a/hphp/runtime/vm/verifier/cfg.h +++ b/hphp/runtime/vm/verifier/cfg.h @@ -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 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 diff --git a/hphp/runtime/vm/verifier/check_func.cpp b/hphp/runtime/vm/verifier/check_func.cpp index c189b2506..dad0b0b86 100644 --- a/hphp/runtime/vm/verifier/check_func.cpp +++ b/hphp/runtime/vm/verifier/check_func.cpp @@ -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 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); diff --git a/hphp/runtime/vm/verifier/pretty.cpp b/hphp/runtime/vm/verifier/pretty.cpp index af45e5a19..10404cc5d 100644 --- a/hphp/runtime/vm/verifier/pretty.cpp +++ b/hphp/runtime/vm/verifier/pretty.cpp @@ -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) {