static bool executeCommand()

in tools/hbcdump/hbcdump.cpp [291:449]


static bool executeCommand(
    llvh::raw_ostream &os,
    ProfileAnalyzer &analyzer,
    BytecodeDisassembler &disassembler,
    const std::string &commandWithOptions) {
  // Parse command tokens.
  llvh::SmallVector<llvh::StringRef, 8> commandTokens;
  llvh::StringRef(commandWithOptions).split(commandTokens, ' ');
  if (commandTokens.empty()) {
    // Ignore empty input.
    return false;
  }

  const llvh::StringRef command = commandTokens[0];
  if (command == "function" || command == "fun") {
    if (findAndRemoveOne(commandTokens, "-used")) {
      analyzer.dumpUsedFunctionIDs();
    } else if (commandTokens.size() == 1) {
      analyzer.dumpFunctionStats();
    } else if (commandTokens.size() == 2) {
      uint32_t funcId;
      if (commandTokens[1].getAsInteger(0, funcId)) {
        os << "Error: cannot parse func_id as integer.\n";
        return false;
      }
      analyzer.dumpFunctionBasicBlockStat(funcId);
    } else {
      printHelp(command);
      return false;
    }
  } else if (command == "instruction" || command == "inst") {
    if (commandTokens.size() == 1) {
      analyzer.dumpInstructionStats();
    } else {
      printHelp(command);
      return false;
    }
  } else if (command == "disassemble" || command == "dis") {
    auto localOptions = findAndRemoveOne(commandTokens, "-offsets")
        ? DisassemblyOptions::IncludeVirtualOffsets
        : DisassemblyOptions::None;
    DisassemblerOptionsHolder optionsHolder(
        disassembler, disassembler.getOptions() | localOptions);
    if (commandTokens.size() == 1) {
      disassembler.disassemble(os);
    } else if (commandTokens.size() == 2) {
      uint32_t funcId;
      if (commandTokens[1].getAsInteger(0, funcId)) {
        os << "Error: cannot parse func_id as integer.\n";
        return false;
      }
      if (funcId >= disassembler.getFunctionCount()) {
        os << "Error: no function with id: " << funcId << " exists.\n";
        return false;
      }
      disassembler.disassembleFunction(funcId, os);
    } else {
      printHelp(command);
      return false;
    }
  } else if (command == "string" || command == "str") {
    if (commandTokens.size() != 2) {
      printHelp(command);
      return false;
    }
    uint32_t stringId;
    if (commandTokens[1].getAsInteger(0, stringId)) {
      os << "Error: cannot parse string_id as integer.\n";
      return false;
    }
    analyzer.dumpString(stringId);
  } else if (command == "filename") {
    if (commandTokens.size() != 2) {
      printHelp(command);
      return false;
    }
    uint32_t filenameId;
    if (commandTokens[1].getAsInteger(0, filenameId)) {
      os << "Error: cannot parse filename_id as integer.\n";
      return false;
    }
    analyzer.dumpFileName(filenameId);
  } else if (command == "function-info") {
    JSONEmitter json(os, /* pretty */ true);
    if (commandTokens.size() == 1) {
      analyzer.dumpAllFunctionInfo(json);
    } else if (commandTokens.size() == 2) {
      uint32_t funcId;
      if (commandTokens[1].getAsInteger(0, funcId)) {
        os << "Error: cannot parse func_id as integer.\n";
        return false;
      }
      analyzer.dumpFunctionInfo(funcId, json);
    } else {
      printHelp(command);
      return false;
    }
  } else if (command == "io") {
    analyzer.dumpIO();
  } else if (command == "summary" || command == "sum") {
    analyzer.dumpSummary();
  } else if (command == "block") {
    analyzer.dumpBasicBlockStats();
  } else if (command == "at_virtual" || command == "at-virtual") {
    JSONEmitter json(os, /* pretty */ true);
    if (commandTokens.size() == 2) {
      uint32_t virtualOffset;
      if (commandTokens[1].getAsInteger(0, virtualOffset)) {
        os << "Error: cannot parse virtualOffset as integer.\n";
        return false;
      }
      auto funcId = analyzer.getFunctionFromVirtualOffset(virtualOffset);
      if (funcId.hasValue()) {
        analyzer.dumpFunctionInfo(*funcId, json);
      } else {
        os << "Virtual offset " << virtualOffset << " is invalid.\n";
      }
    } else {
      printHelp(command);
      return false;
    }
  } else if (command == "at_offset" || command == "at-offset") {
    JSONEmitter json(os, /* pretty */ true);
    if (commandTokens.size() == 2) {
      uint32_t offset;
      if (commandTokens[1].getAsInteger(0, offset)) {
        os << "Error: cannot parse offset as integer.\n";
        return false;
      }
      auto funcId = analyzer.getFunctionFromOffset(offset);
      if (funcId.hasValue()) {
        analyzer.dumpFunctionInfo(*funcId, json);
      } else {
        os << "Offset " << offset << " is invalid.\n";
      }
    } else {
      printHelp(command);
      return false;
    }
  } else if (command == "epilogue" || command == "epi") {
    analyzer.dumpEpilogue();
  } else if (command == "help" || command == "h") {
    // Interactive help command.
    if (commandTokens.size() == 2) {
      printHelp(commandTokens[1]);
    } else {
      printHelp();
    }
    return false;
  } else if (command == "quit") {
    // Quit command loop.
    return true;
  } else {
    printHelp(command);
    return false;
  }
  os << "\n";
  return false;
}