Index: llvm/lib/CodeGen/MachineOutliner.cpp =================================================================== --- llvm/lib/CodeGen/MachineOutliner.cpp +++ llvm/lib/CodeGen/MachineOutliner.cpp @@ -632,6 +632,12 @@ })) F->addFnAttr(Attribute::NoUnwind); + // Set uwtable, so we generate eh_frame. + if (llvm::any_of(OF.Candidates, [](const outliner::Candidate &C) { + return C.getMF()->getFunction().hasFnAttribute(Attribute::UWTable); + })) + F->addFnAttr(Attribute::UWTable); + BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F); IRBuilder<> Builder(EntryBB); Builder.CreateRetVoid(); Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -1109,8 +1109,7 @@ const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineModuleInfo &MMI = MF.getMMI(); AArch64FunctionInfo *AFI = MF.getInfo(); - bool needsFrameMoves = - MF.needsFrameMoves() && !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); + bool EmitCFI = AFI->needsUnwindInfo(); bool HasFP = hasFP(MF); bool NeedsWinCFI = needsWinCFI(MF); bool HasWinCFI = false; @@ -1145,12 +1144,13 @@ .addReg(AArch64::LR) .addReg(AArch64::SP, RegState::InternalRead); MI.setMIFlag(MachineInstr::FrameSetup); - - unsigned CFIIndex = - MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); - BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex) - .setMIFlags(MachineInstr::FrameSetup); + if (EmitCFI) { + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlags(MachineInstr::FrameSetup); + } } // We signal the presence of a Swift extended frame to external tools by @@ -1227,7 +1227,7 @@ emitFrameOffset(MBB, MBBI, DL, AArch64::SP, AArch64::SP, StackOffset::getFixed(-NumBytes), TII, MachineInstr::FrameSetup, false, NeedsWinCFI, &HasWinCFI); - if (needsFrameMoves) { + if (EmitCFI) { // Label used to tie together the PROLOG_LABEL and the MachineMoves. MCSymbol *FrameLabel = MMI.getContext().createTempSymbol(); // Encode the stack size of the leaf function. @@ -1533,7 +1533,7 @@ } } - if (needsFrameMoves) { + if (EmitCFI) { // An example of the prologue: // // .globl __foo @@ -2497,27 +2497,29 @@ .addImm(8) .setMIFlag(MachineInstr::FrameSetup); + // This instruction also makes x18 live-in to the entry block. + MBB.addLiveIn(AArch64::X18); + if (NeedsWinCFI) BuildMI(MBB, MI, DL, TII.get(AArch64::SEH_Nop)) .setMIFlag(MachineInstr::FrameSetup); - // Emit a CFI instruction that causes 8 to be subtracted from the value of - // x18 when unwinding past this frame. - static const char CFIInst[] = { - dwarf::DW_CFA_val_expression, - 18, // register - 2, // length - static_cast(unsigned(dwarf::DW_OP_breg18)), - static_cast(-8) & 0x7f, // addend (sleb128) - }; - unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createEscape( - nullptr, StringRef(CFIInst, sizeof(CFIInst)))); - BuildMI(MBB, MI, DL, TII.get(AArch64::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex) - .setMIFlag(MachineInstr::FrameSetup); - - // This instruction also makes x18 live-in to the entry block. - MBB.addLiveIn(AArch64::X18); + if (MF.getInfo()->needsUnwindInfo()) { + // Emit a CFI instruction that causes 8 to be subtracted from the value of + // x18 when unwinding past this frame. + static const char CFIInst[] = { + dwarf::DW_CFA_val_expression, + 18, // register + 2, // length + static_cast(unsigned(dwarf::DW_OP_breg18)), + static_cast(-8) & 0x7f, // addend (sleb128) + }; + unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createEscape( + nullptr, StringRef(CFIInst, sizeof(CFIInst)))); + BuildMI(MBB, MI, DL, TII.get(AArch64::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlag(MachineInstr::FrameSetup); + } } if (homogeneousPrologEpilog(MF)) { Index: llvm/lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -7159,11 +7159,13 @@ .addReg(AArch64::SP, RegState::InternalRead); MI.setMIFlag(MachineInstr::FrameSetup); - unsigned CFIIndex = - MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); - BuildMI(MBB, MBBPAC, DebugLoc(), TII->get(AArch64::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex) - .setMIFlags(MachineInstr::FrameSetup); + if (MF.getInfo()->needsUnwindInfo()) { + unsigned CFIIndex = + MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); + BuildMI(MBB, MBBPAC, DebugLoc(), TII->get(AArch64::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex) + .setMIFlags(MachineInstr::FrameSetup); + } // If v8.3a features are available we can replace a RET instruction by // RETAA or RETAB and omit the AUT instructions. In this case the @@ -7256,24 +7258,26 @@ .addImm(-16); It = MBB.insert(It, STRXpre); - const TargetSubtargetInfo &STI = MF.getSubtarget(); - const MCRegisterInfo *MRI = STI.getRegisterInfo(); - unsigned DwarfReg = MRI->getDwarfRegNum(AArch64::LR, true); - - // Add a CFI saying the stack was moved 16 B down. - int64_t StackPosEntry = - MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 16)); - BuildMI(MBB, It, DebugLoc(), get(AArch64::CFI_INSTRUCTION)) - .addCFIIndex(StackPosEntry) - .setMIFlags(MachineInstr::FrameSetup); - - // Add a CFI saying that the LR that we want to find is now 16 B higher than - // before. - int64_t LRPosEntry = - MF.addFrameInst(MCCFIInstruction::createOffset(nullptr, DwarfReg, -16)); - BuildMI(MBB, It, DebugLoc(), get(AArch64::CFI_INSTRUCTION)) - .addCFIIndex(LRPosEntry) - .setMIFlags(MachineInstr::FrameSetup); + if (MF.getInfo()->needsUnwindInfo()) { + const TargetSubtargetInfo &STI = MF.getSubtarget(); + const MCRegisterInfo *MRI = STI.getRegisterInfo(); + unsigned DwarfReg = MRI->getDwarfRegNum(AArch64::LR, true); + + // Add a CFI saying the stack was moved 16 B down. + int64_t StackPosEntry = + MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 16)); + BuildMI(MBB, It, DebugLoc(), get(AArch64::CFI_INSTRUCTION)) + .addCFIIndex(StackPosEntry) + .setMIFlags(MachineInstr::FrameSetup); + + // Add a CFI saying that the LR that we want to find is now 16 B higher + // than before. + int64_t LRPosEntry = MF.addFrameInst( + MCCFIInstruction::createOffset(nullptr, DwarfReg, -16)); + BuildMI(MBB, It, DebugLoc(), get(AArch64::CFI_INSTRUCTION)) + .addCFIIndex(LRPosEntry) + .setMIFlags(MachineInstr::FrameSetup); + } // Insert a restore before the terminator for the function. MachineInstr *LDRXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost)) Index: llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h =================================================================== --- llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -173,6 +173,12 @@ /// The stack slot where the Swift asynchronous context is stored. int SwiftAsyncContextFrameIdx = std::numeric_limits::max(); + /// True if the function need unwind information. + mutable Optional NeedsUnwindInfo; + + /// True if the function need asynchronous unwind information. + mutable Optional NeedsAsyncUnwindInfo; + public: explicit AArch64FunctionInfo(MachineFunction &MF); @@ -408,6 +414,9 @@ } int getSwiftAsyncContextFrameIdx() const { return SwiftAsyncContextFrameIdx; } + bool needsUnwindInfo() const; + bool needsAsyncUnwindInfo() const; + private: // Hold the lists of LOHs. MILOHContainer LOHContainerSet; Index: llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp +++ llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp @@ -15,8 +15,10 @@ #include "AArch64MachineFunctionInfo.h" #include "AArch64InstrInfo.h" +#include "AArch64Subtarget.h" #include #include +#include using namespace llvm; @@ -114,3 +116,22 @@ MF.getFrameInfo().getCalleeSavedInfo(), [](const auto &Info) { return Info.getReg() == AArch64::LR; })); } + +bool AArch64FunctionInfo::needsUnwindInfo() const { + if (!NeedsUnwindInfo.hasValue()) + NeedsUnwindInfo = MF.needsFrameMoves() && + !MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); + + return NeedsUnwindInfo.getValue(); +} + +bool AArch64FunctionInfo::needsAsyncUnwindInfo() const { + if (!NeedsAsyncUnwindInfo.hasValue()) + NeedsAsyncUnwindInfo = MF.needsFrameMoves() && + !MF.getTarget().getMCAsmInfo()->usesWindowsCFI() && + !MF.getSubtarget().isTargetMachO(); + + assert((!NeedsAsyncUnwindInfo.getValue() || needsUnwindInfo()) && + "Async unwind info must imply unwind info"); + return NeedsAsyncUnwindInfo.getValue(); +} Index: llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-regsave.mir =================================================================== --- llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-regsave.mir +++ llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-regsave.mir @@ -9,18 +9,19 @@ ret void } - define void @bar() #0 { + define void @bar() #1 { ret void } - attributes #0 = { nounwind "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" minsize noinline noredzone "frame-pointer"="all" } + attributes #0 = { nounwind "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" minsize noinline noredzone "frame-pointer"="all" } + attributes #1 = { nounwind uwtable "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" minsize noinline noredzone "frame-pointer"="all" } ... --- # CHECK-LABEL: name: foo # CHECK: bb.0: # CHECK: frame-setup EMITBKEY # CHECK-NEXT: frame-setup PACIBSP -# CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state +# CHECK-NOT: frame-setup CFI_INSTRUCTION negate_ra_sign_state # CHECK: bb.1: # CHECK: BL @[[OUTLINED_FUNCTION:OUTLINED_FUNCTION_[0-9]+]] # CHECK: bb.2: @@ -80,6 +81,9 @@ --- # CHECK: name: bar # CHECK: bb.0: +# CHECK: frame-setup EMITBKEY +# CHECK-NEXT: frame-setup PACIBSP implicit-def $lr, implicit $lr, implicit $sp +# CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state # CHECK-NOT: OUTLINED_FUNCTION_ # CHECK: bb.1: # CHECK-NOT: OUTLINED_FUNCTION_ Index: llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.mir =================================================================== --- llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.mir +++ llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.mir @@ -58,7 +58,7 @@ ret void } - attributes #0 = { nounwind "sign-return-address"="all" "sign-return-address-key"="a_key" noinline noredzone "frame-pointer"="all" } + attributes #0 = { nounwind uwtable "sign-return-address"="all" "sign-return-address-key"="a_key" noinline noredzone "frame-pointer"="all" } ... ---