summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCStreamer.h5
-rw-r--r--lib/MC/MCAsmStreamer.cpp113
-rw-r--r--lib/MC/MCAssembler.cpp8
-rw-r--r--tools/llvm-mc/llvm-mc.cpp5
4 files changed, 104 insertions, 27 deletions
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 624d9a6c06..69c1267080 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -278,12 +278,15 @@ namespace llvm {
///
/// \param ShowInst - Whether to show the MCInst representation inline with
/// the assembly.
+ ///
+ /// \param ShowFixups - Whether to show the fixups in an encoded instruction.
MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
const MCAsmInfo &MAI, bool isLittleEndian,
bool isVerboseAsm,
MCInstPrinter *InstPrint = 0,
MCCodeEmitter *CE = 0,
- bool ShowInst = false);
+ bool ShowInst = false,
+ bool ShowFixups = false);
// FIXME: These two may end up getting rolled into a single
// createObjectStreamer interface, which implements the assembler backend, and
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index f3c636c6a5..0abd485ac1 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -37,21 +37,22 @@ class MCAsmStreamer : public MCStreamer {
unsigned IsLittleEndian : 1;
unsigned IsVerboseAsm : 1;
+ unsigned ShowFixups : 1;
unsigned ShowInst : 1;
public:
MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
const MCAsmInfo &mai,
bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer,
- MCCodeEmitter *emitter, bool showInst)
+ MCCodeEmitter *emitter, bool showInst, bool showFixups)
: MCStreamer(Context), OS(os), MAI(mai), InstPrinter(printer),
Emitter(emitter), CommentStream(CommentToEmit),
IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm),
- ShowInst(showInst) {}
+ ShowFixups(showFixups), ShowInst(showInst) {}
~MCAsmStreamer() {}
bool isLittleEndian() const { return IsLittleEndian; }
-
+
inline void EmitEOL() {
// If we don't have any comments, just emit a \n.
if (!IsVerboseAsm) {
@@ -65,13 +66,16 @@ public:
/// isVerboseAsm - Return true if this streamer supports verbose assembly at
/// all.
virtual bool isVerboseAsm() const { return IsVerboseAsm; }
-
+
/// AddComment - Add a comment that can be emitted to the generated .s
/// file if applicable as a QoI issue to make the output of the compiler
/// more readable. This only affects the MCAsmStreamer, and only when
/// verbose assembly output is enabled.
virtual void AddComment(const Twine &T);
-
+
+ /// AddEncodingComment - Add a comment showing the encoding of an instruction.
+ virtual void AddEncodingComment(const MCInst &Inst);
+
/// GetCommentOS - Return a raw_ostream that comments can be written to.
/// Unlike AddComment, you are required to terminate comments with \n if you
/// use this method.
@@ -80,12 +84,12 @@ public:
return nulls(); // Discard comments unless in verbose asm mode.
return CommentStream;
}
-
+
/// AddBlankLine - Emit a blank line to a .s file to pretty it up.
virtual void AddBlankLine() {
EmitEOL();
}
-
+
/// @name MCStreamer Interface
/// @{
@@ -528,19 +532,16 @@ void MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){
EmitEOL();
}
+void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) {
+ raw_ostream &OS = GetCommentOS();
+ SmallString<256> Code;
+ SmallVector<MCFixup, 4> Fixups;
+ raw_svector_ostream VecOS(Code);
+ Emitter->EncodeInstruction(Inst, VecOS, Fixups);
+ VecOS.flush();
-void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
- assert(CurSection && "Cannot emit contents before setting section!");
-
- // Show the encoding in a comment if we have a code emitter.
- if (Emitter) {
- SmallString<256> Code;
- SmallVector<MCFixup, 4> Fixups;
- raw_svector_ostream VecOS(Code);
- Emitter->EncodeInstruction(Inst, VecOS, Fixups);
- VecOS.flush();
-
- raw_ostream &OS = GetCommentOS();
+ // If we aren't showing fixups, just show the bytes.
+ if (!ShowFixups) {
OS << "encoding: [";
for (unsigned i = 0, e = Code.size(); i != e; ++i) {
if (i)
@@ -550,6 +551,75 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
OS << "]\n";
}
+ // If we are showing fixups, create symbolic markers in the encoded
+ // representation. We do this by making a per-bit map to the fixup item index,
+ // then trying to display it as nicely as possible.
+ uint8_t *FixupMap = new uint8_t[Code.size() * 8];
+ for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
+ FixupMap[i] = 0;
+
+ for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
+ MCFixup &F = Fixups[i];
+ MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind());
+ for (unsigned j = 0; j != Info.TargetSize; ++j) {
+ unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
+ assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
+ FixupMap[Index] = 1 + i;
+ }
+ }
+
+ OS << "encoding: [";
+ for (unsigned i = 0, e = Code.size(); i != e; ++i) {
+ if (i)
+ OS << ',';
+
+ // See if all bits are the same map entry.
+ uint8_t MapEntry = FixupMap[i * 8 + 0];
+ for (unsigned j = 1; j != 8; ++j) {
+ if (FixupMap[i * 8 + j] == MapEntry)
+ continue;
+
+ MapEntry = uint8_t(~0U);
+ break;
+ }
+
+ if (MapEntry != uint8_t(~0U)) {
+ if (MapEntry == 0) {
+ OS << format("0x%02x", uint8_t(Code[i]));
+ } else {
+ assert(Code[i] == 0 && "Encoder wrote into fixed up bit!");
+ OS << char('A' + MapEntry - 1);
+ }
+ } else {
+ // Otherwise, write out in binary.
+ OS << "0b";
+ for (unsigned j = 8; j--;) {
+ unsigned Bit = (Code[i] >> j) & 1;
+ if (uint8_t MapEntry = FixupMap[i * 8 + j]) {
+ assert(Bit == 0 && "Encoder wrote into fixed up bit!");
+ OS << char('A' + MapEntry - 1);
+ } else
+ OS << Bit;
+ }
+ }
+ }
+ OS << "]\n";
+
+ for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
+ MCFixup &F = Fixups[i];
+ MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind());
+ OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
+ << ", op: " << F.getOpIndex() << ", kind: " << Info.Name << "\n";
+ }
+}
+
+void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
+ assert(CurSection && "Cannot emit contents before setting section!");
+
+ // Show the encoding in a comment if we have a code emitter.
+ if (Emitter)
+ AddEncodingComment(Inst);
+
// Show the MCInst if enabled.
if (ShowInst) {
raw_ostream &OS = GetCommentOS();
@@ -578,7 +648,8 @@ MCStreamer *llvm::createAsmStreamer(MCContext &Context,
formatted_raw_ostream &OS,
const MCAsmInfo &MAI, bool isLittleEndian,
bool isVerboseAsm, MCInstPrinter *IP,
- MCCodeEmitter *CE, bool ShowInst) {
+ MCCodeEmitter *CE, bool ShowInst,
+ bool ShowFixups) {
return new MCAsmStreamer(Context, OS, MAI, isLittleEndian, isVerboseAsm,
- IP, CE, ShowInst);
+ IP, CE, ShowInst, ShowFixups);
}
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index c471a02eb7..bdc886bc67 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -746,7 +746,7 @@ public:
SD.getAddress() + SD.getFileSize());
}
- // The section data is passed to 4 bytes.
+ // The section data is padded to 4 bytes.
//
// FIXME: Is this machine dependent?
unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
@@ -761,9 +761,9 @@ public:
// ... and then the section headers.
//
// We also compute the section relocations while we do this. Note that
- // compute relocation info will also update the fixup to have the correct
- // value; this will be overwrite the appropriate data in the fragment when
- // it is written.
+ // computing relocation info will also update the fixup to have the correct
+ // value; this will overwrite the appropriate data in the fragment when it
+ // is written.
std::vector<MachRelocationEntry> RelocInfos;
uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie;
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index c05bd522c5..250d4dc22f 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -47,6 +47,9 @@ static cl::opt<bool>
ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
static cl::opt<bool>
+ShowFixups("show-fixups", cl::desc("Show fixups inside encodings"));
+
+static cl::opt<bool>
ShowInst("show-inst", cl::desc("Show internal instruction representation"));
static cl::opt<unsigned>
@@ -270,7 +273,7 @@ static int AssembleInput(const char *ProgName) {
Str.reset(createAsmStreamer(Ctx, *Out, *MAI,
TM->getTargetData()->isLittleEndian(),
/*asmverbose*/true, IP.get(), CE.get(),
- ShowInst));
+ ShowInst, ShowFixups));
} else {
assert(FileType == OFT_ObjectFile && "Invalid file type!");
CE.reset(TheTarget->createCodeEmitter(*TM));