Allow the use of an alternate symbol for calculating a function's size.

The standard function epilog includes a .size directive, but ppc64 uses
an alternate local symbol to tag the actual start of each function.

Until recently, binutils accepted the .size directive as:
 .size	test1, .Ltmp0-test1
however, using this directive with recent binutils will result in the error:
 .size expression for XXX does not evaluate to a constant
so we must use the label which actually tags the start of the function.

llvm-svn: 151200
This commit is contained in:
Hal Finkel 2012-02-22 21:11:47 +00:00
parent 9ea87ef77b
commit ad4d9f5848
4 changed files with 32 additions and 2 deletions

View File

@ -88,6 +88,11 @@ namespace llvm {
///
MCSymbol *CurrentFnSym;
/// The symbol used to represent the start of the current function for the
/// purpose of calculating its size (e.g. using the .size directive). By
/// default, this is equal to CurrentFnSym.
MCSymbol *CurrentFnSymForSize;
private:
// GCMetadataPrinters - The garbage collection metadata printer table.
void *GCMetadataPrinters; // Really a DenseMap.

View File

@ -100,6 +100,7 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer)
OutStreamer(Streamer),
LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) {
DD = 0; DE = 0; MMI = 0; LI = 0;
CurrentFnSym = CurrentFnSymForSize = 0;
GCMetadataPrinters = 0;
VerboseAsm = Streamer.isVerboseAsm();
}
@ -761,7 +762,8 @@ void AsmPrinter::EmitFunctionBody() {
const MCExpr *SizeExp =
MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(FnEndLabel, OutContext),
MCSymbolRefExpr::Create(CurrentFnSym, OutContext),
MCSymbolRefExpr::Create(CurrentFnSymForSize,
OutContext),
OutContext);
OutStreamer.EmitELFSize(CurrentFnSym, SizeExp);
}
@ -951,6 +953,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
this->MF = &MF;
// Get the function symbol.
CurrentFnSym = Mang->getSymbol(MF.getFunction());
CurrentFnSymForSize = CurrentFnSym;
if (isVerbose())
LI = &getAnalysis<MachineLoopInfo>();

View File

@ -398,7 +398,11 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
OutStreamer.EmitRawText("\t.quad .L." + Twine(CurrentFnSym->getName()) +
",.TOC.@tocbase");
OutStreamer.EmitRawText(StringRef("\t.previous"));
OutStreamer.EmitRawText(".L." + Twine(CurrentFnSym->getName()) + ":");
MCSymbol *RealFnSym = OutContext.GetOrCreateSymbol(
".L." + Twine(CurrentFnSym->getName()));
OutStreamer.EmitLabel(RealFnSym);
CurrentFnSymForSize = RealFnSym;
}

View File

@ -0,0 +1,18 @@
; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=g5 | FileCheck %s
; CHECK: test1:
; CHECK-NEXT: .quad .L.test1,.TOC.@tocbase
; CHECK-NEXT: .previous
; CHECK-NEXT: .L.test1:
define i32 @test1(i32 %a) nounwind {
entry:
ret i32 %a
}
; Until recently, binutils accepted the .size directive as:
; .size test1, .Ltmp0-test1
; however, using this directive with recent binutils will result in the error:
; .size expression for XXX does not evaluate to a constant
; so we must use the label which actually tags the start of the function.
; CHECK: .size test1, .Ltmp0-.L.test1