mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-01 00:33:09 +00:00
llvm-mc: Add --show-fixups option, for displaying the instruction fixup information in the asm comments.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95710 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
869fe12cc0
commit
6b71653c82
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user