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
Expand Up @@ -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;
Expand Down
25 changes: 25 additions & 0 deletions libunwind/src/DwarfInstructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
22 changes: 20 additions & 2 deletions libunwind/src/assembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions lld/ELF/Arch/PPC64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/MC/ELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
33 changes: 27 additions & 6 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
};

Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down