Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,9 @@ class TargetInfo : public TransferrableTargetInfo,
return true;
if (getTriple().getArch() == llvm::Triple::ArchType::avr)
return true;
if (getTriple().isOSAIX())
return getTriple().getOSMajorVersion() == 0 ||
getTriple().getOSVersion() >= VersionTuple(7, 2);
return getTriple().isOSBinFormatELF() &&
((getTriple().isOSLinux() && !getTriple().isMusl()) ||
getTriple().isOSFreeBSD());
Expand Down
23 changes: 4 additions & 19 deletions clang/lib/Driver/ToolChains/AIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,25 +146,10 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-bforceimprw");
}

// PGO instrumentation generates symbols belonging to special sections, and
// the linker needs to place all symbols in a particular section together in
// memory; the AIX linker does that under an option.
if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
Args.hasFlag(options::OPT_fprofile_generate,
options::OPT_fno_profile_generate, false) ||
Args.hasFlag(options::OPT_fprofile_generate_EQ,
options::OPT_fno_profile_generate, false) ||
Args.hasFlag(options::OPT_fprofile_instr_generate,
options::OPT_fno_profile_instr_generate, false) ||
Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
options::OPT_fno_profile_instr_generate, false) ||
Args.hasFlag(options::OPT_fcs_profile_generate,
options::OPT_fno_profile_generate, false) ||
Args.hasFlag(options::OPT_fcs_profile_generate_EQ,
options::OPT_fno_profile_generate, false) ||
Args.hasArg(options::OPT_fcreate_profile) ||
Args.hasArg(options::OPT_coverage))
// PGO and ifunc support depends on the named sections linker feature that is
// available on AIX 7.2 TL5 SP5 onwards.
if (ToolChain.getTriple().getOSMajorVersion() == 0 ||
ToolChain.getTriple().getOSVersion() >= VersionTuple(7, 2))
CmdArgs.push_back("-bdbg:namedsects:ss");

if (Arg *A =
Expand Down
2 changes: 2 additions & 0 deletions clang/test/CodeGen/attr-ifunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// RUN: %clang_cc1 -triple x86_64-apple-macosx -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple aarch64-pc-windows-msvcu -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -verify -emit-llvm-only -DCHECK_ALIASES %s

#if defined(_WIN32) && !defined(__aarch64__)
void foo(void) {}
Expand Down
2 changes: 2 additions & 0 deletions clang/test/CodeGen/attr-ifunc.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// RUN: %clang_cc1 -triple x86_64-linux -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple arm64-apple-macosx -verify -emit-llvm-only %s
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -verify -emit-llvm-only %s
// RUN: not %clang_cc1 -triple x86_64-linux -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -triple x86_64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -triple arm64-apple-macosx -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -triple powerpc64-ibm-aix-xcoff -emit-llvm-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s

void *f1_ifunc(void) { return nullptr; }
void f1(void) __attribute__((ifunc("f1_ifunc")));
Expand Down
4 changes: 3 additions & 1 deletion clang/test/CodeGen/ifunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -O2 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -O2 -emit-llvm -o - %s | FileCheck %s


/// The ifunc is emitted before its resolver.
Expand Down Expand Up @@ -65,7 +67,7 @@ extern void hoo(int) __attribute__ ((ifunc("hoo_ifunc")));
// AVR: @goo = ifunc void (), ptr addrspace(1) @goo_ifunc
// AVR: @hoo = ifunc void (i16), ptr addrspace(1) @hoo_ifunc

// CHECK: call i32 @foo(i32
// CHECK: call {{(signext )?}}i32 @foo(i32
// CHECK: call void @goo()

// SAN: define {{(dso_local )?}}noalias {{(noundef )?}}ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaCXX/ifunc-has-attribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-apple-macosx -verify %s -DSUPPORTED=1
// RUN: %clang_cc1 -emit-llvm-only -triple arm64-apple-macosx -verify %s -DSUPPORTED=1
// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-pc-win32 -verify %s -DNOT_SUPPORTED=1
// RUN: %clang_cc1 -emit-llvm-only -triple powerpc64-ibm-aix-xcoff -verify %s -DSUPPORTED=1

// expected-no-diagnostics

Expand Down
10 changes: 10 additions & 0 deletions compiler-rt/lib/builtins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,16 @@ if (NOT OS_NAME MATCHES "AIX")
${powerpc64_SOURCES}
)
endif()
if (OS_NAME MATCHES "AIX")
set(powerpc_SOURCES
ppc/init_ifuncs.c
${powerpc_SOURCES}
)
set(powerpc64_SOURCES
ppc/init_ifuncs.c
${powerpc64_SOURCES}
)
endif()
set(powerpc64le_SOURCES ${powerpc64_SOURCES})

set(riscv_SOURCES
Expand Down
38 changes: 38 additions & 0 deletions compiler-rt/lib/builtins/ppc/init_ifuncs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
typedef void *Ptr;
typedef struct {
Ptr addr, toc, env;
} Descr;
typedef struct {
Descr *desc;
Ptr (*resolver)();
} IFUNCPair;

#define CONC2(A, B) A##B
#define CONC(A, B) CONC2(A, B)

#define IFUNC_SEC __ifunc_sec
#define IFUNC_SEC_STR "__ifunc_sec"
#define START_SEC CONC(__start_, IFUNC_SEC)
#define STOP_SEC CONC(__stop_, IFUNC_SEC)

// A zero-length entry in section "__ifunc_sec" to satisfy the START_SEC and
// STOP_SEC references in this file, when no user code has any ifuncs.
__attribute__((section(IFUNC_SEC_STR))) static int dummy_ifunc_sec[0];

extern IFUNCPair START_SEC, STOP_SEC;

__attribute__((constructor)) void __init_ifuncs() {
void *volatile ref = &dummy_ifunc_sec; // hack to keep dummy_ifunc_sec alive

// hack to prevent compiler from assuming START_SEC and STOP_SEC
// occupy different addresses.
IFUNCPair *volatile volatile_end = &STOP_SEC;
for (IFUNCPair *pair = &START_SEC, *end = volatile_end; pair != end; pair++) {
// Call the resolver and copy the entire descriptor because:
// - the resolved function might be in another DSO, so copy the TOC address
// - we might be linking with objects from a language that uses the
// enviroment pointer, so copy it too.
Descr *result = (Descr *)pair->resolver();
*(pair->desc) = *result;
}
}
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/AsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
virtual void emitModuleCommandLines(Module &M);

GCMetadataPrinter *getOrCreateGCPrinter(GCStrategy &S);
void emitGlobalIFunc(Module &M, const GlobalIFunc &GI);
virtual void emitGlobalIFunc(Module &M, const GlobalIFunc &GI);

/// This method decides whether the specified basic block requires a label.
bool shouldEmitLabelForBasicBlock(const MachineBasicBlock &MBB) const;
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile {
static XCOFF::StorageClass getStorageClassForGlobal(const GlobalValue *GV);

MCSection *
getSectionForFunctionDescriptor(const Function *F,
getSectionForFunctionDescriptor(const GlobalObject *F,
const TargetMachine &TM) const override;
MCSection *getSectionForTOCEntry(const MCSymbol *Sym,
const TargetMachine &TM) const override;
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Target/TargetLoweringObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ class LLVM_ABI TargetLoweringObjectFile : public MCObjectFileInfo {
/// On targets that use separate function descriptor symbols, return a section
/// for the descriptor given its symbol. Use only with defined functions.
virtual MCSection *
getSectionForFunctionDescriptor(const Function *F,
getSectionForFunctionDescriptor(const GlobalObject *F,
const TargetMachine &TM) const {
return nullptr;
}
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2427,8 +2427,7 @@ void AsmPrinter::emitGlobalAlias(const Module &M, const GlobalAlias &GA) {

void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
assert(!TM.getTargetTriple().isOSBinFormatXCOFF() &&
"IFunc is not supported on AIX.");

"AIX has non-default implementation.");
auto EmitLinkage = [&](MCSymbol *Sym) {
if (GI.hasExternalLinkage() || !MAI->getWeakRefDirective())
OutStreamer->emitSymbolAttribute(Sym, MCSA_Global);
Expand Down
17 changes: 13 additions & 4 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2391,7 +2391,9 @@ MCSymbol *
TargetLoweringObjectFileXCOFF::getTargetSymbol(const GlobalValue *GV,
const TargetMachine &TM) const {
// We always use a qualname symbol for a GV that represents
// a declaration, a function descriptor, or a common symbol.
// a declaration, a function descriptor, or a common symbol. An IFunc is
// lowered as a special trampoline function which has an entry point and a
// descriptor.
// If a GV represents a GlobalVariable and -fdata-sections is enabled, we
// also return a qualname so that a label symbol could be avoided.
// It is inherently ambiguous when the GO represents the address of a
Expand All @@ -2410,6 +2412,11 @@ TargetLoweringObjectFileXCOFF::getTargetSymbol(const GlobalValue *GV,
SectionForGlobal(GVar, SectionKind::getData(), TM))
->getQualNameSymbol();

if (isa<GlobalIFunc>(GO))
return static_cast<const MCSectionXCOFF *>(
getSectionForFunctionDescriptor(GO, TM))
->getQualNameSymbol();

SectionKind GOKind = getKindForGlobal(GO, TM);
if (GOKind.isText())
return static_cast<const MCSectionXCOFF *>(
Expand Down Expand Up @@ -2682,7 +2689,7 @@ TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(const GlobalValue *GV) {

MCSymbol *TargetLoweringObjectFileXCOFF::getFunctionEntryPointSymbol(
const GlobalValue *Func, const TargetMachine &TM) const {
assert((isa<Function>(Func) ||
assert((isa<Function>(Func) || isa<GlobalIFunc>(Func) ||
(isa<GlobalAlias>(Func) &&
isa_and_nonnull<Function>(
cast<GlobalAlias>(Func)->getAliaseeObject()))) &&
Expand All @@ -2699,7 +2706,7 @@ MCSymbol *TargetLoweringObjectFileXCOFF::getFunctionEntryPointSymbol(
// undefined symbols gets treated as csect with XTY_ER property.
if (((TM.getFunctionSections() && !Func->hasSection()) ||
Func->isDeclarationForLinker()) &&
isa<Function>(Func)) {
(isa<Function>(Func) || isa<GlobalIFunc>(Func))) {
return getContext()
.getXCOFFSection(
NameStr, SectionKind::getText(),
Expand All @@ -2713,7 +2720,9 @@ MCSymbol *TargetLoweringObjectFileXCOFF::getFunctionEntryPointSymbol(
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForFunctionDescriptor(
const Function *F, const TargetMachine &TM) const {
const GlobalObject *F, const TargetMachine &TM) const {
assert((isa<Function>(F) || isa<GlobalIFunc>(F)) &&
"F must be a function or ifunc object.");
SmallString<128> NameStr;
getNameWithPrefix(NameStr, F, TM);
return getContext().getXCOFFSection(
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/PowerPC/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ add_llvm_target(PowerPCCodeGen
PPCMachineScheduler.cpp
PPCMacroFusion.cpp
PPCMIPeephole.cpp
PPCPrepareIFuncsOnAIX.cpp
PPCRegisterInfo.cpp
PPCSelectionDAGInfo.cpp
PPCSubtarget.cpp
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/PowerPC/PPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ModulePass;
FunctionPass *createPPCPreEmitPeepholePass();
FunctionPass *createPPCExpandAtomicPseudoPass();
FunctionPass *createPPCCTRLoopsPass();
ModulePass *createPPCPrepareIFuncsOnAIXPass();
void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
AsmPrinter &AP);
bool LowerPPCMachineOperandToMCOperand(const MachineOperand &MO,
Expand All @@ -78,6 +79,7 @@ class ModulePass;
void initializePPCExpandAtomicPseudoPass(PassRegistry &);
void initializePPCCTRLoopsPass(PassRegistry &);
void initializePPCDAGToDAGISelLegacyPass(PassRegistry &);
void initializePPCPrepareIFuncsOnAIXPass(PassRegistry &);
void initializePPCLinuxAsmPrinterPass(PassRegistry &);
void initializePPCAIXAsmPrinterPass(PassRegistry &);

Expand Down
Loading
Loading