Example #1
0
ArgUnion getImm(const PC origPC, int idx, const Unit* unit) {
  auto pc = origPC;
  auto const op = decode_op(pc);
  assertx(idx >= 0 && idx < numImmediates(op));
  ArgUnion retval;
  retval.u_NA = 0;
  int cursor = 0;
  for (cursor = 0; cursor < idx; cursor++) {
    // Advance over this immediate.
    pc += immSize(immType(op, cursor), pc);
  }
  always_assert(cursor == idx);
  auto const type = immType(op, idx);
  if (type == IVA || type == LA || type == IA ||
      type == CAR || type == CAW) {
    retval.u_IVA = decode_iva(pc);
  } else if (type == KA) {
    assertx(unit != nullptr);
    retval.u_KA = decode_member_key(pc, unit);
  } else if (type == LAR) {
    retval.u_LAR = decodeLocalRange(pc);
  } else if (type == FCA) {
    retval.u_FCA = decodeFCallArgs(pc);
  } else if (type == RATA) {
    assertx(unit != nullptr);
    retval.u_RATA = decodeRAT(unit, pc);
  } else if (!argTypeIsVector(type)) {
    memcpy(&retval.bytes, pc, immSize(type, pc));
  }
  always_assert(numImmediates(op) > idx);
  return retval;
}
Example #2
0
File: hhbc.cpp Project: 5heri/hhvm
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();
}
Example #3
0
File: hhbc.cpp Project: lpathy/hhvm
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();
}
Example #4
0
void emitAwait(IRGS& env, int32_t numIters) {
  auto const resumeOffset = nextBcOff(env);
  assertx(curFunc(env)->isAsync());

  if (curFunc(env)->isAsyncGenerator()) PUNT(Await-AsyncGenerator);

  auto const exitSlow   = makeExitSlow(env);

  if (!topC(env)->isA(TObj)) PUNT(Await-NonObject);

  auto const child = popC(env);
  gen(env, JmpZero, exitSlow, gen(env, IsWaitHandle, child));

  // cns() would ODR-use these
  auto const kSucceeded = c_WaitHandle::STATE_SUCCEEDED;
  auto const kFailed    = c_WaitHandle::STATE_FAILED;

  auto const state = gen(env, LdWHState, child);

  /*
   * HHBBC may have proven something about the inner type of this wait handle.
   *
   * So, we may have an assertion on the type of the top of the stack after
   * this instruction.  We know the next bytecode instruction is reachable from
   * fallthrough on the Await, so if it is an AssertRATStk 0, anything coming
   * out of the wait handle must be a subtype of that type, so this is a safe
   * and conservative way to do this optimization (even if our successor
   * bytecode offset is a jump target from things we aren't thinking about
   * here).
   */
  auto const knownTy = [&] {
    auto pc = curUnit(env)->at(resumeOffset);
    if (*reinterpret_cast<const Op*>(pc) != Op::AssertRATStk) return TInitCell;
    ++pc;
    auto const stkLoc = decodeVariableSizeImm(&pc);
    if (stkLoc != 0) return TInitCell;
    auto const rat = decodeRAT(curUnit(env), pc);
    auto const ty = ratToAssertType(env, rat);
    return ty ? *ty : TInitCell;
  }();

  ifThenElse(
    env,
    [&] (Block* taken) {
      auto const succeeded = gen(env, EqInt, state, cns(env, kSucceeded));
      gen(env, JmpNZero, taken, succeeded);
    },
    [&] { // Next: the wait handle is not finished, we need to suspend
      auto const failed = gen(env, EqInt, state, cns(env, kFailed));
      gen(env, JmpNZero, exitSlow, failed);
      if (resumed(env)) {
        implAwaitR(env, child, resumeOffset);
      } else {
        implAwaitE(env, child, resumeOffset, numIters);
      }
    },
    [&] { // Taken: retrieve the result from the wait handle
      auto const res = gen(env, LdWHResult, knownTy, child);
      gen(env, IncRef, res);
      gen(env, DecRef, child);
      push(env, res);
    }
  );
}
Example #5
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;
}