Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions llvm/tools/llvm-mc/Disassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "Disassembler.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
Expand All @@ -24,6 +25,7 @@
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"

Expand All @@ -32,24 +34,25 @@ using namespace llvm;
typedef std::pair<std::vector<unsigned char>, std::vector<const char *>>
ByteArrayTy;

static bool PrintInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes,
static bool printInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes,
SourceMgr &SM, MCStreamer &Streamer, bool InAtomicBlock,
const MCSubtargetInfo &STI) {
const MCSubtargetInfo &STI, unsigned BenchmarkNumRuns) {
ArrayRef<uint8_t> Data(Bytes.first);

// Disassemble it to strings.
uint64_t Size;
uint64_t Index;

for (Index = 0; Index < Bytes.first.size(); Index += Size) {
MCInst Inst;
for (uint64_t Index = 0; Index < Bytes.first.size(); Index += Size) {
auto getInstruction = [&](MCInst &Inst) -> MCDisassembler::DecodeStatus {
if (STI.getTargetTriple().getArch() == Triple::hexagon)
return DisAsm.getInstructionBundle(Inst, Size, Data.slice(Index), Index,
nulls());
return DisAsm.getInstruction(Inst, Size, Data.slice(Index), Index,
nulls());
};

MCDisassembler::DecodeStatus S;
if (STI.getTargetTriple().getArch() == Triple::hexagon)
S = DisAsm.getInstructionBundle(Inst, Size, Data.slice(Index), Index,
nulls());
else
S = DisAsm.getInstruction(Inst, Size, Data.slice(Index), Index, nulls());
MCInst Inst;
MCDisassembler::DecodeStatus S = getInstruction(Inst);
switch (S) {
case MCDisassembler::Fail:
SM.PrintMessage(SMLoc::getFromPointer(Bytes.second[Index]),
Expand All @@ -74,12 +77,24 @@ static bool PrintInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes,
Streamer.emitInstruction(Inst, STI);
break;
}

if (S == MCDisassembler::Success && BenchmarkNumRuns != 0) {
// Benchmark mode, collect timing for decoding the instruction several
// times.
MCInst BMInst;
TimeTraceScope timeScope("getInstruction");
for (unsigned _ : llvm::seq<unsigned>(BenchmarkNumRuns)) {
BMInst.clear();
BMInst.setOpcode(0);
S = getInstruction(BMInst);
}
}
}

return false;
}

static bool SkipToToken(StringRef &Str) {
static bool skipToToken(StringRef &Str) {
for (;;) {
if (Str.empty())
return false;
Expand All @@ -101,7 +116,7 @@ static bool SkipToToken(StringRef &Str) {

static bool byteArrayFromString(ByteArrayTy &ByteArray, StringRef &Str,
SourceMgr &SM, bool HexBytes) {
while (SkipToToken(Str)) {
while (skipToToken(Str)) {
// Handled by higher level
if (Str[0] == '[' || Str[0] == ']')
return false;
Expand Down Expand Up @@ -151,7 +166,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,
MCSubtargetInfo &STI, MCStreamer &Streamer,
MemoryBuffer &Buffer, SourceMgr &SM,
MCContext &Ctx, const MCTargetOptions &MCOptions,
bool HexBytes) {
bool HexBytes, unsigned BenchmarkNumRuns) {
std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple));
if (!MRI) {
errs() << "error: no register info for target " << Triple << "\n";
Expand Down Expand Up @@ -179,7 +194,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,
StringRef Str = Buffer.getBuffer();
bool InAtomicBlock = false;

while (SkipToToken(Str)) {
while (skipToToken(Str)) {
ByteArray.first.clear();
ByteArray.second.clear();

Expand Down Expand Up @@ -207,8 +222,8 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,
ErrorOccurred |= byteArrayFromString(ByteArray, Str, SM, HexBytes);

if (!ByteArray.first.empty())
ErrorOccurred |=
PrintInsts(*DisAsm, ByteArray, SM, Streamer, InAtomicBlock, STI);
ErrorOccurred |= printInsts(*DisAsm, ByteArray, SM, Streamer,
InAtomicBlock, STI, BenchmarkNumRuns);
}

if (InAtomicBlock) {
Expand Down
3 changes: 2 additions & 1 deletion llvm/tools/llvm-mc/Disassembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class Disassembler {
static int disassemble(const Target &T, const std::string &Triple,
MCSubtargetInfo &STI, MCStreamer &Streamer,
MemoryBuffer &Buffer, SourceMgr &SM, MCContext &Ctx,
const MCTargetOptions &MCOptions, bool HexBytes);
const MCTargetOptions &MCOptions, bool HexBytes,
unsigned BenchmarkNumRuns);
};

} // namespace llvm
Expand Down
46 changes: 42 additions & 4 deletions llvm/tools/llvm-mc/llvm-mc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "Disassembler.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/DWARFCFIChecker/DWARFCFIFunctionFrameAnalyzer.h"
#include "llvm/DWARFCFIChecker/DWARFCFIFunctionFrameStreamer.h"
#include "llvm/MC/MCAsmBackend.h"
Expand All @@ -37,6 +38,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
#include "llvm/TargetParser/Host.h"
Expand Down Expand Up @@ -240,6 +242,24 @@ static cl::opt<ActionType> Action(
"Colored disassembly of strings of hex bytes")),
cl::cat(MCCategory));

static cl::opt<unsigned>
BenchmarkNumRuns("benchmark-num-runs",
cl::desc("Number of runs for decoder benchmarking"),
cl::cat(MCCategory));

static cl::opt<bool> TimeTrace("time-trace", cl::desc("Record time trace"));

static cl::opt<unsigned> TimeTraceGranularity(
"time-trace-granularity",
cl::desc(
"Minimum time granularity (in microseconds) traced by time profiler"),
cl::init(500), cl::Hidden);

static cl::opt<std::string>
TimeTraceFile("time-trace-file",
cl::desc("Specify time trace file destination"),
cl::value_desc("filename"));

static const Target *GetTarget(const char *ProgName) {
// Figure out the target triple.
if (TripleName.empty())
Expand Down Expand Up @@ -371,6 +391,22 @@ int main(int argc, char **argv) {

cl::HideUnrelatedOptions({&MCCategory, &getColorCategory()});
cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");

if (TimeTrace)
timeTraceProfilerInitialize(TimeTraceGranularity, argv[0]);

auto TimeTraceScopeExit = make_scope_exit([]() {
if (!TimeTrace)
return;
if (auto E = timeTraceProfilerWrite(TimeTraceFile, OutputFilename)) {
handleAllErrors(std::move(E), [&](const StringError &SE) {
errs() << SE.getMessage() << "\n";
});
return;
}
timeTraceProfilerCleanup();
});

MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
MCOptions.CompressDebugSections = CompressDebugSections.getValue();
MCOptions.ShowMCInst = ShowInst;
Expand Down Expand Up @@ -603,7 +639,7 @@ int main(int argc, char **argv) {
}

int Res = 1;
bool disassemble = false;
bool Disassemble = false;
switch (Action) {
case AC_AsLex:
Res = AsLexInput(SrcMgr, *MAI, Out->os());
Expand All @@ -615,18 +651,20 @@ int main(int argc, char **argv) {
case AC_MDisassemble:
case AC_CDisassemble:
case AC_Disassemble:
disassemble = true;
Disassemble = true;
break;
}
if (disassemble)
if (Disassemble)
Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer,
SrcMgr, Ctx, MCOptions, HexBytes);
SrcMgr, Ctx, MCOptions, HexBytes,
BenchmarkNumRuns);

// Keep output if no errors.
if (Res == 0) {
Out->keep();
if (DwoOut)
DwoOut->keep();
}

return Res;
}