This patch removes some nondeterminism from direct object file output

for TLS dynamic models on 64-bit PowerPC ELF.  The default sort routine
for relocations only sorts on the r_offset field; but with TLS, there
can be two relocations with the same r_offset.  For PowerPC, this patch
sorts secondarily on descending r_type, which matches the behavior
expected by the linker.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@170237 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bill Schmidt 2012-12-14 20:28:38 +00:00
parent 99cbdde619
commit d3eb4f46f0
2 changed files with 45 additions and 4 deletions

View File

@ -9,6 +9,7 @@
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCFixupKinds.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCValue.h"
@ -33,9 +34,25 @@ namespace {
const MCFixup &Fixup,
bool IsPCRel) const;
virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset);
virtual void sortRelocs(const MCAssembler &Asm,
std::vector<ELFRelocationEntry> &Relocs);
};
class PPCELFRelocationEntry : public ELFRelocationEntry {
public:
PPCELFRelocationEntry(const ELFRelocationEntry &RE);
bool operator<(const PPCELFRelocationEntry &RE) const {
return (RE.r_offset < r_offset ||
(RE.r_offset == r_offset && RE.Type > Type));
}
};
}
PPCELFRelocationEntry::PPCELFRelocationEntry(const ELFRelocationEntry &RE)
: ELFRelocationEntry(RE.r_offset, RE.Index, RE.Type, RE.Symbol,
RE.r_addend, *RE.Fixup) {}
PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
: MCELFObjectTargetWriter(Is64Bit, OSABI,
Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
@ -223,6 +240,34 @@ adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) {
}
}
// The standard sorter only sorts on the r_offset field, but PowerPC can
// have multiple relocations at the same offset. Sort secondarily on the
// relocation type to avoid nondeterminism.
void PPCELFObjectWriter::sortRelocs(const MCAssembler &Asm,
std::vector<ELFRelocationEntry> &Relocs) {
// Copy to a temporary vector of relocation entries having a different
// sort function.
std::vector<PPCELFRelocationEntry> TmpRelocs;
for (std::vector<ELFRelocationEntry>::iterator R = Relocs.begin();
R != Relocs.end(); ++R) {
TmpRelocs.push_back(PPCELFRelocationEntry(*R));
}
// Sort in place by ascending r_offset and descending r_type.
array_pod_sort(TmpRelocs.begin(), TmpRelocs.end());
// Copy back to the original vector.
unsigned I = 0;
for (std::vector<PPCELFRelocationEntry>::iterator R = TmpRelocs.begin();
R != TmpRelocs.end(); ++R, ++I) {
Relocs[I] = ELFRelocationEntry(R->r_offset, R->Index, R->Type,
R->Symbol, R->r_addend, *R->Fixup);
}
}
MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS,
bool Is64Bit,
uint8_t OSABI) {

View File

@ -4,10 +4,6 @@
; Test correct relocation generation for thread-local storage using
; the local dynamic model.
; Relocations 2 and 3 seem to come out in unpredictable order on some
; architectures, so restrict this for now.
; REQUIRES: ppc64-registered-target
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
target triple = "powerpc64-unknown-linux-gnu"