[llvm] r351370 - [COFF, ARM64] Implement support for SEH extensions __try/__except/__finally

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 17 07:41:06 PST 2019


Merged to 8.0 in r351451.

On Wed, Jan 16, 2019 at 8:56 PM Mandeep Singh Grang via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
>
> Author: mgrang
> Date: Wed Jan 16 11:52:59 2019
> New Revision: 351370
>
> URL: http://llvm.org/viewvc/llvm-project?rev=351370&view=rev
> Log:
> [COFF, ARM64] Implement support for SEH extensions __try/__except/__finally
>
> Summary:
> This patch supports MS SEH extensions __try/__except/__finally. The intrinsics localescape and localrecover are responsible for communicating escaped static allocas from the try block to the handler.
>
> We need to preserve frame pointers for SEH. So we create a new function/property HasLocalEscape.
>
> Reviewers: rnk, compnerd, mstorsjo, TomTan, efriedma, ssijaric
>
> Reviewed By: rnk, efriedma
>
> Subscribers: smeenai, jrmuizel, alex, majnemer, ssijaric, ehsan, dmajor, kristina, javed.absar, kristof.beyls, chrib, llvm-commits
>
> Differential Revision: https://reviews.llvm.org/D53540
>
> Added:
>     llvm/trunk/test/CodeGen/AArch64/seh-finally.ll
>     llvm/trunk/test/CodeGen/AArch64/seh-localescape.ll
> Modified:
>     llvm/trunk/include/llvm/CodeGen/MachineFunction.h
>     llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp
>     llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
>     llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp
>     llvm/trunk/lib/Target/AArch64/AArch64FrameLowering.cpp
>     llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
>     llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td
>     llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp
>
> Modified: llvm/trunk/include/llvm/CodeGen/MachineFunction.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFunction.h?rev=351370&r1=351369&r2=351370&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/MachineFunction.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/MachineFunction.h Wed Jan 16 11:52:59 2019
> @@ -329,6 +329,7 @@ class MachineFunction {
>    bool CallsUnwindInit = false;
>    bool HasEHScopes = false;
>    bool HasEHFunclets = false;
> +  bool HasLocalEscape = false;
>
>    /// List of C++ TypeInfo used.
>    std::vector<const GlobalValue *> TypeInfos;
> @@ -811,6 +812,9 @@ public:
>    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);
>
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp?rev=351370&r1=351369&r2=351370&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp Wed Jan 16 11:52:59 2019
> @@ -545,15 +545,17 @@ void WinException::emitCSpecificHandlerT
>        OS.AddComment(Comment);
>    };
>
> -  // Emit a label assignment with the SEH frame offset so we can use it for
> -  // llvm.eh.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 (!isAArch64) {
> +    // Emit a label assignment with the SEH frame offset so we can use it for
> +    // llvm.eh.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.
> @@ -937,6 +939,9 @@ void WinException::emitEHRegistrationOff
>    if (FI != INT_MAX) {
>      const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
>      unsigned UnusedReg;
> +    // FIXME: getFrameIndexReference needs to match the behavior of
> +    // AArch64RegisterInfo::hasBasePointer in which one of the scenarios where
> +    // SP is used is if frame size >= 256.
>      Offset = TFI->getFrameIndexReference(*Asm->MF, FI, UnusedReg);
>    }
>
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=351370&r1=351369&r2=351370&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Jan 16 11:52:59 2019
> @@ -6183,6 +6183,8 @@ SelectionDAGBuilder::visitIntrinsicCall(
>            .addFrameIndex(FI);
>      }
>
> +    MF.setHasLocalEscape(true);
> +
>      return nullptr;
>    }
>
>
> Modified: llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp?rev=351370&r1=351369&r2=351370&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp (original)
> +++ llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp Wed Jan 16 11:52:59 2019
> @@ -694,6 +694,34 @@ void AArch64AsmPrinter::EmitInstruction(
>    switch (MI->getOpcode()) {
>    default:
>      break;
> +    case AArch64::MOVMCSym: {
> +    unsigned DestReg = MI->getOperand(0).getReg();
> +    const MachineOperand &MO_Sym = MI->getOperand(1);
> +    MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
> +    MCOperand Hi_MCSym, Lo_MCSym;
> +
> +    Hi_MOSym.setTargetFlags(AArch64II::MO_G1 | AArch64II::MO_S);
> +    Lo_MOSym.setTargetFlags(AArch64II::MO_G0 | AArch64II::MO_NC);
> +
> +    MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
> +    MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
> +
> +    MCInst MovZ;
> +    MovZ.setOpcode(AArch64::MOVZXi);
> +    MovZ.addOperand(MCOperand::createReg(DestReg));
> +    MovZ.addOperand(Hi_MCSym);
> +    MovZ.addOperand(MCOperand::createImm(16));
> +    EmitToStreamer(*OutStreamer, MovZ);
> +
> +    MCInst MovK;
> +    MovK.setOpcode(AArch64::MOVKXi);
> +    MovK.addOperand(MCOperand::createReg(DestReg));
> +    MovK.addOperand(MCOperand::createReg(DestReg));
> +    MovK.addOperand(Lo_MCSym);
> +    MovK.addOperand(MCOperand::createImm(0));
> +    EmitToStreamer(*OutStreamer, MovK);
> +    return;
> +  }
>    case AArch64::MOVIv2d_ns:
>      // If the target has <rdar://problem/16473581>, lower this
>      // instruction to movi.16b instead.
>
> Modified: llvm/trunk/lib/Target/AArch64/AArch64FrameLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64FrameLowering.cpp?rev=351370&r1=351369&r2=351370&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/AArch64/AArch64FrameLowering.cpp (original)
> +++ llvm/trunk/lib/Target/AArch64/AArch64FrameLowering.cpp Wed Jan 16 11:52:59 2019
> @@ -228,6 +228,10 @@ bool AArch64FrameLowering::hasFP(const M
>        MFI.getMaxCallFrameSize() > DefaultSafeSPDisplacement)
>      return true;
>
> +  // Win64 SEH requires frame pointer if funclets are present.
> +  if (MF.hasLocalEscape())
> +    return true;
> +
>    return false;
>  }
>
>
> Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp?rev=351370&r1=351369&r2=351370&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp Wed Jan 16 11:52:59 2019
> @@ -2743,6 +2743,34 @@ SDValue AArch64TargetLowering::LowerINTR
>    case Intrinsic::aarch64_neon_umin:
>      return DAG.getNode(ISD::UMIN, dl, Op.getValueType(),
>                         Op.getOperand(1), Op.getOperand(2));
> +
> +  case Intrinsic::localaddress: {
> +    // Returns one of the stack, base, or frame pointer registers, depending on
> +    // which is used to reference local variables.
> +    MachineFunction &MF = DAG.getMachineFunction();
> +    const AArch64RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
> +    unsigned Reg;
> +    if (RegInfo->hasBasePointer(MF))
> +      Reg = RegInfo->getBaseRegister();
> +    else // This function handles the SP or FP case.
> +      Reg = RegInfo->getFrameRegister(MF);
> +    return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg,
> +                              Op.getSimpleValueType());
> +  }
> +
> +  case Intrinsic::eh_recoverfp: {
> +    // FIXME: This needs to be implemented to correctly handle highly aligned
> +    // stack objects. For now we simply return the incoming FP. Refer D53541
> +    // for more details.
> +    SDValue FnOp = Op.getOperand(1);
> +    SDValue IncomingFPOp = Op.getOperand(2);
> +    GlobalAddressSDNode *GSD = dyn_cast<GlobalAddressSDNode>(FnOp);
> +    auto *Fn = dyn_cast_or_null<Function>(GSD ? GSD->getGlobal() : nullptr);
> +    if (!Fn)
> +      report_fatal_error(
> +          "llvm.eh.recoverfp must take a function as the first argument");
> +    return IncomingFPOp;
> +  }
>    }
>  }
>
>
> Modified: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td?rev=351370&r1=351369&r2=351370&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td (original)
> +++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td Wed Jan 16 11:52:59 2019
> @@ -133,6 +133,10 @@ def UseNegativeImmediates
>      : Predicate<"false">, AssemblerPredicate<"!FeatureNoNegativeImmediates",
>                                               "NegativeImmediates">;
>
> +def AArch64LocalRecover : SDNode<"ISD::LOCAL_RECOVER",
> +                                  SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
> +                                                       SDTCisInt<1>]>>;
> +
>
>  //===----------------------------------------------------------------------===//
>  // AArch64-specific DAG Nodes.
> @@ -6801,5 +6805,8 @@ def : Pat<(AArch64tcret tglobaladdr:$dst
>  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"
>
> Modified: llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp?rev=351370&r1=351369&r2=351370&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp (original)
> +++ llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp Wed Jan 16 11:52:59 2019
> @@ -466,6 +466,13 @@ void AArch64RegisterInfo::eliminateFrame
>
>    // 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;
>
>
> Added: llvm/trunk/test/CodeGen/AArch64/seh-finally.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/seh-finally.ll?rev=351370&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/AArch64/seh-finally.ll (added)
> +++ llvm/trunk/test/CodeGen/AArch64/seh-finally.ll Wed Jan 16 11:52:59 2019
> @@ -0,0 +1,67 @@
> +; RUN: llc -mtriple arm64-windows -o - %s | FileCheck %s
> +
> +; Function Attrs: noinline optnone uwtable
> +define dso_local i32 @foo() {
> +entry:
> +; CHECK-LABEL: foo
> +; CHECK: orr     w8, wzr, #0x1
> +; CHECK: mov     w0, wzr
> +; CHECK: mov     x1, x29
> +; CHECK: .set .Lfoo$frame_escape_0, -4
> +; CHECK: stur    w8, [x29, #-4]
> +; CHECK: bl      "?fin$0 at 0@foo@@"
> +; CHECK: ldur    w0, [x29, #-4]
> +
> +  %count = alloca i32, align 4
> +  call void (...) @llvm.localescape(i32* %count)
> +  store i32 0, i32* %count, align 4
> +  %0 = load i32, i32* %count, align 4
> +  %add = add nsw i32 %0, 1
> +  store i32 %add, i32* %count, align 4
> +  %1 = call i8* @llvm.localaddress()
> +  call void @"?fin$0 at 0@foo@@"(i8 0, i8* %1)
> +  %2 = load i32, i32* %count, align 4
> +  ret i32 %2
> +}
> +
> +define internal void @"?fin$0 at 0@foo@@"(i8 %abnormal_termination, i8* %frame_pointer) {
> +entry:
> +; CHECK-LABEL: @"?fin$0 at 0@foo@@"
> +; CHECK: sub     sp, sp, #16
> +; CHECK: str     x1, [sp, #8]
> +; CHECK: strb    w0, [sp, #7]
> +; CHECK: movz    x8, #:abs_g1_s:.Lfoo$frame_escape_0
> +; CHECK: movk    x8, #:abs_g0_nc:.Lfoo$frame_escape_0
> +; CHECK: add     x8, x1, x8
> +; CHECK: ldr     w9, [x8]
> +; CHECK: add     w9, w9, #1
> +; CHECK: str     w9, [x8]
> +
> +  %frame_pointer.addr = alloca i8*, align 8
> +  %abnormal_termination.addr = alloca i8, align 1
> +  %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @foo to i8*), i8* %frame_pointer, i32 0)
> +  %count = bitcast i8* %0 to i32*
> +  store i8* %frame_pointer, i8** %frame_pointer.addr, align 8
> +  store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1
> +  %1 = zext i8 %abnormal_termination to i32
> +  %cmp = icmp eq i32 %1, 0
> +  br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:                                          ; preds = %entry
> +  %2 = load i32, i32* %count, align 4
> +  %add = add nsw i32 %2, 1
> +  store i32 %add, i32* %count, align 4
> +  br label %if.end
> +
> +if.end:                                           ; preds = %if.then, %entry
> +  ret void
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare i8* @llvm.localrecover(i8*, i8*, i32)
> +
> +; Function Attrs: nounwind readnone
> +declare i8* @llvm.localaddress()
> +
> +; Function Attrs: nounwind
> +declare void @llvm.localescape(...)
>
> Added: llvm/trunk/test/CodeGen/AArch64/seh-localescape.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/seh-localescape.ll?rev=351370&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/AArch64/seh-localescape.ll (added)
> +++ llvm/trunk/test/CodeGen/AArch64/seh-localescape.ll Wed Jan 16 11:52:59 2019
> @@ -0,0 +1,30 @@
> +; RUN: llc -mtriple arm64-windows %s -o - | FileCheck %s
> +
> +; Function Attrs: noinline nounwind optnone uwtable
> +define dso_local i32 @foo() {
> +entry:
> +; CHECK-LABEL: foo
> +; CHECK: .set .Lfoo$frame_escape_0, -4
> +
> +  %count = alloca i32, align 4
> +  call void (...) @llvm.localescape(i32* %count)
> +  ret i32 0
> +}
> +
> +define internal i32 @"?filt$0 at 0@foo@@"(i8* %exception_pointers, i8* %frame_pointer) {
> +entry:
> +; CHECK-LABEL: @"?filt$0 at 0@foo@@"
> +; CHECK: movz    x8, #:abs_g1_s:.Lfoo$frame_escape_0
> +; CHECK: movk    x8, #:abs_g0_nc:.Lfoo$frame_escape_0
> +
> +  %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @foo to i8*), i8* %frame_pointer, i32 0)
> +  %count = bitcast i8* %0 to i32*
> +  %1 = load i32, i32* %count, align 4
> +  ret i32 %1
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare i8* @llvm.localrecover(i8*, i8*, i32) #2
> +
> +; Function Attrs: nounwind
> +declare void @llvm.localescape(...) #3
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list