Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -2027,8 +2027,8 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal( const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { - assert(!TM.getFunctionSections() && !TM.getDataSections() && - "XCOFF unique sections not yet implemented."); + assert(!TM.getDataSections() && + "XCOFF unique data sections not yet implemented."); // Common symbols go into a csect with matching name which will get mapped // into the .bss section. @@ -2057,8 +2057,13 @@ Kind, /* BeginSymbolName */ nullptr); } - if (Kind.isText()) + if (Kind.isText()) { + if (TM.getFunctionSections()) { + return cast(getFunctionEntryPointSymbol(GO, TM)) + ->getRepresentedCsect(); + } return TextSection; + } if (Kind.isData() || Kind.isReadOnlyWithRel()) // TODO: We may put this under option control, because user may want to @@ -2149,10 +2154,26 @@ } MCSymbol *TargetLoweringObjectFileXCOFF::getFunctionEntryPointSymbol( - const GlobalValue *Function, const TargetMachine &TM) const { + const GlobalValue *Func, const TargetMachine &TM) const { SmallString<128> NameStr; NameStr.push_back('.'); - getNameWithPrefix(NameStr, Function, TM); + getNameWithPrefix(NameStr, Func, TM); + + // When -function-sections is enabled, it's not necessary to emit + // function entry point label any more. We will use function entry + // point csect instead. For function delcarations, it's Okay to continue + // using label semantic because undefined symbols gets treated as csect with + // XTY_ER property anyway. + if (TM.getFunctionSections() && !Func->isDeclaration() && + isa(Func)) { + XCOFF::StorageClass SC = + TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(Func); + return cast(getContext().getXCOFFSection( + NameStr, XCOFF::XMC_PR, XCOFF::XTY_SD, SC, + SectionKind::getText())) + ->getQualNameSymbol(); + } + return getContext().getOrCreateSymbol(NameStr); } Index: llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1763,7 +1763,11 @@ } void PPCAIXAsmPrinter::emitFunctionEntryLabel() { - PPCAsmPrinter::emitFunctionEntryLabel(); + // It's not necessary to emit the label when we have individual + // function in its own csect. + if (!TM.getFunctionSections()) + PPCAsmPrinter::emitFunctionEntryLabel(); + // Emit aliasing label for function entry point label. llvm::for_each( GOAliasMap[&MF->getFunction()], [this](const GlobalAlias *Alias) { Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -74,6 +74,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSectionXCOFF.h" #include "llvm/MC/MCSymbolXCOFF.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/BranchProbability.h" @@ -5333,10 +5334,9 @@ // entry point, which is named by prepending a "." before the function's // C-linkage name. const auto getAIXFuncEntryPointSymbolSDNode = - [&](StringRef FuncName, bool IsDeclaration, + [&](StringRef FuncName, bool IsDeclaration, bool IsAlias, const XCOFF::StorageClass &SC) { auto &Context = DAG.getMachineFunction().getMMI().getContext(); - MCSymbolXCOFF *S = cast( Context.getOrCreateSymbol(Twine(".") + Twine(FuncName))); @@ -5348,6 +5348,12 @@ S->getSymbolTableName(), XCOFF::XMC_PR, XCOFF::XTY_ER, SC, SectionKind::getMetadata()); S->setRepresentedCsect(Sec); + } else if (!IsAlias && + Subtarget.getTargetMachine().getFunctionSections()) { + MCSectionXCOFF *Sec = Context.getXCOFFSection( + S->getSymbolTableName(), XCOFF::XMC_PR, XCOFF::XTY_SD, SC, + SectionKind::getText()); + S = Sec->getQualNameSymbol(); } MVT PtrVT = @@ -5367,7 +5373,7 @@ const XCOFF::StorageClass SC = TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV); return getAIXFuncEntryPointSymbolSDNode(GV->getName(), GV->isDeclaration(), - SC); + isa(GV), SC); } if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { @@ -5384,10 +5390,11 @@ const XCOFF::StorageClass SC = TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(F); return getAIXFuncEntryPointSymbolSDNode(F->getName(), F->isDeclaration(), - SC); + /* IsAlias= */ false, SC); } - return getAIXFuncEntryPointSymbolSDNode(SymName, true, XCOFF::C_EXT); + return getAIXFuncEntryPointSymbolSDNode(SymName, /* IsDeclaration= */ true, + /* IsAlias= */ false, XCOFF::C_EXT); } // No transformation needed. Index: llvm/test/CodeGen/PowerPC/aix-xcoff-funcsect.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/aix-xcoff-funcsect.ll @@ -0,0 +1,95 @@ +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -mattr=-altivec -function-sections < %s | \ +; RUN: FileCheck --check-prefix=ASM %s +; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -mattr=-altivec -function-sections < %s | \ +; RUN: FileCheck --check-prefix=ASM %s + +@alias_foo = alias void (...), bitcast (void ()* @foo to void (...)*) + +define void @foo() { +entry: + ret void +} + +define hidden void @hidden_foo() { +entry: + ret void +} + +define void @bar() { +entry: + call void @foo() + call void @static_overalign_foo() + call void bitcast (void (...)* @alias_foo to void ()*)() + call void bitcast (void (...)* @extern_foo to void ()*)() + call void @hidden_foo() + ret void +} + +declare void @extern_foo(...) + +define internal void @static_overalign_foo() align 64 { +entry: + ret void +} + +; ASM: .csect .foo[PR],2 +; ASM-NEXT: .globl foo[DS] # -- Begin function foo +; ASM-NEXT: .globl .foo[PR] +; ASM-NEXT: .align 4 +; ASM-NEXT: .csect foo[DS] +; ASM-NEXT: alias_foo: # @foo +; ASM-NEXT: .vbyte {{[0-9]+}}, .foo[PR] +; ASM-NEXT: .vbyte {{[0-9]+}}, TOC[TC0] +; ASM-NEXT: .vbyte {{[0-9]+}}, 0 +; ASM-NEXT: .csect .foo[PR],2 +; ASM-NEXT: .alias_foo: +; ASM-NEXT: # %bb.0: # %entry +; ASM-NEXT: blr +; ASM: .csect .hidden_foo[PR],2 +; ASM-NEXT: .globl hidden_foo[DS],hidden # -- Begin function hidden_foo +; ASM-NEXT: .globl .hidden_foo[PR],hidden +; ASM-NEXT: .align 4 +; ASM-NEXT: .csect hidden_foo[DS] +; ASM-NEXT: .vbyte {{[0-9]+}}, .hidden_foo[PR] # @hidden_foo +; ASM-NEXT: .vbyte {{[0-9]+}}, TOC[TC0] +; ASM-NEXT: .vbyte {{[0-9]+}}, 0 +; ASM-NEXT: .csect .hidden_foo[PR] +; ASM-NEXT: # %bb.0: # %entry +; ASM-NEXT: blr +; ASM: .csect .bar[PR],2 +; ASM-NEXT: .globl bar[DS] # -- Begin function bar +; ASM-NEXT: .globl .bar[PR] +; ASM-NEXT: .align 4 +; ASM-NEXT: .csect bar[DS] +; ASM-NEXT: .vbyte {{[0-9]+}}, .bar[PR] # @bar +; ASM-NEXT: .vbyte {{[0-9]+}}, TOC[TC0] +; ASM-NEXT: .vbyte {{[0-9]+}}, 0 +; ASM-NEXT: .csect .bar[PR],2 +; ASM-NEXT: # %bb.0: # %entry +; ASM: bl .foo[PR] +; ASM-NEXT: nop +; ASM-NEXT: bl .static_overalign_foo[PR] +; ASM-NEXT: nop +; ASM-NEXT: bl .alias_foo +; ASM-NEXT: nop +; ASM-NEXT: bl .extern_foo +; ASM-NEXT: nop +; ASM-NEXT: bl .hidden_foo[PR] +; ASM-NEXT: nop +; ASM: .csect .static_overalign_foo[PR],6 +; ASM-NEXT: .lglobl static_overalign_foo[DS] # -- Begin function static_overalign_foo +; ASM-NEXT: .lglobl .static_overalign_foo[PR] +; ASM-NEXT: .align 6 +; ASM-NEXT: .csect static_overalign_foo[DS] +; ASM-NEXT: .vbyte {{[0-9]+}}, .static_overalign_foo[PR] # @static_overalign_foo +; ASM-NEXT: .vbyte {{[0-9]+}}, TOC[TC0] +; ASM-NEXT: .vbyte {{[0-9]+}}, 0 +; ASM-NEXT: .csect .static_overalign_foo[PR],6 +; ASM-NEXT: # %bb.0: # %entry +; ASM-NEXT: blr +; ASM: .extern .extern_foo +; ASM-NEXT: .extern extern_foo[DS] +; ASM-NEXT: .globl alias_foo +; ASM-NEXT: .globl .alias_foo