Index: include/llvm/CodeGen/MachineFunction.h =================================================================== --- include/llvm/CodeGen/MachineFunction.h +++ include/llvm/CodeGen/MachineFunction.h @@ -329,6 +329,7 @@ bool CallsUnwindInit = false; bool HasEHScopes = false; bool HasEHFunclets = false; + bool HasLocalEscape = false; /// List of C++ TypeInfo used. std::vector TypeInfos; @@ -809,6 +810,9 @@ bool hasEHFunclets() const { return HasEHFunclets; } void setHasEHFunclets(bool V) { HasEHFunclets = V; } + bool hasLocalEscape() const { return HasLocalEscape; } + void setHasLocalEscape(bool V) { HasLocalEscape = V; } + /// Find or create an LandingPadInfo for the specified MachineBasicBlock. LandingPadInfo &getOrCreateLandingPadInfo(MachineBasicBlock *LandingPad); Index: lib/CodeGen/AsmPrinter/WinException.cpp =================================================================== --- lib/CodeGen/AsmPrinter/WinException.cpp +++ lib/CodeGen/AsmPrinter/WinException.cpp @@ -545,15 +545,18 @@ OS.AddComment(Comment); }; - // Emit a label assignment with the SEH frame offset so we can use it for - // llvm.x86.seh.recoverfp. - StringRef FLinkageName = - GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName()); - MCSymbol *ParentFrameOffset = - Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); - const MCExpr *MCOffset = - MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx); - Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset); + if (MF->getTarget().getTargetTriple().getArch() != + Triple::ArchType::aarch64) { + // Emit a label assignment with the SEH frame offset so we can use it for + // llvm.x86.seh.recoverfp. + StringRef FLinkageName = + GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName()); + MCSymbol *ParentFrameOffset = + Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); + const MCExpr *MCOffset = + MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx); + Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset); + } // Use the assembler to compute the number of table entries through label // difference and division. Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6163,6 +6163,8 @@ .addFrameIndex(FI); } + MF.setHasLocalEscape(true); + return nullptr; } Index: lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- lib/Target/AArch64/AArch64AsmPrinter.cpp +++ lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -694,6 +694,34 @@ switch (MI->getOpcode()) { default: break; + case AArch64::MOVMCSym: { + MCSymbol *Sym = MI->getOperand(1).getMCSymbol(); + assert(Sym->isVariable() && "Invalid frame alloc symbol"); + + const MCExpr *Expr = Sym->getVariableValue(); + assert(isa(Expr) && + "Frame alloc symbol should be a constant"); + + const MCConstantExpr *C = cast(Expr); + int64_t Val = C->getValue(); + + MCInst TmpInst; + + if (Val < 0) { + TmpInst.setOpcode(AArch64::MOVNXi); + Val = -Val - 1; + } + else { + TmpInst.setOpcode(AArch64::MOVKXi); + TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); + } + + TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::createImm(Val)); + TmpInst.addOperand(MCOperand::createImm(0)); // unsused shift. + EmitToStreamer(*OutStreamer, TmpInst); + return; + } case AArch64::MOVIv2d_ns: // If the target has , lower this // instruction to movi.16b instead. Index: lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64FrameLowering.cpp +++ lib/Target/AArch64/AArch64FrameLowering.cpp @@ -228,6 +228,10 @@ MFI.getMaxCallFrameSize() > DefaultSafeSPDisplacement) return true; + // Win64 SEH requires frame pointer if funclets are present. + if (MF.hasLocalEscape()) + return true; + return false; } Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -85,6 +85,10 @@ : Predicate<"false">, AssemblerPredicate<"!FeatureNoNegativeImmediates", "NegativeImmediates">; +def AArch64LocalRecover : SDNode<"ISD::LOCAL_RECOVER", + SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, + SDTCisInt<1>]>>; + //===----------------------------------------------------------------------===// // AArch64-specific DAG Nodes. @@ -6740,5 +6744,8 @@ def : Pat<(AArch64tcret texternalsym:$dst, (i32 timm:$FPDiff)), (TCRETURNdi texternalsym:$dst, imm:$FPDiff)>; +def MOVMCSym : Pseudo<(outs GPR64:$dst), (ins i64imm:$sym), []>, Sched<[]>; +def : Pat<(i64 (AArch64LocalRecover mcsym:$sym)), (MOVMCSym mcsym:$sym)>; + include "AArch64InstrAtomics.td" include "AArch64SVEInstrInfo.td" Index: lib/Target/AArch64/AArch64RegisterInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64RegisterInfo.cpp +++ lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -263,7 +263,8 @@ // Furthermore, if both variable sized objects are present, and the // stack needs to be dynamically re-aligned, the base pointer is the only // reliable way to reference the locals. - if (MFI.hasVarSizedObjects() || MF.hasEHFunclets()) { + if (MFI.hasVarSizedObjects() || (MF.hasEHFunclets() && + !MF.hasLocalEscape())) { if (needsStackRealignment(MF)) return true; // Conservatively estimate whether the negative offset from the frame @@ -462,6 +463,13 @@ // Modify MI as necessary to handle as much of 'Offset' as possible Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg); + + if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE) { + MachineOperand &FI = MI.getOperand(FIOperandNum); + FI.ChangeToImmediate(Offset); + return; + } + if (rewriteAArch64FrameIndex(MI, FIOperandNum, FrameReg, Offset, TII)) return;