diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 930199509c5..2910b2024ab 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -847,10 +847,8 @@ public: MachineBasicBlock::iterator MI) const; - /// getNoopForMachoTarget - Return the noop instruction to use for a noop. - virtual void getNoopForMachoTarget(MCInst &NopInst) const { - // Default to just using 'nop' string. - } + /// Return the noop instruction to use for a noop. + virtual void getNoopForMachoTarget(MCInst &NopInst) const; /// isPredicated - Returns true if the instruction is already predicated. diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index b1fc46b4112..b26d8d6f101 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -731,12 +731,10 @@ void AsmPrinter::EmitFunctionBody() { // Print out code for the function. bool HasAnyRealCode = false; - const MachineInstr *LastMI = nullptr; for (auto &MBB : *MF) { // Print a label for the basic block. EmitBasicBlockStart(MBB); for (auto &MI : MBB) { - LastMI = &MI; // Print the assembly for the instruction. if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && @@ -797,24 +795,14 @@ void AsmPrinter::EmitFunctionBody() { EmitBasicBlockEnd(MBB); } - // If the last instruction was a prolog label, then we have a situation where - // we emitted a prolog but no function body. This results in the ending prolog - // label equaling the end of function label and an invalid "row" in the - // FDE. We need to emit a noop in this situation so that the FDE's rows are - // valid. - bool RequiresNoop = LastMI && LastMI->isCFIInstruction(); - // If the function is empty and the object file uses .subsections_via_symbols, // then we need to emit *something* to the function body to prevent the // labels from collapsing together. Just emit a noop. - if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode) || RequiresNoop) { + if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode)) { MCInst Noop; TM.getSubtargetImpl()->getInstrInfo()->getNoopForMachoTarget(Noop); - if (Noop.getOpcode()) { - OutStreamer.AddComment("avoids zero-length function"); - OutStreamer.EmitInstruction(Noop, getSubtargetInfo()); - } else // Target not mc-ized yet. - OutStreamer.EmitRawText(StringRef("\tnop\n")); + OutStreamer.AddComment("avoids zero-length function"); + OutStreamer.EmitInstruction(Noop, getSubtargetInfo()); } const Function *F = MF->getFunction(); diff --git a/lib/CodeGen/TargetInstrInfo.cpp b/lib/CodeGen/TargetInstrInfo.cpp index 277073f0c8a..ab45f89a628 100644 --- a/lib/CodeGen/TargetInstrInfo.cpp +++ b/lib/CodeGen/TargetInstrInfo.cpp @@ -372,6 +372,10 @@ static const TargetRegisterClass *canFoldCopy(const MachineInstr *MI, return nullptr; } +void TargetInstrInfo::getNoopForMachoTarget(MCInst &NopInst) const { + llvm_unreachable("Not a MachO target"); +} + bool TargetInstrInfo:: canFoldMemoryOperand(const MachineInstr *MI, const SmallVectorImpl &Ops) const { diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp index 6836d8d6f68..8b2e6bc5f32 100644 --- a/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/lib/Target/Sparc/SparcInstrInfo.cpp @@ -37,11 +37,6 @@ SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST) RI(ST), Subtarget(ST) { } -/// getNoopForMachoTarget - Return the noop instruction to use for a noop. -void SparcInstrInfo::getNoopForMachoTarget(MCInst &NopInst) const { - NopInst.setOpcode(SP::NOP); -} - /// isLoadFromStackSlot - If the specified machine instruction is a direct /// load from a stack slot, return the virtual or physical register number of /// the destination along with the FrameIndex of the loaded stack slot. If diff --git a/lib/Target/Sparc/SparcInstrInfo.h b/lib/Target/Sparc/SparcInstrInfo.h index 2c39bbc3000..fe93ed7b57c 100644 --- a/lib/Target/Sparc/SparcInstrInfo.h +++ b/lib/Target/Sparc/SparcInstrInfo.h @@ -93,8 +93,6 @@ public: const TargetRegisterInfo *TRI) const override; unsigned getGlobalBaseReg(MachineFunction *MF) const; - - void getNoopForMachoTarget(MCInst &NopInst) const override; }; } diff --git a/test/CodeGen/PowerPC/empty-functions.ll b/test/CodeGen/PowerPC/empty-functions.ll deleted file mode 100644 index bed16cfe82a..00000000000 --- a/test/CodeGen/PowerPC/empty-functions.ll +++ /dev/null @@ -1,13 +0,0 @@ -; RUN: llc < %s -mtriple=powerpc-apple-darwin | FileCheck -check-prefix=CHECK-NO-FP %s -; RUN: llc < %s -mtriple=powerpc-apple-darwin -disable-fp-elim | FileCheck -check-prefix=CHECK-FP %s -; RUN: llc < %s -mtriple=powerpc-netbsd -disable-fp-elim | FileCheck -check-prefix=CHECK-FP %s - -define void @func() { -entry: - unreachable -} -; CHECK-NO-FP: _func: -; CHECK-NO-FP: nop - -; CHECK-FP: {{_?}}func: -; CHECK-FP: nop {{[;#]}} avoids zero-length function diff --git a/test/CodeGen/SPARC/empty-functions.ll b/test/CodeGen/SPARC/empty-functions.ll deleted file mode 100644 index 92522994cc7..00000000000 --- a/test/CodeGen/SPARC/empty-functions.ll +++ /dev/null @@ -1,8 +0,0 @@ -; RUN: llc < %s -mtriple=sparc-unknown-openbsd -disable-fp-elim | FileCheck -check-prefix=CHECK-FP-LABEL %s - -define void @func() { -entry: - unreachable -} -; CHECK-FP-LABEL: {{_?}}func: -; CHECK-FP-LABEL: nop {{[;!]}} avoids zero-length function diff --git a/test/CodeGen/X86/empty-functions.ll b/test/CodeGen/X86/empty-functions.ll index ac5174db5fc..42349688a71 100644 --- a/test/CodeGen/X86/empty-functions.ll +++ b/test/CodeGen/X86/empty-functions.ll @@ -1,10 +1,14 @@ ; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck -check-prefix=CHECK-NO-FP %s ; RUN: llc < %s -mtriple=x86_64-apple-darwin -disable-fp-elim | FileCheck -check-prefix=CHECK-FP %s +; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=LINUX-NO-FP %s +; RUN: llc < %s -mtriple=x86_64-linux-gnu -disable-fp-elim | FileCheck -check-prefix=LINUX-FP %s define void @func() { entry: unreachable } + +; MachO cannot handle an empty function. ; CHECK-NO-FP: _func: ; CHECK-NO-FP-NEXT: .cfi_startproc ; CHECK-NO-FP: nop @@ -21,5 +25,30 @@ entry: ; CHECK-FP-NEXT: movq %rsp, %rbp ; CHECK-FP-NEXT: : ; CHECK-FP-NEXT: .cfi_def_cfa_register %rbp -; CHECK-FP-NEXT: nop ; CHECK-FP-NEXT: .cfi_endproc + +; An empty function is perfectly fine on ELF. +; LINUX-NO-FP: func: +; LINUX-NO-FP-NEXT: .cfi_startproc +; LINUX-NO-FP-NEXT: {{^}}# +; LINUX-NO-FP-NEXT: {{^}}.L{{.*}}:{{$}} +; LINUX-NO-FP-NEXT: .size func, .L{{.*}}-func +; LINUX-NO-FP-NEXT: .cfi_endproc + +; A cfi directive can point to the end of a function. It (and in fact the +; entire body) could be optimized out because of the unreachable, but we +; don't do it right now. +; LINUX-FP: func: +; LINUX-FP-NEXT: .cfi_startproc +; LINUX-FP-NEXT: {{^}}# +; LINUX-FP-NEXT: pushq %rbp +; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}} +; LINUX-FP-NEXT: .cfi_def_cfa_offset 16 +; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}} +; LINUX-FP-NEXT: .cfi_offset %rbp, -16 +; LINUX-FP-NEXT: movq %rsp, %rbp +; LINUX-FP-NEXT:{{^}}.L{{.*}}:{{$}} +; LINUX-FP-NEXT: .cfi_def_cfa_register %rbp +; LINUX-FP-NEXT:{{^}}.L{{.*}}:{{$}} +; LINUX-FP-NEXT: .size func, .Ltmp3-func +; LINUX-FP-NEXT: .cfi_endproc