mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-29 10:25:12 +00:00
MC/Mach-O: Implement initial support for relaxation.
- The implementation is currently very brain dead and inefficient, but I have a clear plan on how to fix it. - The good news is, it works and correctly assembles 403.gcc (when built with Clang, at '-Os', '-Os -g', and '-O3'). Even better, at '-Os' and '-Os -g', the resulting binary is exactly equivalent to that when built with the system assembler. So it probably works! :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98396 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1275,6 +1275,40 @@ void MCAssembler::Finish() {
|
||||
llvm::errs() << "assembler backend - pre-layout\n--\n";
|
||||
dump(); });
|
||||
|
||||
// Layout until everything fits.
|
||||
while (LayoutOnce())
|
||||
continue;
|
||||
|
||||
DEBUG_WITH_TYPE("mc-dump", {
|
||||
llvm::errs() << "assembler backend - post-layout\n--\n";
|
||||
dump(); });
|
||||
|
||||
// Write the object file.
|
||||
MachObjectWriter MOW(OS);
|
||||
MOW.WriteObject(*this);
|
||||
|
||||
OS.flush();
|
||||
}
|
||||
|
||||
bool MCAssembler::FixupNeedsRelaxation(MCAsmFixup &Fixup, MCDataFragment *DF) {
|
||||
// FIXME: Share layout object.
|
||||
MCAsmLayout Layout(*this);
|
||||
|
||||
// Currently we only need to relax X86::reloc_pcrel_1byte.
|
||||
if (unsigned(Fixup.Kind) != X86::reloc_pcrel_1byte)
|
||||
return false;
|
||||
|
||||
// If we cannot resolve the fixup value, it requires relaxation.
|
||||
MCValue Target;
|
||||
uint64_t Value;
|
||||
if (!EvaluateFixup(Layout, Fixup, DF, Target, Value))
|
||||
return true;
|
||||
|
||||
// Otherwise, relax if the value is too big for a (signed) i8.
|
||||
return int64_t(Value) != int64_t(int8_t(Value));
|
||||
}
|
||||
|
||||
bool MCAssembler::LayoutOnce() {
|
||||
// Layout the concrete sections and fragments.
|
||||
uint64_t Address = 0;
|
||||
MCSectionData *Prev = 0;
|
||||
@@ -1316,21 +1350,95 @@ void MCAssembler::Finish() {
|
||||
SD.setAddress(Address);
|
||||
LayoutSection(SD);
|
||||
Address += SD.getSize();
|
||||
|
||||
}
|
||||
|
||||
DEBUG_WITH_TYPE("mc-dump", {
|
||||
llvm::errs() << "assembler backend - post-layout\n--\n";
|
||||
dump(); });
|
||||
// Scan the fixups in order and relax any that don't fit.
|
||||
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
||||
MCSectionData &SD = *it;
|
||||
|
||||
// Write the object file.
|
||||
MachObjectWriter MOW(OS);
|
||||
MOW.WriteObject(*this);
|
||||
for (MCSectionData::iterator it2 = SD.begin(),
|
||||
ie2 = SD.end(); it2 != ie2; ++it2) {
|
||||
MCDataFragment *DF = dyn_cast<MCDataFragment>(it2);
|
||||
if (!DF)
|
||||
continue;
|
||||
|
||||
OS.flush();
|
||||
for (MCDataFragment::fixup_iterator it3 = DF->fixup_begin(),
|
||||
ie3 = DF->fixup_end(); it3 != ie3; ++it3) {
|
||||
MCAsmFixup &Fixup = *it3;
|
||||
|
||||
// Check whether we need to relax this fixup.
|
||||
if (!FixupNeedsRelaxation(Fixup, DF))
|
||||
continue;
|
||||
|
||||
// Relax the instruction.
|
||||
//
|
||||
// FIXME: This is a huge temporary hack which just looks for x86
|
||||
// branches; the only thing we need to relax on x86 is
|
||||
// 'X86::reloc_pcrel_1byte'. Once we have MCInst fragments, this will be
|
||||
// replaced by a TargetAsmBackend hook (most likely tblgen'd) to relax
|
||||
// an individual MCInst.
|
||||
SmallVectorImpl<char> &C = DF->getContents();
|
||||
uint64_t PrevOffset = Fixup.Offset;
|
||||
unsigned Amt = 0;
|
||||
|
||||
// jcc instructions
|
||||
if (unsigned(C[Fixup.Offset-1]) >= 0x70 &&
|
||||
unsigned(C[Fixup.Offset-1]) <= 0x7f) {
|
||||
C[Fixup.Offset] = C[Fixup.Offset-1] + 0x10;
|
||||
C[Fixup.Offset-1] = char(0x0f);
|
||||
++Fixup.Offset;
|
||||
Amt = 4;
|
||||
|
||||
// jmp rel8
|
||||
} else if (C[Fixup.Offset-1] == char(0xeb)) {
|
||||
C[Fixup.Offset-1] = char(0xe9);
|
||||
Amt = 3;
|
||||
|
||||
} else
|
||||
llvm_unreachable("unknown 1 byte pcrel instruction!");
|
||||
|
||||
Fixup.Value = MCBinaryExpr::Create(
|
||||
MCBinaryExpr::Sub, Fixup.Value,
|
||||
MCConstantExpr::Create(3, getContext()),
|
||||
getContext());
|
||||
C.insert(C.begin() + Fixup.Offset, Amt, char(0));
|
||||
Fixup.Kind = MCFixupKind(X86::reloc_pcrel_4byte);
|
||||
|
||||
// Update the remaining fixups, which have slid.
|
||||
//
|
||||
// FIXME: This is bad for performance, but will be eliminated by the
|
||||
// move to MCInst specific fragments.
|
||||
++it3;
|
||||
for (; it3 != ie3; ++it3)
|
||||
it3->Offset += Amt;
|
||||
|
||||
// Update all the symbols for this fragment, which may have slid.
|
||||
//
|
||||
// FIXME: This is really really bad for performance, but will be
|
||||
// eliminated by the move to MCInst specific fragments.
|
||||
for (MCAssembler::symbol_iterator it = symbol_begin(),
|
||||
ie = symbol_end(); it != ie; ++it) {
|
||||
MCSymbolData &SD = *it;
|
||||
|
||||
if (it->getFragment() != DF)
|
||||
continue;
|
||||
|
||||
if (SD.getOffset() > PrevOffset)
|
||||
SD.setOffset(SD.getOffset() + Amt);
|
||||
}
|
||||
|
||||
// Restart layout.
|
||||
//
|
||||
// FIXME: This is O(N^2), but will be eliminated once we have a smart
|
||||
// MCAsmLayout object.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Debugging methods
|
||||
|
||||
namespace llvm {
|
||||
|
Reference in New Issue
Block a user