1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

llvm-mc: Add --show-fixups option, for displaying the instruction fixup information in the asm comments.

llvm-svn: 95710
This commit is contained in:
Daniel Dunbar 2010-02-09 23:00:14 +00:00
parent 75c5ab93a0
commit 1b050afd4e
4 changed files with 104 additions and 27 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -46,6 +46,9 @@ OutputFilename("o", cl::desc("Output filename"),
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"));
@ -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));