void read_immvector_immediate(AsmState& as, std::vector<uchar>& ret, MemberCode mcode = InvalidMemberCode) { if (memberCodeImmIsLoc(mcode) || mcode == InvalidMemberCode) { if (as.in.getc() != '$') { as.error("*L member code in vector immediate must be followed by " "a local variable name"); } std::string name; if (!as.in.readword(name)) { as.error("couldn't read name for local variable in vector immediate"); } encodeIvaToVector(ret, as.getLocalId("$" + name)); } else if (memberCodeImmIsString(mcode)) { encodeToVector<int32>(ret, as.ue->mergeLitstr(read_litstr(as))); } else if (memberCodeImmIsInt(mcode)) { encodeToVector<int64>(ret, read_opcode_arg<int64>(as)); } else { as.error(std::string("don't understand immediate for member code ") + memberCodeString(mcode)); } }
std::string show(MemberKey mk) { std::string ret = memberCodeString(mk.mcode); switch (mk.mcode) { case MEL: case MEC: case MPL: case MPC: folly::toAppend(':', mk.iva, &ret); break; case MEI: folly::toAppend(':', mk.int64, &ret); break; case MET: case MPT: case MQT: folly::toAppend( ":\"", escapeStringForCPP(mk.litstr->data(), mk.litstr->size()), '"', &ret ); break; case MW: break; } return ret; }
void print_instr(Output& out, const FuncInfo& finfo, PC pc) { auto const startPc = pc; auto rel_label = [&] (Offset off) { auto const tgt = startPc - finfo.unit->at(0) + off; return jmp_label(finfo, tgt); }; auto print_minstr = [&] { auto const immVec = ImmVector::createFromStream(pc); pc += immVec.size() + sizeof(int32_t) + sizeof(int32_t); auto vec = immVec.vec(); auto const lcode = static_cast<LocationCode>(*vec++); out.fmt(" <{}", locationCodeString(lcode)); if (numLocationCodeImms(lcode)) { always_assert(numLocationCodeImms(lcode) == 1); out.fmt(":${}", loc_name(finfo, decodeVariableSizeImm(&vec))); } while (vec < pc) { auto const mcode = static_cast<MemberCode>(*vec++); out.fmt(" {}", memberCodeString(mcode)); auto const imm = [&] { return decodeMemberCodeImm(&vec, mcode); }; switch (memberCodeImmType(mcode)) { case MCodeImm::None: break; case MCodeImm::Local: out.fmt(":${}", loc_name(finfo, imm())); break; case MCodeImm::String: out.fmt(":{}", escaped(finfo.unit->lookupLitstrId(imm()))); break; case MCodeImm::Int: out.fmt(":{}", imm()); break; } } assert(vec == pc); out.fmt(">"); }; auto print_switch = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = int32_t{0}; i < vecLen; ++i) { auto const off = decode<Offset>(pc); FTRACE(1, "sw label: {}\n", off); out.fmt("{}{}", i != 0 ? " " : "", rel_label(off)); } out.fmt(">"); }; auto print_sswitch = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = int32_t{0}; i < vecLen; ++i) { auto const strId = decode<Id>(pc); auto const offset = decode<Offset>(pc); out.fmt("{}{}:{}", i != 0 ? " " : "", strId == -1 ? "-" : escaped(finfo.unit->lookupLitstrId(strId)), rel_label(offset) ); } out.fmt(">"); }; auto print_itertab = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = int32_t{0}; i < vecLen; ++i) { auto const kind = static_cast<IterKind>(decode<int32_t>(pc)); auto const id = decode<int32_t>(pc); auto const kindStr = [&]() -> const char* { switch (kind) { case KindOfIter: return "(Iter)"; case KindOfMIter: return "(MIter)"; case KindOfCIter: return "(CIter)"; } not_reached(); }(); out.fmt("{}{} {}", i != 0 ? ", " : "", kindStr, id); } out.fmt(">"); }; auto print_stringvec = [&] { auto const vecLen = decode<int32_t>(pc); out.fmt(" <"); for (auto i = uint32_t{0}; i < vecLen; ++i) { auto const str = finfo.unit->lookupLitstrId(decode<int32_t>(pc)); out.fmt("{}{}", i != 0 ? " " : "", escaped(str)); } out.fmt(">"); }; #define IMM_MA print_minstr(); #define IMM_BLA print_switch(); #define IMM_SLA print_sswitch(); #define IMM_ILA print_itertab(); #define IMM_IVA out.fmt(" {}", decodeVariableSizeImm(&pc)); #define IMM_I64A out.fmt(" {}", decode<int64_t>(pc)); #define IMM_LA out.fmt(" ${}", loc_name(finfo, decodeVariableSizeImm(&pc))); #define IMM_IA out.fmt(" {}", decodeVariableSizeImm(&pc)); #define IMM_DA out.fmt(" {}", decode<double>(pc)); #define IMM_SA out.fmt(" {}", \ escaped(finfo.unit->lookupLitstrId(decode<Id>(pc)))); #define IMM_AA out.fmt(" @A_{}", decode<Id>(pc)); #define IMM_BA out.fmt(" {}", rel_label(decode<Offset>(pc))); #define IMM_OA(ty) out.fmt(" {}", \ subopToName(static_cast<ty>(decode<uint8_t>(pc)))); #define IMM_VSA print_stringvec(); #define IMM_NA #define IMM_ONE(x) IMM_##x #define IMM_TWO(x,y) IMM_ONE(x) IMM_ONE(y) #define IMM_THREE(x,y,z) IMM_TWO(x,y) IMM_ONE(z) #define IMM_FOUR(x,y,z,l) IMM_THREE(x,y,z) IMM_ONE(l) out.indent(); #define O(opcode, imms, ...) \ case Op::opcode: \ ++pc; \ out.fmt("{}", #opcode); \ IMM_##imms \ break; switch (*reinterpret_cast<const Op*>(pc)) { OPCODES } #undef O assert(pc == startPc + instrLen(reinterpret_cast<const Op*>(startPc))); #undef IMM_NA #undef IMM_ONE #undef IMM_TWO #undef IMM_THREE #undef IMM_FOUR #undef IMM_MA #undef IMM_BLA #undef IMM_SLA #undef IMM_ILA #undef IMM_IVA #undef IMM_I64A #undef IMM_LA #undef IMM_IA #undef IMM_DA #undef IMM_SA #undef IMM_AA #undef IMM_BA #undef IMM_OA #undef IMM_VSA out.nl(); }