Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next80 merge test #9

Closed
wants to merge 9 commits into from
4 changes: 3 additions & 1 deletion clang/lib/Basic/Targets/PPC.h
Original file line number Diff line number Diff line change
@@ -370,10 +370,12 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo {
ABI = "elfv1";
}

switch (getTriple().getOS()) {
switch (Triple.getOS()) {
case llvm::Triple::FreeBSD:
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
if (Triple.getOSMajorVersion() >= 13)
ABI = "elfv2";
break;
default:
break;
25 changes: 25 additions & 0 deletions libunwind/src/DwarfInstructions.hpp
Original file line number Diff line number Diff line change
@@ -234,6 +234,31 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
}
#endif

#if defined(_LIBUNWIND_TARGET_PPC64)
#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
#define PPC64_ELFV1_R2_OFFSET 40
#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
#define PPC64_ELFV2_R2_OFFSET 24
// If the instruction at return address is a TOC (r2) restore,
// then r2 was saved and needs to be restored.
// ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
// while in ELFv1 ABI it is saved at SP + 40.
if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {
pint_t sp = newRegisters.getRegister(UNW_REG_SP);
pint_t r2 = 0;
switch (addressSpace.get32(returnAddress)) {
case PPC64_ELFV1_R2_LOAD_INST_ENCODING:
r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);
break;
case PPC64_ELFV2_R2_LOAD_INST_ENCODING:
r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
break;
}
if (r2)
newRegisters.setRegister(UNW_PPC64_R2, r2);
}
#endif

// Return address is address after call site instruction, so setting IP to
// that does simualates a return.
newRegisters.setIP(returnAddress);
22 changes: 20 additions & 2 deletions libunwind/src/assembly.h
Original file line number Diff line number Diff line change
@@ -37,6 +37,20 @@
#define SEPARATOR ;
#endif

#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR
#define PPC64_OPD2 SEPARATOR \
.p2align 3 SEPARATOR \
.quad .Lfunc_begin0 SEPARATOR \
.quad .TOC.@tocbase SEPARATOR \
.quad 0 SEPARATOR \
.text SEPARATOR \
.Lfunc_begin0:
#else
#define PPC64_OPD1
#define PPC64_OPD2
#endif

#define GLUE2(a, b) a ## b
#define GLUE(a, b) GLUE2(a, b)
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
@@ -97,13 +111,17 @@
.globl SYMBOL_NAME(name) SEPARATOR \
EXPORT_SYMBOL(name) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
SYMBOL_NAME(name):
PPC64_OPD1 \
SYMBOL_NAME(name): \
PPC64_OPD2

#define DEFINE_LIBUNWIND_PRIVATE_FUNCTION(name) \
.globl SYMBOL_NAME(name) SEPARATOR \
HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
SYMBOL_NAME(name):
PPC64_OPD1 \
SYMBOL_NAME(name): \
PPC64_OPD2

#if defined(__arm__)
#if !defined(__ARM_ARCH)
18 changes: 18 additions & 0 deletions lld/ELF/Arch/PPC64.cpp
Original file line number Diff line number Diff line change
@@ -123,6 +123,7 @@ class PPC64 final : public TargetInfo {

bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End,
uint8_t StOther) const override;
uint32_t getThunkSectionSpacing() const override;
};
} // namespace

@@ -925,6 +926,23 @@ bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End,
return true;
}


uint32_t PPC64::getThunkSectionSpacing() const {
// The placing of pre-created ThunkSections is controlled by the value
// ThunkSectionSpacing returned by getThunkSectionSpacing(). The aim is to
// place the ThunkSection such that all branches from the InputSections
// prior to the ThunkSection can reach a Thunk placed at the end of the
// ThunkSection. Graphically:
// | up to ThunkSectionSpacing .text input sections |
// | ThunkSection |
// | up to ThunkSectionSpacing .text input sections |
// | ThunkSection |
//
// On PowerPC64, we return the PPC64_REL14 relocation range
return 0x8000;
}


TargetInfo *elf::getPPC64TargetInfo() {
static PPC64 Target;
return &Target;
5 changes: 5 additions & 0 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
@@ -2001,6 +2001,11 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
ESym->setVisibility(Sym->Visibility);
}

// The 3 most significant bits of st_other are used by OpenPOWER ABI.
// See getPPC64GlobalEntryToLocalEntryOffset() for more details.
if (Config->EMachine == EM_PPC64)
ESym->st_other |= Sym->StOther & 0xe0;

ESym->st_name = Ent.StrTabOffset;
ESym->st_shndx = getSymSectionIndex(Ent.Sym);

1 change: 1 addition & 0 deletions llvm/lib/MC/ELFObjectWriter.cpp
Original file line number Diff line number Diff line change
@@ -1271,6 +1271,7 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
// This is the first place we are able to copy this information.
Alias->setExternal(Symbol.isExternal());
Alias->setBinding(Symbol.getBinding());
Alias->setOther(Symbol.getOther());

if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
continue;
33 changes: 27 additions & 6 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
Original file line number Diff line number Diff line change
@@ -36,6 +36,8 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"

#include <set>

using namespace llvm;

#define GET_INSTRINFO_MC_DESC
@@ -182,16 +184,35 @@ class PPCTargetELFStreamer : public PPCTargetStreamer {

void emitAssignment(MCSymbol *S, const MCExpr *Value) override {
auto *Symbol = cast<MCSymbolELF>(S);

auto I = UpdateOther.find(Symbol);
if (I != UpdateOther.end())
UpdateOther.erase(I);

// When encoding an assignment to set symbol A to symbol B, also copy
// the st_other bits encoding the local entry point offset.
if (Value->getKind() != MCExpr::SymbolRef)
return;
const auto &RhsSym = cast<MCSymbolELF>(
static_cast<const MCSymbolRefExpr *>(Value)->getSymbol());
unsigned Other = Symbol->getOther();
if (copyLocalEntry(Symbol, Value))
UpdateOther.insert(Symbol);
}

void finish() override {
for (auto *Sym : UpdateOther)
copyLocalEntry(Sym, Sym->getVariableValue());
}

private:
std::set<MCSymbolELF *> UpdateOther;

bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) {
if (S->getKind() != MCExpr::SymbolRef)
return false;
const auto &RhsSym =
cast<MCSymbolELF>(static_cast<const MCSymbolRefExpr *>(S)->getSymbol());
unsigned Other = D->getOther();
Other &= ~ELF::STO_PPC64_LOCAL_MASK;
Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK;
Symbol->setOther(Other);
D->setOther(Other);
return true;
}
};

14 changes: 14 additions & 0 deletions llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
Original file line number Diff line number Diff line change
@@ -195,6 +195,20 @@ static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT,
if (TT.isMacOSX())
return PPCTargetMachine::PPC_ABI_UNKNOWN;

if (TT.isOSFreeBSD()) {
switch (TT.getArch()) {
case Triple::ppc64le:
case Triple::ppc64:
if (TT.getOSMajorVersion() >= 13)
return PPCTargetMachine::PPC_ABI_ELFv2;
else
return PPCTargetMachine::PPC_ABI_ELFv1;
case Triple::ppc:
default:
return PPCTargetMachine::PPC_ABI_UNKNOWN;
}
}

switch (TT.getArch()) {
case Triple::ppc64le:
return PPCTargetMachine::PPC_ABI_ELFv2;