mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-01 01:30:36 +00:00
MCELF: Port EmitInstruction changes from MachO streamer. Patch by Roman Divacky.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@112260 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
95c602ade3
commit
93ded7371f
@ -34,6 +34,8 @@ using namespace llvm;
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class MCELFStreamer : public MCObjectStreamer {
|
class MCELFStreamer : public MCObjectStreamer {
|
||||||
|
void EmitInstToFragment(const MCInst &Inst);
|
||||||
|
void EmitInstToData(const MCInst &Inst);
|
||||||
public:
|
public:
|
||||||
MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
|
MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
|
||||||
raw_ostream &OS, MCCodeEmitter *Emitter)
|
raw_ostream &OS, MCCodeEmitter *Emitter)
|
||||||
@ -328,6 +330,40 @@ void MCELFStreamer::EmitFileDirective(StringRef Filename) {
|
|||||||
SD.setFlags(ELF_STT_File | ELF_STB_Local | ELF_STV_Default);
|
SD.setFlags(ELF_STT_File | ELF_STB_Local | ELF_STV_Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MCELFStreamer::EmitInstToFragment(const MCInst &Inst) {
|
||||||
|
MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData());
|
||||||
|
|
||||||
|
// Add the fixups and data.
|
||||||
|
//
|
||||||
|
// FIXME: Revisit this design decision when relaxation is done, we may be
|
||||||
|
// able to get away with not storing any extra data in the MCInst.
|
||||||
|
SmallVector<MCFixup, 4> Fixups;
|
||||||
|
SmallString<256> Code;
|
||||||
|
raw_svector_ostream VecOS(Code);
|
||||||
|
getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
|
||||||
|
VecOS.flush();
|
||||||
|
|
||||||
|
IF->getCode() = Code;
|
||||||
|
IF->getFixups() = Fixups;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
|
||||||
|
MCDataFragment *DF = getOrCreateDataFragment();
|
||||||
|
|
||||||
|
SmallVector<MCFixup, 4> Fixups;
|
||||||
|
SmallString<256> Code;
|
||||||
|
raw_svector_ostream VecOS(Code);
|
||||||
|
getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
|
||||||
|
VecOS.flush();
|
||||||
|
|
||||||
|
// Add the fixups and data.
|
||||||
|
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
|
||||||
|
Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
|
||||||
|
DF->addFixup(Fixups[i]);
|
||||||
|
}
|
||||||
|
DF->getContents().append(Code.begin(), Code.end());
|
||||||
|
}
|
||||||
|
|
||||||
void MCELFStreamer::EmitInstruction(const MCInst &Inst) {
|
void MCELFStreamer::EmitInstruction(const MCInst &Inst) {
|
||||||
// Scan for values.
|
// Scan for values.
|
||||||
for (unsigned i = 0; i != Inst.getNumOperands(); ++i)
|
for (unsigned i = 0; i != Inst.getNumOperands(); ++i)
|
||||||
@ -336,56 +372,25 @@ void MCELFStreamer::EmitInstruction(const MCInst &Inst) {
|
|||||||
|
|
||||||
getCurrentSectionData()->setHasInstructions(true);
|
getCurrentSectionData()->setHasInstructions(true);
|
||||||
|
|
||||||
// FIXME-PERF: Common case is that we don't need to relax, encode directly
|
// If this instruction doesn't need relaxation, just emit it as data.
|
||||||
// onto the data fragments buffers.
|
if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) {
|
||||||
|
EmitInstToData(Inst);
|
||||||
SmallVector<MCFixup, 4> Fixups;
|
|
||||||
SmallString<256> Code;
|
|
||||||
raw_svector_ostream VecOS(Code);
|
|
||||||
getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
|
|
||||||
VecOS.flush();
|
|
||||||
|
|
||||||
// FIXME: Eliminate this copy.
|
|
||||||
SmallVector<MCFixup, 4> AsmFixups;
|
|
||||||
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
|
|
||||||
MCFixup &F = Fixups[i];
|
|
||||||
AsmFixups.push_back(MCFixup::Create(F.getOffset(), F.getValue(),
|
|
||||||
F.getKind()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if we might need to relax this instruction, if so it needs its own
|
|
||||||
// fragment.
|
|
||||||
//
|
|
||||||
// FIXME-PERF: Support target hook to do a fast path that avoids the encoder,
|
|
||||||
// when we can immediately tell that we will get something which might need
|
|
||||||
// relaxation (and compute its size).
|
|
||||||
//
|
|
||||||
// FIXME-PERF: We should also be smart about immediately relaxing instructions
|
|
||||||
// which we can already show will never possibly fit (we can also do a very
|
|
||||||
// good job of this before we do the first relaxation pass, because we have
|
|
||||||
// total knowledge about undefined symbols at that point). Even now, though,
|
|
||||||
// we can do a decent job, especially on Darwin where scattering means that we
|
|
||||||
// are going to often know that we can never fully resolve a fixup.
|
|
||||||
if (getAssembler().getBackend().MayNeedRelaxation(Inst)) {
|
|
||||||
MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData());
|
|
||||||
|
|
||||||
// Add the fixups and data.
|
|
||||||
//
|
|
||||||
// FIXME: Revisit this design decision when relaxation is done, we may be
|
|
||||||
// able to get away with not storing any extra data in the MCInst.
|
|
||||||
IF->getCode() = Code;
|
|
||||||
IF->getFixups() = AsmFixups;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the fixups and data.
|
// Otherwise, if we are relaxing everything, relax the instruction as much as
|
||||||
MCDataFragment *DF = getOrCreateDataFragment();
|
// possible and emit it as data.
|
||||||
for (unsigned i = 0, e = AsmFixups.size(); i != e; ++i) {
|
if (getAssembler().getRelaxAll()) {
|
||||||
AsmFixups[i].setOffset(AsmFixups[i].getOffset() + DF->getContents().size());
|
MCInst Relaxed;
|
||||||
DF->addFixup(AsmFixups[i]);
|
getAssembler().getBackend().RelaxInstruction(Inst, Relaxed);
|
||||||
|
while (getAssembler().getBackend().MayNeedRelaxation(Relaxed))
|
||||||
|
getAssembler().getBackend().RelaxInstruction(Relaxed, Relaxed);
|
||||||
|
EmitInstToData(Relaxed);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
DF->getContents().append(Code.begin(), Code.end());
|
|
||||||
|
// Otherwise emit to a separate fragment.
|
||||||
|
EmitInstToFragment(Inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCELFStreamer::Finish() {
|
void MCELFStreamer::Finish() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user