mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Initial TOC support for PowerPC64 object creation
This patch adds initial PPC64 TOC MC object creation using the small mcmodel (a single 64K TOC) adding the some TOC relocations (R_PPC64_TOC, R_PPC64_TOC16, and R_PPC64_TOC16DS). The addition of 'undefinedExplicitRelSym' hook on 'MCELFObjectTargetWriter' is meant to avoid the creation of an unreferenced ".TOC." symbol (used in the .odp creation) as well to set the R_PPC64_TOC relocation target as the temporary ".TOC." symbol. On PPC64 ABI, the R_PPC64_TOC relocation should not point to any symbol. llvm-svn: 166677
This commit is contained in:
parent
d93b6e7cd4
commit
b08709a59f
@ -85,6 +85,9 @@ public:
|
||||
const MCFragment &F,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const;
|
||||
virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const;
|
||||
virtual void adjustFixupOffset(const MCFixup &Fixup,
|
||||
uint64_t &RelocOffset);
|
||||
|
||||
|
@ -133,6 +133,11 @@ class ELFObjectWriter : public MCObjectWriter {
|
||||
bool IsPCRel) const {
|
||||
return TargetObjectWriter->ExplicitRelSym(Asm, Target, F, Fixup, IsPCRel);
|
||||
}
|
||||
const MCSymbol *undefinedExplicitRelSym(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
return TargetObjectWriter->undefinedExplicitRelSym(Target, Fixup, IsPCRel);
|
||||
}
|
||||
|
||||
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
|
||||
bool hasRelocationAddend() const {
|
||||
@ -639,7 +644,7 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
|
||||
if (ASymbol.isUndefined()) {
|
||||
if (Renamed)
|
||||
return Renamed;
|
||||
return &ASymbol;
|
||||
return undefinedExplicitRelSym(Target, Fixup, IsPCRel);
|
||||
}
|
||||
|
||||
if (SD.isExternal()) {
|
||||
@ -721,10 +726,13 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
|
||||
MCSymbolData &SD = Asm.getSymbolData(ASymbol);
|
||||
MCFragment *F = SD.getFragment();
|
||||
|
||||
Index = F->getParent()->getOrdinal() + 1;
|
||||
|
||||
// Offset of the symbol in the section
|
||||
Value += Layout.getSymbolOffset(&SD);
|
||||
if (F) {
|
||||
Index = F->getParent()->getOrdinal() + 1;
|
||||
// Offset of the symbol in the section
|
||||
Value += Layout.getSymbolOffset(&SD);
|
||||
} else {
|
||||
Index = 0;
|
||||
}
|
||||
} else {
|
||||
if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref)
|
||||
WeakrefUsedInReloc.insert(RelocSymbol);
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -35,6 +37,12 @@ const MCSymbol *MCELFObjectTargetWriter::ExplicitRelSym(const MCAssembler &Asm,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const MCSymbol *MCELFObjectTargetWriter::undefinedExplicitRelSym(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
const MCSymbol &Symbol = Target.getSymA()->getSymbol();
|
||||
return &Symbol.AliasedSymbol();
|
||||
}
|
||||
|
||||
void MCELFObjectTargetWriter::adjustFixupOffset(const MCFixup &Fixup,
|
||||
uint64_t &RelocOffset) {
|
||||
|
@ -29,9 +29,14 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
case FK_Data_1:
|
||||
case FK_Data_2:
|
||||
case FK_Data_4:
|
||||
case FK_Data_8:
|
||||
case PPC::fixup_ppc_toc:
|
||||
return Value;
|
||||
case PPC::fixup_ppc_lo14:
|
||||
case PPC::fixup_ppc_toc16_ds:
|
||||
return (Value & 0xffff) << 2;
|
||||
case PPC::fixup_ppc_brcond14:
|
||||
return Value & 0x3ffc;
|
||||
return Value & 0xfffc;
|
||||
case PPC::fixup_ppc_br24:
|
||||
return Value & 0x3fffffc;
|
||||
#if 0
|
||||
@ -41,6 +46,7 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
case PPC::fixup_ppc_ha16:
|
||||
return ((Value >> 16) + ((Value & 0x8000) ? 1 : 0)) & 0xffff;
|
||||
case PPC::fixup_ppc_lo16:
|
||||
case PPC::fixup_ppc_toc16:
|
||||
return Value & 0xffff;
|
||||
}
|
||||
}
|
||||
@ -72,7 +78,10 @@ public:
|
||||
{ "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_ppc_lo16", 16, 16, 0 },
|
||||
{ "fixup_ppc_ha16", 16, 16, 0 },
|
||||
{ "fixup_ppc_lo14", 16, 14, 0 }
|
||||
{ "fixup_ppc_lo14", 16, 14, 0 },
|
||||
{ "fixup_ppc_toc", 0, 64, 0 },
|
||||
{ "fixup_ppc_toc16", 16, 16, 0 },
|
||||
{ "fixup_ppc_toc16_ds", 16, 14, 0 }
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "MCTargetDesc/PPCMCTargetDesc.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -21,9 +23,15 @@ namespace {
|
||||
|
||||
virtual ~PPCELFObjectWriter();
|
||||
protected:
|
||||
virtual unsigned getRelocTypeInner(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const;
|
||||
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
|
||||
bool IsPCRel, bool IsRelocWithSymbol,
|
||||
int64_t Addend) const;
|
||||
virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const;
|
||||
virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset);
|
||||
};
|
||||
}
|
||||
@ -36,11 +44,13 @@ PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
|
||||
PPCELFObjectWriter::~PPCELFObjectWriter() {
|
||||
}
|
||||
|
||||
unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel,
|
||||
bool IsRelocWithSymbol,
|
||||
int64_t Addend) const {
|
||||
unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const
|
||||
{
|
||||
MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
|
||||
MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
|
||||
|
||||
// determine the type of the relocation
|
||||
unsigned Type;
|
||||
if (IsPCRel) {
|
||||
@ -61,7 +71,7 @@ unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
Type = ELF::R_PPC_ADDR24;
|
||||
break;
|
||||
case PPC::fixup_ppc_brcond14:
|
||||
Type = ELF::R_PPC_ADDR14_BRTAKEN; // XXX: or BRNTAKEN?_
|
||||
Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
|
||||
break;
|
||||
case PPC::fixup_ppc_ha16:
|
||||
Type = ELF::R_PPC_ADDR16_HA;
|
||||
@ -72,6 +82,26 @@ unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
case PPC::fixup_ppc_lo14:
|
||||
Type = ELF::R_PPC_ADDR14;
|
||||
break;
|
||||
case PPC::fixup_ppc_toc:
|
||||
Type = ELF::R_PPC64_TOC;
|
||||
break;
|
||||
case PPC::fixup_ppc_toc16:
|
||||
Type = ELF::R_PPC64_TOC16;
|
||||
break;
|
||||
case PPC::fixup_ppc_toc16_ds:
|
||||
Type = ELF::R_PPC64_TOC16_DS;
|
||||
break;
|
||||
case FK_Data_8:
|
||||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_PPC_TOC:
|
||||
Type = ELF::R_PPC64_TOC;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
Type = ELF::R_PPC64_ADDR64;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FK_Data_4:
|
||||
Type = ELF::R_PPC_ADDR32;
|
||||
break;
|
||||
@ -83,6 +113,34 @@ unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
return Type;
|
||||
}
|
||||
|
||||
unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel,
|
||||
bool IsRelocWithSymbol,
|
||||
int64_t Addend) const {
|
||||
return getRelocTypeInner(Target, Fixup, IsPCRel);
|
||||
}
|
||||
|
||||
const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
assert(Target.getSymA() && "SymA cannot be 0");
|
||||
const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol();
|
||||
|
||||
unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel);
|
||||
|
||||
// The .odp creation emits a relocation against the symbol ".TOC." which
|
||||
// create a R_PPC64_TOC relocation. However the relocation symbol name
|
||||
// in final object creation should be NULL, since the symbol does not
|
||||
// really exist, it is just the reference to TOC base for the current
|
||||
// object file.
|
||||
bool EmitThisSym = RelocType != ELF::R_PPC64_TOC;
|
||||
|
||||
if (EmitThisSym && !Symbol.isTemporary())
|
||||
return &Symbol;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PPCELFObjectWriter::
|
||||
adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) {
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
|
@ -34,6 +34,16 @@ enum Fixups {
|
||||
/// fixup_ppc_lo14 - A 14-bit fixup corresponding to lo16(_foo) for instrs
|
||||
/// like 'std'.
|
||||
fixup_ppc_lo14,
|
||||
|
||||
/// fixup_ppc_toc - Insert value of TOC base (.TOC.).
|
||||
fixup_ppc_toc,
|
||||
|
||||
/// fixup_ppc_toc16 - A 16-bit signed fixup relative to the TOC base.
|
||||
fixup_ppc_toc16,
|
||||
|
||||
/// fixup_ppc_toc16_ds - A 14-bit signed fixup relative to the TOC base with
|
||||
/// implied 2 zero bits
|
||||
fixup_ppc_toc16_ds,
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
|
@ -15,7 +15,9 @@
|
||||
#include "MCTargetDesc/PPCBaseInfo.h"
|
||||
#include "MCTargetDesc/PPCFixupKinds.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -28,13 +30,25 @@ class PPCMCCodeEmitter : public MCCodeEmitter {
|
||||
PPCMCCodeEmitter(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
const MCSubtargetInfo &STI;
|
||||
Triple TT;
|
||||
|
||||
public:
|
||||
PPCMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
|
||||
MCContext &ctx) {
|
||||
MCContext &ctx)
|
||||
: STI(sti), TT(STI.getTargetTriple()) {
|
||||
}
|
||||
|
||||
~PPCMCCodeEmitter() {}
|
||||
|
||||
bool is64BitMode() const {
|
||||
return (STI.getFeatureBits() & PPC::Feature64Bit) != 0;
|
||||
}
|
||||
|
||||
bool isSVR4ABI() const {
|
||||
return TT.isMacOSX() == 0;
|
||||
}
|
||||
|
||||
unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
|
||||
@ -140,8 +154,12 @@ unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
|
||||
return (getMachineOpValue(MI, MO, Fixups) & 0xFFFF) | RegBits;
|
||||
|
||||
// Add a fixup for the displacement field.
|
||||
Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_lo16));
|
||||
if (isSVR4ABI() && is64BitMode())
|
||||
Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_toc16));
|
||||
else
|
||||
Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_lo16));
|
||||
return RegBits;
|
||||
}
|
||||
|
||||
@ -158,8 +176,12 @@ unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
|
||||
return (getMachineOpValue(MI, MO, Fixups) & 0x3FFF) | RegBits;
|
||||
|
||||
// Add a fixup for the branch target.
|
||||
Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_lo14));
|
||||
if (isSVR4ABI() && is64BitMode())
|
||||
Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_toc16_ds));
|
||||
else
|
||||
Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
|
||||
(MCFixupKind)PPC::fixup_ppc_lo14));
|
||||
return RegBits;
|
||||
}
|
||||
|
||||
|
@ -420,10 +420,14 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
|
||||
OutStreamer.EmitValueToAlignment(8);
|
||||
MCSymbol *Symbol1 =
|
||||
OutContext.GetOrCreateSymbol(".L." + Twine(CurrentFnSym->getName()));
|
||||
MCSymbol *Symbol2 = OutContext.GetOrCreateSymbol(StringRef(".TOC.@tocbase"));
|
||||
// Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function
|
||||
// entry point.
|
||||
OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol1, OutContext),
|
||||
8/*size*/, 0/*addrspace*/);
|
||||
OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol2, OutContext),
|
||||
MCSymbol *Symbol2 = OutContext.GetOrCreateSymbol(StringRef(".TOC."));
|
||||
// Generates a R_PPC64_TOC relocation for TOC base insertion.
|
||||
OutStreamer.EmitValue(MCSymbolRefExpr::Create(Symbol2,
|
||||
MCSymbolRefExpr::VK_PPC_TOC, OutContext),
|
||||
8/*size*/, 0/*addrspace*/);
|
||||
// Emit a null environment pointer.
|
||||
OutStreamer.EmitIntValue(0, 8 /* size */, 0 /* addrspace */);
|
||||
|
@ -54,19 +54,26 @@ PPCSubtarget::PPCSubtarget(const std::string &TT, const std::string &CPU,
|
||||
CPUName = sys::getHostCPUName();
|
||||
#endif
|
||||
|
||||
// Parse features string.
|
||||
ParseSubtargetFeatures(CPUName, FS);
|
||||
|
||||
// Initialize scheduling itinerary for the specified CPU.
|
||||
InstrItins = getInstrItineraryForCPU(CPUName);
|
||||
|
||||
// Make sure 64-bit features are available when CPUname is generic
|
||||
std::string FullFS = FS;
|
||||
|
||||
// If we are generating code for ppc64, verify that options make sense.
|
||||
if (is64Bit) {
|
||||
Has64BitSupport = true;
|
||||
// Silently force 64-bit register use on ppc64.
|
||||
Use64BitRegs = true;
|
||||
if (!FullFS.empty())
|
||||
FullFS = "+64bit," + FullFS;
|
||||
else
|
||||
FullFS = "+64bit";
|
||||
}
|
||||
|
||||
// Parse features string.
|
||||
ParseSubtargetFeatures(CPUName, FullFS);
|
||||
|
||||
// If the user requested use of 64-bit regs, but the cpu selected doesn't
|
||||
// support it, ignore.
|
||||
if (use64BitRegs() && !has64BitSupport())
|
||||
|
5
test/MC/PowerPC/lit.local.cfg
Normal file
5
test/MC/PowerPC/lit.local.cfg
Normal file
@ -0,0 +1,5 @@
|
||||
config.suffixes = ['.ll', '.c', '.cpp', '.s']
|
||||
|
||||
targets = set(config.root.targets_to_build.split())
|
||||
if not 'PowerPC' in targets:
|
||||
config.unsupported = True
|
66
test/MC/PowerPC/ppc64-relocs-01.ll
Normal file
66
test/MC/PowerPC/ppc64-relocs-01.ll
Normal file
@ -0,0 +1,66 @@
|
||||
;; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -O3 \
|
||||
;; RUN: -filetype=obj %s -o - | \
|
||||
;; RUN: elf-dump --dump-section-data | FileCheck %s
|
||||
|
||||
;; FIXME: this file need to be in .s form, change when asm parse is done.
|
||||
|
||||
@number64 = global i64 10, align 8
|
||||
|
||||
define i64 @access_int64(i64 %a) nounwind readonly {
|
||||
entry:
|
||||
%0 = load i64* @number64, align 8
|
||||
%cmp = icmp eq i64 %0, %a
|
||||
%conv1 = zext i1 %cmp to i64
|
||||
ret i64 %conv1
|
||||
}
|
||||
|
||||
declare double @sin(double) nounwind
|
||||
|
||||
define double @test_branch24 (double %x) nounwind readonly {
|
||||
entry:
|
||||
%add = call double @sin(double %x) nounwind
|
||||
ret double %add
|
||||
}
|
||||
|
||||
;; The relocations in .rela.text are the 'number64' load using a
|
||||
;; R_PPC64_TOC16_DS against the .toc and the 'sin' external function
|
||||
;; address using a R_PPC64_REL24
|
||||
;; CHECK: '.rela.text'
|
||||
;; CHECK: Relocation 0
|
||||
;; CHECK-NEXT: 'r_offset',
|
||||
;; CHECK-NEXT: 'r_sym', 0x00000006
|
||||
;; CHECK-NEXT: 'r_type', 0x0000003f
|
||||
;; CHECK: Relocation 1
|
||||
;; CHECK-NEXT: 'r_offset',
|
||||
;; CHECK-NEXT: 'r_sym', 0x0000000a
|
||||
;; CHECK-NEXT: 'r_type', 0x0000000a
|
||||
|
||||
;; The .opd entry for the 'access_int64' function creates 2 relocations:
|
||||
;; 1. A R_PPC64_ADDR64 against the .text segment plus addend (the function
|
||||
; address itself);
|
||||
;; 2. And a R_PPC64_TOC against no symbol (the linker will replace for the
|
||||
;; module's TOC base).
|
||||
;; CHECK: '.rela.opd'
|
||||
;; CHECK: Relocation 0
|
||||
;; CHECK-NEXT: 'r_offset',
|
||||
;; CHECK-NEXT: 'r_sym', 0x00000002
|
||||
;; CHECK-NEXT: 'r_type', 0x00000026
|
||||
;; CHECK: Relocation 1
|
||||
;; CHECK-NEXT: 'r_offset',
|
||||
;; CHECK-NEXT: 'r_sym', 0x00000000
|
||||
;; CHECK-NEXT: 'r_type', 0x00000033
|
||||
|
||||
;; Finally the TOC creates the relocation for the 'number64'.
|
||||
;; CHECK: '.rela.toc'
|
||||
;; CHECK: Relocation 0
|
||||
;; CHECK-NEXT: 'r_offset',
|
||||
;; CHECK-NEXT: 'r_sym', 0x00000008
|
||||
;; CHECK-NEXT: 'r_type', 0x00000026
|
||||
|
||||
;; Check if the relocation references are for correct symbols.
|
||||
;; CHECK: Symbol 7
|
||||
;; CHECK-NEXT: 'access_int64'
|
||||
;; CHECK: Symbol 8
|
||||
;; CHECK-NEXT: 'number64'
|
||||
;; CHECK: Symbol 10
|
||||
;; CHECK-NEXT: 'sin'
|
Loading…
Reference in New Issue
Block a user