[XCOFF][AIX] Enable -ffunction-sections

Summary:
This patch implements -ffunction-sections on AIX.
This patch focuses on assembly generation.
Follow-on patch needs to handle:
1. -ffunction-sections implication for jump table.
2. Object file generation path and associated testing.

Differential Revision: https://reviews.llvm.org/D83875
This commit is contained in:
jasonliu 2020-07-29 15:06:04 +00:00
parent f7237ee74f
commit 04dc9691eb
3 changed files with 124 additions and 4 deletions

View File

@ -2027,8 +2027,8 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForExternalReference(
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 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal(
Kind, /* BeginSymbolName */ nullptr);
}
if (Kind.isText())
if (Kind.isText()) {
if (TM.getFunctionSections()) {
return cast<MCSymbolXCOFF>(getFunctionEntryPointSymbol(GO, TM))
->getRepresentedCsect();
}
return TextSection;
}
if (Kind.isData() || Kind.isReadOnlyWithRel())
// TODO: We may put this under option control, because user may want to
@ -2161,6 +2166,22 @@ MCSymbol *TargetLoweringObjectFileXCOFF::getFunctionEntryPointSymbol(
SmallString<128> NameStr;
NameStr.push_back('.');
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<Function>(Func)) {
XCOFF::StorageClass SC =
TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(Func);
return cast<MCSectionXCOFF>(getContext().getXCOFFSection(
NameStr, XCOFF::XMC_PR, XCOFF::XTY_SD, SC,
SectionKind::getText()))
->getQualNameSymbol();
}
return getContext().getOrCreateSymbol(NameStr);
}

View File

@ -1779,7 +1779,11 @@ void PPCAIXAsmPrinter::emitFunctionDescriptor() {
}
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) {

View File

@ -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