Skip to content

Next80 merge test #9

New issue

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

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

Already on GitHub? # to your account

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