Beispiel #1
0
const uint8_t* ImmVector::findLastMember() const {
  assert(m_length > 0);

  // Loop that does basically the same as numStackValues(), except
  // stop at the last.
  const uint8_t* vec = m_start;
  const LocationCode locCode = LocationCode(*vec++);
  const int numLocImms = numLocationCodeImms(locCode);
  for (int i = 0; i < numLocImms; ++i) {
    decodeVariableSizeImm(&vec);
  }

  for (;;) {
    const uint8_t* ret = vec;
    MemberCode code = MemberCode(*vec++);
    if (memberCodeHasImm(code)) {
      decodeMemberCodeImm(&vec, code);
    }
    if (vec - m_start == m_length) {
      return ret;
    }
    assert(vec - m_start < m_length);
  }

  NOT_REACHED();
}
Beispiel #2
0
bool ImmVector::decodeLastMember(const Unit* u,
                                 StringData*& sdOut,
                                 MemberCode& membOut,
                                 int64_t* strIdOut /*=NULL*/) const {
  const uint8_t* vec = findLastMember();
  membOut = MemberCode(*vec++);
  if (memberCodeImmIsString(membOut)) {
    int64_t strId = decodeMemberCodeImm(&vec, membOut);
    if (strIdOut) *strIdOut = strId;
    sdOut = u->lookupLitstrId(strId);
    return true;
  }
  return false;
}
Beispiel #3
0
std::vector<MVectorItem> getMVector(const Op* opcode) {
  auto immVec = getImmVector(opcode);
  std::vector<MVectorItem> result;
  auto it = immVec.vec();
  auto end = it + immVec.size();

  // Skip the LocationCode and its immediate
  auto const lcode = LocationCode(*it++);
  if (numLocationCodeImms(lcode)) decodeVariableSizeImm(&it);

  while (it < end) {
    auto const mcode = MemberCode(*it++);
    auto const imm = memberCodeHasImm(mcode) ? decodeMemberCodeImm(&it, mcode)
                                             : 0;
    result.push_back({mcode, imm});
  }

  return result;
}
Beispiel #4
0
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();
}