std::string instrToString(const Op* it, const Unit* u /* = NULL */) { std::stringstream out; PC iStart = reinterpret_cast<PC>(it); Op op = *it; ++it; auto readRATA = [&] { if (!u) { auto const pc = reinterpret_cast<const unsigned char*>(it); it += encodedRATSize(pc); out << " <RepoAuthType>"; return; } auto pc = reinterpret_cast<const unsigned char*>(it); auto const rat = decodeRAT(u, pc); it = reinterpret_cast<const Op*>(pc); out << ' ' << show(rat); }; switch (op) { #define READ(t) out << " " << *((t*)&*it); it += sizeof(t) #define READOFF() do { \ Offset _value = *(Offset*)it; \ out << " " << _value; \ if (u != nullptr) { \ out << " (" << u->offsetOf(iStart + _value) << ")"; \ } \ it += sizeof(Offset); \ } while (false) #define READV() out << " " << decodeVariableSizeImm((const uint8_t**)&it); #define READIVA() do { \ out << " "; \ auto imm = decodeVariableSizeImm((const uint8_t**)&it); \ if (op == OpIncStat && immIdx == 0) { \ out << Stats::g_counterNames[imm]; \ } else { \ out << imm; \ } \ immIdx++; \ } while (false) #define READOA(type) do { \ auto const immVal = static_cast<type>( \ *reinterpret_cast<const uint8_t*>(it) \ ); \ it += sizeof(unsigned char); \ out << " " << subopToName(immVal); \ } while (false) #define READVEC() do { \ int sz = *((int*)&*it); \ it += sizeof(int) * 2; \ const uint8_t* const start = (uint8_t*)it; \ out << " <"; \ if (sz > 0) { \ int immVal = (int)*((unsigned char*)&*it); \ out << ((immVal >= 0 && size_t(immVal) < locationNamesCount) ? \ locationCodeString(LocationCode(immVal)) : "?"); \ it += sizeof(unsigned char); \ int numLocImms = numLocationCodeImms(LocationCode(immVal)); \ for (int i = 0; i < numLocImms; ++i) { \ out << ':' << decodeVariableSizeImm((const uint8_t**)&it); \ } \ while (reinterpret_cast<const uint8_t*>(it) - start < sz) { \ immVal = (int)*((unsigned char*)&*it); \ out << " " << ((immVal >=0 && size_t(immVal) < memberNamesCount) ? \ memberCodeString(MemberCode(immVal)) : "?"); \ it += sizeof(unsigned char); \ if (memberCodeHasImm(MemberCode(immVal))) { \ int64_t imm = decodeMemberCodeImm((const uint8_t**)&it, \ MemberCode(immVal)); \ out << ':'; \ if (memberCodeImmIsString(MemberCode(immVal)) && u) { \ const StringData* str = u->lookupLitstrId(imm); \ int len = str->size(); \ String escaped = string_addslashes(str->data(), len); \ out << '"' << escaped.data() << '"'; \ } else { \ out << imm; \ } \ } \ } \ assert(reinterpret_cast<const uint8_t*>(it) - start == sz); \ } \ out << ">"; \ } while (false) #define READLITSTR(sep) do { \ Id id = readData<Id>(it); \ if (id < 0) { \ assert(op == OpSSwitch); \ out << sep << "-"; \ } else if (u) { \ const StringData* sd = u->lookupLitstrId(id); \ out << sep << "\"" << \ escapeStringForCPP(sd->data(), sd->size()) << "\""; \ } else { \ out << sep << id; \ } \ } while (false) #define READSVEC() do { \ int sz = readData<int>(it); \ out << " <"; \ const char* sep = ""; \ for (int i = 0; i < sz; ++i) { \ out << sep; \ if (op == OpSSwitch) { \ READLITSTR(""); \ out << ":"; \ } \ Offset o = readData<Offset>(it); \ if (u != nullptr) { \ if (iStart + o == u->entry() - 1) { \ out << "Invalid"; \ } else { \ out << u->offsetOf(iStart + o); \ } \ } else { \ out << o; \ } \ sep = " "; \ } \ out << ">"; \ } while (false) #define READIVEC() do { \ int sz = readData<int>(it); \ out << " <"; \ const char* sep = ""; \ for (int i = 0; i < sz; ++i) { \ out << sep; \ IterKind k = (IterKind)readData<Id>(it); \ switch(k) { \ case KindOfIter: out << "(Iter) "; break; \ case KindOfMIter: out << "(MIter) "; break; \ case KindOfCIter: out << "(CIter) "; break; \ } \ out << readData<Id>(it); \ sep = ", "; \ } \ out << ">"; \ } while (false) #define ONE(a) H_##a #define TWO(a, b) H_##a; H_##b #define THREE(a, b, c) H_##a; H_##b; H_##c; #define FOUR(a, b, c, d) H_##a; H_##b; H_##c; H_##d; #define NA #define H_MA READVEC() #define H_BLA READSVEC() #define H_SLA READSVEC() #define H_ILA READIVEC() #define H_IVA READIVA() #define H_I64A READ(int64_t) #define H_LA READV() #define H_IA READV() #define H_DA READ(double) #define H_BA READOFF() #define H_OA(type) READOA(type) #define H_SA READLITSTR(" ") #define H_RATA readRATA() #define H_AA \ if (u) { \ out << " "; \ staticArrayStreamer(u->lookupArrayId(*((Id*)it)), out); \ } else { \ out << " " << *((Id*)it); \ } \ it += sizeof(Id) #define H_VSA do { \ int sz = readData<int32_t>(it); \ out << " <"; \ for (int i = 0; i < sz; ++i) { \ H_SA; \ } \ out << " >"; \ } while (false) #define O(name, imm, push, pop, flags) \ case Op##name: { \ out << #name; \ UNUSED unsigned immIdx = 0; \ imm; \ break; \ } OPCODES #undef O #undef READ #undef ONE #undef TWO #undef THREE #undef FOUR #undef NA #undef H_MA #undef H_BLA #undef H_SLA #undef H_ILA #undef H_IVA #undef H_I64A #undef H_LA #undef H_IA #undef H_DA #undef H_BA #undef H_OA #undef H_SA #undef H_AA #undef H_VSA default: assert(false); }; return out.str(); }
int immSize(const Op* opcode, int idx) { assert(idx >= 0 && idx < numImmediates(*opcode)); always_assert(idx < 4); // No opcodes have more than four immediates static const int8_t argTypeToSizes[] = { #define ARGTYPE(nm, type) sizeof(type), #define ARGTYPEVEC(nm, type) 0, ARGTYPES #undef ARGTYPE #undef ARGTYPEVEC }; if (immType(*opcode, idx) == IVA || immType(*opcode, idx) == LA || immType(*opcode, idx) == IA) { intptr_t offset = 1; if (idx >= 1) offset += immSize(opcode, 0); if (idx >= 2) offset += immSize(opcode, 1); if (idx >= 3) offset += immSize(opcode, 2); unsigned char imm = *(const unsigned char*)(opcode + offset); // Low order bit set => 4-byte. return (imm & 0x1 ? sizeof(int32_t) : sizeof(unsigned char)); } if (immType(*opcode, idx) == RATA) { intptr_t offset = 1; if (idx >= 1) offset += immSize(opcode, 0); if (idx >= 2) offset += immSize(opcode, 1); if (idx >= 3) offset += immSize(opcode, 2); return encodedRATSize(reinterpret_cast<PC>(opcode) + offset); } if (immIsVector(*opcode, idx)) { intptr_t offset = 1; if (idx >= 1) offset += immSize(opcode, 0); if (idx >= 2) offset += immSize(opcode, 1); if (idx >= 3) offset += immSize(opcode, 2); int prefixes, vecElemSz; auto itype = immType(*opcode, idx); if (itype == MA) { prefixes = 2; vecElemSz = sizeof(uint8_t); } else if (itype == BLA) { prefixes = 1; vecElemSz = sizeof(Offset); } else if (itype == ILA) { prefixes = 1; vecElemSz = 2 * sizeof(uint32_t); } else if (itype == VSA) { prefixes = 1; vecElemSz = sizeof(Id); } else { assert(itype == SLA); prefixes = 1; vecElemSz = sizeof(StrVecItem); } return prefixes * sizeof(int32_t) + vecElemSz * *(int32_t*)((int8_t*)opcode + offset); } ArgType type = immType(*opcode, idx); return (type >= 0) ? argTypeToSizes[type] : 0; }
std::string instrToString(PC it, Either<const Unit*, const UnitEmitter*> u) { std::stringstream out; PC iStart = it; Op op = decode_op(it); auto readRATA = [&] { if (auto unit = u.left()) { auto const rat = decodeRAT(unit, it); out << ' ' << show(rat); return; } auto const pc = it; it += encodedRATSize(pc); out << " <RepoAuthType>"; }; auto offsetOf = [u](PC pc) { return u.match( [pc](const Unit* u) { return u->offsetOf(pc); }, [pc](const UnitEmitter* ue) { return ue->offsetOf(pc); } ); }; auto lookupLitstrId = [u](Id id) { return u.match( [id](const Unit* u) { return u->lookupLitstrId(id); }, [id](const UnitEmitter* ue) { return ue->lookupLitstr(id); } ); }; auto lookupArrayId = [u](Id id) { return u.match( [id](const Unit* u) { return u->lookupArrayId(id); }, [id](const UnitEmitter* ue) { return ue->lookupArray(id); } ); }; switch (op) { #define READ(t) out << " " << *((t*)&*it); it += sizeof(t) #define READOFF() do { \ Offset _value = *(Offset*)it; \ out << " " << _value; \ if (u != nullptr) { \ out << " (" << offsetOf(iStart + _value) << ")"; \ } \ it += sizeof(Offset); \ } while (false) #define READV() out << " " << decodeVariableSizeImm(&it); #define READLA() out << " L:" << decodeVariableSizeImm(&it); #define READIVA() do { \ out << " "; \ auto imm = decodeVariableSizeImm((const uint8_t**)&it); \ if (op == OpIncStat && immIdx == 0) { \ out << Stats::g_counterNames[imm]; \ } else { \ out << imm; \ } \ immIdx++; \ } while (false) #define READOA(type) do { \ auto const immVal = static_cast<type>( \ *reinterpret_cast<const uint8_t*>(it) \ ); \ it += sizeof(unsigned char); \ out << " " << subopToName(immVal); \ } while (false) #define READLITSTR(sep) do { \ Id id = decode_raw<Id>(it); \ if (id < 0) { \ assert(op == OpSSwitch); \ out << sep << "-"; \ } else { \ auto const sd = lookupLitstrId(id); \ out << sep << "\"" << \ escapeStringForCPP(sd->data(), sd->size()) << "\""; \ } \ } while (false) #define READSVEC() do { \ int sz = decode_raw<int>(it); \ out << " <"; \ const char* sep = ""; \ for (int i = 0; i < sz; ++i) { \ out << sep; \ if (op == OpSSwitch) { \ READLITSTR(""); \ out << ":"; \ } \ Offset o = decode_raw<Offset>(it); \ out << offsetOf(iStart + o); \ sep = " "; \ } \ out << ">"; \ } while (false) #define READIVEC() do { \ int sz = decode_raw<int>(it); \ out << " <"; \ const char* sep = ""; \ for (int i = 0; i < sz; ++i) { \ out << sep; \ IterKind k = (IterKind)decode_raw<Id>(it); \ switch(k) { \ case KindOfIter: out << "(Iter) "; break; \ case KindOfMIter: out << "(MIter) "; break; \ case KindOfCIter: out << "(CIter) "; break; \ } \ out << decode_raw<Id>(it); \ sep = ", "; \ } \ out << ">"; \ } while (false) #define ONE(a) H_##a #define TWO(a, b) H_##a; H_##b #define THREE(a, b, c) H_##a; H_##b; H_##c; #define FOUR(a, b, c, d) H_##a; H_##b; H_##c; H_##d; #define NA #define H_BLA READSVEC() #define H_SLA READSVEC() #define H_ILA READIVEC() #define H_IVA READIVA() #define H_I64A READ(int64_t) #define H_LA READLA() #define H_IA READV() #define H_DA READ(double) #define H_BA READOFF() #define H_OA(type) READOA(type) #define H_SA READLITSTR(" ") #define H_RATA readRATA() #define H_AA do { \ out << ' '; \ staticArrayStreamer(lookupArrayId(decode_raw<Id>(it)), out); \ } while (false) #define H_VSA do { \ int sz = decode_raw<int32_t>(it); \ out << " <"; \ for (int i = 0; i < sz; ++i) { \ H_SA; \ } \ out << " >"; \ } while (false) #define H_KA out << ' ' << show(decode_member_key(it, u)) #define O(name, imm, push, pop, flags) \ case Op##name: { \ out << #name; \ UNUSED unsigned immIdx = 0; \ imm; \ break; \ } OPCODES #undef O #undef READ #undef READV #undef READLA #undef ONE #undef TWO #undef THREE #undef FOUR #undef NA #undef H_BLA #undef H_SLA #undef H_ILA #undef H_IVA #undef H_I64A #undef H_LA #undef H_IA #undef H_DA #undef H_BA #undef H_OA #undef H_SA #undef H_AA #undef H_VSA #undef H_KA default: assert(false); }; return out.str(); }
int immSize(PC origPC, int idx) { auto pc = origPC; auto const op = decode_op(pc); assert(idx >= 0 && idx < numImmediates(op)); always_assert(idx < 4); // No origPCs have more than four immediates static const int8_t argTypeToSizes[] = { #define ARGTYPE(nm, type) sizeof(type), #define ARGTYPEVEC(nm, type) 0, ARGTYPES #undef ARGTYPE #undef ARGTYPEVEC }; if (immType(op, idx) == IVA || immType(op, idx) == LA || immType(op, idx) == IA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); return encoded_iva_size(decode_raw<uint8_t>(pc)); } if (immType(op, idx) == KA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); switch (decode_raw<MemberCode>(pc)) { case MW: return 1; case MEL: case MPL: case MEC: case MPC: return 1 + encoded_iva_size(decode_raw<uint8_t>(pc)); case MEI: return 1 + sizeof(int64_t); case MET: case MPT: case MQT: return 1 + sizeof(Id); } not_reached(); } if (immType(op, idx) == RATA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); return encodedRATSize(pc); } if (immIsVector(op, idx)) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); int vecElemSz; auto itype = immType(op, idx); if (itype == BLA) { vecElemSz = sizeof(Offset); } else if (itype == ILA) { vecElemSz = 2 * sizeof(uint32_t); } else if (itype == VSA) { vecElemSz = sizeof(Id); } else { assert(itype == SLA); vecElemSz = sizeof(StrVecItem); } return sizeof(int32_t) + vecElemSz * decode_raw<int32_t>(pc); } ArgType type = immType(op, idx); return (type >= 0) ? argTypeToSizes[type] : 0; }
int immSize(PC origPC, int idx) { auto pc = origPC; auto const op = decode_op(pc); assert(idx >= 0 && idx < numImmediates(op)); always_assert(idx < 4); // No origPCs have more than four immediates static const int8_t argTypeToSizes[] = { #define ARGTYPE(nm, type) sizeof(type), #define ARGTYPEVEC(nm, type) 0, ARGTYPES #undef ARGTYPE #undef ARGTYPEVEC }; if (immType(op, idx) == IVA || immType(op, idx) == LA || immType(op, idx) == IA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); auto const imm = decode_raw<uint8_t>(pc); // Low order bit set => 4-byte. return (imm & 0x1 ? sizeof(int32_t) : sizeof(unsigned char)); } if (immType(op, idx) == RATA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); return encodedRATSize(pc); } if (immIsVector(op, idx)) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); int prefixes, vecElemSz; auto itype = immType(op, idx); if (itype == MA) { prefixes = 2; vecElemSz = sizeof(uint8_t); } else if (itype == BLA) { prefixes = 1; vecElemSz = sizeof(Offset); } else if (itype == ILA) { prefixes = 1; vecElemSz = 2 * sizeof(uint32_t); } else if (itype == VSA) { prefixes = 1; vecElemSz = sizeof(Id); } else { assert(itype == SLA); prefixes = 1; vecElemSz = sizeof(StrVecItem); } return prefixes * sizeof(int32_t) + vecElemSz * decode_raw<int32_t>(pc); } ArgType type = immType(op, idx); return (type >= 0) ? argTypeToSizes[type] : 0; }
std::string instrToString(PC it, Either<const Unit*, const UnitEmitter*> u) { std::string out; PC iStart = it; Op op = decode_op(it); auto readRATA = [&] { if (auto unit = u.left()) { auto const rat = decodeRAT(unit, it); folly::format(&out, " {}", show(rat)); return; } auto const pc = it; it += encodedRATSize(pc); out += " <RepoAuthType>"; }; auto offsetOf = [u](PC pc) { return u.match( [pc](const Unit* u) { return u->offsetOf(pc); }, [pc](const UnitEmitter* ue) { return ue->offsetOf(pc); } ); }; auto lookupLitstrId = [u](Id id) { return u.match( [id](const Unit* u) { return u->lookupLitstrId(id); }, [id](const UnitEmitter* ue) { return ue->lookupLitstr(id); } ); }; auto lookupArrayId = [u](Id id) { return u.match( [id](const Unit* u) { return u->lookupArrayId(id); }, [id](const UnitEmitter* ue) { return ue->lookupArray(id); } ); }; switch (op) { #define READ(t) folly::format(&out, " {}", *((t*)&*it)); it += sizeof(t) #define READOFF() do { \ Offset _value = *(Offset*)it; \ folly::format(&out, " {}", _value); \ if (u != nullptr) { \ folly::format(&out, " ({})", offsetOf(iStart + _value)); \ } \ it += sizeof(Offset); \ } while (false) #define READV() folly::format(&out, " {}", decode_iva(it)); #define READLA() folly::format(&out, " L:{}", decode_iva(it)); #define READIVA() do { \ auto imm = decode_iva(it); \ folly::format(&out, " {}", imm); \ immIdx++; \ } while (false) #define READOA(type) do { \ auto const immVal = static_cast<type>( \ *reinterpret_cast<const uint8_t*>(it) \ ); \ it += sizeof(unsigned char); \ folly::format(&out, " {}", subopToName(immVal)); \ } while (false) #define READLITSTR(sep) do { \ Id id = decode_raw<Id>(it); \ if (id < 0) { \ assertx(op == OpSSwitch); \ folly::format(&out, "{}-", sep); \ } else { \ auto const sd = lookupLitstrId(id); \ folly::format(&out, "{}\"{}\"", sep, \ escapeStringForCPP(sd->data(), sd->size())); \ } \ } while (false) #define READSVEC() do { \ int sz = decode_iva(it); \ out += " <"; \ const char* sep = ""; \ for (int i = 0; i < sz; ++i) { \ out += sep; \ if (op == OpSSwitch) { \ READLITSTR(""); \ out += ":"; \ } \ Offset o = decode_raw<Offset>(it); \ folly::format(&out, "{}", offsetOf(iStart + o)); \ sep = " "; \ } \ out += ">"; \ } while (false) #define READI32VEC() do { \ int sz = decode_iva(it); \ out += " <"; \ const char* sep = ""; \ for (int i = 0; i < sz; ++i) { \ folly::format(&out, "{}{}", sep, decode_raw<uint32_t>(it));\ sep = ", "; \ } \ out += ">"; \ } while (false) #define READBOOLVEC() do { \ int sz = decode_iva(it); \ uint8_t tmp = 0; \ out += " \""; \ for (int i = 0; i < sz; ++i) { \ if (i % 8 == 0) tmp = decode_raw<uint8_t>(it); \ out += ((tmp >> (i % 8)) & 1) ? "1" : "0"; \ } \ out += "\""; \ } while (false) #define READITERTAB() do { \ auto const sz = decode_iva(it); \ out += " <"; \ const char* sep = ""; \ for (int i = 0; i < sz; ++i) { \ out += sep; \ auto const k = (IterKind)decode_iva(it); \ switch (k) { \ case KindOfIter: out += "(Iter) "; break; \ case KindOfMIter: out += "(MIter) "; break; \ case KindOfCIter: out += "(CIter) "; break; \ case KindOfLIter: out += "(LIter) "; break; \ } \ folly::format(&out, "{}", decode_iva(it)); \ if (k == KindOfLIter) { \ folly::format(&out, " L:{}", decode_iva(it)); \ } \ sep = ", "; \ } \ out += ">"; \ } while (false) #define ONE(a) H_##a #define TWO(a, b) H_##a; H_##b #define THREE(a, b, c) H_##a; H_##b; H_##c; #define FOUR(a, b, c, d) H_##a; H_##b; H_##c; H_##d; #define FIVE(a, b, c, d, e) H_##a; H_##b; H_##c; H_##d; H_##e; #define NA #define H_BLA READSVEC() #define H_SLA READSVEC() #define H_ILA READITERTAB() #define H_I32LA READI32VEC() #define H_BLLA READBOOLVEC() #define H_IVA READIVA() #define H_I64A READ(int64_t) #define H_LA READLA() #define H_IA READV() #define H_CAR READV() #define H_CAW READV() #define H_DA READ(double) #define H_BA READOFF() #define H_OA(type) READOA(type) #define H_SA READLITSTR(" ") #define H_RATA readRATA() #define H_AA do { \ out += ' '; \ staticArrayStreamer(lookupArrayId(decode_raw<Id>(it)), out); \ } while (false) #define H_VSA do { \ int sz = decode_iva(it); \ out += " <"; \ for (int i = 0; i < sz; ++i) { \ H_SA; \ } \ out += " >"; \ } while (false) #define H_KA (out += ' ', out += show(decode_member_key(it, u))) #define H_LAR (out += ' ', out += show(decodeLocalRange(it))) #define H_FCA (out += ' ', out += show(decodeFCallArgs(it))) #define O(name, imm, push, pop, flags) \ case Op##name: { \ out += #name; \ UNUSED unsigned immIdx = 0; \ imm; \ break; \ } OPCODES #undef O #undef READ #undef READV #undef READLA #undef ONE #undef TWO #undef THREE #undef FOUR #undef FIVE #undef NA #undef H_BLA #undef H_SLA #undef H_ILA #undef H_I32LA #undef H_BLLA #undef H_IVA #undef H_I64A #undef H_LA #undef H_IA #undef H_CAR #undef H_CAW #undef H_DA #undef H_BA #undef H_OA #undef H_SA #undef H_AA #undef H_VSA #undef H_KA #undef H_LAR #undef H_FCA default: assertx(false); }; return out; }