Shorten SSATmp::getInstruction, SSATmp::getType, IRInstruction::getOpcode
The function names were too damn long.
Esse commit está contido em:
@@ -220,27 +220,27 @@ const char* getContextName(Class* ctx) {
|
||||
|
||||
ArgDesc::ArgDesc(SSATmp* tmp, bool val) : m_imm(-1), m_zeroExtend(false),
|
||||
m_done(false) {
|
||||
if (tmp->getType() == Type::None) {
|
||||
if (tmp->type() == Type::None) {
|
||||
assert(val);
|
||||
m_kind = None;
|
||||
return;
|
||||
}
|
||||
if (tmp->getInstruction()->getOpcode() == DefConst) {
|
||||
if (tmp->inst()->op() == DefConst) {
|
||||
m_srcReg = InvalidReg;
|
||||
if (val) {
|
||||
m_imm = tmp->getValBits();
|
||||
} else {
|
||||
m_imm = toDataTypeForCall(tmp->getType());
|
||||
m_imm = toDataTypeForCall(tmp->type());
|
||||
}
|
||||
m_kind = Imm;
|
||||
return;
|
||||
}
|
||||
if (tmp->getType().isNull()) {
|
||||
if (tmp->type().isNull()) {
|
||||
m_srcReg = InvalidReg;
|
||||
if (val) {
|
||||
m_imm = 0;
|
||||
} else {
|
||||
m_imm = toDataTypeForCall(tmp->getType());
|
||||
m_imm = toDataTypeForCall(tmp->type());
|
||||
}
|
||||
m_kind = Imm;
|
||||
return;
|
||||
@@ -261,7 +261,7 @@ ArgDesc::ArgDesc(SSATmp* tmp, bool val) : m_imm(-1), m_zeroExtend(false),
|
||||
return;
|
||||
}
|
||||
m_srcReg = InvalidReg;
|
||||
m_imm = toDataTypeForCall(tmp->getType());
|
||||
m_imm = toDataTypeForCall(tmp->type());
|
||||
m_kind = Imm;
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ const Func* CodeGenerator::getCurFunc() const {
|
||||
}
|
||||
|
||||
Address CodeGenerator::cgInst(IRInstruction* inst) {
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
auto const start = m_as.code.frontier;
|
||||
switch (opc) {
|
||||
#define O(name, dsts, srcs, flags) \
|
||||
@@ -581,10 +581,10 @@ asm_label(a, notPF);
|
||||
void CodeGenerator::cgJcc(IRInstruction* inst) {
|
||||
SSATmp* src1 = inst->getSrc(0);
|
||||
SSATmp* src2 = inst->getSrc(1);
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
ConditionCode cc = queryJmpToCC(opc);
|
||||
Type src1Type = src1->getType();
|
||||
Type src2Type = src2->getType();
|
||||
Type src1Type = src1->type();
|
||||
Type src2Type = src2->type();
|
||||
|
||||
// can't generate CMP instructions correctly for anything that isn't
|
||||
// a bool or a numeric, and we can't mix bool/numerics because
|
||||
@@ -733,7 +733,7 @@ static void shuffleArgs(Asm& a, ArgGroup& args) {
|
||||
|
||||
void CodeGenerator::cgCallNative(Asm& a, IRInstruction* inst) {
|
||||
using namespace NativeCalls;
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
always_assert(CallMap::hasInfo(opc));
|
||||
|
||||
const CallInfo& info = CallMap::getInfo(opc);
|
||||
@@ -863,7 +863,7 @@ void CodeGenerator::cgMov(IRInstruction* inst) {
|
||||
auto dstReg = dst->getReg();
|
||||
if (!src->hasReg(0)) {
|
||||
assert(src->isConst());
|
||||
if (src->getType() == Type::Bool) {
|
||||
if (src->type() == Type::Bool) {
|
||||
emitLoadImm(m_as, (int64_t)src->getValBool(), dstReg);
|
||||
} else {
|
||||
emitLoadImm(m_as, src->getValRawInt(), dstReg);
|
||||
@@ -879,7 +879,7 @@ void CodeGenerator::cgUnaryIntOp(SSATmp* dst,
|
||||
SSATmp* src,
|
||||
OpInstr instr,
|
||||
Oper oper) {
|
||||
if (src->getType() != Type::Int && src->getType() != Type::Bool) {
|
||||
if (src->type() != Type::Int && src->type() != Type::Bool) {
|
||||
assert(0); CG_PUNT(UnaryIntOp);
|
||||
}
|
||||
auto dstReg = dst->getReg();
|
||||
@@ -1111,7 +1111,7 @@ void CodeGenerator::cgOpXor(IRInstruction* inst) {
|
||||
SSATmp* dst = inst->getDst();
|
||||
SSATmp* src1 = inst->getSrc(0);
|
||||
SSATmp* src2 = inst->getSrc(1);
|
||||
if (src2->isConst() && src2->getType() == Type::Int &&
|
||||
if (src2->isConst() && src2->type() == Type::Int &&
|
||||
src2->getValInt() == ~0L) {
|
||||
return cgNotWork(dst, src1);
|
||||
}
|
||||
@@ -1196,8 +1196,8 @@ void CodeGenerator::cgOpCmpHelper(
|
||||
SSATmp* src1 = inst->getSrc(0);
|
||||
SSATmp* src2 = inst->getSrc(1);
|
||||
|
||||
Type type1 = src1->getType();
|
||||
Type type2 = src2->getType();
|
||||
Type type1 = src1->type();
|
||||
Type type2 = src2->type();
|
||||
|
||||
auto src1Reg = src1->getReg();
|
||||
auto src2Reg = src2->getReg();
|
||||
@@ -1773,8 +1773,8 @@ void CodeGenerator::cgUnbox(IRInstruction* inst) {
|
||||
auto srcTypeReg = src->getReg(1);
|
||||
|
||||
assert(dstValReg != dstTypeReg);
|
||||
assert(src->getType().equals(Type::Gen));
|
||||
assert(dst->getType().notBoxed());
|
||||
assert(src->type().equals(Type::Gen));
|
||||
assert(dst->type().notBoxed());
|
||||
|
||||
emitCmpTVType(m_as, HPHP::KindOfRef, srcTypeReg);
|
||||
ifThenElse(CC_E, [&] {
|
||||
@@ -1895,16 +1895,16 @@ void CodeGenerator::cgRetVal(IRInstruction* inst) {
|
||||
|
||||
// Store return value at the top of the caller's eval stack
|
||||
// (a) Store the type
|
||||
if (val->getType().needsReg()) {
|
||||
if (val->type().needsReg()) {
|
||||
emitStoreTVType(a, val->getReg(1), rFp[AROFF(m_r) + TVOFF(m_type)]);
|
||||
} else {
|
||||
emitStoreTVType(a, val->getType().toDataType(),
|
||||
emitStoreTVType(a, val->type().toDataType(),
|
||||
rFp[AROFF(m_r) + TVOFF(m_type)]);
|
||||
}
|
||||
|
||||
// (b) Store the actual value (not necessary when storing Null)
|
||||
if (val->getType().isNull()) return;
|
||||
if (val->getInstruction()->getOpcode() == DefConst) {
|
||||
if (val->type().isNull()) return;
|
||||
if (val->inst()->op() == DefConst) {
|
||||
a. storeq (val->getValRawInt(),
|
||||
rFp[AROFF(m_r) + TVOFF(m_data)]);
|
||||
} else {
|
||||
@@ -2299,7 +2299,7 @@ void CodeGenerator::cgExitTrace(IRInstruction* inst) {
|
||||
IRInstruction* toSmash = nullptr;
|
||||
assert(pc->isConst() && inst->getNumSrcs() <= 6);
|
||||
|
||||
TraceExitType::ExitType exitType = getExitType(inst->getOpcode());
|
||||
TraceExitType::ExitType exitType = getExitType(inst->op());
|
||||
if (exitType == TraceExitType::Normal && inst->getExtra<ExitTrace>()) {
|
||||
// Unconditional trace exit
|
||||
toSmash = inst->getExtra<ExitTrace>()->toSmash;
|
||||
@@ -2335,7 +2335,7 @@ void CodeGenerator::cgExitTrace(IRInstruction* inst) {
|
||||
}
|
||||
// Patch the original jcc;jmp, don't emit another
|
||||
IRInstruction* jcc = toSmash;
|
||||
Opcode opc = jcc->getOpcode();
|
||||
Opcode opc = jcc->op();
|
||||
ConditionCode cc = queryJmpToCC(opc);
|
||||
uint64_t taken = pc->getValInt();
|
||||
uint64_t notTaken = notTakenPC->getValInt();
|
||||
@@ -2467,7 +2467,7 @@ void CodeGenerator::cgIncRefWork(Type type, SSATmp* src) {
|
||||
void CodeGenerator::cgIncRef(IRInstruction* inst) {
|
||||
SSATmp* dst = inst->getDst();
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
Type type = src->getType();
|
||||
Type type = src->type();
|
||||
|
||||
cgIncRefWork(type, src);
|
||||
shuffle2(m_as, src->getReg(0), src->getReg(1),
|
||||
@@ -2527,7 +2527,7 @@ void CodeGenerator::cgDecRefKillThis(IRInstruction* inst) {
|
||||
assert(!inst->getTaken());
|
||||
|
||||
cgDecRefStaticType(
|
||||
src->getType(),
|
||||
src->type(),
|
||||
src->getReg(),
|
||||
nullptr,
|
||||
true /* genZeroCheck */,
|
||||
@@ -2964,7 +2964,7 @@ void CodeGenerator::cgDecRefMem(Type type,
|
||||
}
|
||||
|
||||
void CodeGenerator::cgDecRefMem(IRInstruction* inst) {
|
||||
assert(inst->getSrc(0)->getType().isPtr());
|
||||
assert(inst->getSrc(0)->type().isPtr());
|
||||
cgDecRefMem(inst->getTypeParam(),
|
||||
inst->getSrc(0)->getReg(),
|
||||
inst->getSrc(1)->getValInt(),
|
||||
@@ -2975,7 +2975,7 @@ void CodeGenerator::cgDecRefWork(IRInstruction* inst, bool genZeroCheck) {
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
if (!isRefCounted(src)) return;
|
||||
Block* exit = inst->getTaken();
|
||||
Type type = src->getType();
|
||||
Type type = src->type();
|
||||
if (type.isKnownDataType()) {
|
||||
cgDecRefStaticType(type, src->getReg(), exit, genZeroCheck);
|
||||
} else {
|
||||
@@ -3064,7 +3064,7 @@ void CodeGenerator::cgSpillFrame(IRInstruction* inst) {
|
||||
spReg);
|
||||
// actRec->m_func and possibly actRec->m_cls
|
||||
// Note m_cls is unioned with m_this and may overwrite previous value
|
||||
if (func->getType().isNull()) {
|
||||
if (func->type().isNull()) {
|
||||
assert(func->isConst());
|
||||
} else if (func->isConst()) {
|
||||
const Func* f = func->getValFunc();
|
||||
@@ -3233,7 +3233,7 @@ void CodeGenerator::cgCall(IRInstruction* inst) {
|
||||
for (int32_t i = 0; i < numArgs; i++) {
|
||||
// Type::None here means that the simplifier proved that the value
|
||||
// matches the value already in memory, thus the store is redundant.
|
||||
if (args[i]->getType() != Type::None) {
|
||||
if (args[i]->type() != Type::None) {
|
||||
cgStore(spReg, -(i + 1) * sizeof(Cell), args[i]);
|
||||
}
|
||||
}
|
||||
@@ -3246,7 +3246,7 @@ void CodeGenerator::cgCall(IRInstruction* inst) {
|
||||
|
||||
assert(m_state.lastMarker);
|
||||
SrcKey srcKey = SrcKey(m_state.lastMarker->func, m_state.lastMarker->bcOff);
|
||||
bool isImmutable = (func->isConst() && !func->getType().isNull());
|
||||
bool isImmutable = (func->isConst() && !func->type().isNull());
|
||||
const Func* funcd = isImmutable ? func->getValFunc() : nullptr;
|
||||
assert(&m_as == &m_tx64->getAsm());
|
||||
int32_t adjust = m_tx64->emitBindCall(srcKey, funcd, numArgs);
|
||||
@@ -3325,7 +3325,7 @@ void CodeGenerator::cgCallBuiltin(IRInstruction* inst) {
|
||||
for (int i = 0; i < numArgs; i++) {
|
||||
const Func::ParamInfo& pi = func->params()[i];
|
||||
if (TVOFF(m_data) && isSmartPtrRef(pi.builtinType())) {
|
||||
assert(args[i]->getType().isPtr() && args[i]->getReg() != InvalidReg);
|
||||
assert(args[i]->type().isPtr() && args[i]->getReg() != InvalidReg);
|
||||
callArgs.addr(args[i]->getReg(), TVOFF(m_data));
|
||||
} else {
|
||||
callArgs.ssa(args[i]);
|
||||
@@ -3390,20 +3390,20 @@ void CodeGenerator::cgSpillStack(IRInstruction* inst) {
|
||||
int64_t adjustment = (spDeficit - spillCells) * sizeof(Cell);
|
||||
for (uint32_t i = 0; i < numSpillSrcs; ++i) {
|
||||
const int64_t offset = i * sizeof(Cell) + adjustment;
|
||||
if (spillVals[i]->getType() == Type::None) {
|
||||
if (spillVals[i]->type() == Type::None) {
|
||||
// The simplifier detected that we're storing the same value
|
||||
// already in there.
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* val = spillVals[i];
|
||||
auto* inst = val->getInstruction();
|
||||
auto* inst = val->inst();
|
||||
while (inst->isPassthrough()) {
|
||||
inst = inst->getPassthroughValue()->getInstruction();
|
||||
inst = inst->getPassthroughValue()->inst();
|
||||
}
|
||||
// If our value came from a LdStack on the same sp and offset,
|
||||
// we don't need to spill it.
|
||||
if (inst->getOpcode() == LdStack && inst->getSrc(0) == sp &&
|
||||
if (inst->op() == LdStack && inst->getSrc(0) == sp &&
|
||||
inst->getSrc(1)->getValInt() * sizeof(Cell) == offset) {
|
||||
FTRACE(1, "{}: Not spilling spill value {} from {}\n",
|
||||
__func__, i, inst->toString());
|
||||
@@ -3434,7 +3434,7 @@ void CodeGenerator::cgNativeImpl(IRInstruction* inst) {
|
||||
SSATmp* fp = inst->getSrc(1);
|
||||
|
||||
assert(func->isConst());
|
||||
assert(func->getType() == Type::Func);
|
||||
assert(func->type() == Type::Func);
|
||||
|
||||
BuiltinFunction builtinFuncPtr = func->getValFunc()->builtinFuncPtr();
|
||||
emitMovRegReg(m_as, fp->getReg(), argNumToRegName[0]);
|
||||
@@ -3555,7 +3555,7 @@ void CodeGenerator::cgLdRaw(IRInstruction* inst) {
|
||||
}
|
||||
|
||||
if (offset->isConst()) {
|
||||
assert(offset->getType() == Type::Int);
|
||||
assert(offset->type() == Type::Int);
|
||||
int64_t kind = offset->getValInt();
|
||||
RawMemSlot& slot = RawMemSlot::Get(RawMemSlot::Kind(kind));
|
||||
int ldSize = slot.getSize();
|
||||
@@ -3569,7 +3569,7 @@ void CodeGenerator::cgLdRaw(IRInstruction* inst) {
|
||||
m_as.loadzbl (addrReg[off], r32(destReg));
|
||||
}
|
||||
} else {
|
||||
int ldSize = getNativeTypeSize(dest->getType());
|
||||
int ldSize = getNativeTypeSize(dest->type());
|
||||
Reg64 offsetReg = r64(offset->getReg());
|
||||
if (ldSize == sz::qword) {
|
||||
m_as.loadq (addrReg[offsetReg], destReg);
|
||||
@@ -3587,7 +3587,7 @@ void CodeGenerator::cgStRaw(IRInstruction* inst) {
|
||||
SSATmp* value = inst->getSrc(2);
|
||||
|
||||
RawMemSlot& slot = RawMemSlot::Get(RawMemSlot::Kind(kind));
|
||||
assert(value->getType().equals(slot.getType()));
|
||||
assert(value->type().equals(slot.type()));
|
||||
int stSize = slot.getSize();
|
||||
int64_t off = slot.getOffset();
|
||||
auto dest = baseReg[off];
|
||||
@@ -3631,7 +3631,7 @@ void CodeGenerator::cgLoadTypedValue(PhysReg base,
|
||||
Type type = inst->getTypeParam();
|
||||
SSATmp* dst = inst->getDst();
|
||||
|
||||
assert(type == dst->getType());
|
||||
assert(type == dst->type());
|
||||
assert(type.needsReg());
|
||||
auto valueDstReg = dst->getReg(0);
|
||||
auto typeDstReg = dst->getReg(1);
|
||||
@@ -3671,7 +3671,7 @@ void CodeGenerator::cgLoadTypedValue(PhysReg base,
|
||||
void CodeGenerator::cgStoreTypedValue(PhysReg base,
|
||||
int64_t off,
|
||||
SSATmp* src) {
|
||||
assert(src->getType().needsReg());
|
||||
assert(src->type().needsReg());
|
||||
m_as.storeq(src->getReg(0), base[off + TVOFF(m_data)]);
|
||||
emitStoreTVType(m_as, src->getReg(1), base[off + TVOFF(m_type)]);
|
||||
}
|
||||
@@ -3680,7 +3680,7 @@ void CodeGenerator::cgStore(PhysReg base,
|
||||
int64_t off,
|
||||
SSATmp* src,
|
||||
bool genStoreType) {
|
||||
Type type = src->getType();
|
||||
Type type = src->type();
|
||||
if (type.needsReg()) {
|
||||
cgStoreTypedValue(base, off, src);
|
||||
return;
|
||||
@@ -3828,7 +3828,7 @@ void CodeGenerator::cgGuardLoc(IRInstruction* inst) {
|
||||
}
|
||||
|
||||
void CodeGenerator::cgDefMIStateBase(IRInstruction* inst) {
|
||||
assert(inst->getDst()->getType() == Type::PtrToCell);
|
||||
assert(inst->getDst()->type() == Type::PtrToCell);
|
||||
assert(inst->getDst()->getReg() == rsp);
|
||||
}
|
||||
|
||||
@@ -3860,29 +3860,29 @@ void CodeGenerator::cgGuardRefs(IRInstruction* inst) {
|
||||
Block* exitLabel = inst->getTaken();
|
||||
|
||||
// Get values in place
|
||||
assert(funcPtrTmp->getType() == Type::Func);
|
||||
assert(funcPtrTmp->type() == Type::Func);
|
||||
auto funcPtrReg = funcPtrTmp->getReg();
|
||||
assert(funcPtrReg != InvalidReg);
|
||||
|
||||
assert(nParamsTmp->getType() == Type::Int);
|
||||
assert(nParamsTmp->type() == Type::Int);
|
||||
auto nParamsReg = nParamsTmp->getReg();
|
||||
assert(nParamsReg != InvalidReg);
|
||||
|
||||
assert(bitsPtrTmp->getType() == Type::Int);
|
||||
assert(bitsPtrTmp->type() == Type::Int);
|
||||
auto bitsPtrReg = bitsPtrTmp->getReg();
|
||||
assert(bitsPtrReg != InvalidReg);
|
||||
|
||||
assert(firstBitNumTmp->isConst() && firstBitNumTmp->getType() == Type::Int);
|
||||
assert(firstBitNumTmp->isConst() && firstBitNumTmp->type() == Type::Int);
|
||||
uint32_t firstBitNum = (uint32_t)(firstBitNumTmp->getValInt());
|
||||
|
||||
assert(mask64Tmp->getType() == Type::Int);
|
||||
assert(mask64Tmp->getInstruction()->getOpcode() == LdConst);
|
||||
assert(mask64Tmp->type() == Type::Int);
|
||||
assert(mask64Tmp->inst()->op() == LdConst);
|
||||
auto mask64Reg = mask64Tmp->getReg();
|
||||
assert(mask64Reg != InvalidReg);
|
||||
int64_t mask64 = mask64Tmp->getValInt();
|
||||
|
||||
assert(vals64Tmp->getType() == Type::Int);
|
||||
assert(vals64Tmp->getInstruction()->getOpcode() == LdConst);
|
||||
assert(vals64Tmp->type() == Type::Int);
|
||||
assert(vals64Tmp->inst()->op() == LdConst);
|
||||
auto vals64Reg = vals64Tmp->getReg();
|
||||
assert(vals64Reg != InvalidReg);
|
||||
int64_t vals64 = vals64Tmp->getValInt();
|
||||
@@ -3927,7 +3927,7 @@ void CodeGenerator::cgLdPropAddr(IRInstruction* inst) {
|
||||
SSATmp* obj = inst->getSrc(0);
|
||||
SSATmp* prop = inst->getSrc(1);
|
||||
|
||||
assert(prop->isConst() && prop->getType() == Type::Int);
|
||||
assert(prop->isConst() && prop->type() == Type::Int);
|
||||
|
||||
auto dstReg = dst->getReg();
|
||||
auto objReg = obj->getReg();
|
||||
@@ -3944,8 +3944,8 @@ void CodeGenerator::cgLdClsMethod(IRInstruction* inst) {
|
||||
SSATmp* cls = inst->getSrc(0);
|
||||
SSATmp* mSlot = inst->getSrc(1);
|
||||
|
||||
assert(cls->getType() == Type::Cls);
|
||||
assert(mSlot->isConst() && mSlot->getType() == Type::Int);
|
||||
assert(cls->type() == Type::Cls);
|
||||
assert(mSlot->isConst() && mSlot->type() == Type::Int);
|
||||
uint64_t mSlotInt64 = mSlot->getValRawInt();
|
||||
// We're going to multiply mSlotVal by sizeof(Func*) and use
|
||||
// it as a 32-bit offset (methOff) below.
|
||||
@@ -4125,7 +4125,7 @@ void CodeGenerator::cgLdClsMethodFCache(IRInstruction* inst) {
|
||||
emitFwdJcc(a, CC_Z, exitLabel);
|
||||
});
|
||||
|
||||
auto t = srcCtxTmp->getType();
|
||||
auto t = srcCtxTmp->type();
|
||||
assert(!t.equals(Type::Cls));
|
||||
if (t.equals(Type::Cctx)) {
|
||||
return; // done: destCtxReg already has srcCtxReg
|
||||
@@ -4286,8 +4286,8 @@ void CodeGenerator::cgLookupClsCns(IRInstruction* inst) {
|
||||
SSATmp* cls = inst->getSrc(1);
|
||||
|
||||
assert(inst->getTypeParam() == Type::Cell);
|
||||
assert(cnsName->isConst() && cnsName->getType() == Type::StaticStr);
|
||||
assert(cls->isConst() && cls->getType() == Type::StaticStr);
|
||||
assert(cnsName->isConst() && cnsName->type() == Type::StaticStr);
|
||||
assert(cls->isConst() && cls->type() == Type::StaticStr);
|
||||
|
||||
StringData* fullName = fullConstName(cls, cnsName);
|
||||
TargetCache::CacheHandle ch = TargetCache::allocClassConstant(fullName);
|
||||
@@ -4342,7 +4342,7 @@ void CodeGenerator::cgLookupCns(IRInstruction* inst) {
|
||||
SSATmp* cnsNameTmp = inst->getSrc(0);
|
||||
|
||||
assert(inst->getTypeParam() == Type::Cell);
|
||||
assert(cnsNameTmp->isConst() && cnsNameTmp->getType() == Type::StaticStr);
|
||||
assert(cnsNameTmp->isConst() && cnsNameTmp->type() == Type::StaticStr);
|
||||
|
||||
const StringData* cnsName = cnsNameTmp->getValStr();
|
||||
TargetCache::CacheHandle ch = StringData::DefCnsHandle(cnsName, false);
|
||||
@@ -4394,7 +4394,7 @@ void CodeGenerator::cgAKExists(IRInstruction* inst) {
|
||||
SSATmp* arr = inst->getSrc(0);
|
||||
SSATmp* key = inst->getSrc(1);
|
||||
|
||||
if (key->getType().isNull()) {
|
||||
if (key->type().isNull()) {
|
||||
if (arr->isA(Type::Arr)) {
|
||||
cgCallHelper(m_as,
|
||||
(TCA)ak_exist_string,
|
||||
@@ -4465,7 +4465,7 @@ void CodeGenerator::cgJmpZeroHelper(IRInstruction* inst,
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (src->getType() == Type::Bool) {
|
||||
if (src->type() == Type::Bool) {
|
||||
m_as.testb(Reg8(int(srcReg)), Reg8(int(srcReg)));
|
||||
} else {
|
||||
m_as.test_reg64_reg64(srcReg, srcReg);
|
||||
@@ -4492,7 +4492,7 @@ void CodeGenerator::cgJmp_(IRInstruction* inst) {
|
||||
DstRange dsts = inst->getTaken()->getLabel()->getDsts();
|
||||
ArgGroup args;
|
||||
for (unsigned i = 0, j = 0; i < n; i++) {
|
||||
assert(srcs[i]->getType().subtypeOf(dsts[i].getType()));
|
||||
assert(srcs[i]->type().subtypeOf(dsts[i].type()));
|
||||
SSATmp *dst = &dsts[i], *src = srcs[i];
|
||||
if (dst->getReg(0) == InvalidReg) continue; // dst is unused.
|
||||
// first dst register
|
||||
@@ -4502,8 +4502,8 @@ void CodeGenerator::cgJmp_(IRInstruction* inst) {
|
||||
if (dst->numNeededRegs() == 2) {
|
||||
if (src->numNeededRegs() < 2) {
|
||||
// src has known data type, but dst doesn't - pass immediate type
|
||||
assert(src->getType().isKnownDataType());
|
||||
args.imm(src->getType().toDataType());
|
||||
assert(src->type().isKnownDataType());
|
||||
args.imm(src->type().toDataType());
|
||||
} else {
|
||||
// pass src's second register
|
||||
assert(src->getReg(1) != InvalidReg);
|
||||
@@ -4528,7 +4528,7 @@ void CodeGenerator::cgCheckInit(IRInstruction* inst) {
|
||||
assert(label);
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
|
||||
if (src->getType().isInit()) return;
|
||||
if (src->type().isInit()) return;
|
||||
|
||||
auto typeReg = src->getReg(1);
|
||||
assert(typeReg != InvalidReg);
|
||||
@@ -4543,7 +4543,7 @@ void CodeGenerator::cgCheckInitMem(IRInstruction* inst) {
|
||||
assert(label);
|
||||
SSATmp* base = inst->getSrc(0);
|
||||
int64_t offset = inst->getSrc(1)->getValInt();
|
||||
Type t = base->getType().deref();
|
||||
Type t = base->type().deref();
|
||||
if (t.isInit()) return;
|
||||
emitCmpTVType(m_as, KindOfUninit, base->getReg()[offset + TVOFF(m_type)]);
|
||||
emitFwdJcc(CC_Z, label);
|
||||
@@ -4615,8 +4615,8 @@ void CodeGenerator::cgConcat(IRInstruction* inst) {
|
||||
SSATmp* tl = inst->getSrc(0);
|
||||
SSATmp* tr = inst->getSrc(1);
|
||||
|
||||
Type lType = tl->getType();
|
||||
Type rType = tr->getType();
|
||||
Type lType = tl->type();
|
||||
Type rType = tr->type();
|
||||
// We have specialized helpers for concatenating two strings, a
|
||||
// string and an int, and an int and a string.
|
||||
void* fptr = nullptr;
|
||||
@@ -4830,7 +4830,7 @@ void CodeGenerator::cgIterInitCommon(IRInstruction* inst, bool isInitK) {
|
||||
TCA helperAddr = isInitK ? (TCA)new_iter_array_key : (TCA)new_iter_array;
|
||||
cgCallHelper(m_as, helperAddr, inst->getDst(), kSyncPoint, args);
|
||||
} else {
|
||||
assert(src->getType() == Type::Obj);
|
||||
assert(src->type() == Type::Obj);
|
||||
args.imm(uintptr_t(getCurClass())).addr(fpReg, valLocalOffset);
|
||||
if (isInitK) {
|
||||
args.addr(fpReg, getLocalOffset(inst->getSrc(4)));
|
||||
@@ -4911,7 +4911,7 @@ static void patchJumps(Asm& as, CodegenState& state, Block* block) {
|
||||
void CodeGenerator::cgBlock(Block* block, vector<TransBCMapping>* bcMap) {
|
||||
for (IRInstruction& instr : *block) {
|
||||
IRInstruction* inst = &instr;
|
||||
if (inst->getOpcode() == Marker) {
|
||||
if (inst->op() == Marker) {
|
||||
if (!m_state.firstMarkerSeen) {
|
||||
m_state.firstMarkerSeen = true;
|
||||
// This will be generated right after the tracelet guards
|
||||
@@ -4969,7 +4969,7 @@ void cgTrace(Trace* trace, Asm& amain, Asm& astubs, Transl::TranslatorX64* tx64,
|
||||
// assembler, it doesn't need to actually emit a jmp.
|
||||
IRInstruction* last = block->back();
|
||||
state.noTerminalJmp_ =
|
||||
last->getOpcode() == Jmp_ && last->getTaken() == nextThisAs;
|
||||
last->op() == Jmp_ && last->getTaken() == nextThisAs;
|
||||
|
||||
CodeGenerator cg(trace, *as, astubs, tx64, state);
|
||||
if (state.asmInfo) {
|
||||
|
||||
@@ -41,13 +41,13 @@ struct CSEHash {
|
||||
return (*it).second;
|
||||
}
|
||||
SSATmp* insert(SSATmp* opnd) {
|
||||
return insert(opnd, opnd->getInstruction());
|
||||
return insert(opnd, opnd->inst());
|
||||
}
|
||||
SSATmp* insert(SSATmp* opnd, IRInstruction* inst) {
|
||||
return map[inst] = opnd;
|
||||
}
|
||||
void erase(SSATmp* opnd) {
|
||||
map.erase(opnd->getInstruction());
|
||||
map.erase(opnd->inst());
|
||||
}
|
||||
void clear() {
|
||||
map.clear();
|
||||
|
||||
@@ -129,14 +129,14 @@ void removeDeadInstructions(Trace* trace, const DceState& state) {
|
||||
|
||||
bool isUnguardedLoad(IRInstruction* inst) {
|
||||
if (!inst->hasDst() || !inst->getDst()) return false;
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
SSATmp* dst = inst->getDst();
|
||||
Type type = dst->getType();
|
||||
Type type = dst->type();
|
||||
return ((opc == LdStack && (type == Type::Gen || type == Type::Cell)) ||
|
||||
(opc == LdLoc && type == Type::Gen) ||
|
||||
(opc == LdRef && type == Type::Cell) ||
|
||||
(opc == LdMem && type == Type::Cell &&
|
||||
inst->getSrc(0)->getType() == Type::PtrToCell) ||
|
||||
inst->getSrc(0)->type() == Type::PtrToCell) ||
|
||||
(opc == Unbox && type == Type::Cell));
|
||||
}
|
||||
|
||||
@@ -193,11 +193,11 @@ initInstructions(const BlockList& blocks, DceState& state) {
|
||||
state[inst].setLive();
|
||||
wl.push_back(&inst);
|
||||
}
|
||||
if (inst.getOpcode() == DecRefNZ) {
|
||||
auto* srcInst = inst.getSrc(0)->getInstruction();
|
||||
Opcode srcOpc = srcInst->getOpcode();
|
||||
if (inst.op() == DecRefNZ) {
|
||||
auto* srcInst = inst.getSrc(0)->inst();
|
||||
Opcode srcOpc = srcInst->op();
|
||||
if (srcOpc != DefConst) {
|
||||
assert(srcInst->getOpcode() == IncRef);
|
||||
assert(srcInst->op() == IncRef);
|
||||
assert(state[srcInst].isDead()); // IncRef isn't essential so it should
|
||||
// be dead here
|
||||
state[srcInst].setDecRefNZed();
|
||||
@@ -218,7 +218,7 @@ initInstructions(const BlockList& blocks, DceState& state) {
|
||||
void optimizeRefCount(Trace* trace, DceState& state) {
|
||||
WorkList decrefs;
|
||||
forEachInst(trace, [&](IRInstruction* inst) {
|
||||
if (inst->getOpcode() == IncRef && !state[inst].countConsumedAny()) {
|
||||
if (inst->op() == IncRef && !state[inst].countConsumedAny()) {
|
||||
// This assert is often hit when an instruction should have a
|
||||
// consumesReferences flag but doesn't.
|
||||
auto& s = state[inst];
|
||||
@@ -231,19 +231,19 @@ void optimizeRefCount(Trace* trace, DceState& state) {
|
||||
inst->setOpcode(Mov);
|
||||
s.setDead();
|
||||
}
|
||||
if (inst->getOpcode() == DecRefNZ) {
|
||||
if (inst->op() == DecRefNZ) {
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
IRInstruction* srcInst = src->getInstruction();
|
||||
IRInstruction* srcInst = src->inst();
|
||||
if (state[srcInst].countConsumedAny()) {
|
||||
state[inst].setLive();
|
||||
src->incUseCount();
|
||||
}
|
||||
}
|
||||
if (inst->getOpcode() == DecRef) {
|
||||
if (inst->op() == DecRef) {
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
if (src->getUseCount() == 1 && !src->getType().canRunDtor()) {
|
||||
IRInstruction* srcInst = src->getInstruction();
|
||||
if (srcInst->getOpcode() == IncRef) {
|
||||
if (src->getUseCount() == 1 && !src->type().canRunDtor()) {
|
||||
IRInstruction* srcInst = src->inst();
|
||||
if (srcInst->op() == IncRef) {
|
||||
decrefs.push_back(inst);
|
||||
}
|
||||
}
|
||||
@@ -253,13 +253,13 @@ void optimizeRefCount(Trace* trace, DceState& state) {
|
||||
copyProp(inst);
|
||||
});
|
||||
for (const IRInstruction* decref : decrefs) {
|
||||
assert(decref->getOpcode() == DecRef);
|
||||
assert(decref->op() == DecRef);
|
||||
SSATmp* src = decref->getSrc(0);
|
||||
assert(src->getInstruction()->getOpcode() == IncRef);
|
||||
assert(!src->getType().canRunDtor());
|
||||
assert(src->inst()->op() == IncRef);
|
||||
assert(!src->type().canRunDtor());
|
||||
if (src->getUseCount() == 1) {
|
||||
state[decref].setDead();
|
||||
state[src->getInstruction()].setDead();
|
||||
state[src->inst()].setDead();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,7 +327,7 @@ void sinkIncRefs(Trace* trace, IRFactory* irFactory, DceState& state) {
|
||||
// them multiple times.
|
||||
boost::dynamic_bitset<> pushedTo(irFactory->numBlocks());
|
||||
forEachInst(trace, [&](IRInstruction* inst) {
|
||||
if (inst->getOpcode() == IncRef) {
|
||||
if (inst->op() == IncRef) {
|
||||
// Must be REFCOUNT_CONSUMED or REFCOUNT_CONSUMED_OFF_TRACE;
|
||||
// otherwise, it should be already removed in optimizeRefCount.
|
||||
if (state[inst].countConsumedOffTrace()) {
|
||||
@@ -340,8 +340,8 @@ void sinkIncRefs(Trace* trace, IRFactory* irFactory, DceState& state) {
|
||||
assert(state[inst].countConsumed());
|
||||
}
|
||||
}
|
||||
if (inst->getOpcode() == DecRefNZ) {
|
||||
IRInstruction* srcInst = inst->getSrc(0)->getInstruction();
|
||||
if (inst->op() == DecRefNZ) {
|
||||
IRInstruction* srcInst = inst->getSrc(0)->inst();
|
||||
if (state[srcInst].isDead()) {
|
||||
state[inst].setDead();
|
||||
// This may take O(I) time where I is the number of IncRefs
|
||||
@@ -375,12 +375,12 @@ void optimizeActRecs(Trace* trace, DceState& state) {
|
||||
bool killedFrames = false;
|
||||
|
||||
forEachInst(trace, [&](IRInstruction* inst) {
|
||||
switch (inst->getOpcode()) {
|
||||
switch (inst->op()) {
|
||||
case DecRefKillThis:
|
||||
{
|
||||
auto frame = inst->getSrc(1);
|
||||
auto frameInst = frame->getInstruction();
|
||||
if (frameInst->getOpcode() == DefInlineFP) {
|
||||
auto frameInst = frame->inst();
|
||||
if (frameInst->op() == DefInlineFP) {
|
||||
FTRACE(5, "DecRefKillThis ({}): weak use of frame {}\n",
|
||||
inst->getIId(),
|
||||
frameInst->getIId());
|
||||
@@ -392,8 +392,8 @@ void optimizeActRecs(Trace* trace, DceState& state) {
|
||||
case InlineReturn:
|
||||
{
|
||||
auto frameUses = inst->getSrc(0)->getUseCount();
|
||||
auto srcInst = inst->getSrc(0)->getInstruction();
|
||||
if (srcInst->getOpcode() == DefInlineFP) {
|
||||
auto srcInst = inst->getSrc(0)->inst();
|
||||
if (srcInst->op() == DefInlineFP) {
|
||||
auto weakUses = state[srcInst].weakUseCount();
|
||||
// We haven't counted this InlineReturn as a weak use yet,
|
||||
// which is where this '1' comes from.
|
||||
@@ -420,11 +420,11 @@ void optimizeActRecs(Trace* trace, DceState& state) {
|
||||
* is going away.
|
||||
*/
|
||||
forEachInst(trace, [&](IRInstruction* inst) {
|
||||
switch (inst->getOpcode()) {
|
||||
switch (inst->op()) {
|
||||
case DecRefKillThis:
|
||||
{
|
||||
auto fp = inst->getSrc(1);
|
||||
if (state[fp->getInstruction()].isDead()) {
|
||||
if (state[fp->inst()].isDead()) {
|
||||
FTRACE(5, "DecRefKillThis ({}) -> DecRef\n", inst->getIId());
|
||||
inst->setOpcode(DecRef);
|
||||
inst->setSrc(1, nullptr);
|
||||
@@ -436,7 +436,7 @@ void optimizeActRecs(Trace* trace, DceState& state) {
|
||||
case InlineReturn:
|
||||
{
|
||||
auto fp = inst->getSrc(0);
|
||||
if (state[fp->getInstruction()].isDead()) {
|
||||
if (state[fp->inst()].isDead()) {
|
||||
FTRACE(5, "InlineReturn ({}) setDead\n", inst->getIId());
|
||||
state[inst].setDead();
|
||||
}
|
||||
@@ -471,15 +471,15 @@ void consumeIncRef(const IRInstruction* consumer, const SSATmp* src,
|
||||
return;
|
||||
}
|
||||
|
||||
const IRInstruction* srcInst = src->getInstruction();
|
||||
const IRInstruction* srcInst = src->inst();
|
||||
visitedSrcs.insert(src);
|
||||
if (srcInst->getOpcode() == GuardType &&
|
||||
if (srcInst->op() == GuardType &&
|
||||
srcInst->getTypeParam().maybeCounted()) {
|
||||
// srcInst is a GuardType that guards to a refcounted type. We need to
|
||||
// trace through to its source. If the GuardType guards to a non-refcounted
|
||||
// type then the reference is consumed by GuardType itself.
|
||||
consumeIncRef(consumer, srcInst->getSrc(0), state, ssas, visitedSrcs);
|
||||
} else if (srcInst->getOpcode() == DefLabel) {
|
||||
} else if (srcInst->op() == DefLabel) {
|
||||
// srcInst is a DefLabel that may be a join node. We need to find
|
||||
// the dst index of src in srcInst and trace through to each jump
|
||||
// providing a value for it.
|
||||
@@ -504,7 +504,7 @@ void consumeIncRef(const IRInstruction* consumer, const SSATmp* src,
|
||||
}
|
||||
}
|
||||
|
||||
if (srcInst->getOpcode() == IncRef) {
|
||||
if (srcInst->op() == IncRef) {
|
||||
// <inst> consumes <srcInst> which is an IncRef, so we mark <srcInst> as
|
||||
// REFCOUNT_CONSUMED.
|
||||
if (consumer->getTrace()->isMain() || !srcInst->getTrace()->isMain()) {
|
||||
@@ -563,8 +563,8 @@ void eliminateDeadCode(Trace* trace, IRFactory* irFactory) {
|
||||
wl.pop_front();
|
||||
for (uint32_t i = 0; i < inst->getNumSrcs(); i++) {
|
||||
SSATmp* src = inst->getSrc(i);
|
||||
IRInstruction* srcInst = src->getInstruction();
|
||||
if (srcInst->getOpcode() == DefConst) {
|
||||
IRInstruction* srcInst = src->inst();
|
||||
if (srcInst->op() == DefConst) {
|
||||
continue;
|
||||
}
|
||||
src->incUseCount();
|
||||
|
||||
@@ -62,14 +62,14 @@ SSATmp* HhbcTranslator::push(SSATmp* tmp) {
|
||||
|
||||
void HhbcTranslator::refineType(SSATmp* tmp, Type type) {
|
||||
// If type is more refined than tmp's type, reset tmp's type to type
|
||||
IRInstruction* inst = tmp->getInstruction();
|
||||
if (type.strictSubtypeOf(tmp->getType())) {
|
||||
IRInstruction* inst = tmp->inst();
|
||||
if (type.strictSubtypeOf(tmp->type())) {
|
||||
// If tmp is incref or move, then chase down its src
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
if (opc == Mov || opc == IncRef) {
|
||||
refineType(inst->getSrc(0), type);
|
||||
tmp->setType(outputType(inst));
|
||||
} else if (tmp->getType().isNull() && type.isNull()) {
|
||||
} else if (tmp->type().isNull() && type.isNull()) {
|
||||
// Refining Null to Uninit or InitNull is supported
|
||||
tmp->setType(type);
|
||||
} else {
|
||||
@@ -313,7 +313,7 @@ void HhbcTranslator::setBcOff(Offset newOff, bool lastBcOff) {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitPrint() {
|
||||
Type type = topC()->getType();
|
||||
Type type = topC()->type();
|
||||
if (type.subtypeOfAny(Type::Int, Type::Bool, Type::Null, Type::Str)) {
|
||||
auto const cell = popC();
|
||||
|
||||
@@ -411,8 +411,8 @@ void HhbcTranslator::emitNewTuple(int numArgs) {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitArrayAdd() {
|
||||
Type type1 = topC(0)->getType();
|
||||
Type type2 = topC(1)->getType();
|
||||
Type type1 = topC(0)->type();
|
||||
Type type2 = topC(1)->type();
|
||||
if (!type1.isArray() || !type2.isArray()) {
|
||||
// This happens when we have a prior spillstack that optimizes away
|
||||
// its spilled values because they were already on the stack. This
|
||||
@@ -436,7 +436,7 @@ void HhbcTranslator::emitAddElemC() {
|
||||
// the AddElem* instructions decrefs their args, so don't decref
|
||||
// pop'ed values. TODO task 1805916: verify that AddElem* increfs
|
||||
// their result
|
||||
auto kt = key->getType();
|
||||
auto kt = key->type();
|
||||
Opcode op;
|
||||
if (kt.subtypeOf(Type::Int)) {
|
||||
op = AddElemIntKey;
|
||||
@@ -725,11 +725,11 @@ void HhbcTranslator::emitSetOpL(Opcode subOpc, uint32_t id) {
|
||||
SSATmp* result = m_tb->genConcat(loc, val);
|
||||
pushIncRef(m_tb->genStLoc(id, result, false, true, exitTrace));
|
||||
} else if (isSupportedBinaryArith(subOpc,
|
||||
loc->getType(),
|
||||
topC()->getType())) {
|
||||
loc->type(),
|
||||
topC()->type())) {
|
||||
SSATmp* val = popC();
|
||||
Type resultType = Type::binArithResultType(loc->getType(),
|
||||
val->getType());
|
||||
Type resultType = Type::binArithResultType(loc->type(),
|
||||
val->type());
|
||||
SSATmp* result = m_tb->gen(subOpc, resultType, loc, val);
|
||||
push(m_tb->genStLoc(id, result, true, true, exitTrace));
|
||||
} else {
|
||||
@@ -788,7 +788,7 @@ void HhbcTranslator::emitReqDoc(const StringData* name) {
|
||||
template<class Lambda>
|
||||
SSATmp* HhbcTranslator::emitIterInitCommon(int offset, Lambda genFunc) {
|
||||
SSATmp* src = popC();
|
||||
Type type = src->getType();
|
||||
Type type = src->type();
|
||||
if (!type.isArray() && type != Type::Obj) {
|
||||
PUNT(IterInit);
|
||||
}
|
||||
@@ -1011,7 +1011,7 @@ void HhbcTranslator::emitContHandle() {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitStrlen() {
|
||||
Type inType = topC()->getType();
|
||||
Type inType = topC()->type();
|
||||
|
||||
if (inType.isString()) {
|
||||
SSATmp* input = popC();
|
||||
@@ -1246,7 +1246,7 @@ void HhbcTranslator::emitJmpNZ(int32_t offset) {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitCmp(Opcode opc) {
|
||||
if (cmpOpTypesMayReenter(opc, topC(0)->getType(), topC(1)->getType())) {
|
||||
if (cmpOpTypesMayReenter(opc, topC(0)->type(), topC(1)->type())) {
|
||||
exceptionBarrier();
|
||||
}
|
||||
// src2 opc src1
|
||||
@@ -1335,7 +1335,7 @@ void HhbcTranslator::emitFPushCufOp(VM::Op op, Class* cls, StringData* invName,
|
||||
// can't really do better than the interpreter here, so punt.
|
||||
SPUNT(StringData::GetStaticString(
|
||||
folly::format("FPushCuf-{}",
|
||||
callable->getType().toString()).str())
|
||||
callable->type().toString()).str())
|
||||
->data());
|
||||
}
|
||||
|
||||
@@ -1830,10 +1830,10 @@ void HhbcTranslator::emitRetFromInlined(Type type) {
|
||||
SSATmp* HhbcTranslator::emitDecRefLocalsInline(SSATmp* retVal) {
|
||||
SSATmp* retValSrcLoc = nullptr;
|
||||
Opcode retValSrcOpc = Nop; // Nop flags the ref-count opt is impossible
|
||||
IRInstruction* retValSrcInstr = retVal->getInstruction();
|
||||
if (retValSrcInstr->getOpcode() == IncRef) {
|
||||
IRInstruction* retValSrcInstr = retVal->inst();
|
||||
if (retValSrcInstr->op() == IncRef) {
|
||||
retValSrcLoc = retValSrcInstr->getSrc(0);
|
||||
retValSrcOpc = retValSrcLoc->getInstruction()->getOpcode();
|
||||
retValSrcOpc = retValSrcLoc->inst()->op();
|
||||
if (retValSrcOpc != LdLoc && retValSrcOpc != LdThis) {
|
||||
retValSrcLoc = nullptr;
|
||||
retValSrcOpc = Nop;
|
||||
@@ -1855,7 +1855,7 @@ SSATmp* HhbcTranslator::emitDecRefLocalsInline(SSATmp* retVal) {
|
||||
* matter. This will need to be revisted then.
|
||||
*/
|
||||
int retValLocId = (!isInlining() && retValSrcLoc && retValSrcOpc == LdLoc) ?
|
||||
retValSrcLoc->getInstruction()->getExtra<LocalId>()->locId : -1;
|
||||
retValSrcLoc->inst()->getExtra<LocalId>()->locId : -1;
|
||||
for (int id = getCurFunc()->numLocals() - 1; id >= 0; --id) {
|
||||
if (retValLocId == id) {
|
||||
m_tb->genDecRef(retVal);
|
||||
@@ -1912,7 +1912,7 @@ void HhbcTranslator::emitSwitch(const ImmVector& iv,
|
||||
int nTargets = bounded ? iv.size() - 2 : iv.size();
|
||||
|
||||
SSATmp* const switchVal = popC();
|
||||
Type type = switchVal->getType();
|
||||
Type type = switchVal->type();
|
||||
assert(IMPLIES(!type.equals(Type::Int), bounded));
|
||||
assert(IMPLIES(bounded, iv.size() > 2));
|
||||
SSATmp* index;
|
||||
@@ -2172,7 +2172,7 @@ void HhbcTranslator::emitVerifyParamType(int32_t paramId) {
|
||||
const Func* func = getCurFunc();
|
||||
const TypeConstraint& tc = func->params()[paramId].typeConstraint();
|
||||
SSATmp* locVal = m_tb->genLdLoc(paramId);
|
||||
Type locType = locVal->getType().unbox();
|
||||
Type locType = locVal->type().unbox();
|
||||
assert(locType.isKnownDataType());
|
||||
|
||||
if (tc.nullable() && locType.isNull()) {
|
||||
@@ -2277,7 +2277,7 @@ void HhbcTranslator::emitInstanceOfD(int classNameStrId) {
|
||||
* types, but if it's Gen/Cell we're going to PUNT because it's
|
||||
* natural to translate that case with control flow TODO(#2020251)
|
||||
*/
|
||||
if (Type::Obj.strictSubtypeOf(src->getType())) {
|
||||
if (Type::Obj.strictSubtypeOf(src->type())) {
|
||||
PUNT(InstanceOfD_MaybeObj);
|
||||
}
|
||||
if (!src->isA(Type::Obj)) {
|
||||
@@ -2341,7 +2341,7 @@ void HhbcTranslator::emitCastArray() {
|
||||
// escape the trace.
|
||||
|
||||
SSATmp* src = popC();
|
||||
Type fromType = src->getType();
|
||||
Type fromType = src->type();
|
||||
if (fromType.isArray()) {
|
||||
push(src);
|
||||
} else if (fromType.isNull()) {
|
||||
@@ -2369,7 +2369,7 @@ void HhbcTranslator::emitCastBool() {
|
||||
|
||||
void HhbcTranslator::emitCastDouble() {
|
||||
SSATmp* src = popC();
|
||||
Type fromType = src->getType();
|
||||
Type fromType = src->type();
|
||||
if (fromType.isDbl()) {
|
||||
push(src);
|
||||
} else if (fromType.isNull()) {
|
||||
@@ -2394,7 +2394,7 @@ void HhbcTranslator::emitCastDouble() {
|
||||
|
||||
void HhbcTranslator::emitCastInt() {
|
||||
SSATmp* src = popC();
|
||||
Type fromType = src->getType();
|
||||
Type fromType = src->type();
|
||||
if (fromType.isInt()) {
|
||||
push(src);
|
||||
} else if (fromType.isNull()) {
|
||||
@@ -2420,7 +2420,7 @@ void HhbcTranslator::emitCastInt() {
|
||||
|
||||
void HhbcTranslator::emitCastObject() {
|
||||
SSATmp* src = popC();
|
||||
Type srcType = src->getType();
|
||||
Type srcType = src->type();
|
||||
if (srcType.isObj()) {
|
||||
push(src);
|
||||
} else {
|
||||
@@ -2430,7 +2430,7 @@ void HhbcTranslator::emitCastObject() {
|
||||
|
||||
void HhbcTranslator::emitCastString() {
|
||||
SSATmp* src = popC();
|
||||
Type fromType = src->getType();
|
||||
Type fromType = src->type();
|
||||
if (fromType.isString()) {
|
||||
push(src);
|
||||
} else if (fromType.isNull()) {
|
||||
@@ -2496,10 +2496,10 @@ SSATmp* HhbcTranslator::unboxPtr(SSATmp* ptr) {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitBindMem(SSATmp* ptr, SSATmp* src) {
|
||||
SSATmp* prevValue = m_tb->genLdMem(ptr, ptr->getType().deref(), NULL);
|
||||
SSATmp* prevValue = m_tb->genLdMem(ptr, ptr->type().deref(), NULL);
|
||||
pushIncRef(src);
|
||||
m_tb->genStMem(ptr, src, true);
|
||||
if (isRefCounted(src) && src->getType().canRunDtor()) {
|
||||
if (isRefCounted(src) && src->type().canRunDtor()) {
|
||||
Block* exitBlock = getExitTrace(getNextSrcKey().offset())->front();
|
||||
Block::iterator markerInst = exitBlock->skipLabel();
|
||||
exitBlock->insert(++markerInst, m_irFactory.gen(DecRef, prevValue));
|
||||
@@ -2513,7 +2513,7 @@ template<class CheckSupportedFun, class EmitLdAddrFun>
|
||||
void HhbcTranslator::emitBind(const StringData* name,
|
||||
CheckSupportedFun checkSupported,
|
||||
EmitLdAddrFun emitLdAddr) {
|
||||
if (!(this->*checkSupported)(name, topC(0)->getType(), 1)) return;
|
||||
if (!(this->*checkSupported)(name, topC(0)->type(), 1)) return;
|
||||
SSATmp* src = popV();
|
||||
emitBindMem((this->*emitLdAddr)(name), src);
|
||||
}
|
||||
@@ -2526,7 +2526,7 @@ template<class CheckSupportedFun, class EmitLdAddrFun>
|
||||
void HhbcTranslator::emitSet(const StringData* name,
|
||||
CheckSupportedFun checkSupported,
|
||||
EmitLdAddrFun emitLdAddr) {
|
||||
if (!(this->*checkSupported)(name, topC(0)->getType(), 1)) return;
|
||||
if (!(this->*checkSupported)(name, topC(0)->type(), 1)) return;
|
||||
SSATmp* src = popC();
|
||||
emitSetMem((this->*emitLdAddr)(name), src);
|
||||
}
|
||||
@@ -2674,8 +2674,8 @@ void HhbcTranslator::emitCGetS(const StringData* propName,
|
||||
|
||||
void HhbcTranslator::emitBinaryArith(Opcode opc) {
|
||||
bool isBitOp = (opc == OpAnd || opc == OpOr || opc == OpXor);
|
||||
Type type1 = topC(0)->getType();
|
||||
Type type2 = topC(1)->getType();
|
||||
Type type1 = topC(0)->type();
|
||||
Type type2 = topC(1)->type();
|
||||
if (isSupportedBinaryArith(opc, type1, type2)) {
|
||||
SSATmp* tr = popC();
|
||||
SSATmp* tl = popC();
|
||||
@@ -2731,8 +2731,8 @@ void HhbcTranslator::emitMod() {
|
||||
// XXX: Disabled until t2299606 is fixed
|
||||
PUNT(emitMod);
|
||||
|
||||
auto tl = topC(1)->getType();
|
||||
auto tr = topC(0)->getType();
|
||||
auto tl = topC(1)->type();
|
||||
auto tr = topC(0)->type();
|
||||
auto isInty = [&](Type t) {
|
||||
return t.subtypeOf(Type::Null | Type::Bool | Type::Int);
|
||||
};
|
||||
@@ -2767,7 +2767,7 @@ void HhbcTranslator::emitMod() {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitBitNot() {
|
||||
Type srcType = topC()->getType();
|
||||
Type srcType = topC()->type();
|
||||
if (srcType == Type::Int) {
|
||||
SSATmp* src = popC();
|
||||
SSATmp* ones = m_tb->genDefConst<int64_t>(~0);
|
||||
@@ -2945,7 +2945,7 @@ SSATmp* HhbcTranslator::emitLdLocWarn(uint32_t id,
|
||||
Trace* target) {
|
||||
SSATmp* locVal = m_tb->genLdLocAsCell(id, target);
|
||||
|
||||
if (locVal->getType().subtypeOf(Type::Uninit)) {
|
||||
if (locVal->type().subtypeOf(Type::Uninit)) {
|
||||
exceptionBarrier();
|
||||
m_tb->genRaiseUninitLoc(id);
|
||||
return m_tb->genDefInitNull();
|
||||
|
||||
@@ -65,7 +65,7 @@ struct EvalStack {
|
||||
uint32_t numCells() const {
|
||||
uint32_t ret = 0;
|
||||
for (auto& t : m_vector) {
|
||||
ret += t->getType() == Type::ActRec ? kNumActRecCells : 1;
|
||||
ret += t->type() == Type::ActRec ? kNumActRecCells : 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ class TypeGuard {
|
||||
|
||||
Kind getKind() const { return m_kind; }
|
||||
uint32_t getIndex() const { return m_index; }
|
||||
Type getType() const { return m_type; }
|
||||
Type type() const { return m_type; }
|
||||
|
||||
private:
|
||||
Kind m_kind;
|
||||
|
||||
@@ -304,7 +304,7 @@ IRInstruction::IRInstruction(Arena& arena, const IRInstruction* inst, IId iid)
|
||||
, m_taken(nullptr)
|
||||
, m_block(nullptr)
|
||||
, m_tca(nullptr)
|
||||
, m_extra(inst->m_extra ? cloneExtra(getOpcode(), inst->m_extra, arena)
|
||||
, m_extra(inst->m_extra ? cloneExtra(op(), inst->m_extra, arena)
|
||||
: nullptr)
|
||||
{
|
||||
std::copy(inst->m_srcs, inst->m_srcs + inst->m_numSrcs, m_srcs);
|
||||
@@ -325,39 +325,39 @@ Opcode getStackModifyingOpcode(Opcode opc) {
|
||||
}
|
||||
|
||||
bool IRInstruction::hasExtra() const {
|
||||
return opcodeHasFlags(getOpcode(), HasExtra) && m_extra;
|
||||
return opcodeHasFlags(op(), HasExtra) && m_extra;
|
||||
}
|
||||
|
||||
// Instructions with ModifiesStack are always naryDst regardless of
|
||||
// the inner dest.
|
||||
|
||||
bool IRInstruction::hasDst() const {
|
||||
return opcodeHasFlags(getOpcode(), HasDest) &&
|
||||
!opcodeHasFlags(getOpcode(), ModifiesStack);
|
||||
return opcodeHasFlags(op(), HasDest) &&
|
||||
!opcodeHasFlags(op(), ModifiesStack);
|
||||
}
|
||||
|
||||
bool IRInstruction::naryDst() const {
|
||||
return opcodeHasFlags(getOpcode(), NaryDest | ModifiesStack);
|
||||
return opcodeHasFlags(op(), NaryDest | ModifiesStack);
|
||||
}
|
||||
|
||||
bool IRInstruction::isNative() const {
|
||||
return opcodeHasFlags(getOpcode(), CallsNative);
|
||||
return opcodeHasFlags(op(), CallsNative);
|
||||
}
|
||||
|
||||
bool IRInstruction::producesReference() const {
|
||||
return opcodeHasFlags(getOpcode(), ProducesRC);
|
||||
return opcodeHasFlags(op(), ProducesRC);
|
||||
}
|
||||
|
||||
bool IRInstruction::isRematerializable() const {
|
||||
return opcodeHasFlags(getOpcode(), Rematerializable);
|
||||
return opcodeHasFlags(op(), Rematerializable);
|
||||
}
|
||||
|
||||
bool IRInstruction::hasMemEffects() const {
|
||||
return opcodeHasFlags(getOpcode(), MemEffects) || mayReenterHelper();
|
||||
return opcodeHasFlags(op(), MemEffects) || mayReenterHelper();
|
||||
}
|
||||
|
||||
bool IRInstruction::canCSE() const {
|
||||
auto canCSE = opcodeHasFlags(getOpcode(), CanCSE);
|
||||
auto canCSE = opcodeHasFlags(op(), CanCSE);
|
||||
// Make sure that instructions that are CSE'able can't produce a reference
|
||||
// count or consume reference counts. GuardType is special because it can
|
||||
// refine a maybeCounted type to a notCounted type, so it logically consumes
|
||||
@@ -368,7 +368,7 @@ bool IRInstruction::canCSE() const {
|
||||
}
|
||||
|
||||
bool IRInstruction::consumesReferences() const {
|
||||
return opcodeHasFlags(getOpcode(), ConsumesRC);
|
||||
return opcodeHasFlags(op(), ConsumesRC);
|
||||
}
|
||||
|
||||
bool IRInstruction::consumesReference(int srcNo) const {
|
||||
@@ -379,7 +379,7 @@ bool IRInstruction::consumesReference(int srcNo) const {
|
||||
// to a notCounted type.
|
||||
if (m_op == GuardType) {
|
||||
assert(srcNo == 0);
|
||||
return getSrc(0)->getType().maybeCounted() && getTypeParam().notCounted();
|
||||
return getSrc(0)->type().maybeCounted() && getTypeParam().notCounted();
|
||||
}
|
||||
// SpillStack consumes inputs 2 and onward
|
||||
if (m_op == SpillStack) return srcNo >= 2;
|
||||
@@ -404,11 +404,11 @@ bool IRInstruction::consumesReference(int srcNo) const {
|
||||
}
|
||||
|
||||
bool IRInstruction::mayModifyRefs() const {
|
||||
Opcode opc = getOpcode();
|
||||
Opcode opc = op();
|
||||
// DecRefNZ does not have side effects other than decrementing the ref
|
||||
// count. Therefore, its MayModifyRefs should be false.
|
||||
if (opc == DecRef) {
|
||||
auto type = getSrc(0)->getType();
|
||||
auto type = getSrc(0)->type();
|
||||
if (isControlFlowInstruction()) {
|
||||
// If the decref has a target label, then it exits if the destructor
|
||||
// has to be called, so it does not have any side effects on the main
|
||||
@@ -423,18 +423,18 @@ bool IRInstruction::mayModifyRefs() const {
|
||||
}
|
||||
|
||||
bool IRInstruction::mayRaiseError() const {
|
||||
return opcodeHasFlags(getOpcode(), MayRaiseError) || mayReenterHelper();
|
||||
return opcodeHasFlags(op(), MayRaiseError) || mayReenterHelper();
|
||||
}
|
||||
|
||||
bool IRInstruction::isEssential() const {
|
||||
Opcode opc = getOpcode();
|
||||
Opcode opc = op();
|
||||
if (opc == DecRefNZ) {
|
||||
// If the source of a DecRefNZ is not an IncRef, mark it as essential
|
||||
// because we won't remove its source as well as itself.
|
||||
// If the ref count optimization is turned off, mark all DecRefNZ as
|
||||
// essential.
|
||||
if (!RuntimeOption::EvalHHIREnableRefCountOpt ||
|
||||
getSrc(0)->getInstruction()->getOpcode() != IncRef) {
|
||||
getSrc(0)->inst()->op() != IncRef) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -444,11 +444,11 @@ bool IRInstruction::isEssential() const {
|
||||
}
|
||||
|
||||
bool IRInstruction::isTerminal() const {
|
||||
return opcodeHasFlags(getOpcode(), Terminal);
|
||||
return opcodeHasFlags(op(), Terminal);
|
||||
}
|
||||
|
||||
bool IRInstruction::isPassthrough() const {
|
||||
return opcodeHasFlags(getOpcode(), Passthrough);
|
||||
return opcodeHasFlags(op(), Passthrough);
|
||||
}
|
||||
|
||||
SSATmp* IRInstruction::getPassthroughValue() const {
|
||||
@@ -458,7 +458,7 @@ SSATmp* IRInstruction::getPassthroughValue() const {
|
||||
}
|
||||
|
||||
bool IRInstruction::killsSources() const {
|
||||
return opcodeHasFlags(getOpcode(), KillsSources);
|
||||
return opcodeHasFlags(op(), KillsSources);
|
||||
}
|
||||
|
||||
bool IRInstruction::killsSource(int idx) const {
|
||||
@@ -490,7 +490,7 @@ bool IRInstruction::killsSource(int idx) const {
|
||||
}
|
||||
|
||||
bool IRInstruction::modifiesStack() const {
|
||||
return opcodeHasFlags(getOpcode(), ModifiesStack);
|
||||
return opcodeHasFlags(op(), ModifiesStack);
|
||||
}
|
||||
|
||||
SSATmp* IRInstruction::modifiedStkPtr() const {
|
||||
@@ -502,14 +502,14 @@ SSATmp* IRInstruction::modifiedStkPtr() const {
|
||||
}
|
||||
|
||||
bool IRInstruction::hasMainDst() const {
|
||||
return opcodeHasFlags(getOpcode(), HasDest);
|
||||
return opcodeHasFlags(op(), HasDest);
|
||||
}
|
||||
|
||||
bool IRInstruction::mayReenterHelper() const {
|
||||
if (isCmpOp(getOpcode())) {
|
||||
return cmpOpTypesMayReenter(getOpcode(),
|
||||
getSrc(0)->getType(),
|
||||
getSrc(1)->getType());
|
||||
if (isCmpOp(op())) {
|
||||
return cmpOpTypesMayReenter(op(),
|
||||
getSrc(0)->type(),
|
||||
getSrc(1)->type());
|
||||
}
|
||||
// Not necessarily actually false; this is just a helper for other
|
||||
// bits.
|
||||
@@ -584,11 +584,11 @@ Opcode getExitOpcode(TraceExitType::ExitType type) {
|
||||
}
|
||||
|
||||
bool isRefCounted(SSATmp* tmp) {
|
||||
if (tmp->getType().notCounted()) {
|
||||
if (tmp->type().notCounted()) {
|
||||
return false;
|
||||
}
|
||||
IRInstruction* inst = tmp->getInstruction();
|
||||
Opcode opc = inst->getOpcode();
|
||||
IRInstruction* inst = tmp->inst();
|
||||
Opcode opc = inst->op();
|
||||
if (opc == DefConst || opc == LdConst || opc == LdClsCns) {
|
||||
return false;
|
||||
}
|
||||
@@ -692,7 +692,7 @@ bool IRInstruction::cseEquals(IRInstruction* inst) const {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (hasExtra() && !cseEqualsExtra(getOpcode(), m_extra, inst->m_extra)) {
|
||||
if (hasExtra() && !cseEqualsExtra(op(), m_extra, inst->m_extra)) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
@@ -714,7 +714,7 @@ size_t IRInstruction::cseHash() const {
|
||||
}
|
||||
if (hasExtra()) {
|
||||
srcHash = CSEHash::hashCombine(srcHash,
|
||||
cseHashExtra(getOpcode(), m_extra));
|
||||
cseHashExtra(op(), m_extra));
|
||||
}
|
||||
return CSEHash::hashCombine(srcHash, m_op, m_typeParam);
|
||||
}
|
||||
@@ -740,7 +740,7 @@ void IRInstruction::printOpcode(std::ostream& os) const {
|
||||
}
|
||||
if (hasExtra()) {
|
||||
os << color(ANSI_COLOR_GREEN)
|
||||
<< showExtra(getOpcode(), m_extra)
|
||||
<< showExtra(op(), m_extra)
|
||||
<< color(ANSI_COLOR_END);
|
||||
}
|
||||
os << color(ANSI_COLOR_LIGHT_BLUE)
|
||||
@@ -777,7 +777,7 @@ void IRInstruction::printSrc(std::ostream& ostream, uint32_t i) const {
|
||||
|
||||
void IRInstruction::printSrcs(std::ostream& os) const {
|
||||
bool first = true;
|
||||
if (getOpcode() == IncStat) {
|
||||
if (op() == IncStat) {
|
||||
os << " " << Stats::g_counterNames[getSrc(0)->getValInt()]
|
||||
<< ", " << getSrc(1)->getValInt();
|
||||
return;
|
||||
@@ -794,7 +794,7 @@ void IRInstruction::printSrcs(std::ostream& os) const {
|
||||
}
|
||||
|
||||
void IRInstruction::print(std::ostream& ostream) const {
|
||||
if (getOpcode() == Marker) {
|
||||
if (op() == Marker) {
|
||||
auto* marker = getExtra<Marker>();
|
||||
ostream << color(ANSI_COLOR_BLUE)
|
||||
<< folly::format("--- bc {}, spOff {} ({})",
|
||||
@@ -913,8 +913,8 @@ void Block::printLabel(std::ostream& os) const {
|
||||
}
|
||||
|
||||
int SSATmp::numNeededRegs() const {
|
||||
auto type = getType();
|
||||
if (type.subtypeOfAny(Type::None, Type::Null, Type::ActRec, Type::RetAddr)) {
|
||||
auto t = type();
|
||||
if (t.subtypeOfAny(Type::None, Type::Null, Type::ActRec, Type::RetAddr)) {
|
||||
// These don't need a register because their values are static or unused.
|
||||
//
|
||||
// RetAddr doesn't take any register because currently we only target x86,
|
||||
@@ -922,23 +922,23 @@ int SSATmp::numNeededRegs() const {
|
||||
// moved to a machine-specific section once we target other architectures.
|
||||
return 0;
|
||||
}
|
||||
if (type.subtypeOf(Type::Ctx) || type.isPtr()) {
|
||||
if (t.subtypeOf(Type::Ctx) || t.isPtr()) {
|
||||
// Ctx and PtrTo* may be statically unknown but always need just 1 register.
|
||||
return 1;
|
||||
}
|
||||
if (type.subtypeOf(Type::FuncCtx)) {
|
||||
if (t.subtypeOf(Type::FuncCtx)) {
|
||||
// 2 registers regardless of union status: 1 for the Func* and 1
|
||||
// for the {Obj|Cctx}, differentiated by the low bit.
|
||||
return 2;
|
||||
}
|
||||
if (!type.isUnion()) {
|
||||
if (!t.isUnion()) {
|
||||
// Not a union type and not a special case: 1 register.
|
||||
assert(IMPLIES(type.subtypeOf(Type::Gen), type.isKnownDataType()));
|
||||
assert(IMPLIES(t.subtypeOf(Type::Gen), t.isKnownDataType()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
assert(type.subtypeOf(Type::Gen));
|
||||
return type.needsReg() ? 2 : 1;
|
||||
assert(t.subtypeOf(Type::Gen));
|
||||
return t.needsReg() ? 2 : 1;
|
||||
}
|
||||
|
||||
int SSATmp::numAllocatedRegs() const {
|
||||
@@ -1067,7 +1067,7 @@ std::string SSATmp::toString() const {
|
||||
}
|
||||
|
||||
void SSATmp::print(std::ostream& os, bool printLastUse) const {
|
||||
if (m_inst->getOpcode() == DefConst) {
|
||||
if (m_inst->op() == DefConst) {
|
||||
printConst(os, m_inst);
|
||||
return;
|
||||
}
|
||||
@@ -1096,7 +1096,7 @@ void SSATmp::print(std::ostream& os, bool printLastUse) const {
|
||||
}
|
||||
os << punc(":")
|
||||
<< color(ANSI_COLOR_GREEN)
|
||||
<< getType().toString()
|
||||
<< type().toString()
|
||||
<< color(ANSI_COLOR_END)
|
||||
;
|
||||
}
|
||||
@@ -1139,7 +1139,7 @@ void Trace::print(std::ostream& os, const AsmInfo* asmInfo) const {
|
||||
for (auto it = block->begin(); it != block->end();) {
|
||||
auto& inst = *it; ++it;
|
||||
|
||||
if (inst.getOpcode() == Marker) {
|
||||
if (inst.op() == Marker) {
|
||||
os << std::string(kIndent, ' ');
|
||||
inst.print(os);
|
||||
os << '\n';
|
||||
@@ -1165,7 +1165,7 @@ void Trace::print(std::ostream& os, const AsmInfo* asmInfo) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (inst.getOpcode() == DefLabel) {
|
||||
if (inst.op() == DefLabel) {
|
||||
os << std::string(kIndent - 2, ' ');
|
||||
inst.getBlock()->printLabel(os);
|
||||
os << punc(":") << "\n";
|
||||
@@ -1233,7 +1233,7 @@ void Trace::print(std::ostream& os, const AsmInfo* asmInfo) const {
|
||||
}
|
||||
|
||||
int32_t spillValueCells(IRInstruction* spillStack) {
|
||||
assert(spillStack->getOpcode() == SpillStack);
|
||||
assert(spillStack->op() == SpillStack);
|
||||
int32_t numSrcs = spillStack->getNumSrcs();
|
||||
return numSrcs - 2;
|
||||
}
|
||||
@@ -1346,11 +1346,11 @@ bool dominates(const Block* b1, const Block* b2, const IdomVector& idoms) {
|
||||
*/
|
||||
bool checkBlock(Block* b) {
|
||||
assert(!b->empty());
|
||||
assert(b->front()->getOpcode() == DefLabel);
|
||||
assert(b->front()->op() == DefLabel);
|
||||
if (b->back()->isTerminal()) assert(!b->getNext());
|
||||
if (b->getTaken()) {
|
||||
// only Jmp_ can branch to a join block expecting values.
|
||||
assert(b->back()->getOpcode() == Jmp_ ||
|
||||
assert(b->back()->op() == Jmp_ ||
|
||||
b->getTaken()->front()->getNumDsts() == 0);
|
||||
}
|
||||
if (b->getNext()) {
|
||||
@@ -1361,7 +1361,7 @@ bool checkBlock(Block* b) {
|
||||
++i;
|
||||
if (b->back()->isBlockEnd()) --e;
|
||||
for (UNUSED IRInstruction& inst : folly::makeRange(i, e)) {
|
||||
assert(inst.getOpcode() != DefLabel);
|
||||
assert(inst.op() != DefLabel);
|
||||
assert(!inst.isBlockEnd());
|
||||
}
|
||||
return true;
|
||||
@@ -1394,19 +1394,19 @@ bool checkCfg(Trace* trace, const IRFactory& factory) {
|
||||
[] (Block* block, boost::dynamic_bitset<>& defined) {
|
||||
for (IRInstruction& inst : *block) {
|
||||
for (SSATmp* UNUSED src : inst.getSrcs()) {
|
||||
assert(src->getInstruction() != &inst);
|
||||
assert_log(src->getInstruction()->getOpcode() == DefConst ||
|
||||
assert(src->inst() != &inst);
|
||||
assert_log(src->inst()->op() == DefConst ||
|
||||
defined[src->getId()],
|
||||
[&]{ return folly::format(
|
||||
"src '{}' in '{}' came from '{}', which is not a "
|
||||
"DefConst and is not defined at this use site",
|
||||
src->toString(), inst.toString(),
|
||||
src->getInstruction()->toString()).str();
|
||||
src->inst()->toString()).str();
|
||||
});
|
||||
}
|
||||
for (SSATmp& dst : inst.getDsts()) {
|
||||
assert(dst.getInstruction() == &inst &&
|
||||
inst.getOpcode() != DefConst);
|
||||
assert(dst.inst() == &inst &&
|
||||
inst.op() != DefConst);
|
||||
assert(!defined[dst.getId()]);
|
||||
defined[dst.getId()] = 1;
|
||||
}
|
||||
|
||||
@@ -1532,7 +1532,7 @@ class RawMemSlot {
|
||||
|
||||
int64_t getOffset() const { return m_offset; }
|
||||
int32_t getSize() const { return m_size; }
|
||||
Type getType() const { return m_type; }
|
||||
Type type() const { return m_type; }
|
||||
bool allowExtra() const { return m_allowExtra; }
|
||||
|
||||
private:
|
||||
@@ -1661,18 +1661,18 @@ struct IRInstruction {
|
||||
* Return access to extra-data on this instruction, for the
|
||||
* specified opcode type.
|
||||
*
|
||||
* Pre: getOpcode() == opc
|
||||
* Pre: op() == opc
|
||||
*/
|
||||
template<Opcode opc>
|
||||
const typename IRExtraDataType<opc>::type* getExtra() const {
|
||||
assert(opc == getOpcode() && "getExtra type error");
|
||||
assert(opc == op() && "getExtra type error");
|
||||
assert(m_extra != nullptr);
|
||||
return static_cast<typename IRExtraDataType<opc>::type*>(m_extra);
|
||||
}
|
||||
|
||||
template<Opcode opc>
|
||||
typename IRExtraDataType<opc>::type* getExtra() {
|
||||
assert(opc == getOpcode() && "getExtra type error");
|
||||
assert(opc == op() && "getExtra type error");
|
||||
return static_cast<typename IRExtraDataType<opc>::type*>(m_extra);
|
||||
}
|
||||
|
||||
@@ -1686,7 +1686,7 @@ struct IRInstruction {
|
||||
* share the same kind of extra data.
|
||||
*/
|
||||
template<class T> const T* getExtra() const {
|
||||
auto opcode = getOpcode();
|
||||
auto opcode = op();
|
||||
if (debug) assert_opcode_extra<T>(opcode);
|
||||
return static_cast<const T*>(m_extra);
|
||||
}
|
||||
@@ -1735,7 +1735,7 @@ struct IRInstruction {
|
||||
*/
|
||||
IRInstruction* clone(IRFactory* factory) const;
|
||||
|
||||
Opcode getOpcode() const { return m_op; }
|
||||
Opcode op() const { return m_op; }
|
||||
void setOpcode(Opcode newOpc) { m_op = newOpc; }
|
||||
Type getTypeParam() const { return m_typeParam; }
|
||||
void setTypeParam(Type t) { m_typeParam = t; }
|
||||
@@ -1930,9 +1930,9 @@ inline std::ostream& operator<<(std::ostream& os, SpillInfo si) {
|
||||
class SSATmp {
|
||||
public:
|
||||
uint32_t getId() const { return m_id; }
|
||||
IRInstruction* getInstruction() const { return m_inst; }
|
||||
IRInstruction* inst() const { return m_inst; }
|
||||
void setInstruction(IRInstruction* i) { m_inst = i; }
|
||||
Type getType() const { return m_type; }
|
||||
Type type() const { return m_type; }
|
||||
void setType(Type t) { m_type = t; }
|
||||
uint32_t getLastUseId() const { return m_lastUseId; }
|
||||
void setLastUseId(uint32_t newId) { m_lastUseId = newId; }
|
||||
@@ -1940,7 +1940,7 @@ public:
|
||||
void setUseCount(uint32_t count) { m_useCount = count; }
|
||||
void incUseCount() { m_useCount++; }
|
||||
uint32_t decUseCount() { return --m_useCount; }
|
||||
bool isBoxed() const { return getType().isBoxed(); }
|
||||
bool isBoxed() const { return type().isBoxed(); }
|
||||
bool isString() const { return isA(Type::Str); }
|
||||
bool isArray() const { return isA(Type::Arr); }
|
||||
std::string toString() const;
|
||||
@@ -1951,17 +1951,17 @@ public:
|
||||
// XXX: false for Null, etc. Would rather it returns whether we
|
||||
// have a compile-time constant value.
|
||||
bool isConst() const {
|
||||
return m_inst->getOpcode() == DefConst ||
|
||||
m_inst->getOpcode() == LdConst;
|
||||
return m_inst->op() == DefConst ||
|
||||
m_inst->op() == LdConst;
|
||||
}
|
||||
|
||||
/*
|
||||
* For SSATmps with a compile-time constant value, the following
|
||||
* functions allow accessing it.
|
||||
*
|
||||
* Pre: getInstruction() &&
|
||||
* (getInstruction()->getOpcode() == DefConst ||
|
||||
* getInstruction()->getOpcode() == LdConst)
|
||||
* Pre: inst() &&
|
||||
* (inst()->op() == DefConst ||
|
||||
* inst()->op() == LdConst)
|
||||
*/
|
||||
bool getValBool() const;
|
||||
int64_t getValInt() const;
|
||||
@@ -1977,13 +1977,13 @@ public:
|
||||
TCA getValTCA() const;
|
||||
|
||||
/*
|
||||
* Returns: Type::subtypeOf(getType(), tag).
|
||||
* Returns: Type::subtypeOf(type(), tag).
|
||||
*
|
||||
* This should be used for most checks on the types of IRInstruction
|
||||
* sources.
|
||||
*/
|
||||
bool isA(Type tag) const {
|
||||
return getType().subtypeOf(tag);
|
||||
return type().subtypeOf(tag);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2092,19 +2092,19 @@ int vectorBaseIdx(Opcode opc);
|
||||
int vectorKeyIdx(Opcode opc);
|
||||
int vectorValIdx(Opcode opc);
|
||||
inline int vectorBaseIdx(const IRInstruction* inst) {
|
||||
return vectorBaseIdx(inst->getOpcode());
|
||||
return vectorBaseIdx(inst->op());
|
||||
}
|
||||
inline int vectorKeyIdx(const IRInstruction* inst) {
|
||||
return vectorKeyIdx(inst->getOpcode());
|
||||
return vectorKeyIdx(inst->op());
|
||||
}
|
||||
inline int vectorValIdx(const IRInstruction* inst) {
|
||||
return vectorValIdx(inst->getOpcode());
|
||||
return vectorValIdx(inst->op());
|
||||
}
|
||||
|
||||
struct VectorEffects {
|
||||
static bool supported(Opcode op);
|
||||
static bool supported(const IRInstruction* inst) {
|
||||
return supported(inst->getOpcode());
|
||||
return supported(inst->op());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2136,10 +2136,10 @@ struct VectorEffects {
|
||||
explicit VectorEffects(const IRInstruction* inst) {
|
||||
int keyIdx = vectorKeyIdx(inst);
|
||||
int valIdx = vectorValIdx(inst);
|
||||
init(inst->getOpcode(),
|
||||
inst->getSrc(vectorBaseIdx(inst))->getType(),
|
||||
keyIdx == -1 ? Type::None : inst->getSrc(keyIdx)->getType(),
|
||||
valIdx == -1 ? Type::None : inst->getSrc(valIdx)->getType());
|
||||
init(inst->op(),
|
||||
inst->getSrc(vectorBaseIdx(inst))->type(),
|
||||
keyIdx == -1 ? Type::None : inst->getSrc(keyIdx)->type(),
|
||||
valIdx == -1 ? Type::None : inst->getSrc(valIdx)->type());
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
@@ -2147,9 +2147,9 @@ struct VectorEffects {
|
||||
int keyIdx = vectorKeyIdx(opc);
|
||||
int valIdx = vectorValIdx(opc);
|
||||
init(opc,
|
||||
srcs[vectorBaseIdx(opc)]->getType(),
|
||||
keyIdx == -1 ? Type::None : srcs[keyIdx]->getType(),
|
||||
valIdx == -1 ? Type::None : srcs[valIdx]->getType());
|
||||
srcs[vectorBaseIdx(opc)]->type(),
|
||||
keyIdx == -1 ? Type::None : srcs[keyIdx]->type(),
|
||||
valIdx == -1 ? Type::None : srcs[valIdx]->type());
|
||||
}
|
||||
|
||||
VectorEffects(Opcode op, Type base, Type key, Type val) {
|
||||
@@ -2158,7 +2158,7 @@ struct VectorEffects {
|
||||
|
||||
VectorEffects(Opcode op, SSATmp* base, SSATmp* key, SSATmp* val) {
|
||||
auto typeOrNone =
|
||||
[](SSATmp* val){ return val ? val->getType() : Type::None; };
|
||||
[](SSATmp* val){ return val ? val->type() : Type::None; };
|
||||
init(op, typeOrNone(base), typeOrNone(key), typeOrNone(val));
|
||||
}
|
||||
|
||||
@@ -2198,7 +2198,7 @@ struct Block : boost::noncopyable {
|
||||
}
|
||||
|
||||
IRInstruction* getLabel() const {
|
||||
assert(front()->getOpcode() == DefLabel);
|
||||
assert(front()->op() == DefLabel);
|
||||
return front();
|
||||
}
|
||||
|
||||
@@ -2244,7 +2244,7 @@ struct Block : boost::noncopyable {
|
||||
// insert inst after this block's label, return an iterator to the
|
||||
// newly inserted instruction.
|
||||
iterator prepend(IRInstruction* inst) {
|
||||
assert(front()->getOpcode() == DefLabel);
|
||||
assert(front()->op() == DefLabel);
|
||||
auto it = begin();
|
||||
return insert(++it, inst);
|
||||
}
|
||||
@@ -2266,7 +2266,7 @@ struct Block : boost::noncopyable {
|
||||
template<typename L>
|
||||
void forEachSrc(unsigned i, L body) {
|
||||
for (const EdgeData* n = m_preds; n; n = n->next) {
|
||||
assert(n->jmp->getOpcode() == Jmp_ && n->jmp->getTaken() == this);
|
||||
assert(n->jmp->op() == Jmp_ && n->jmp->getTaken() == this);
|
||||
body(n->jmp, n->jmp->getSrc(i));
|
||||
}
|
||||
}
|
||||
@@ -2442,11 +2442,11 @@ void optimizeTrace(Trace*, IRFactory* irFactory);
|
||||
int32_t spillValueCells(IRInstruction* spillStack);
|
||||
|
||||
inline bool isConvIntOrPtrToBool(IRInstruction* instr) {
|
||||
switch (instr->getOpcode()) {
|
||||
switch (instr->op()) {
|
||||
case ConvIntToBool:
|
||||
return true;
|
||||
case ConvCellToBool:
|
||||
return instr->getSrc(0)->getType().subtypeOfAny(
|
||||
return instr->getSrc(0)->type().subtypeOfAny(
|
||||
Type::Func, Type::Cls, Type::FuncCls, Type::VarEnv, Type::TCA);
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -39,7 +39,7 @@ Block* IRFactory::defBlock(const Func* func, IRInstruction* label) {
|
||||
}
|
||||
|
||||
IRInstruction* IRFactory::mov(SSATmp* dst, SSATmp* src) {
|
||||
IRInstruction* inst = gen(Mov, dst->getType(), src);
|
||||
IRInstruction* inst = gen(Mov, dst->type(), src);
|
||||
dst->setInstruction(inst);
|
||||
inst->setDst(dst);
|
||||
return inst;
|
||||
@@ -50,7 +50,7 @@ SSATmp* IRFactory::findConst(ConstData& cdata, Type ctype) {
|
||||
inst.setExtra(&cdata);
|
||||
inst.setTypeParam(ctype);
|
||||
if (SSATmp* tmp = m_constTable.lookup(&inst)) {
|
||||
assert(tmp->getType().equals(ctype));
|
||||
assert(tmp->type().equals(ctype));
|
||||
return tmp;
|
||||
}
|
||||
return m_constTable.insert(cloneInstruction(&inst)->getDst());
|
||||
|
||||
@@ -48,7 +48,7 @@ static void elimUnconditionalJump(Trace* trace, IRFactory* irFactory) {
|
||||
Block* lastBlock = trace->back();
|
||||
auto lastInst = lastBlock->backIter(); // iterator to last instruction
|
||||
IRInstruction& jmp = *lastInst;
|
||||
if (jmp.getOpcode() == Jmp_ && !isJoin[jmp.getTaken()->getId()]) {
|
||||
if (jmp.op() == Jmp_ && !isJoin[jmp.getTaken()->getId()]) {
|
||||
Block* target = jmp.getTaken();
|
||||
lastBlock->splice(lastInst, target, target->skipLabel(), target->end());
|
||||
lastBlock->erase(lastInst); // delete the jmp
|
||||
@@ -95,12 +95,12 @@ static void hoistConditionalJumps(Trace* trace, IRFactory* irFactory) {
|
||||
Block* jccBlock = *(--it);
|
||||
|
||||
IRInstruction& jccInst = *(jccBlock->back());
|
||||
if (!jccCanBeDirectExit(jccInst.getOpcode())) return;
|
||||
if (!jccCanBeDirectExit(jccInst.op())) return;
|
||||
|
||||
for (auto it = lastBlock->skipLabel(), end = lastBlock->end(); it != end;
|
||||
it++) {
|
||||
IRInstruction& inst = *it;
|
||||
opc = inst.getOpcode();
|
||||
opc = inst.op();
|
||||
if (opc == ExitTrace) {
|
||||
exitInst = &inst;
|
||||
break;
|
||||
@@ -118,7 +118,7 @@ static void hoistConditionalJumps(Trace* trace, IRFactory* irFactory) {
|
||||
for (auto it = targetInstIter, end = targetBlock->end(); it != end; ++it) {
|
||||
IRInstruction* instr = &*it;
|
||||
// Extend to support ExitSlow, ExitSlowNoProgress, ...
|
||||
Opcode opc = instr->getOpcode();
|
||||
Opcode opc = instr->op();
|
||||
if (opc == ExitTraceCc) {
|
||||
exitCcInst = instr;
|
||||
break;
|
||||
@@ -147,7 +147,7 @@ static void hoistGuardJumps(Trace* trace, IRFactory* irFactory) {
|
||||
for (Block* block : trace->getBlocks()) {
|
||||
for (IRInstruction& instr : *block) {
|
||||
IRInstruction* inst = &instr;
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
if (inst->getTaken() &&
|
||||
(opc == LdLoc || opc == LdStack ||
|
||||
opc == GuardLoc || opc == GuardStk)) {
|
||||
@@ -157,7 +157,7 @@ static void hoistGuardJumps(Trace* trace, IRFactory* irFactory) {
|
||||
auto instIter = exitLabel->skipLabel();
|
||||
// Confirm this is a GuardExit
|
||||
for (auto it = instIter, end = exitLabel->end(); it != end; ++it) {
|
||||
Opcode op = it->getOpcode();
|
||||
Opcode op = it->op();
|
||||
if (op == Marker) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ private:
|
||||
bool isPinned() const { return m_pinned; }
|
||||
bool isRetAddr() const {
|
||||
if (!m_ssaTmp) return false;
|
||||
Type type = m_ssaTmp->getType();
|
||||
Type type = m_ssaTmp->type();
|
||||
return type == Type::RetAddr;
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@ static_assert(kReservedRSPSpillSpace == NumPreAllocatedSpillLocs * sizeof(void*)
|
||||
// following the dst-src chain.
|
||||
static SSATmp* canonicalize(SSATmp* tmp) {
|
||||
while (true) {
|
||||
IRInstruction* inst = tmp->getInstruction();
|
||||
Opcode opc = inst->getOpcode();
|
||||
IRInstruction* inst = tmp->inst();
|
||||
Opcode opc = inst->op();
|
||||
// The dst of IncRef, Mov, StRef, and StRefNT has the same value
|
||||
// as the src.
|
||||
// We follow these instructions to canonicalize an SSATmp.
|
||||
@@ -300,7 +300,7 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) {
|
||||
inst->setSrc(i, reloadTmp);
|
||||
// reloadTmp and tmp share the same type. Since it was spilled, it
|
||||
// must be using its entire needed-count of registers.
|
||||
assert(reloadTmp->getType() == tmp->getType());
|
||||
assert(reloadTmp->type() == tmp->type());
|
||||
assert(tmp->numNeededRegs() == tmp->numAllocatedRegs());
|
||||
for (int locIndex = 0; locIndex < tmp->numNeededRegs(); ++locIndex) {
|
||||
allocRegToTmp(reloadTmp, locIndex);
|
||||
@@ -322,7 +322,7 @@ void LinearScan::allocRegToInstruction(InstructionList::iterator it) {
|
||||
Range<SSATmp*> dsts = inst->getDsts();
|
||||
if (dsts.empty()) return;
|
||||
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
if (opc == DefMIStateBase) {
|
||||
assert(dsts[0].isA(Type::PtrToCell));
|
||||
allocRegToTmp(&m_regs[int(rsp)], &dsts[0], 0);
|
||||
@@ -421,7 +421,7 @@ void LinearScan::allocRegToTmp(SSATmp* ssaTmp, uint32_t index) {
|
||||
}
|
||||
if (reg == nullptr &&
|
||||
RuntimeOption::EvalHHIREnablePreColoring &&
|
||||
ssaTmp->getInstruction()->isNative()) {
|
||||
ssaTmp->inst()->isNative()) {
|
||||
// Pre-colors ssaTmp if it's the return value of a native.
|
||||
if (index == 0) {
|
||||
reg = getReg(&m_regs[int(rax)]);
|
||||
@@ -489,7 +489,7 @@ uint32_t LinearScan::assignSpillLoc() {
|
||||
assert(!m_natives.empty());
|
||||
m_natives.pop_front();
|
||||
}
|
||||
if (inst.getOpcode() == Spill) {
|
||||
if (inst.op() == Spill) {
|
||||
SSATmp* dst = inst.getDst();
|
||||
SSATmp* src = inst.getSrc(0);
|
||||
for (int locIndex = 0;
|
||||
@@ -505,7 +505,7 @@ uint32_t LinearScan::assignSpillLoc() {
|
||||
TRACE(3, "[counter] 1 spill\n");
|
||||
}
|
||||
}
|
||||
if (inst.getOpcode() == Reload) {
|
||||
if (inst.op() == Reload) {
|
||||
SSATmp* src = inst.getSrc(0);
|
||||
for (int locIndex = 0;
|
||||
locIndex < src->numNeededRegs();
|
||||
@@ -534,7 +534,7 @@ void LinearScan::insertAllocFreeSpillAux(Trace* trace,
|
||||
for (auto it = block->begin(); it != block->end(); ) {
|
||||
auto next = it; ++next;
|
||||
IRInstruction& inst = *it;
|
||||
Opcode opc = inst.getOpcode();
|
||||
Opcode opc = inst.op();
|
||||
if (opc == Call) {
|
||||
// Insert FreeSpill and AllocSpill around each Call.
|
||||
IRInstruction* allocSpill = m_irFactory->gen(AllocSpill, tmp);
|
||||
@@ -574,7 +574,7 @@ void LinearScan::collectJmps() {
|
||||
m_jmps.reset();
|
||||
for (Block* block : m_blocks) {
|
||||
IRInstruction* jmp = block->back();
|
||||
if (jmp->getOpcode() != Jmp_ || jmp->getNumSrcs() == 0) continue;
|
||||
if (jmp->op() != Jmp_ || jmp->getNumSrcs() == 0) continue;
|
||||
for (SSATmp* src : jmp->getSrcs()) {
|
||||
m_jmps[src].push_back(jmp);
|
||||
}
|
||||
@@ -588,7 +588,7 @@ void LinearScan::computePreColoringHint() {
|
||||
return;
|
||||
}
|
||||
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
using namespace NativeCalls;
|
||||
if (CallMap::hasInfo(opc)) {
|
||||
unsigned reg = 0;
|
||||
@@ -626,8 +626,8 @@ void LinearScan::computePreColoringHint() {
|
||||
break;
|
||||
case Concat:
|
||||
{
|
||||
Type lType = inst->getSrc(0)->getType();
|
||||
Type rType = inst->getSrc(1)->getType();
|
||||
Type lType = inst->getSrc(0)->type();
|
||||
Type rType = inst->getSrc(1)->type();
|
||||
if ((lType.isString() && rType.isString()) ||
|
||||
(lType.isString() && rType == Type::Int) ||
|
||||
(lType == Type::Int && rType.isString())) {
|
||||
@@ -653,8 +653,8 @@ void LinearScan::computePreColoringHint() {
|
||||
auto src1 = inst->getSrc(0);
|
||||
auto src2 = inst->getSrc(1);
|
||||
|
||||
auto type1 = src1->getType();
|
||||
auto type2 = src2->getType();
|
||||
auto type1 = src1->type();
|
||||
auto type2 = src2->type();
|
||||
|
||||
if ((type1.isArray() && type2.isArray())
|
||||
|| (type1.isString() && type2.isString())
|
||||
@@ -705,10 +705,10 @@ void LinearScan::computePreColoringHint() {
|
||||
// allocated at the specified index.
|
||||
static RegNumber findLabelSrcReg(IRInstruction* label, unsigned dstIdx,
|
||||
uint32_t regIndex) {
|
||||
assert(label->getOpcode() == DefLabel);
|
||||
assert(label->op() == DefLabel);
|
||||
SSATmp* withReg = label->getBlock()->findSrc(dstIdx, [&](SSATmp* src) {
|
||||
return src->getReg(regIndex) != InvalidReg &&
|
||||
src->getInstruction()->getBlock()->getHint() != Block::Unlikely;
|
||||
src->inst()->getBlock()->getHint() != Block::Unlikely;
|
||||
});
|
||||
return withReg ? withReg->getReg(regIndex) : reg::noreg;
|
||||
}
|
||||
@@ -722,9 +722,9 @@ static RegNumber findLabelSrcReg(IRInstruction* label, unsigned dstIdx,
|
||||
// proceed unhinted.
|
||||
RegNumber LinearScan::getJmpPreColor(SSATmp* tmp, uint32_t regIndex,
|
||||
bool isReload) {
|
||||
IRInstruction* srcInst = tmp->getInstruction();
|
||||
IRInstruction* srcInst = tmp->inst();
|
||||
const JmpList& jmps = m_jmps[tmp];
|
||||
if (isReload && (srcInst->getOpcode() == DefLabel || !jmps.empty())) {
|
||||
if (isReload && (srcInst->op() == DefLabel || !jmps.empty())) {
|
||||
// If we're precoloring a Reload of a temp that we'd normally find
|
||||
// a hint for, just return the register allocated to the spilled
|
||||
// temp.
|
||||
@@ -733,7 +733,7 @@ RegNumber LinearScan::getJmpPreColor(SSATmp* tmp, uint32_t regIndex,
|
||||
return reg;
|
||||
}
|
||||
|
||||
if (srcInst->getOpcode() == DefLabel) {
|
||||
if (srcInst->op() == DefLabel) {
|
||||
// Figure out which dst of the label is tmp
|
||||
for (unsigned i = 0, n = srcInst->getNumDsts(); i < n; ++i) {
|
||||
if (srcInst->getDst(i) == tmp) {
|
||||
@@ -799,7 +799,7 @@ void LinearScan::coalesce(Trace* trace) {
|
||||
void LinearScan::preAllocSpillLoc(uint32_t numSpillLocs) {
|
||||
for (Block* block : m_blocks) {
|
||||
for (IRInstruction& inst : *block) {
|
||||
if (inst.getOpcode() == Spill) {
|
||||
if (inst.op() == Spill) {
|
||||
SSATmp* dst = inst.getDst();
|
||||
for (int index = 0; index < dst->numNeededRegs(); ++index) {
|
||||
assert(!dst->hasReg(index));
|
||||
@@ -842,7 +842,7 @@ void numberInstructions(const BlockList& blocks) {
|
||||
});
|
||||
uint32_t nextId = 1;
|
||||
forEachInst(blocks, [&](IRInstruction* inst) {
|
||||
if (inst->getOpcode() == Marker) return; // don't number markers
|
||||
if (inst->op() == Marker) return; // don't number markers
|
||||
uint32_t id = nextId++;
|
||||
inst->setId(id);
|
||||
for (SSATmp* tmp : inst->getSrcs()) {
|
||||
@@ -912,7 +912,7 @@ void LinearScan::allocRegsToTrace() {
|
||||
// clear remembered reloads that don't dominate this block
|
||||
for (SlotInfo& slot : m_slots) {
|
||||
if (SSATmp* reload = slot.m_latestReload) {
|
||||
if (!dominates(reload->getInstruction()->getBlock(), block, m_idoms)) {
|
||||
if (!dominates(reload->inst()->getBlock(), block, m_idoms)) {
|
||||
slot.m_latestReload = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -929,8 +929,8 @@ void LinearScan::allocRegsToTrace() {
|
||||
// For each spill slot, insert the spill right after the instruction
|
||||
// that generated the value (without traversing everything else).
|
||||
for (SlotInfo& slot : m_slots) {
|
||||
IRInstruction* spill = slot.m_spillTmp->getInstruction();
|
||||
IRInstruction* inst = spill->getSrc(0)->getInstruction();
|
||||
IRInstruction* spill = slot.m_spillTmp->inst();
|
||||
IRInstruction* inst = spill->getSrc(0)->inst();
|
||||
Block* block = inst->getBlock();
|
||||
if (inst->isBlockEnd()) {
|
||||
block->getNext()->prepend(spill);
|
||||
@@ -1009,7 +1009,7 @@ void LinearScan::rematerializeAux() {
|
||||
}
|
||||
for (auto it = block->begin(); it != block->end(); ++it) {
|
||||
IRInstruction& inst = *it;
|
||||
Opcode opc = inst.getOpcode();
|
||||
Opcode opc = inst.op();
|
||||
if (opc == DefFP || opc == FreeActRec) {
|
||||
assert(inst.getDst()->getReg() == rVmFp);
|
||||
curFp = inst.getDst();
|
||||
@@ -1019,10 +1019,10 @@ void LinearScan::rematerializeAux() {
|
||||
// t = Reload s
|
||||
SSATmp* dst = inst.getDst();
|
||||
SSATmp* spilledTmp = getSpilledTmp(dst);
|
||||
IRInstruction* spilledInst = spilledTmp->getInstruction();
|
||||
IRInstruction* spilledInst = spilledTmp->inst();
|
||||
IRInstruction* newInst = NULL;
|
||||
if (spilledInst->isRematerializable() ||
|
||||
(spilledInst->getOpcode() == LdStack &&
|
||||
(spilledInst->op() == LdStack &&
|
||||
spilledInst->getSrc(0) == curSp)) {
|
||||
// XXX: could change <newInst> to the non-check version.
|
||||
// Rematerialize those rematerializable instructions (i.e.,
|
||||
@@ -1039,14 +1039,14 @@ void LinearScan::rematerializeAux() {
|
||||
if (loc != -1) {
|
||||
newInst = m_irFactory->gen(
|
||||
LdLoc,
|
||||
dst->getType(),
|
||||
dst->type(),
|
||||
LocalId(loc),
|
||||
curFp
|
||||
);
|
||||
}
|
||||
}
|
||||
if (newInst) {
|
||||
UNUSED Type oldType = dst->getType();
|
||||
UNUSED Type oldType = dst->type();
|
||||
newInst->setDst(dst);
|
||||
dst->setInstruction(newInst);
|
||||
assert(outputType(newInst) == oldType);
|
||||
@@ -1088,13 +1088,13 @@ void LinearScan::rematerializeAux() {
|
||||
|
||||
void LinearScan::removeUnusedSpills() {
|
||||
for (SlotInfo& slot : m_slots) {
|
||||
IRInstruction* spill = slot.m_spillTmp->getInstruction();
|
||||
IRInstruction* spill = slot.m_spillTmp->inst();
|
||||
if (spill->getDst()->getUseCount() == 0) {
|
||||
Block* block = spill->getBlock();
|
||||
block->erase(block->iteratorTo(spill));
|
||||
SSATmp* src = spill->getSrc(0);
|
||||
if (src->decUseCount() == 0) {
|
||||
Opcode srcOpc = src->getInstruction()->getOpcode();
|
||||
Opcode srcOpc = src->inst()->op();
|
||||
// Not all instructions are able to take noreg as its dest
|
||||
// reg. We pick LdLoc and IncRef because they occur often.
|
||||
if (srcOpc == IncRef || srcOpc == LdLoc) {
|
||||
@@ -1273,16 +1273,16 @@ uint32_t LinearScan::getNextNativeId() const {
|
||||
}
|
||||
|
||||
SSATmp* LinearScan::getSpilledTmp(SSATmp* tmp) {
|
||||
assert(tmp->getInstruction()->getOpcode() == Reload);
|
||||
SSATmp* slot = tmp->getInstruction()->getSrc(0);
|
||||
assert(slot->getInstruction()->getOpcode() == Spill);
|
||||
return slot->getInstruction()->getSrc(0);
|
||||
assert(tmp->inst()->op() == Reload);
|
||||
SSATmp* slot = tmp->inst()->getSrc(0);
|
||||
assert(slot->inst()->op() == Spill);
|
||||
return slot->inst()->getSrc(0);
|
||||
}
|
||||
|
||||
// If <tmp> is a reloaded value, follow the spill-reload chain to find
|
||||
// its source; otherwise, return <tmp> itself.
|
||||
SSATmp* LinearScan::getOrigTmp(SSATmp* tmp) {
|
||||
if (tmp->getInstruction()->getOpcode() == Reload)
|
||||
if (tmp->inst()->op() == Reload)
|
||||
return getSpilledTmp(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ private:
|
||||
for (it = map.begin(), end = map.end(); it != end; ) {
|
||||
copy = it;
|
||||
++it;
|
||||
if (copy->first->getInstruction()->getOpcode() != Mov) {
|
||||
if (copy->first->inst()->op() != Mov) {
|
||||
copy->second->dec();
|
||||
}
|
||||
map.erase(copy);
|
||||
@@ -215,7 +215,7 @@ private:
|
||||
static SSATmp* findValue(IRInstruction* inst) {
|
||||
assert(inst != nullptr);
|
||||
|
||||
Opcode op = inst->getOpcode();
|
||||
Opcode op = inst->op();
|
||||
if (isLoad(op)) {
|
||||
return inst->getDst();
|
||||
}
|
||||
@@ -240,7 +240,7 @@ private:
|
||||
|
||||
static SSATmp* findRefValue(IRInstruction* inst) {
|
||||
assert(inst != nullptr);
|
||||
switch (inst->getOpcode()) {
|
||||
switch (inst->op()) {
|
||||
case LdRef:
|
||||
return inst->getDst();
|
||||
case StRef:
|
||||
@@ -293,11 +293,11 @@ void MemMap::killRefInfo(IRInstruction* save) {
|
||||
it != end; ++it) {
|
||||
// if 'save' is a load, then don't kill access info of refs that have a
|
||||
// different type than 'save'
|
||||
if ((isLoad(save->getOpcode()) || save->getOpcode() == LdMem)) {
|
||||
auto saveType = save->getDst()->getType();
|
||||
if ((isLoad(save->op()) || save->op() == LdMem)) {
|
||||
auto saveType = save->getDst()->type();
|
||||
if (it->second->value != nullptr &&
|
||||
it->second->value->getType() != saveType &&
|
||||
it->second->value->getType().isKnownDataType() &&
|
||||
it->second->value->type() != saveType &&
|
||||
it->second->value->type().isKnownDataType() &&
|
||||
saveType.isKnownDataType()) {
|
||||
continue;
|
||||
}
|
||||
@@ -309,8 +309,8 @@ void MemMap::killRefInfo(IRInstruction* save) {
|
||||
// we're saving, kill its info
|
||||
if (it->second->access != save) {
|
||||
it->second->access = nullptr;
|
||||
if (isStore(save->getOpcode()) ||
|
||||
save->getOpcode() == StMem || save->getOpcode() == StMemNT) {
|
||||
if (isStore(save->op()) ||
|
||||
save->op() == StMem || save->op() == StMemNT) {
|
||||
it->second->value = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -328,7 +328,7 @@ void MemMap::killPropInfo(IRInstruction* save) {
|
||||
|
||||
// get out the offset only if we know one exists (we might be killing because
|
||||
// of a LdMem or StMem), otherwise -1
|
||||
Opcode op = save->getOpcode();
|
||||
Opcode op = save->op();
|
||||
int offset = (op == LdProp || op == StProp || op == StPropNT) ?
|
||||
save->getSrc(1)->getValInt() : -1;
|
||||
|
||||
@@ -349,18 +349,18 @@ void MemMap::killPropInfo(IRInstruction* save) {
|
||||
if (offset == -1 || (copy->offset == offset && copy->access != save)) {
|
||||
// if 'save' is a load, then don't kill access info of properties that
|
||||
// have a different type than 'save'
|
||||
if ((isLoad(save->getOpcode()) || save->getOpcode() == LdMem) &&
|
||||
if ((isLoad(save->op()) || save->op() == LdMem) &&
|
||||
copy->value != nullptr &&
|
||||
copy->value->getType() != save->getDst()->getType() &&
|
||||
copy->value->getType().isKnownDataType() &&
|
||||
save->getDst()->getType().isKnownDataType()) {
|
||||
copy->value->type() != save->getDst()->type() &&
|
||||
copy->value->type().isKnownDataType() &&
|
||||
save->getDst()->type().isKnownDataType()) {
|
||||
continue;
|
||||
}
|
||||
// TODO consider doing the same with the type of the base ref pointer
|
||||
// of a store
|
||||
|
||||
if (isStore(save->getOpcode()) ||
|
||||
save->getOpcode() == StMem || save->getOpcode() == StMemNT) {
|
||||
if (isStore(save->op()) ||
|
||||
save->op() == StMem || save->op() == StMemNT) {
|
||||
accesses.erase(copy);
|
||||
} else {
|
||||
copy->access = nullptr;
|
||||
@@ -408,7 +408,7 @@ void MemMap::processInstruction(IRInstruction* inst, bool isPseudoMain) {
|
||||
|
||||
assert(inst != nullptr);
|
||||
|
||||
Opcode op = inst->getOpcode();
|
||||
Opcode op = inst->op();
|
||||
|
||||
switch (op) {
|
||||
case Box: {
|
||||
@@ -458,7 +458,7 @@ void MemMap::processInstruction(IRInstruction* inst, bool isPseudoMain) {
|
||||
SSATmp* source = inst->getSrc(0);
|
||||
|
||||
// figure out which map the new alias is supposed to be inserted into
|
||||
if (source->getType().isBoxed()) {
|
||||
if (source->type().isBoxed()) {
|
||||
if (m_unescaped.count(source) > 0) {
|
||||
m_unescaped[dest] = m_unescaped[source];
|
||||
if (op == IncRef) {
|
||||
@@ -470,13 +470,13 @@ void MemMap::processInstruction(IRInstruction* inst, bool isPseudoMain) {
|
||||
m_unknown[dest]->inc();
|
||||
}
|
||||
} else {
|
||||
m_unknown[source] = new RefInfo(source->getInstruction());
|
||||
m_unknown[source] = new RefInfo(source->inst());
|
||||
m_unknown[dest] = m_unknown[source];
|
||||
if (op == IncRef) {
|
||||
m_unknown[dest]->inc();
|
||||
}
|
||||
}
|
||||
} else if (source->getType() == Type::Obj) {
|
||||
} else if (source->type() == Type::Obj) {
|
||||
if (m_props.count(source) > 0) {
|
||||
m_props[dest] = m_props[source];
|
||||
if (op == IncRef) {
|
||||
@@ -566,7 +566,7 @@ void MemMap::processInstruction(IRInstruction* inst, bool isPseudoMain) {
|
||||
case DecRef:
|
||||
case DecRefNZ: {
|
||||
SSATmp* ref = inst->getSrc(0);
|
||||
Type ty = inst->getSrc(0)->getType();
|
||||
Type ty = inst->getSrc(0)->type();
|
||||
|
||||
if (ref->isConst()) {
|
||||
// cannot be ref-counted
|
||||
@@ -678,14 +678,14 @@ void MemMap::optimizeMemoryAccesses(Trace* trace) {
|
||||
|
||||
for (Block* block : trace->getBlocks()) {
|
||||
for (IRInstruction& inst : *block) {
|
||||
if (inst.getOpcode() == Marker) {
|
||||
if (inst.op() == Marker) {
|
||||
curFunc = inst.getExtra<Marker>()->func;
|
||||
}
|
||||
// initialize each instruction as live
|
||||
setLive(inst, true);
|
||||
|
||||
int offset = -1;
|
||||
Opcode op = inst.getOpcode();
|
||||
Opcode op = inst.op();
|
||||
|
||||
if (isLoad(op)) {
|
||||
if (op == LdProp) {
|
||||
@@ -702,17 +702,17 @@ void MemMap::optimizeMemoryAccesses(Trace* trace) {
|
||||
|
||||
// if we see a store, first check if its last available access is a store
|
||||
// if it is, then the last access is a dead store
|
||||
auto access = inst.getOpcode() == StLoc || inst.getOpcode() == StLocNT
|
||||
auto access = inst.op() == StLoc || inst.op() == StLocNT
|
||||
? lastLocalAccess(inst.getExtra<LocalId>()->locId)
|
||||
: getLastAccess(inst.getSrc(0), offset);
|
||||
if (access && isStore(access->getOpcode())) {
|
||||
if (access && isStore(access->op())) {
|
||||
// if a dead St* is followed by a St*NT, then the second store needs to
|
||||
// now write in the type because the first store will be removed
|
||||
if (access->getOpcode() == StProp && op == StPropNT) {
|
||||
if (access->op() == StProp && op == StPropNT) {
|
||||
inst.setOpcode(StProp);
|
||||
} else if (access->getOpcode() == StLoc && op == StLocNT) {
|
||||
} else if (access->op() == StLoc && op == StLocNT) {
|
||||
inst.setOpcode(StLoc);
|
||||
} else if (access->getOpcode() == StRef && op == StRefNT) {
|
||||
} else if (access->op() == StRef && op == StRefNT) {
|
||||
inst.setOpcode(StRef);
|
||||
}
|
||||
|
||||
@@ -759,22 +759,22 @@ void MemMap::optimizeMemoryAccesses(Trace* trace) {
|
||||
void MemMap::optimizeLoad(IRInstruction* inst, int offset) {
|
||||
// check if we still know the value at this memory location. if we do,
|
||||
// then replace the load with a Mov
|
||||
auto value = inst->getOpcode() == LdLoc
|
||||
auto value = inst->op() == LdLoc
|
||||
? getLocalValue(inst->getExtra<LocalId>()->locId)
|
||||
: getValue(inst->getSrc(0), offset);
|
||||
if (value == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Type instTy = inst->getDst()->getType();
|
||||
Type valTy = value->getType();
|
||||
Type instTy = inst->getDst()->type();
|
||||
Type valTy = value->type();
|
||||
|
||||
// check for loads that have a guard that will definitely fail
|
||||
if (inst->getTaken() && instTy.not(valTy)) {
|
||||
return inst->convertToJmp();
|
||||
}
|
||||
|
||||
Opcode op = inst->getOpcode();
|
||||
Opcode op = inst->op();
|
||||
|
||||
// fix the instruction's arguments and rip off its label if it had one
|
||||
inst->setSrc(0, value);
|
||||
@@ -806,7 +806,7 @@ void MemMap::sinkStores(StoreList& stores) {
|
||||
|
||||
// StRefs cannot just be removed, they have to be converted into Movs
|
||||
// as the destination of the StRef still has the DecRef attached to it.
|
||||
if (store->getOpcode() == StRef || store->getOpcode() == StRefNT) {
|
||||
if (store->op() == StRef || store->op() == StRefNT) {
|
||||
store->setOpcode(Mov);
|
||||
store->setSrc(1, nullptr);
|
||||
store->setNumSrcs(1);
|
||||
|
||||
@@ -37,7 +37,7 @@ static void insertAfter(IRInstruction* definer, IRInstruction* inst) {
|
||||
*/
|
||||
static void insertRefCountAsserts(IRInstruction& inst, IRFactory* factory) {
|
||||
for (SSATmp& dst : inst.getDsts()) {
|
||||
Type t = dst.getType();
|
||||
Type t = dst.type();
|
||||
if (t.subtypeOf(Type::Counted | Type::StaticStr | Type::StaticArr)) {
|
||||
insertAfter(&inst, factory->gen(DbgAssertRefCount, &dst));
|
||||
}
|
||||
@@ -54,7 +54,7 @@ static void insertSpillStackAsserts(IRInstruction& inst, IRFactory* factory) {
|
||||
auto* block = inst.getBlock();
|
||||
auto pos = block->iteratorTo(&inst); ++pos;
|
||||
for (unsigned i = 0, n = vals.size(); i < n; ++i) {
|
||||
Type t = vals[i]->getType();
|
||||
Type t = vals[i]->type();
|
||||
if (t.subtypeOf(Type::Gen)) {
|
||||
IRInstruction* addr = factory->gen(LdStackAddr, Type::PtrToGen,
|
||||
sp, factory->defConst(i));
|
||||
@@ -74,11 +74,11 @@ static void insertAsserts(Trace* trace, IRFactory* factory) {
|
||||
for (auto it = block->begin(), end = block->end(); it != end; ) {
|
||||
IRInstruction& inst = *it;
|
||||
++it;
|
||||
if (inst.getOpcode() == SpillStack) {
|
||||
if (inst.op() == SpillStack) {
|
||||
insertSpillStackAsserts(inst, factory);
|
||||
continue;
|
||||
}
|
||||
if (inst.getOpcode() == Call) {
|
||||
if (inst.op() == Call) {
|
||||
SSATmp* sp = inst.getDst();
|
||||
IRInstruction* addr = factory->gen(LdStackAddr, Type::PtrToGen,
|
||||
sp, factory->defConst(0));
|
||||
|
||||
@@ -31,9 +31,9 @@ TRACE_SET_MOD(hhir);
|
||||
|
||||
static void copyPropSrc(IRInstruction* inst, int index) {
|
||||
auto tmp = inst->getSrc(index);
|
||||
auto srcInst = tmp->getInstruction();
|
||||
auto srcInst = tmp->inst();
|
||||
|
||||
switch (srcInst->getOpcode()) {
|
||||
switch (srcInst->op()) {
|
||||
case Mov:
|
||||
inst->setSrc(index, srcInst->getSrc(0));
|
||||
break;
|
||||
@@ -58,20 +58,20 @@ void copyProp(IRInstruction* inst) {
|
||||
|
||||
static bool isNotInst(SSATmp *src1, SSATmp *src2) {
|
||||
// right operand should be 1
|
||||
if (!src2->isConst() || src2->getType() != Type::Int ||
|
||||
if (!src2->isConst() || src2->type() != Type::Int ||
|
||||
src2->getValInt() != 1) {
|
||||
return false;
|
||||
}
|
||||
// left operand should be a boolean
|
||||
if (src1->getType() != Type::Bool) {
|
||||
if (src1->type() != Type::Bool) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isNotInst(SSATmp *tmp) {
|
||||
IRInstruction* inst = tmp->getInstruction();
|
||||
if (inst->getOpcode() != OpXor) {
|
||||
IRInstruction* inst = tmp->inst();
|
||||
if (inst->op() != OpXor) {
|
||||
return false;
|
||||
}
|
||||
return isNotInst(inst->getSrc(0), inst->getSrc(1));
|
||||
@@ -81,7 +81,7 @@ SSATmp* Simplifier::simplify(IRInstruction* inst) {
|
||||
SSATmp* src1 = inst->getSrc(0);
|
||||
SSATmp* src2 = inst->getSrc(1);
|
||||
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
switch (opc) {
|
||||
case OpAdd: return simplifyAdd(src1, src2);
|
||||
case OpSub: return simplifySub(src1, src2);
|
||||
@@ -177,8 +177,8 @@ SSATmp* Simplifier::simplify(IRInstruction* inst) {
|
||||
* type. Returns true if it succeeds.
|
||||
*/
|
||||
static bool hoistGuardToLoad(SSATmp* tmp, Type type) {
|
||||
IRInstruction* inst = tmp->getInstruction();
|
||||
switch (inst->getOpcode()) {
|
||||
IRInstruction* inst = tmp->inst();
|
||||
switch (inst->op()) {
|
||||
case Mov:
|
||||
case IncRef:
|
||||
{
|
||||
@@ -205,7 +205,7 @@ static bool hoistGuardToLoad(SSATmp* tmp, Type type) {
|
||||
// Not a control flow instruction, so can't give it check semantics
|
||||
break;
|
||||
}
|
||||
Type instType = tmp->getType();
|
||||
Type instType = tmp->type();
|
||||
if (instType == Type::Gen ||
|
||||
(instType == Type::Cell && !type.isBoxed())) {
|
||||
tmp->setType(type);
|
||||
@@ -229,10 +229,10 @@ SSATmp* Simplifier::simplifySpillStack(IRInstruction* inst) {
|
||||
int64_t adjustment = spDeficit - spillCells;
|
||||
for (uint32_t i = 0, cellOff = 0; i < numSpillSrcs; i++) {
|
||||
const int64_t offset = cellOff + adjustment;
|
||||
auto* srcInst = spillVals[i]->getInstruction();
|
||||
auto* srcInst = spillVals[i]->inst();
|
||||
// If our value came from a LdStack on the same sp and offset,
|
||||
// we don't need to spill it.
|
||||
if (srcInst->getOpcode() == LdStack && srcInst->getSrc(0) == sp &&
|
||||
if (srcInst->op() == LdStack && srcInst->getSrc(0) == sp &&
|
||||
srcInst->getSrc(1)->getValInt() == offset) {
|
||||
spillVals[i] = m_tb->genDefNone();
|
||||
}
|
||||
@@ -246,13 +246,13 @@ SSATmp* Simplifier::simplifySpillStack(IRInstruction* inst) {
|
||||
|
||||
SSATmp* Simplifier::simplifyCall(IRInstruction* inst) {
|
||||
auto spillVals = inst->getSrcs().subpiece(3);
|
||||
IRInstruction* spillStack = m_tb->getSp()->getInstruction();
|
||||
if (spillStack->getOpcode() != SpillStack) {
|
||||
IRInstruction* spillStack = m_tb->getSp()->inst();
|
||||
if (spillStack->op() != SpillStack) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SSATmp* sp = spillStack->getSrc(0);
|
||||
if (sp->getInstruction()->getOpcode() == NewObjNoCtorCached) {
|
||||
if (sp->inst()->op() == NewObjNoCtorCached) {
|
||||
inst->convertToNop();
|
||||
}
|
||||
int baseOffset = spillStack->getSrc(1)->getValInt() -
|
||||
@@ -260,11 +260,11 @@ SSATmp* Simplifier::simplifyCall(IRInstruction* inst) {
|
||||
auto const numSpillSrcs = spillVals.size();
|
||||
for (int32_t i = 0; i < numSpillSrcs; i++) {
|
||||
const int64_t offset = -(i + 1) + baseOffset;
|
||||
assert(spillVals[i]->getType() != Type::ActRec);
|
||||
IRInstruction* srcInst = spillVals[i]->getInstruction();
|
||||
assert(spillVals[i]->type() != Type::ActRec);
|
||||
IRInstruction* srcInst = spillVals[i]->inst();
|
||||
// If our value came from a LdStack on the same sp and offset,
|
||||
// we don't need to spill it.
|
||||
if (srcInst->getOpcode() == LdStack && srcInst->getSrc(0) == sp &&
|
||||
if (srcInst->op() == LdStack && srcInst->getSrc(0) == sp &&
|
||||
srcInst->getSrc(1)->getValInt() == offset) {
|
||||
spillVals[i] = m_tb->genDefNone();
|
||||
}
|
||||
@@ -287,7 +287,7 @@ SSATmp* Simplifier::simplifyLdCtx(IRInstruction* inst) {
|
||||
|
||||
SSATmp* Simplifier::simplifyLdClsCtx(IRInstruction* inst) {
|
||||
SSATmp* ctx = inst->getSrc(0);
|
||||
Type ctxType = ctx->getType();
|
||||
Type ctxType = ctx->type();
|
||||
if (ctxType.equals(Type::Obj)) {
|
||||
// this pointer... load its class ptr
|
||||
return m_tb->gen(LdObjClass, ctx);
|
||||
@@ -331,7 +331,7 @@ SSATmp* Simplifier::simplifyLdCls(IRInstruction* inst) {
|
||||
SSATmp* Simplifier::simplifyGuardType(IRInstruction* inst) {
|
||||
Type type = inst->getTypeParam();
|
||||
SSATmp* src = inst->getSrc(0);
|
||||
Type srcType = src->getType();
|
||||
Type srcType = src->type();
|
||||
if (srcType.subtypeOf(type)) {
|
||||
/*
|
||||
* the type of the src is the same or more refined than type, so the
|
||||
@@ -369,7 +369,7 @@ SSATmp* Simplifier::simplifyGuardType(IRInstruction* inst) {
|
||||
SSATmp* Simplifier::simplifyQueryJmp(IRInstruction* inst) {
|
||||
SSATmp* src1 = inst->getSrc(0);
|
||||
SSATmp* src2 = inst->getSrc(1);
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
// reuse the logic in simplifyCmp.
|
||||
SSATmp* newCmp = simplifyCmp(queryJmpToQueryOp(opc), src1, src2);
|
||||
if (!newCmp) return nullptr;
|
||||
@@ -378,7 +378,7 @@ SSATmp* Simplifier::simplifyQueryJmp(IRInstruction* inst) {
|
||||
[=] (IRInstruction* condJmp) -> SSATmp* {
|
||||
SSATmp* newCondJmp = simplifyCondJmp(condJmp);
|
||||
if (newCondJmp) return newCondJmp;
|
||||
if (condJmp->getOpcode() == Nop) {
|
||||
if (condJmp->op() == Nop) {
|
||||
// simplifyCondJmp folded the branch into a nop
|
||||
inst->convertToNop();
|
||||
}
|
||||
@@ -397,8 +397,8 @@ SSATmp* Simplifier::simplifyMov(SSATmp* src) {
|
||||
}
|
||||
|
||||
SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
IRInstruction* inst = src->getInstruction();
|
||||
Opcode op = inst->getOpcode();
|
||||
IRInstruction* inst = src->inst();
|
||||
Opcode op = inst->op();
|
||||
|
||||
// TODO: Add more algebraic simplification rules for NOT
|
||||
switch (op) {
|
||||
@@ -452,21 +452,21 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
#define SIMPLIFY_CONST(OP) do { \
|
||||
/* don't canonicalize to the right, OP might not be commutative */ \
|
||||
if (src1->isConst() && src2->isConst()) { \
|
||||
if (src1->getType().isNull()) { \
|
||||
if (src1->type().isNull()) { \
|
||||
/* Null op Null */ \
|
||||
if (src2->getType().isNull()) { \
|
||||
if (src2->type().isNull()) { \
|
||||
return genDefInt(0 OP 0); \
|
||||
} \
|
||||
/* Null op ConstInt */ \
|
||||
if (src2->getType() == Type::Int) { \
|
||||
if (src2->type() == Type::Int) { \
|
||||
return genDefInt(0 OP src2->getValInt()); \
|
||||
} \
|
||||
/* Null op ConstBool */ \
|
||||
if (src2->getType() == Type::Bool) { \
|
||||
if (src2->type() == Type::Bool) { \
|
||||
return genDefInt(0 OP src2->getValBool()); \
|
||||
} \
|
||||
/* Null op StaticStr */ \
|
||||
if (src2->getType() == Type::StaticStr) { \
|
||||
if (src2->type() == Type::StaticStr) { \
|
||||
const StringData* str = src2->getValStr(); \
|
||||
if (str->isInteger()) { \
|
||||
return genDefInt(0 OP str->toInt64()); \
|
||||
@@ -474,23 +474,23 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
return genDefInt(0 OP 0); \
|
||||
} \
|
||||
} \
|
||||
if (src1->getType() == Type::Int) { \
|
||||
if (src1->type() == Type::Int) { \
|
||||
/* ConstInt op Null */ \
|
||||
if (src2->getType().isNull()) { \
|
||||
if (src2->type().isNull()) { \
|
||||
return genDefInt(src1->getValInt() OP 0); \
|
||||
} \
|
||||
/* ConstInt op ConstInt */ \
|
||||
if (src2->getType() == Type::Int) { \
|
||||
if (src2->type() == Type::Int) { \
|
||||
return genDefInt(src1->getValInt() OP \
|
||||
src2->getValInt()); \
|
||||
} \
|
||||
/* ConstInt op ConstBool */ \
|
||||
if (src2->getType() == Type::Bool) { \
|
||||
if (src2->type() == Type::Bool) { \
|
||||
return genDefInt(src1->getValInt() OP \
|
||||
int(src2->getValBool())); \
|
||||
} \
|
||||
/* ConstInt op StaticStr */ \
|
||||
if (src2->getType() == Type::StaticStr) { \
|
||||
if (src2->type() == Type::StaticStr) { \
|
||||
const StringData* str = src2->getValStr(); \
|
||||
if (str->isInteger()) { \
|
||||
return genDefInt(src1->getValInt() OP str->toInt64()); \
|
||||
@@ -498,23 +498,23 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
return genDefInt(src1->getValInt() OP 0); \
|
||||
} \
|
||||
} \
|
||||
if (src1->getType() == Type::Bool) { \
|
||||
if (src1->type() == Type::Bool) { \
|
||||
/* ConstBool op Null */ \
|
||||
if (src2->getType().isNull()) { \
|
||||
if (src2->type().isNull()) { \
|
||||
return genDefInt(src1->getValBool() OP 0); \
|
||||
} \
|
||||
/* ConstBool op ConstInt */ \
|
||||
if (src2->getType() == Type::Int) { \
|
||||
if (src2->type() == Type::Int) { \
|
||||
return genDefInt(int(src1->getValBool()) OP \
|
||||
src2->getValInt()); \
|
||||
} \
|
||||
/* ConstBool op ConstBool */ \
|
||||
if (src2->getType() == Type::Bool) { \
|
||||
if (src2->type() == Type::Bool) { \
|
||||
return genDefInt(src1->getValBool() OP \
|
||||
src2->getValBool()); \
|
||||
} \
|
||||
/* ConstBool op StaticStr */ \
|
||||
if (src2->getType() == Type::StaticStr) { \
|
||||
if (src2->type() == Type::StaticStr) { \
|
||||
const StringData* str = src2->getValStr(); \
|
||||
if (str->isInteger()) { \
|
||||
return genDefInt(int(src1->getValBool()) OP str->toInt64()); \
|
||||
@@ -522,26 +522,26 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
return genDefInt(int(src1->getValBool()) OP 0); \
|
||||
} \
|
||||
} \
|
||||
if (src1->getType() == Type::StaticStr) { \
|
||||
if (src1->type() == Type::StaticStr) { \
|
||||
const StringData* str = src1->getValStr(); \
|
||||
int64_t strInt = 0; \
|
||||
if (str->isInteger()) { \
|
||||
strInt = str->toInt64(); \
|
||||
} \
|
||||
/* StaticStr op Null */ \
|
||||
if (src2->getType().isNull()) { \
|
||||
if (src2->type().isNull()) { \
|
||||
return genDefInt(strInt OP 0); \
|
||||
} \
|
||||
/* StaticStr op ConstInt */ \
|
||||
if (src2->getType() == Type::Int) { \
|
||||
if (src2->type() == Type::Int) { \
|
||||
return genDefInt(strInt OP src2->getValInt()); \
|
||||
} \
|
||||
/* StaticStr op ConstBool */ \
|
||||
if (src2->getType() == Type::Bool) { \
|
||||
if (src2->type() == Type::Bool) { \
|
||||
return genDefInt(strInt OP int(src2->getValBool())); \
|
||||
} \
|
||||
/* StaticStr op StaticStr */ \
|
||||
if (src2->getType() == Type::StaticStr) { \
|
||||
if (src2->type() == Type::StaticStr) { \
|
||||
const StringData* str2 = src2->getValStr(); \
|
||||
if (str2->isInteger()) { \
|
||||
return genDefInt(strInt OP str2->toInt64()); \
|
||||
@@ -558,9 +558,9 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
return m_tb->gen##NAME(src2, src1); \
|
||||
} \
|
||||
if (src1->isA(Type::Int) && src2->isA(Type::Int)) { \
|
||||
IRInstruction* inst1 = src1->getInstruction(); \
|
||||
IRInstruction* inst2 = src2->getInstruction(); \
|
||||
if (inst1->getOpcode() == Op##NAME && inst1->getSrc(1)->isConst()) { \
|
||||
IRInstruction* inst1 = src1->inst(); \
|
||||
IRInstruction* inst2 = src2->inst(); \
|
||||
if (inst1->op() == Op##NAME && inst1->getSrc(1)->isConst()) { \
|
||||
/* (X + C1) + C2 --> X + C3 */ \
|
||||
if (src2->isConst()) { \
|
||||
int64_t right = inst1->getSrc(1)->getValInt(); \
|
||||
@@ -568,7 +568,7 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
return m_tb->gen##NAME(inst1->getSrc(0), genDefInt(right)); \
|
||||
} \
|
||||
/* (X + C1) + (Y + C2) --> X + Y + C3 */ \
|
||||
if (inst2->getOpcode() == Op##NAME && inst2->getSrc(1)->isConst()) { \
|
||||
if (inst2->op() == Op##NAME && inst2->getSrc(1)->isConst()) { \
|
||||
int64_t right = inst1->getSrc(1)->getValInt(); \
|
||||
right OP##= inst2->getSrc(1)->getValInt(); \
|
||||
SSATmp* left = m_tb->gen##NAME(inst1->getSrc(0), inst2->getSrc(0)); \
|
||||
@@ -581,10 +581,10 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
#define SIMPLIFY_DISTRIBUTIVE(OUTOP, INOP, OUTNAME, INNAME) do { \
|
||||
/* assumes that OUTOP is commutative, don't use with subtract! */ \
|
||||
SIMPLIFY_COMMUTATIVE(OUTOP, OUTNAME); \
|
||||
IRInstruction* inst1 = src1->getInstruction(); \
|
||||
IRInstruction* inst2 = src2->getInstruction(); \
|
||||
Opcode op1 = inst1->getOpcode(); \
|
||||
Opcode op2 = inst2->getOpcode(); \
|
||||
IRInstruction* inst1 = src1->inst(); \
|
||||
IRInstruction* inst2 = src2->inst(); \
|
||||
Opcode op1 = inst1->op(); \
|
||||
Opcode op2 = inst2->op(); \
|
||||
/* all combinations of X * Y + X * Z --> X * (Y + Z) */ \
|
||||
if (op1 == Op##INNAME && op2 == Op##INNAME) { \
|
||||
if (inst1->getSrc(0) == inst2->getSrc(0)) { \
|
||||
@@ -608,11 +608,11 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
|
||||
|
||||
SSATmp* Simplifier::simplifyAdd(SSATmp* src1, SSATmp* src2) {
|
||||
SIMPLIFY_DISTRIBUTIVE(+, *, Add, Mul);
|
||||
if (src2->isConst() && src2->getType() == Type::Int) {
|
||||
if (src2->isConst() && src2->type() == Type::Int) {
|
||||
int64_t src2Val = src2->getValInt();
|
||||
// X + 0 --> X
|
||||
if (src2Val == 0) {
|
||||
if (src1->getType() == Type::Bool) {
|
||||
if (src1->type() == Type::Bool) {
|
||||
return m_tb->gen(ConvBoolToInt, src1);
|
||||
}
|
||||
return src1;
|
||||
@@ -623,11 +623,11 @@ SSATmp* Simplifier::simplifyAdd(SSATmp* src1, SSATmp* src2) {
|
||||
}
|
||||
}
|
||||
// X + (0 - Y) --> X - Y
|
||||
IRInstruction* inst2 = src2->getInstruction();
|
||||
Opcode op2 = inst2->getOpcode();
|
||||
IRInstruction* inst2 = src2->inst();
|
||||
Opcode op2 = inst2->op();
|
||||
if (op2 == OpSub) {
|
||||
SSATmp* src = inst2->getSrc(0);
|
||||
if (src->isConst() && src->getType() == Type::Int) {
|
||||
if (src->isConst() && src->type() == Type::Int) {
|
||||
if (src->getValInt() == 0) {
|
||||
return m_tb->genSub(src1, inst2->getSrc(1));
|
||||
}
|
||||
@@ -641,11 +641,11 @@ SSATmp* Simplifier::simplifySub(SSATmp* src1, SSATmp* src2) {
|
||||
if (src1 == src2) {
|
||||
return genDefInt(0);
|
||||
}
|
||||
if (src2->isConst() && src2->getType() == Type::Int) {
|
||||
if (src2->isConst() && src2->type() == Type::Int) {
|
||||
int64_t src2Val = src2->getValInt();
|
||||
// X - 0 --> X
|
||||
if (src2Val == 0) {
|
||||
if (src1->getType() == Type::Bool) {
|
||||
if (src1->type() == Type::Bool) {
|
||||
return m_tb->gen(ConvBoolToInt, src1);
|
||||
}
|
||||
return src1;
|
||||
@@ -656,11 +656,11 @@ SSATmp* Simplifier::simplifySub(SSATmp* src1, SSATmp* src2) {
|
||||
}
|
||||
}
|
||||
// X - (0 - Y) --> X + Y
|
||||
IRInstruction* inst2 = src2->getInstruction();
|
||||
Opcode op2 = inst2->getOpcode();
|
||||
IRInstruction* inst2 = src2->inst();
|
||||
Opcode op2 = inst2->op();
|
||||
if (op2 == OpSub) {
|
||||
SSATmp* src = inst2->getSrc(0);
|
||||
if (src->isConst() && src->getType() == Type::Int) {
|
||||
if (src->isConst() && src->type() == Type::Int) {
|
||||
if (src->getValInt() == 0) {
|
||||
return m_tb->genAdd(src1, inst2->getSrc(1));
|
||||
}
|
||||
@@ -674,7 +674,7 @@ SSATmp* Simplifier::simplifySub(SSATmp* src1, SSATmp* src2) {
|
||||
}
|
||||
SSATmp* Simplifier::simplifyMul(SSATmp* src1, SSATmp* src2) {
|
||||
SIMPLIFY_COMMUTATIVE(*, Mul);
|
||||
if (src2->isConst() && src2->getType() == Type::Int) {
|
||||
if (src2->isConst() && src2->type() == Type::Int) {
|
||||
// X * (-1) --> -X
|
||||
if (src2->getValInt() == -1) {
|
||||
return m_tb->genSub(genDefInt(0), src1);
|
||||
@@ -685,7 +685,7 @@ SSATmp* Simplifier::simplifyMul(SSATmp* src1, SSATmp* src2) {
|
||||
}
|
||||
// X * 1 --> X
|
||||
if (src2->getValInt() == 1) {
|
||||
if (src1->getType() == Type::Bool) {
|
||||
if (src1->type() == Type::Bool) {
|
||||
return m_tb->gen(ConvBoolToInt, src1);
|
||||
}
|
||||
return src1;
|
||||
@@ -707,7 +707,7 @@ SSATmp* Simplifier::simplifyAnd(SSATmp* src1, SSATmp* src2) {
|
||||
if (src1 == src2) {
|
||||
return src1;
|
||||
}
|
||||
if (src2->isConst() && src2->getType() == Type::Int) {
|
||||
if (src2->isConst() && src2->type() == Type::Int) {
|
||||
// X & 0 --> 0
|
||||
if (src2->getValInt() == 0) {
|
||||
return genDefInt(0);
|
||||
@@ -725,7 +725,7 @@ SSATmp* Simplifier::simplifyOr(SSATmp* src1, SSATmp* src2) {
|
||||
if (src1 == src2) {
|
||||
return src1;
|
||||
}
|
||||
if (src2->isConst() && src2->getType() == Type::Int) {
|
||||
if (src2->isConst() && src2->type() == Type::Int) {
|
||||
// X | 0 --> X
|
||||
if (src2->getValInt() == 0) {
|
||||
return src1;
|
||||
@@ -743,7 +743,7 @@ SSATmp* Simplifier::simplifyXor(SSATmp* src1, SSATmp* src2) {
|
||||
if (src1 == src2)
|
||||
return genDefInt(0);
|
||||
// X ^ 0 --> X
|
||||
if (src2->isConst() && src2->getType() == Type::Int) {
|
||||
if (src2->isConst() && src2->type() == Type::Int) {
|
||||
if (src2->getValInt() == 0) {
|
||||
return src1;
|
||||
}
|
||||
@@ -755,8 +755,8 @@ SSATmp* Simplifier::simplifyXor(SSATmp* src1, SSATmp* src2) {
|
||||
}
|
||||
|
||||
static SSATmp* chaseIncRefs(SSATmp* tmp) {
|
||||
while (tmp->getInstruction()->getOpcode() == IncRef) {
|
||||
tmp = tmp->getInstruction()->getSrc(0);
|
||||
while (tmp->inst()->op() == IncRef) {
|
||||
tmp = tmp->inst()->getSrc(0);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
@@ -784,14 +784,14 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
|
||||
// Identity optimization
|
||||
if ((src1 == src2 || chaseIncRefs(src1) == chaseIncRefs(src2)) &&
|
||||
src1->getType() != Type::Dbl) {
|
||||
src1->type() != Type::Dbl) {
|
||||
// (val1 == val1) does not simplify to true when val1 is a NaN
|
||||
return genDefBool(cmpOp(opName, 0, 0));
|
||||
}
|
||||
|
||||
// need both types to be unboxed and known to simplify
|
||||
if (!src1->getType().notBoxed() || src1->getType() == Type::Cell ||
|
||||
!src2->getType().notBoxed() || src2->getType() == Type::Cell) {
|
||||
if (!src1->type().notBoxed() || src1->type() == Type::Cell ||
|
||||
!src2->type().notBoxed() || src2->type() == Type::Cell) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -801,8 +801,8 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
|
||||
if (opName == OpSame || opName == OpNSame) {
|
||||
// OpSame and OpNSame do not perform type juggling
|
||||
if (src1->getType() != src2->getType()) {
|
||||
if (!(src1->getType().isString() && src2->getType().isString())) {
|
||||
if (src1->type() != src2->type()) {
|
||||
if (!(src1->type().isString() && src2->type().isString())) {
|
||||
return genDefBool(opName == OpNSame);
|
||||
}
|
||||
}
|
||||
@@ -811,7 +811,7 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
|
||||
// OpSame and OpNSame have special rules for string and object
|
||||
// Other types may simplify to OpEq and OpNeq, respectively
|
||||
if (src1->getType().isString() && src2->getType().isString()) {
|
||||
if (src1->type().isString() && src2->type().isString()) {
|
||||
if (src1->isConst() && src2->isConst()) {
|
||||
auto str1 = src1->getValStr();
|
||||
auto str2 = src2->getValStr();
|
||||
@@ -821,11 +821,11 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (src1->getType() == Type::Obj && src2->getType() == Type::Obj) {
|
||||
if (src1->type() == Type::Obj && src2->type() == Type::Obj) {
|
||||
return nullptr;
|
||||
}
|
||||
// for arrays, don't simplify Same to Eq
|
||||
if (src1->getType() == Type::Arr && src2->getType() == Type::Arr) {
|
||||
if (src1->type() == Type::Arr && src2->type() == Type::Arr) {
|
||||
return nullptr;
|
||||
}
|
||||
// Type is neither a string nor an object - simplify to OpEq/OpNeq
|
||||
@@ -840,7 +840,7 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// Null cmp Null
|
||||
if (src1->getType().isNull() && src2->getType().isNull()) {
|
||||
if (src1->type().isNull() && src2->type().isNull()) {
|
||||
return genDefBool(cmpOp(opName, 0, 0));
|
||||
}
|
||||
// const cmp const
|
||||
@@ -848,18 +848,18 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
// TODO: can simplify const arrays when sizes are different or both 0
|
||||
if (src1->isConst() && src2->isConst()) {
|
||||
// StaticStr cmp StaticStr
|
||||
if (src1->getType() == Type::StaticStr &&
|
||||
src2->getType() == Type::StaticStr) {
|
||||
if (src1->type() == Type::StaticStr &&
|
||||
src2->type() == Type::StaticStr) {
|
||||
int cmp = src1->getValStr()->compare(src2->getValStr());
|
||||
return genDefBool(cmpOp(opName, cmp, 0));
|
||||
}
|
||||
// ConstInt cmp ConstInt
|
||||
if (src1->getType() == Type::Int && src2->getType() == Type::Int) {
|
||||
if (src1->type() == Type::Int && src2->type() == Type::Int) {
|
||||
return genDefBool(
|
||||
cmpOp(opName, src1->getValInt(), src2->getValInt()));
|
||||
}
|
||||
// ConstBool cmp ConstBool
|
||||
if (src1->getType() == Type::Bool && src2->getType() == Type::Bool) {
|
||||
if (src1->type() == Type::Bool && src2->type() == Type::Bool) {
|
||||
return genDefBool(
|
||||
cmpOp(opName, src1->getValBool(), src2->getValBool()));
|
||||
}
|
||||
@@ -871,7 +871,7 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// Perform constant-bool optimizations
|
||||
if (src2->getType() == Type::Bool && src2->isConst()) {
|
||||
if (src2->type() == Type::Bool && src2->isConst()) {
|
||||
bool b = src2->getValBool();
|
||||
|
||||
// The result of the comparison might be independent of the truth
|
||||
@@ -904,8 +904,8 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
// Then stop - there are no more simplifications left
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
if (src1->getType() == src2->getType() ||
|
||||
(src1->getType().isString() && src2->getType().isString())) {
|
||||
if (src1->type() == src2->type() ||
|
||||
(src1->type().isString() && src2->type().isString())) {
|
||||
if (src1->isConst() && !src2->isConst()) {
|
||||
return m_tb->genCmp(commuteQueryOp(opName), src2, src1);
|
||||
}
|
||||
@@ -918,39 +918,39 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// nulls get canonicalized to the right
|
||||
if (src1->getType().isNull()) {
|
||||
if (src1->type().isNull()) {
|
||||
return m_tb->genCmp(commuteQueryOp(opName), src2, src1);
|
||||
}
|
||||
|
||||
// case 1: null cmp string. Convert null to ""
|
||||
if (src1->getType().isString() && src2->getType().isNull()) {
|
||||
if (src1->type().isString() && src2->type().isNull()) {
|
||||
return m_tb->genCmp(opName, src1,
|
||||
m_tb->genDefConst(StringData::GetStaticString("")));
|
||||
}
|
||||
|
||||
// case 2a: null cmp anything. Convert null to false
|
||||
if (src2->getType().isNull()) {
|
||||
if (src2->type().isNull()) {
|
||||
return m_tb->genCmp(opName, src1, genDefBool(false));
|
||||
}
|
||||
|
||||
// bools get canonicalized to the right
|
||||
if (src1->getType() == Type::Bool) {
|
||||
if (src1->type() == Type::Bool) {
|
||||
return m_tb->genCmp(commuteQueryOp(opName), src2, src1);
|
||||
}
|
||||
|
||||
// case 2b: bool cmp anything. Convert anything to bool
|
||||
if (src2->getType() == Type::Bool) {
|
||||
if (src2->type() == Type::Bool) {
|
||||
if (src1->isConst()) {
|
||||
if (src1->getType() == Type::Int) {
|
||||
if (src1->type() == Type::Int) {
|
||||
return m_tb->genCmp(opName, genDefBool(src1->getValInt()), src2);
|
||||
} else if (src1->getType().isString()) {
|
||||
} else if (src1->type().isString()) {
|
||||
auto str = src1->getValStr();
|
||||
return m_tb->genCmp(opName, genDefBool(str->toBoolean()), src2);
|
||||
}
|
||||
}
|
||||
|
||||
// Optimize comparison between int and const bool
|
||||
if (src1->getType() == Type::Int && src2->isConst()) {
|
||||
if (src1->type() == Type::Int && src2->isConst()) {
|
||||
// Based on the const bool optimization (above) opName should be OpEq
|
||||
always_assert(opName == OpEq);
|
||||
|
||||
@@ -972,12 +972,12 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
// same-type simplification is performed above
|
||||
|
||||
// strings get canonicalized to the left
|
||||
if (src2->getType().isString()) {
|
||||
if (src2->type().isString()) {
|
||||
return m_tb->genCmp(commuteQueryOp(opName), src2, src1);
|
||||
}
|
||||
|
||||
// ints get canonicalized to the right
|
||||
if (src1->getType() == Type::Int) {
|
||||
if (src1->type() == Type::Int) {
|
||||
return m_tb->genCmp(commuteQueryOp(opName), src2, src1);
|
||||
}
|
||||
|
||||
@@ -986,8 +986,8 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
|
||||
// cases (specifically, string-int). Other cases (like string-string)
|
||||
// are dealt with earlier, while other cases (like number-resource)
|
||||
// are not caught at all (and end up exiting this macro at the bottom).
|
||||
if (src1->getType().isString() && src1->isConst() &&
|
||||
src2->getType() == Type::Int) {
|
||||
if (src1->type().isString() && src1->isConst() &&
|
||||
src2->type() == Type::Int) {
|
||||
auto str = src1->getValStr();
|
||||
int64_t si; double sd;
|
||||
auto st = str->isNumericWithVal(si, sd, true /* allow errors */);
|
||||
@@ -1035,10 +1035,10 @@ SSATmp* Simplifier::simplifyJmpIsType(IRInstruction* inst) {
|
||||
|
||||
SSATmp* Simplifier::simplifyIsType(IRInstruction* inst) {
|
||||
bool trueSense =
|
||||
inst->getOpcode() == IsType || inst->getOpcode() == JmpIsType;
|
||||
inst->op() == IsType || inst->op() == JmpIsType;
|
||||
auto type = inst->getTypeParam();
|
||||
auto src = inst->getSrc(0);
|
||||
auto srcType = src->getType();
|
||||
auto srcType = src->type();
|
||||
|
||||
// The comparisons below won't work for these cases covered by this
|
||||
// assert, and we currently don't generate these types.
|
||||
@@ -1061,8 +1061,8 @@ SSATmp* Simplifier::simplifyIsType(IRInstruction* inst) {
|
||||
}
|
||||
|
||||
SSATmp* Simplifier::simplifyConcat(SSATmp* src1, SSATmp* src2) {
|
||||
if (src1->isConst() && src1->getType() == Type::StaticStr &&
|
||||
src2->isConst() && src2->getType() == Type::StaticStr) {
|
||||
if (src1->isConst() && src1->type() == Type::StaticStr &&
|
||||
src2->isConst() && src2->type() == Type::StaticStr) {
|
||||
StringData* str1 = const_cast<StringData *>(src1->getValStr());
|
||||
StringData* str2 = const_cast<StringData *>(src2->getValStr());
|
||||
StringData* merge = StringData::GetStaticString(concat_ss(str1, str2));
|
||||
@@ -1244,8 +1244,8 @@ SSATmp* Simplifier::simplifyLdClsPropAddr(IRInstruction* inst) {
|
||||
: nullptr;
|
||||
if (!clsNameString) {
|
||||
// see if you can get the class name from a LdCls
|
||||
IRInstruction* clsInst = cls->getInstruction();
|
||||
if (clsInst->getOpcode() == LdCls || clsInst->getOpcode() == LdClsCached) {
|
||||
IRInstruction* clsInst = cls->inst();
|
||||
if (clsInst->op() == LdCls || clsInst->op() == LdClsCached) {
|
||||
SSATmp* clsName = clsInst->getSrc(0);
|
||||
assert(clsName->isA(Type::Str));
|
||||
if (clsName->isConst()) {
|
||||
@@ -1279,10 +1279,10 @@ SSATmp* Simplifier::simplifyLdClsPropAddr(IRInstruction* inst) {
|
||||
* calls that will have that.)
|
||||
*/
|
||||
SSATmp* Simplifier::simplifyLdThis(IRInstruction* inst) {
|
||||
auto fpInst = inst->getSrc(0)->getInstruction();
|
||||
if (fpInst->getOpcode() == DefInlineFP) {
|
||||
auto spInst = fpInst->getSrc(0)->getInstruction();
|
||||
if (spInst->getOpcode() == SpillFrame &&
|
||||
auto fpInst = inst->getSrc(0)->inst();
|
||||
if (fpInst->op() == DefInlineFP) {
|
||||
auto spInst = fpInst->getSrc(0)->inst();
|
||||
if (spInst->op() == SpillFrame &&
|
||||
spInst->getSrc(3)->isA(Type::Obj)) {
|
||||
return spInst->getSrc(3);
|
||||
}
|
||||
@@ -1296,7 +1296,7 @@ SSATmp* Simplifier::simplifyUnbox(IRInstruction* inst) {
|
||||
auto* src = inst->getSrc(0);
|
||||
auto type = outputType(inst);
|
||||
|
||||
Type srcType = src->getType();
|
||||
Type srcType = src->type();
|
||||
if (srcType.notBoxed()) {
|
||||
assert(type.equals(srcType));
|
||||
return src;
|
||||
@@ -1318,8 +1318,8 @@ SSATmp* Simplifier::simplifyUnboxPtr(IRInstruction* inst) {
|
||||
}
|
||||
|
||||
SSATmp* Simplifier::simplifyCheckInit(IRInstruction* inst) {
|
||||
Type srcType = inst->getSrc(0)->getType();
|
||||
srcType = inst->getOpcode() == CheckInitMem ? srcType.deref() : srcType;
|
||||
Type srcType = inst->getSrc(0)->type();
|
||||
srcType = inst->op() == CheckInitMem ? srcType.deref() : srcType;
|
||||
assert(srcType.notPtr());
|
||||
assert(inst->getTaken());
|
||||
if (srcType.isInit()) {
|
||||
@@ -1329,7 +1329,7 @@ SSATmp* Simplifier::simplifyCheckInit(IRInstruction* inst) {
|
||||
}
|
||||
|
||||
SSATmp* Simplifier::simplifyPrint(IRInstruction* inst) {
|
||||
if (inst->getSrc(0)->getType().isNull()) {
|
||||
if (inst->getSrc(0)->type().isNull()) {
|
||||
inst->convertToNop();
|
||||
}
|
||||
return nullptr;
|
||||
@@ -1364,19 +1364,19 @@ SSATmp* Simplifier::genDefBool(bool val) {
|
||||
|
||||
SSATmp* Simplifier::simplifyCondJmp(IRInstruction* inst) {
|
||||
SSATmp* const src = inst->getSrc(0);
|
||||
IRInstruction* const srcInst = src->getInstruction();
|
||||
const Opcode srcOpcode = srcInst->getOpcode();
|
||||
IRInstruction* const srcInst = src->inst();
|
||||
const Opcode srcOpcode = srcInst->op();
|
||||
|
||||
// After other simplifications below (isConvIntOrPtrToBool), we can
|
||||
// end up with a non-Bool input. Nothing more to do in this case.
|
||||
if (src->getType() != Type::Bool) {
|
||||
if (src->type() != Type::Bool) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Constant propagate.
|
||||
if (src->isConst()) {
|
||||
bool val = src->getValBool();
|
||||
if (inst->getOpcode() == JmpZero) {
|
||||
if (inst->op() == JmpZero) {
|
||||
val = !val;
|
||||
}
|
||||
if (val) {
|
||||
@@ -1388,7 +1388,7 @@ SSATmp* Simplifier::simplifyCondJmp(IRInstruction* inst) {
|
||||
|
||||
// Pull negations into the jump.
|
||||
if (isNotInst(src)) {
|
||||
return m_tb->gen(inst->getOpcode() == JmpZero ? JmpNZero : JmpZero,
|
||||
return m_tb->gen(inst->op() == JmpZero ? JmpNZero : JmpZero,
|
||||
inst->getTaken(),
|
||||
srcInst->getSrc(0));
|
||||
}
|
||||
@@ -1406,7 +1406,7 @@ SSATmp* Simplifier::simplifyCondJmp(IRInstruction* inst) {
|
||||
// If the source is conversion of an int or pointer to boolean, we
|
||||
// can test the int/ptr value directly.
|
||||
if (isConvIntOrPtrToBool(srcInst)) {
|
||||
return m_tb->gen(inst->getOpcode(),
|
||||
return m_tb->gen(inst->op(),
|
||||
inst->getTaken(),
|
||||
srcInst->getSrc(0));
|
||||
}
|
||||
@@ -1416,7 +1416,7 @@ SSATmp* Simplifier::simplifyCondJmp(IRInstruction* inst) {
|
||||
SrcRange ssas = srcInst->getSrcs();
|
||||
return m_tb->gen(
|
||||
queryToJmpOp(
|
||||
inst->getOpcode() == JmpZero
|
||||
inst->op() == JmpZero
|
||||
? negateQueryOp(srcOpcode)
|
||||
: srcOpcode),
|
||||
srcInst->getTypeParam(), // if it had a type param
|
||||
|
||||
@@ -97,8 +97,8 @@ SSATmp* TraceBuilder::genLdProp(SSATmp* obj,
|
||||
SSATmp* prop,
|
||||
Type type,
|
||||
Trace* exit) {
|
||||
assert(obj->getType() == Type::Obj);
|
||||
assert(prop->getType() == Type::Int);
|
||||
assert(obj->type() == Type::Obj);
|
||||
assert(prop->type() == Type::Int);
|
||||
assert(prop->isConst());
|
||||
return gen(LdProp, type, getFirstBlock(exit), obj, prop);
|
||||
}
|
||||
@@ -147,7 +147,7 @@ SSATmp* TraceBuilder::genLdMem(SSATmp* addr,
|
||||
|
||||
SSATmp* TraceBuilder::genLdRef(SSATmp* ref, Type type, Trace* exit) {
|
||||
assert(type.notBoxed());
|
||||
assert(ref->getType().isBoxed());
|
||||
assert(ref->type().isBoxed());
|
||||
return gen(LdRef, type, getFirstBlock(exit), ref);
|
||||
}
|
||||
|
||||
@@ -165,8 +165,8 @@ bool TraceBuilder::isValueAvailable(SSATmp* tmp) const {
|
||||
if (anyLocalHasValue(tmp)) return true;
|
||||
if (callerLocalHasValue(tmp)) return true;
|
||||
|
||||
IRInstruction* srcInstr = tmp->getInstruction();
|
||||
Opcode srcOpcode = srcInstr->getOpcode();
|
||||
IRInstruction* srcInstr = tmp->inst();
|
||||
Opcode srcOpcode = srcInstr->op();
|
||||
|
||||
if (srcOpcode == LdThis) return true;
|
||||
|
||||
@@ -183,7 +183,7 @@ void TraceBuilder::genDecRef(SSATmp* tmp) {
|
||||
return;
|
||||
}
|
||||
|
||||
Type type = tmp->getType();
|
||||
Type type = tmp->type();
|
||||
if (type.isBoxed()) {
|
||||
// we can't really rely on the types held in the boxed values since
|
||||
// aliasing stores may change them. We conservatively set the type
|
||||
@@ -199,8 +199,8 @@ void TraceBuilder::genDecRef(SSATmp* tmp) {
|
||||
// simple cases:
|
||||
// 1) LdThis is always available.
|
||||
// 2) A value stored in a local is always available.
|
||||
IRInstruction* incRefInst = tmp->getInstruction();
|
||||
if (incRefInst->getOpcode() == IncRef) {
|
||||
IRInstruction* incRefInst = tmp->inst();
|
||||
if (incRefInst->op() == IncRef) {
|
||||
if (isValueAvailable(incRefInst->getSrc(0))) {
|
||||
gen(DecRefNZ, tmp);
|
||||
return;
|
||||
@@ -338,13 +338,13 @@ Trace* TraceBuilder::genExitTrace(uint32_t bcOff,
|
||||
}
|
||||
|
||||
SSATmp* TraceBuilder::genAdd(SSATmp* src1, SSATmp* src2) {
|
||||
Type resultType = Type::binArithResultType(src1->getType(),
|
||||
src2->getType());
|
||||
Type resultType = Type::binArithResultType(src1->type(),
|
||||
src2->type());
|
||||
return gen(OpAdd, resultType, src1, src2);
|
||||
}
|
||||
SSATmp* TraceBuilder::genSub(SSATmp* src1, SSATmp* src2) {
|
||||
Type resultType = Type::binArithResultType(src1->getType(),
|
||||
src2->getType());
|
||||
Type resultType = Type::binArithResultType(src1->type(),
|
||||
src2->type());
|
||||
return gen(OpSub, resultType, src1, src2);
|
||||
}
|
||||
SSATmp* TraceBuilder::genAnd(SSATmp* src1, SSATmp* src2) {
|
||||
@@ -357,13 +357,13 @@ SSATmp* TraceBuilder::genXor(SSATmp* src1, SSATmp* src2) {
|
||||
return gen(OpXor, src1, src2);
|
||||
}
|
||||
SSATmp* TraceBuilder::genMul(SSATmp* src1, SSATmp* src2) {
|
||||
Type resultType = Type::binArithResultType(src1->getType(),
|
||||
src2->getType());
|
||||
Type resultType = Type::binArithResultType(src1->type(),
|
||||
src2->type());
|
||||
return gen(OpMul, resultType, src1, src2);
|
||||
}
|
||||
|
||||
SSATmp* TraceBuilder::genNot(SSATmp* src) {
|
||||
assert(src->getType() == Type::Bool);
|
||||
assert(src->type() == Type::Bool);
|
||||
return genConvToBool(genXor(src, genDefConst<int64_t>(1)));
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ SSATmp* TraceBuilder::genDefNone() {
|
||||
}
|
||||
|
||||
SSATmp* TraceBuilder::genConvToBool(SSATmp* src) {
|
||||
Type fromType = src->getType();
|
||||
Type fromType = src->type();
|
||||
if (fromType.isBool()) {
|
||||
return src;
|
||||
} else if (fromType.isNull()) {
|
||||
@@ -424,7 +424,7 @@ SSATmp* TraceBuilder::genJmp(Trace* targetTrace) {
|
||||
|
||||
SSATmp* TraceBuilder::genJmpCond(SSATmp* boolSrc, Trace* target, bool negate) {
|
||||
assert(target);
|
||||
assert(boolSrc->getType() == Type::Bool);
|
||||
assert(boolSrc->type() == Type::Bool);
|
||||
return gen(negate ? JmpZero : JmpNZero, getFirstBlock(target), boolSrc);
|
||||
}
|
||||
|
||||
@@ -530,7 +530,7 @@ SSATmp* TraceBuilder::genLdClsMethodCache(SSATmp* className,
|
||||
|
||||
SSATmp* TraceBuilder::genBoxLoc(uint32_t id) {
|
||||
SSATmp* prevValue = genLdLoc(id);
|
||||
Type prevType = prevValue->getType();
|
||||
Type prevType = prevValue->type();
|
||||
// Don't box if local's value already boxed
|
||||
if (prevType.isBoxed()) {
|
||||
return prevValue;
|
||||
@@ -583,7 +583,7 @@ SSATmp* TraceBuilder::genLdLoc(uint32_t id) {
|
||||
|
||||
SSATmp* TraceBuilder::genLdLocAsCell(uint32_t id, Trace* exitTrace) {
|
||||
SSATmp* tmp = genLdLoc(id);
|
||||
Type type = tmp->getType();
|
||||
Type type = tmp->type();
|
||||
assert(type.isBoxed() || type.notBoxed());
|
||||
if (!type.isBoxed()) {
|
||||
return tmp;
|
||||
@@ -658,7 +658,7 @@ void TraceBuilder::genBindLoc(uint32_t id,
|
||||
}
|
||||
} else {
|
||||
prevValue = getLocalValue(id);
|
||||
assert(prevValue == nullptr || prevValue->getType() == trackedType);
|
||||
assert(prevValue == nullptr || prevValue->type() == trackedType);
|
||||
if (prevValue == newValue) {
|
||||
// Silent store: local already contains value being stored
|
||||
// NewValue needs to be decref'ed
|
||||
@@ -672,8 +672,8 @@ void TraceBuilder::genBindLoc(uint32_t id,
|
||||
}
|
||||
}
|
||||
bool genStoreType = true;
|
||||
if ((trackedType.isBoxed() && newValue->getType().isBoxed()) ||
|
||||
(trackedType == newValue->getType() && !trackedType.isString())) {
|
||||
if ((trackedType.isBoxed() && newValue->type().isBoxed()) ||
|
||||
(trackedType == newValue->type() && !trackedType.isString())) {
|
||||
// no need to store type with local value
|
||||
genStoreType = false;
|
||||
}
|
||||
@@ -691,7 +691,7 @@ SSATmp* TraceBuilder::genStLoc(uint32_t id,
|
||||
bool doRefCount,
|
||||
bool genStoreType,
|
||||
Trace* exit) {
|
||||
assert(!newValue->getType().isBoxed());
|
||||
assert(!newValue->type().isBoxed());
|
||||
/*
|
||||
* If prior value of local is a cell, then re-use genBindLoc.
|
||||
* Otherwise, if prior value of local is a ref:
|
||||
@@ -711,7 +711,7 @@ SSATmp* TraceBuilder::genStLoc(uint32_t id,
|
||||
}
|
||||
assert(trackedType.isBoxed());
|
||||
SSATmp* prevRef = getLocalValue(id);
|
||||
assert(prevRef == nullptr || prevRef->getType() == trackedType);
|
||||
assert(prevRef == nullptr || prevRef->type() == trackedType);
|
||||
// prevRef is a ref
|
||||
if (prevRef == nullptr) {
|
||||
// prevRef = ldLoc
|
||||
@@ -775,14 +775,14 @@ static SSATmp* getStackValue(SSATmp* sp,
|
||||
uint32_t index,
|
||||
bool& spansCall,
|
||||
Type& type) {
|
||||
IRInstruction* inst = sp->getInstruction();
|
||||
switch (inst->getOpcode()) {
|
||||
IRInstruction* inst = sp->inst();
|
||||
switch (inst->op()) {
|
||||
case DefSP:
|
||||
return nullptr;
|
||||
|
||||
case ReDefGeneratorSP: {
|
||||
auto srcInst = inst->getSrc(0)->getInstruction();
|
||||
assert(srcInst->getOpcode() == StashGeneratorSP);
|
||||
auto srcInst = inst->getSrc(0)->inst();
|
||||
assert(srcInst->op() == StashGeneratorSP);
|
||||
return getStackValue(srcInst->getSrc(0), index, spansCall, type);
|
||||
}
|
||||
case ReDefSP:
|
||||
@@ -830,10 +830,10 @@ static SSATmp* getStackValue(SSATmp* sp,
|
||||
for (int i = 0; i < numSpillSrcs; ++i) {
|
||||
SSATmp* tmp = inst->getSrc(i + 2);
|
||||
if (index == numPushed) {
|
||||
if (tmp->getInstruction()->getOpcode() == IncRef) {
|
||||
tmp = tmp->getInstruction()->getSrc(0);
|
||||
if (tmp->inst()->op() == IncRef) {
|
||||
tmp = tmp->inst()->getSrc(0);
|
||||
}
|
||||
type = tmp->getType();
|
||||
type = tmp->type();
|
||||
if (!type.equals(Type::None)) {
|
||||
return tmp;
|
||||
}
|
||||
@@ -879,7 +879,7 @@ static SSATmp* getStackValue(SSATmp* sp,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return getStackValue(sp->getInstruction()->getSrc(2),
|
||||
return getStackValue(sp->inst()->getSrc(2),
|
||||
// NewObj pushes an object and an ActRec
|
||||
index - (1 + kNumActRecCells),
|
||||
spansCall,
|
||||
@@ -891,14 +891,14 @@ static SSATmp* getStackValue(SSATmp* sp,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return getStackValue(sp->getInstruction()->getSrc(1),
|
||||
return getStackValue(sp->inst()->getSrc(1),
|
||||
index - 1,
|
||||
spansCall,
|
||||
type);
|
||||
|
||||
default: {
|
||||
SSATmp* value;
|
||||
if (VectorEffects::getStackValue(sp->getInstruction(), index,
|
||||
if (VectorEffects::getStackValue(sp->inst(), index,
|
||||
value, type)) {
|
||||
return value;
|
||||
} else {
|
||||
@@ -937,7 +937,7 @@ SSATmp* TraceBuilder::genCastStk(uint32_t id, Type type) {
|
||||
if (knownType.subtypeOf(Type::None) || !knownType.subtypeOf(type)) {
|
||||
SSATmp* off = genDefConst<int>(id);
|
||||
gen(CastStk, m_spValue, off);
|
||||
IRInstruction* inst = m_spValue->getInstruction();
|
||||
IRInstruction* inst = m_spValue->inst();
|
||||
inst->setTypeParam(type);
|
||||
}
|
||||
return m_spValue;
|
||||
@@ -948,7 +948,7 @@ SSATmp* TraceBuilder::genLdStackAddr(SSATmp* sp, int64_t index) {
|
||||
bool spansCall;
|
||||
UNUSED SSATmp* val = getStackValue(sp, index, spansCall, type);
|
||||
type = noneToGen(type);
|
||||
assert(IMPLIES(val != nullptr, val->getType().equals(type)));
|
||||
assert(IMPLIES(val != nullptr, val->type().equals(type)));
|
||||
assert(type.notPtr());
|
||||
return gen(LdStackAddr, type.ptr(), sp, genDefConst(index));
|
||||
}
|
||||
@@ -1009,7 +1009,7 @@ void TraceBuilder::genDecRefStack(Type type, uint32_t stackOff) {
|
||||
bool spansCall = false;
|
||||
Type knownType = Type::None;
|
||||
SSATmp* tmp = getStackValue(m_spValue, stackOff, spansCall, knownType);
|
||||
if (!tmp || (spansCall && tmp->getInstruction()->getOpcode() != DefConst)) {
|
||||
if (!tmp || (spansCall && tmp->inst()->op() != DefConst)) {
|
||||
// We don't want to extend live ranges of tmps across calls, so we
|
||||
// don't get the value if spansCall is true; however, we can use
|
||||
// any type information known.
|
||||
@@ -1025,9 +1025,9 @@ void TraceBuilder::genDecRefStack(Type type, uint32_t stackOff) {
|
||||
void TraceBuilder::genDecRefThis() {
|
||||
if (isThisAvailable()) {
|
||||
auto const thiss = genLdThis(nullptr);
|
||||
auto const thisInst = thiss->getInstruction();
|
||||
auto const thisInst = thiss->inst();
|
||||
|
||||
if (thisInst->getOpcode() == IncRef &&
|
||||
if (thisInst->op() == IncRef &&
|
||||
callerLocalHasValue(thisInst->getSrc(0))) {
|
||||
gen(DecRefNZ, thiss);
|
||||
return;
|
||||
@@ -1077,7 +1077,7 @@ SSATmp* TraceBuilder::genLdStack(int32_t stackOff, Type type) {
|
||||
bool spansCall = false;
|
||||
Type knownType = Type::None;
|
||||
SSATmp* tmp = getStackValue(m_spValue, stackOff, spansCall, knownType);
|
||||
if (!tmp || (spansCall && tmp->getInstruction()->getOpcode() != DefConst)) {
|
||||
if (!tmp || (spansCall && tmp->inst()->op() != DefConst)) {
|
||||
// We don't want to extend live ranges of tmps across calls, so we
|
||||
// don't get the value if spansCall is true; however, we can use
|
||||
// any type information known.
|
||||
@@ -1170,7 +1170,7 @@ SSATmp* TraceBuilder::genIterFree(uint32_t iterId) {
|
||||
}
|
||||
|
||||
void TraceBuilder::updateTrackedState(IRInstruction* inst) {
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
// Update tracked state of local values/types, stack/frame pointer, CSE, etc.
|
||||
|
||||
// kill tracked memory values
|
||||
@@ -1524,7 +1524,7 @@ void TraceBuilder::clearTrackedState() {
|
||||
}
|
||||
|
||||
void TraceBuilder::appendInstruction(IRInstruction* inst, Block* block) {
|
||||
Opcode opc = inst->getOpcode();
|
||||
Opcode opc = inst->op();
|
||||
if (opc != Nop && opc != DefConst) {
|
||||
block->push_back(inst);
|
||||
}
|
||||
@@ -1557,7 +1557,7 @@ void TraceBuilder::appendBlock(Block* block) {
|
||||
}
|
||||
|
||||
CSEHash* TraceBuilder::getCSEHashTable(IRInstruction* inst) {
|
||||
return inst->getOpcode() == DefConst ? &m_irFactory.getConstTable() :
|
||||
return inst->op() == DefConst ? &m_irFactory.getConstTable() :
|
||||
&m_cseHash;
|
||||
}
|
||||
|
||||
@@ -1566,8 +1566,8 @@ void TraceBuilder::cseInsert(IRInstruction* inst) {
|
||||
}
|
||||
|
||||
void TraceBuilder::cseKill(SSATmp* src) {
|
||||
if (src->getInstruction()->canCSE()) {
|
||||
getCSEHashTable(src->getInstruction())->erase(src);
|
||||
if (src->inst()->canCSE()) {
|
||||
getCSEHashTable(src->inst())->erase(src);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1592,7 +1592,7 @@ SSATmp* TraceBuilder::optimizeWork(IRInstruction* inst) {
|
||||
if (result) {
|
||||
// Found a dominating instruction that can be used instead of inst
|
||||
FTRACE(1, " {}cse found: {}\n",
|
||||
indent(), result->getInstruction()->toString());
|
||||
indent(), result->inst()->toString());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1602,7 +1602,7 @@ SSATmp* TraceBuilder::optimizeWork(IRInstruction* inst) {
|
||||
if (result) {
|
||||
// Found a simpler instruction that can be used instead of inst
|
||||
FTRACE(1, " {}simplification returned: {}\n",
|
||||
indent(), result->getInstruction()->toString());
|
||||
indent(), result->inst()->toString());
|
||||
assert(inst->hasDst());
|
||||
return result;
|
||||
}
|
||||
@@ -1615,7 +1615,7 @@ SSATmp* TraceBuilder::optimizeInst(IRInstruction* inst) {
|
||||
return tmp;
|
||||
}
|
||||
// Couldn't CSE or simplify the instruction; clone it and append.
|
||||
if (inst->getOpcode() != Nop) {
|
||||
if (inst->op() != Nop) {
|
||||
inst = inst->clone(&m_irFactory);
|
||||
appendInstruction(inst);
|
||||
// returns nullptr if instruction has no dest, returns the first
|
||||
@@ -1628,7 +1628,7 @@ SSATmp* TraceBuilder::optimizeInst(IRInstruction* inst) {
|
||||
void CSEHash::filter(Block* block, IdomVector& idoms) {
|
||||
for (auto it = map.begin(), end = map.end(); it != end;) {
|
||||
auto next = it; ++next;
|
||||
if (!dominates(it->second->getInstruction()->getBlock(), block, idoms)) {
|
||||
if (!dominates(it->second->inst()->getBlock(), block, idoms)) {
|
||||
map.erase(it);
|
||||
}
|
||||
it = next;
|
||||
@@ -1694,7 +1694,7 @@ void TraceBuilder::optimizeTrace() {
|
||||
continue;
|
||||
}
|
||||
SSATmp* dst = inst->getDst();
|
||||
if (dst->getType() != Type::None && dst != tmp) {
|
||||
if (dst->type() != Type::None && dst != tmp) {
|
||||
// The result of optimization has a different destination than the inst.
|
||||
// Generate a mov(tmp->dst) to get result into dst. If we get here then
|
||||
// assume the last instruction in the block isn't a guard. If it was,
|
||||
@@ -1736,7 +1736,7 @@ Type TraceBuilder::getLocalType(unsigned id) const {
|
||||
void TraceBuilder::setLocalValue(unsigned id, SSATmp* value) {
|
||||
assert(id < m_localValues.size() && id < m_localTypes.size());
|
||||
m_localValues[id] = value;
|
||||
m_localTypes[id] = value ? value->getType() : Type::None;
|
||||
m_localTypes[id] = value ? value->type() : Type::None;
|
||||
}
|
||||
|
||||
void TraceBuilder::setLocalType(uint32_t id, Type type) {
|
||||
@@ -1771,10 +1771,10 @@ bool TraceBuilder::callerLocalHasValue(SSATmp* tmp) const {
|
||||
// This should only be called for ref/boxed types.
|
||||
//
|
||||
void TraceBuilder::updateLocalRefValues(SSATmp* oldRef, SSATmp* newRef) {
|
||||
assert(oldRef->getType().isBoxed());
|
||||
assert(newRef->getType().isBoxed());
|
||||
assert(oldRef->type().isBoxed());
|
||||
assert(newRef->type().isBoxed());
|
||||
|
||||
Type newRefType = newRef->getType();
|
||||
Type newRefType = newRef->type();
|
||||
size_t nTrackedLocs = m_localValues.size();
|
||||
for (size_t id = 0; id < nTrackedLocs; id++) {
|
||||
if (m_localValues[id] == oldRef) {
|
||||
@@ -1805,12 +1805,12 @@ void TraceBuilder::killLocals() {
|
||||
for (uint32_t i = 0; i < m_localValues.size(); i++) {
|
||||
SSATmp* t = m_localValues[i];
|
||||
// should not kill DefConst, and LdConst should be replaced by DefConst
|
||||
if (!t || t->getInstruction()->getOpcode() == DefConst) {
|
||||
if (!t || t->inst()->op() == DefConst) {
|
||||
continue;
|
||||
}
|
||||
if (t->getInstruction()->getOpcode() == LdConst) {
|
||||
if (t->inst()->op() == LdConst) {
|
||||
// make the new DefConst instruction
|
||||
IRInstruction* clone = t->getInstruction()->clone(&m_irFactory);
|
||||
IRInstruction* clone = t->inst()->clone(&m_irFactory);
|
||||
clone->setOpcode(DefConst);
|
||||
m_localValues[i] = clone->getDst();
|
||||
continue;
|
||||
|
||||
@@ -340,7 +340,7 @@ public:
|
||||
genJmp(done_block, v2);
|
||||
appendBlock(done_block);
|
||||
SSATmp* result = done_block->getLabel()->getDst(0);
|
||||
result->setType(Type::unionOf(v1->getType(), v2->getType()));
|
||||
result->setType(Type::unionOf(v1->type(), v2->type()));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ Type vectorReturn(const IRInstruction* inst) {
|
||||
}
|
||||
|
||||
Type builtinReturn(const IRInstruction* inst) {
|
||||
assert(inst->getOpcode() == CallBuiltin);
|
||||
assert(inst->op() == CallBuiltin);
|
||||
|
||||
Type t = inst->getTypeParam();
|
||||
if (t.isSimpleType() || t.equals(Type::Cell)) {
|
||||
@@ -47,7 +47,7 @@ Type builtinReturn(const IRInstruction* inst) {
|
||||
}
|
||||
|
||||
Type boxReturn(const IRInstruction* inst, int srcId) {
|
||||
auto t = inst->getSrc(srcId)->getType();
|
||||
auto t = inst->getSrc(srcId)->type();
|
||||
// If t contains Uninit, replace it with InitNull.
|
||||
t = t.maybe(Type::Uninit) ? (t - Type::Uninit) | Type::InitNull : t;
|
||||
// We don't try to track when a BoxedStaticStr might be converted to
|
||||
@@ -80,8 +80,8 @@ Type stkReturn(const IRInstruction* inst, int dstId,
|
||||
Type outputType(const IRInstruction* inst, int dstId) {
|
||||
|
||||
#define D(type) return Type::type;
|
||||
#define DofS(n) return inst->getSrc(n)->getType();
|
||||
#define DUnbox(n) return inst->getSrc(n)->getType().unbox();
|
||||
#define DofS(n) return inst->getSrc(n)->type();
|
||||
#define DUnbox(n) return inst->getSrc(n)->type().unbox();
|
||||
#define DBox(n) return boxReturn(inst, n);
|
||||
#define DParam return inst->getTypeParam();
|
||||
#define DMulti return Type::None;
|
||||
@@ -93,7 +93,7 @@ Type outputType(const IRInstruction* inst, int dstId) {
|
||||
|
||||
#define O(name, dstinfo, srcinfo, flags) case name: dstinfo not_reached();
|
||||
|
||||
switch (inst->getOpcode()) {
|
||||
switch (inst->op()) {
|
||||
IR_OPCODES
|
||||
default: not_reached();
|
||||
}
|
||||
@@ -178,7 +178,7 @@ void assertOperandTypes(const IRInstruction* inst) {
|
||||
curSrc,
|
||||
inst->toString(),
|
||||
expected,
|
||||
inst->getSrc(curSrc)->getType().toString()
|
||||
inst->getSrc(curSrc)->type().toString()
|
||||
).str()
|
||||
);
|
||||
};
|
||||
@@ -219,7 +219,7 @@ void assertOperandTypes(const IRInstruction* inst) {
|
||||
for (; curSrc < inst->getNumSrcs(); ++curSrc) {
|
||||
// SpillStack slots may be stack types or None, if the
|
||||
// simplifier removed some.
|
||||
auto const valid = inst->getSrc(curSrc)->getType()
|
||||
auto const valid = inst->getSrc(curSrc)->type()
|
||||
.subtypeOfAny(Type::Gen, Type::Cls, Type::None);
|
||||
check(valid, "Gen|Cls|None");
|
||||
}
|
||||
@@ -257,13 +257,13 @@ void assertOperandTypes(const IRInstruction* inst) {
|
||||
#define DofS(src) checkDst(src < inst->getNumSrcs(), \
|
||||
"invalid src num");
|
||||
#define DParam checkDst(inst->getTypeParam() != Type::None || \
|
||||
inst->getOpcode() == DefConst /* for DefNone */, \
|
||||
inst->op() == DefConst /* for DefNone */, \
|
||||
"DParam with paramType None");
|
||||
|
||||
#define O(opcode, dstinfo, srcinfo, flags) \
|
||||
case opcode: dstinfo srcinfo countCheck(); return;
|
||||
|
||||
switch (inst->getOpcode()) {
|
||||
switch (inst->op()) {
|
||||
IR_OPCODES
|
||||
default: assert(0);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ inline unsigned buildBitmask(T c, Args... args) {
|
||||
// both, respectively.
|
||||
static KeyType getKeyType(const SSATmp* key, bool nonLitStr,
|
||||
bool nonLitInt) {
|
||||
auto keyType = key->getType();
|
||||
auto keyType = key->type();
|
||||
assert(keyType.notBoxed());
|
||||
assert(keyType.isKnownDataType() || keyType.equals(Type::Cell));
|
||||
|
||||
|
||||
@@ -46,10 +46,10 @@ void VectorEffects::get(const IRInstruction* inst,
|
||||
// If the base for this instruction is a local address, the
|
||||
// helper call might have side effects on the local's value
|
||||
SSATmp* base = inst->getSrc(vectorBaseIdx(inst));
|
||||
IRInstruction* locInstr = base->getInstruction();
|
||||
if (locInstr->getOpcode() == LdLocAddr) {
|
||||
UNUSED Type baseType = locInstr->getDst()->getType();
|
||||
assert(baseType.equals(base->getType()));
|
||||
IRInstruction* locInstr = base->inst();
|
||||
if (locInstr->op() == LdLocAddr) {
|
||||
UNUSED Type baseType = locInstr->getDst()->type();
|
||||
assert(baseType.equals(base->type()));
|
||||
assert(baseType.isPtr() || baseType.isKnownDataType());
|
||||
int loc = locInstr->getExtra<LdLocAddr>()->locId;
|
||||
|
||||
@@ -64,9 +64,9 @@ void VectorEffects::get(const IRInstruction* inst,
|
||||
bool VectorEffects::getStackValue(const IRInstruction* inst, uint32_t index,
|
||||
SSATmp*& value, Type& type) {
|
||||
SSATmp* base = inst->getSrc(vectorBaseIdx(inst));
|
||||
assert(base->getInstruction()->getOpcode() == LdStackAddr);
|
||||
if (base->getInstruction()->getSrc(1)->getValInt() != index) {
|
||||
value = base->getInstruction()->getSrc(0);
|
||||
assert(base->inst()->op() == LdStackAddr);
|
||||
if (base->inst()->getSrc(1)->getValInt() != index) {
|
||||
value = base->inst()->getSrc(0);
|
||||
assert(value->isA(Type::StkPtr));
|
||||
return false;
|
||||
}
|
||||
@@ -281,7 +281,7 @@ SSATmp* HhbcTranslator::VectorTranslator::genStk(Opcode opc, Srcs... srcs) {
|
||||
/* If the base is a pointer to a stack cell and the operation might change
|
||||
* its type and/or value, use the version of the opcode that returns a new
|
||||
* StkPtr. */
|
||||
if (base->getInstruction()->getOpcode() == LdStackAddr) {
|
||||
if (base->inst()->op() == LdStackAddr) {
|
||||
VectorEffects ve(opc, srcVec);
|
||||
if (ve.baseTypeChanged || ve.baseValChanged) {
|
||||
opc = getStackModifyingOpcode(opc);
|
||||
@@ -494,7 +494,7 @@ SSATmp* HhbcTranslator::VectorTranslator::getBase() {
|
||||
|
||||
SSATmp* HhbcTranslator::VectorTranslator::getKey() {
|
||||
SSATmp* key = getInput(m_iInd);
|
||||
auto keyType = key->getType();
|
||||
auto keyType = key->type();
|
||||
assert(keyType.isBoxed() || keyType.notBoxed());
|
||||
if (keyType.isBoxed()) {
|
||||
key = m_tb.gen(LdRef, Type::Cell, key);
|
||||
@@ -524,9 +524,9 @@ SSATmp* HhbcTranslator::VectorTranslator::getInput(unsigned i) {
|
||||
auto t = Type::fromRuntimeType(dl.rtt);
|
||||
if (!val->isA(t) && !(val->isBoxed() && t.isBoxed())) {
|
||||
FTRACE(1, "{}: hhir stack has a {} where Translator had a {}\n",
|
||||
__func__, val->getType().toString(), t.toString());
|
||||
__func__, val->type().toString(), t.toString());
|
||||
// They'd better not be completely unrelated types...
|
||||
assert(t.subtypeOf(val->getType()));
|
||||
assert(t.subtypeOf(val->type()));
|
||||
m_ht.refineType(val, t);
|
||||
}
|
||||
return val;
|
||||
@@ -600,7 +600,7 @@ void HhbcTranslator::VectorTranslator::emitBaseLCR() {
|
||||
assert(m_stackInputs.count(m_iInd));
|
||||
m_base = m_tb.genLdStackAddr(m_stackInputs[m_iInd]);
|
||||
}
|
||||
assert(m_base->getType().isPtr());
|
||||
assert(m_base->type().isPtr());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,7 +613,7 @@ bool HhbcTranslator::VectorTranslator::isSimpleArrayOp() {
|
||||
isSimpleBase() &&
|
||||
isSingleMember() &&
|
||||
mcodeMaybeArrayKey(m_ni.immVecM[0]) &&
|
||||
base->getType().subtypeOfAny(Type::Arr, Type::BoxedArr)) {
|
||||
base->type().subtypeOfAny(Type::Arr, Type::BoxedArr)) {
|
||||
SSATmp* key = getInput(m_mii.valCount() + 1);
|
||||
return key->isA(Type::Int) || key->isA(Type::Str);
|
||||
}
|
||||
@@ -787,7 +787,7 @@ void HhbcTranslator::VectorTranslator::emitPropGeneric() {
|
||||
MemberCode mCode = m_ni.immVecM[m_mInd];
|
||||
MInstrAttr mia = MInstrAttr(m_mii.getAttr(mCode) & MIA_intermediate_prop);
|
||||
|
||||
if ((mia & Unset) && m_base->getType().strip().not(Type::Obj)) {
|
||||
if ((mia & Unset) && m_base->type().strip().not(Type::Obj)) {
|
||||
m_base = m_tb.genPtrToInitNull();
|
||||
return;
|
||||
}
|
||||
@@ -821,7 +821,7 @@ SSATmp* HhbcTranslator::VectorTranslator::checkInitProp(
|
||||
SSATmp* key = getKey();
|
||||
assert(key->isA(Type::StaticStr));
|
||||
assert(baseAsObj->isA(Type::Obj));
|
||||
assert(propAddr->getType().isPtr());
|
||||
assert(propAddr->type().isPtr());
|
||||
|
||||
auto const needsCheck =
|
||||
propInfo.hphpcType == KindOfInvalid &&
|
||||
@@ -939,7 +939,7 @@ void HhbcTranslator::VectorTranslator::emitPropSpecialized(const MInstrAttr mia,
|
||||
|
||||
// At this point m_base is either a pointer to init_null_variant or
|
||||
// a property in the object that we've verified isn't uninit.
|
||||
assert(m_base->getType().isPtr());
|
||||
assert(m_base->type().isPtr());
|
||||
}
|
||||
|
||||
template <KeyType keyType, bool warn, bool define, bool reffy,
|
||||
@@ -1000,7 +1000,7 @@ void HhbcTranslator::VectorTranslator::emitElem() {
|
||||
assert(!(define && unset));
|
||||
if (unset) {
|
||||
SSATmp* uninit = m_tb.genPtrToUninit();
|
||||
Type baseType = m_base->getType().strip();
|
||||
Type baseType = m_base->type().strip();
|
||||
if (baseType.subtypeOf(Type::Str)) {
|
||||
m_ht.exceptionBarrier();
|
||||
m_tb.gen(
|
||||
@@ -1055,7 +1055,7 @@ void HhbcTranslator::VectorTranslator::emitRatchetRefs() {
|
||||
m_tb.genStMem(m_misBase, HHIR_MISOFF(tvRef), m_tb.genDefUninit(), true);
|
||||
|
||||
// Adjust base pointer.
|
||||
assert(m_base->getType().isPtr());
|
||||
assert(m_base->type().isPtr());
|
||||
return m_tb.genLdAddr(m_misBase, HHIR_MISOFF(tvRef2));
|
||||
},
|
||||
[&] { // Taken: tvRef is Uninit. Do nothing.
|
||||
@@ -1295,7 +1295,7 @@ void HhbcTranslator::VectorTranslator::emitSetProp() {
|
||||
m_ht.exceptionBarrier();
|
||||
SSATmp* result = genStk(SetProp, cns((TCA)opFunc), CTX(),
|
||||
m_base, key, value);
|
||||
VectorEffects ve(result->getInstruction());
|
||||
VectorEffects ve(result->inst());
|
||||
m_result = ve.valTypeChanged ? result : value;
|
||||
}
|
||||
#undef HELPER_TABLE
|
||||
@@ -1443,7 +1443,7 @@ HELPER_TABLE(PROP)
|
||||
void HhbcTranslator::VectorTranslator::emitUnsetProp() {
|
||||
SSATmp* key = getKey();
|
||||
|
||||
if (m_base->getType().strip().not(Type::Obj)) {
|
||||
if (m_base->type().strip().not(Type::Obj)) {
|
||||
// Noop
|
||||
return;
|
||||
}
|
||||
@@ -1764,8 +1764,8 @@ void HhbcTranslator::VectorTranslator::emitArraySet(SSATmp* key,
|
||||
SSATmp* value) {
|
||||
assert(m_iInd == m_mii.valCount() + 1);
|
||||
const int baseStkIdx = m_mii.valCount();
|
||||
assert(key->getType().notBoxed());
|
||||
assert(value->getType().notBoxed());
|
||||
assert(key->type().notBoxed());
|
||||
assert(value->type().notBoxed());
|
||||
KeyType keyType;
|
||||
bool checkForInt;
|
||||
checkStrictlyInteger(key, keyType, checkForInt);
|
||||
@@ -1792,7 +1792,7 @@ void HhbcTranslator::VectorTranslator::emitArraySet(SSATmp* key,
|
||||
if (base.location.space == Location::Local) {
|
||||
m_tb.genStLoc(base.location.offset, newArr, false, false, nullptr);
|
||||
} else if (base.location.space == Location::Stack) {
|
||||
VectorEffects ve(newArr->getInstruction());
|
||||
VectorEffects ve(newArr->inst());
|
||||
assert(ve.baseValChanged);
|
||||
assert(ve.baseType.subtypeOf(Type::Arr));
|
||||
m_ht.extendStack(baseStkIdx, Type::Gen);
|
||||
@@ -1844,7 +1844,7 @@ void HhbcTranslator::VectorTranslator::emitSetElem() {
|
||||
BUILD_OPTAB_HOT(getKeyTypeIS(key));
|
||||
m_ht.exceptionBarrier();
|
||||
SSATmp* result = genStk(SetElem, cns((TCA)opFunc), m_base, key, value);
|
||||
VectorEffects ve(result->getInstruction());
|
||||
VectorEffects ve(result->inst());
|
||||
m_result = ve.valTypeChanged ? result : value;
|
||||
}
|
||||
#undef HELPER_TABLE
|
||||
@@ -1968,7 +1968,7 @@ HELPER_TABLE(ELEM)
|
||||
void HhbcTranslator::VectorTranslator::emitUnsetElem() {
|
||||
SSATmp* key = getKey();
|
||||
|
||||
Type baseType = m_base->getType().strip();
|
||||
Type baseType = m_base->type().strip();
|
||||
if (baseType.subtypeOf(Type::Str)) {
|
||||
m_ht.exceptionBarrier();
|
||||
m_tb.gen(RaiseError,
|
||||
@@ -1999,7 +1999,7 @@ void HhbcTranslator::VectorTranslator::emitSetNewElem() {
|
||||
SSATmp* value = getValue();
|
||||
m_ht.exceptionBarrier();
|
||||
SSATmp* result = m_tb.gen(SetNewElem, m_base, value);
|
||||
VectorEffects ve(result->getInstruction());
|
||||
VectorEffects ve(result->inst());
|
||||
m_result = ve.valTypeChanged ? result : value;
|
||||
}
|
||||
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário