diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index b2697c81fd825..a155de24731c1 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -2135,11 +2135,10 @@ class LLVM_ABI TargetLoweringBase { /// getIRStackGuard returns nullptr. virtual Value *getSDagStackGuard(const Module &M) const; - /// If this function returns true, stack protection checks should XOR the - /// frame pointer (or whichever pointer is used to address locals) into the + /// If this function returns true, stack protection checks should mix the /// stack guard value before checking it. getIRStackGuard must return nullptr /// if this returns true. - virtual bool useStackGuardXorFP() const { return false; } + virtual bool useStackGuardMixCookie() const { return false; } /// If the target has a standard stack protection check function that /// performs validation and error handling, returns the function. Otherwise, @@ -5835,8 +5834,9 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase { /// LOAD_STACK_GUARD node when it is lowering Intrinsic::stackprotector. virtual bool useLoadStackGuardNode(const Module &M) const { return false; } - virtual SDValue emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val, - const SDLoc &DL) const { + virtual SDValue emitStackGuardMixCookie(SelectionDAG &DAG, SDValue Val, + const SDLoc &DL, + bool FailureBB) const { llvm_unreachable("not implemented for this target"); } diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index e0665d99a891d..90dcd3127d043 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -3966,8 +3966,9 @@ bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD, MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile) .getReg(0); - if (TLI->useStackGuardXorFP()) { - LLVM_DEBUG(dbgs() << "Stack protector xor'ing with FP not yet implemented"); + if (TLI->useStackGuardMixCookie()) { + LLVM_DEBUG( + dbgs() << "Stack protector mix'ing the cookie not yet implemented"); return false; } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 53d73ad618bd1..48ffc4f56bc62 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -3126,8 +3126,8 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD, MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), Align, MachineMemOperand::MOVolatile); - if (TLI.useStackGuardXorFP()) - GuardVal = TLI.emitStackGuardXorFP(DAG, GuardVal, dl); + if (TLI.useStackGuardMixCookie()) + GuardVal = TLI.emitStackGuardMixCookie(DAG, GuardVal, dl, false); // If we're using function-based instrumentation, call the guard check // function @@ -3235,8 +3235,8 @@ void SelectionDAGBuilder::visitSPDescriptorFailure( MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), Align, MachineMemOperand::MOVolatile); - if (TLI.useStackGuardXorFP()) - GuardVal = TLI.emitStackGuardXorFP(DAG, GuardVal, dl); + if (TLI.useStackGuardMixCookie()) + GuardVal = TLI.emitStackGuardMixCookie(DAG, GuardVal, dl, true); // The target provides a guard check function to validate the guard value. // Generate a call to that function with the content of the guard slot as @@ -7435,8 +7435,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, MachinePointerInfo(Global, 0), Align, MachineMemOperand::MOVolatile); } - if (TLI.useStackGuardXorFP()) - Res = TLI.emitStackGuardXorFP(DAG, Res, sdl); + if (TLI.useStackGuardMixCookie()) + Res = TLI.emitStackGuardMixCookie(DAG, Res, sdl, false); DAG.setRoot(Chain); setValue(&I, Res); return; diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp index 5fd5d6cce23df..971c3e58b10ef 100644 --- a/llvm/lib/CodeGen/StackProtector.cpp +++ b/llvm/lib/CodeGen/StackProtector.cpp @@ -576,7 +576,7 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F, // impossible to emit the check in IR, so the target *must* support stack // protection in SDAG. bool SupportsSelectionDAGSP = - TLI->useStackGuardXorFP() || + TLI->useStackGuardMixCookie() || (EnableSelectionDAGSP && !TM->Options.EnableFastISel); AllocaInst *AI = nullptr; // Place on stack that stores the stack guard. BasicBlock *FailBB = nullptr; diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp index b721c1f533726..8e3a1ef2ac8f3 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -74,6 +74,8 @@ class AArch64DAGToDAGISel : public SelectionDAGISel { template bool SelectRDSVLShiftImm(SDValue N, SDValue &Imm); + bool SelectAddUXTXRegister(SDValue N, SDValue &Reg, SDValue &Shift); + bool SelectArithExtendedRegister(SDValue N, SDValue &Reg, SDValue &Shift); bool SelectArithUXTXRegister(SDValue N, SDValue &Reg, SDValue &Shift); bool SelectArithImmed(SDValue N, SDValue &Val, SDValue &Shift); @@ -959,6 +961,18 @@ bool AArch64DAGToDAGISel::SelectRDSVLShiftImm(SDValue N, SDValue &Imm) { return false; } +/// SelectAddUXTXRegister - Select a "UXTX register" operand. This +/// operand is referred by the instructions have SP operand +bool AArch64DAGToDAGISel::SelectAddUXTXRegister(SDValue N, SDValue &Reg, + SDValue &Shift) { + if (N.getOpcode() != ISD::LOAD) + return false; + Reg = N; + Shift = CurDAG->getTargetConstant(getArithExtendImm(AArch64_AM::UXTX, 0), + SDLoc(N), MVT::i32); + return true; +} + /// SelectArithExtendedRegister - Select a "extended register" operand. This /// operand folds in an extend followed by an optional left shift. bool AArch64DAGToDAGISel::SelectArithExtendedRegister(SDValue N, SDValue &Reg, diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index dd70d729ffc91..3d0ada80856b8 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -29399,6 +29399,25 @@ bool AArch64TargetLowering::useLoadStackGuardNode(const Module &M) const { return true; } +bool AArch64TargetLowering::useStackGuardMixCookie() const { + // Currently only MSVC CRTs XOR the frame pointer into the stack guard value. + return Subtarget->getTargetTriple().isOSMSVCRT() && + !getTargetMachine().Options.EnableGlobalISel; +} + +SDValue AArch64TargetLowering::emitStackGuardMixCookie(SelectionDAG &DAG, + SDValue Val, + const SDLoc &DL, + bool FailureBB) const { + if (FailureBB) + return DAG.getNode( + ISD::ADD, DL, Val.getValueType(), + DAG.getCopyFromReg(DAG.getEntryNode(), DL, + getStackPointerRegisterToSaveRestore(), MVT::i64), + Val); + return Val; +} + unsigned AArch64TargetLowering::combineRepeatedFPDivisors() const { // Combine multiple FDIVs with the same divisor into multiple FMULs by the // reciprocal if there are three or more FDIVs. diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index ca08eb40c956a..c255d0b748645 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -363,6 +363,10 @@ class AArch64TargetLowering : public TargetLowering { shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override; bool useLoadStackGuardNode(const Module &M) const override; + bool useStackGuardMixCookie() const override; + SDValue emitStackGuardMixCookie(SelectionDAG &DAG, SDValue Val, + const SDLoc &DL, + bool FailureBB) const override; TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const override; diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td index 61a8f764e39ed..85ee023cb7498 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -1386,6 +1386,8 @@ def gi_arith_extended_reg32to64_i64 : def arith_uxtx : ComplexPattern; +def add_uxtx : ComplexPattern; + // Floating-point immediate. def fpimm16XForm : SDNodeXFormgetTargetMachine() + .Options.EnableGlobalISel) { + BuildMI(MBB, MI, DL, get(AArch64::SUBXrx64), Reg) + .addReg(AArch64::SP) + .addReg(Reg, RegState::Kill) + .addImm(AArch64_AM::getArithExtendImm(AArch64_AM::UXTX, 0)); + } MBB.erase(MI); diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index b4d8649b31d6d..bd8b841f6f5bf 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2753,6 +2753,11 @@ def : Pat<(AArch64sub_flag GPR64:$Rn, neg_addsub_shifted_imm64:$imm), (ADDSXri GPR64:$Rn, neg_addsub_shifted_imm64:$imm)>; } +let AddedComplexity = 1 in { +def : Pat<(add copyFromSP:$R2, (add_uxtx GPR64:$R3, arith_extendlsl64:$imm)), + (ADDXrx64 GPR64sp:$R2, GPR64:$R3, arith_extendlsl64:$imm)>; +} + def trunc_isWorthFoldingALU : PatFrag<(ops node:$src), (trunc $src)> { let PredicateCode = [{ return isWorthFoldingALU(SDValue(N, 0)); }]; diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index fe9a598fb5611..5c038b6882204 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -2746,13 +2746,14 @@ bool X86TargetLowering::useLoadStackGuardNode(const Module &M) const { return Subtarget.isTargetMachO() && Subtarget.is64Bit(); } -bool X86TargetLowering::useStackGuardXorFP() const { +bool X86TargetLowering::useStackGuardMixCookie() const { // Currently only MSVC CRTs XOR the frame pointer into the stack guard value. return Subtarget.getTargetTriple().isOSMSVCRT() && !Subtarget.isTargetMachO(); } -SDValue X86TargetLowering::emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val, - const SDLoc &DL) const { +SDValue X86TargetLowering::emitStackGuardMixCookie(SelectionDAG &DAG, + SDValue Val, const SDLoc &DL, + bool FailureBB) const { EVT PtrTy = getPointerTy(DAG.getDataLayout()); unsigned XorOp = Subtarget.is64Bit() ? X86::XOR64_FP : X86::XOR32_FP; MachineSDNode *Node = DAG.getMachineNode(XorOp, DL, PtrTy, Val); diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index b7151f65942b4..0b8ffe74512a4 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -1590,11 +1590,11 @@ namespace llvm { Value *getIRStackGuard(IRBuilderBase &IRB) const override; bool useLoadStackGuardNode(const Module &M) const override; - bool useStackGuardXorFP() const override; + bool useStackGuardMixCookie() const override; void insertSSPDeclarations(Module &M) const override; - SDValue emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val, - const SDLoc &DL) const override; - + SDValue emitStackGuardMixCookie(SelectionDAG &DAG, SDValue Val, + const SDLoc &DL, + bool FailureBB) const override; /// Return true if the target stores SafeStack pointer at a fixed offset in /// some non-standard address space, and populates the address space and diff --git a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll index e6a42c382e4f6..50e563847b853 100644 --- a/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll +++ b/llvm/test/CodeGen/AArch64/arm64ec-indirect-call.ll @@ -32,6 +32,7 @@ define void @stackguard(ptr %g) sspreq { ; CHECK-NEXT: adrp x8, __security_cookie ; CHECK-NEXT: ldr x10, [sp, #8] ; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie] +; CHECK-NEXT: sub x8, sp, x8 ; CHECK-NEXT: cmp x8, x10 ; CHECK-NEXT: b.ne .LBB1_2 ; CHECK-NEXT: // %bb.1: diff --git a/llvm/test/CodeGen/AArch64/mingw-refptr.ll b/llvm/test/CodeGen/AArch64/mingw-refptr.ll index 02c81440dd753..286039ce1e856 100644 --- a/llvm/test/CodeGen/AArch64/mingw-refptr.ll +++ b/llvm/test/CodeGen/AArch64/mingw-refptr.ll @@ -77,39 +77,75 @@ entry: declare dso_local void @otherFunc() define dso_local void @sspFunc() #0 { -; CHECK-LABEL: sspFunc: -; CHECK: .seh_proc sspFunc -; CHECK-NEXT: // %bb.0: // %entry -; CHECK-NEXT: sub sp, sp, #32 -; CHECK-NEXT: .seh_stackalloc 32 -; CHECK-NEXT: str x30, [sp, #16] // 8-byte Spill -; CHECK-NEXT: .seh_save_reg x30, 16 -; CHECK-NEXT: .seh_endprologue -; CHECK-NEXT: adrp x8, .refptr.__stack_chk_guard -; CHECK-NEXT: add x0, sp, #7 -; CHECK-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard] -; CHECK-NEXT: ldr x8, [x8] -; CHECK-NEXT: str x8, [sp, #8] -; CHECK-NEXT: bl ptrUser -; CHECK-NEXT: adrp x8, .refptr.__stack_chk_guard -; CHECK-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard] -; CHECK-NEXT: ldr x9, [sp, #8] -; CHECK-NEXT: ldr x8, [x8] -; CHECK-NEXT: cmp x8, x9 -; CHECK-NEXT: b.ne .LBB6_2 -; CHECK-NEXT: // %bb.1: // %entry -; CHECK-NEXT: .seh_startepilogue -; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Reload -; CHECK-NEXT: .seh_save_reg x30, 16 -; CHECK-NEXT: add sp, sp, #32 -; CHECK-NEXT: .seh_stackalloc 32 -; CHECK-NEXT: .seh_endepilogue -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB6_2: // %entry -; CHECK-NEXT: bl __stack_chk_fail -; CHECK-NEXT: brk #0x1 -; CHECK-NEXT: .seh_endfunclet -; CHECK-NEXT: .seh_endproc +; CHECK-SD-LABEL: sspFunc: +; CHECK-SD: .seh_proc sspFunc +; CHECK-SD-NEXT: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #32 +; CHECK-SD-NEXT: .seh_stackalloc 32 +; CHECK-SD-NEXT: str x30, [sp, #16] // 8-byte Spill +; CHECK-SD-NEXT: .seh_save_reg x30, 16 +; CHECK-SD-NEXT: .seh_endprologue +; CHECK-SD-NEXT: adrp x8, .refptr.__stack_chk_guard +; CHECK-SD-NEXT: add x0, sp, #7 +; CHECK-SD-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard] +; CHECK-SD-NEXT: ldr x8, [x8] +; CHECK-SD-NEXT: sub x8, sp, x8 +; CHECK-SD-NEXT: str x8, [sp, #8] +; CHECK-SD-NEXT: bl ptrUser +; CHECK-SD-NEXT: adrp x8, .refptr.__stack_chk_guard +; CHECK-SD-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard] +; CHECK-SD-NEXT: ldr x9, [sp, #8] +; CHECK-SD-NEXT: ldr x8, [x8] +; CHECK-SD-NEXT: sub x8, sp, x8 +; CHECK-SD-NEXT: cmp x8, x9 +; CHECK-SD-NEXT: b.ne .LBB6_2 +; CHECK-SD-NEXT: // %bb.1: // %entry +; CHECK-SD-NEXT: .seh_startepilogue +; CHECK-SD-NEXT: ldr x30, [sp, #16] // 8-byte Reload +; CHECK-SD-NEXT: .seh_save_reg x30, 16 +; CHECK-SD-NEXT: add sp, sp, #32 +; CHECK-SD-NEXT: .seh_stackalloc 32 +; CHECK-SD-NEXT: .seh_endepilogue +; CHECK-SD-NEXT: ret +; CHECK-SD-NEXT: .LBB6_2: // %entry +; CHECK-SD-NEXT: bl __stack_chk_fail +; CHECK-SD-NEXT: brk #0x1 +; CHECK-SD-NEXT: .seh_endfunclet +; CHECK-SD-NEXT: .seh_endproc +; +; CHECK-GI-LABEL: sspFunc: +; CHECK-GI: .seh_proc sspFunc +; CHECK-GI-NEXT: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #32 +; CHECK-GI-NEXT: .seh_stackalloc 32 +; CHECK-GI-NEXT: str x30, [sp, #16] // 8-byte Spill +; CHECK-GI-NEXT: .seh_save_reg x30, 16 +; CHECK-GI-NEXT: .seh_endprologue +; CHECK-GI-NEXT: adrp x8, .refptr.__stack_chk_guard +; CHECK-GI-NEXT: add x0, sp, #7 +; CHECK-GI-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard] +; CHECK-GI-NEXT: ldr x8, [x8] +; CHECK-GI-NEXT: str x8, [sp, #8] +; CHECK-GI-NEXT: bl ptrUser +; CHECK-GI-NEXT: adrp x8, .refptr.__stack_chk_guard +; CHECK-GI-NEXT: ldr x8, [x8, :lo12:.refptr.__stack_chk_guard] +; CHECK-GI-NEXT: ldr x9, [sp, #8] +; CHECK-GI-NEXT: ldr x8, [x8] +; CHECK-GI-NEXT: cmp x8, x9 +; CHECK-GI-NEXT: b.ne .LBB6_2 +; CHECK-GI-NEXT: // %bb.1: // %entry +; CHECK-GI-NEXT: .seh_startepilogue +; CHECK-GI-NEXT: ldr x30, [sp, #16] // 8-byte Reload +; CHECK-GI-NEXT: .seh_save_reg x30, 16 +; CHECK-GI-NEXT: add sp, sp, #32 +; CHECK-GI-NEXT: .seh_stackalloc 32 +; CHECK-GI-NEXT: .seh_endepilogue +; CHECK-GI-NEXT: ret +; CHECK-GI-NEXT: .LBB6_2: // %entry +; CHECK-GI-NEXT: bl __stack_chk_fail +; CHECK-GI-NEXT: brk #0x1 +; CHECK-GI-NEXT: .seh_endfunclet +; CHECK-GI-NEXT: .seh_endproc entry: %c = alloca i8, align 1 call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %c) @@ -133,6 +169,3 @@ attributes #0 = { sspstrong } ; CHECK: .refptr.var: ; CHECK: .xword var -;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: -; CHECK-GI: {{.*}} -; CHECK-SD: {{.*}} diff --git a/llvm/test/CodeGen/AArch64/stack-protector-target.ll b/llvm/test/CodeGen/AArch64/stack-protector-target.ll index b1ddd1d0d160f..98ffaf830b495 100644 --- a/llvm/test/CodeGen/AArch64/stack-protector-target.ll +++ b/llvm/test/CodeGen/AArch64/stack-protector-target.ll @@ -31,14 +31,18 @@ declare void @_Z7CapturePi(ptr) ; WINDOWS-AARCH64: adrp x8, __security_cookie ; WINDOWS-AARCH64: ldr x8, [x8, :lo12:__security_cookie] +; WINDOWS-AARCH64: sub x8, sp, x8 ; WINDOWS-AARCH64: str x8, [sp, #8] ; WINDOWS-AARCH64: bl _Z7CapturePi -; WINDOWS-AARCH64: ldr x0, [sp, #8] +; WINDOWS-AARCH64: ldr x8, [sp, #8] +; WINDOWS-AARCH64: add x0, sp, x8 ; WINDOWS-AARCH64: bl __security_check_cookie ; WINDOWS-ARM64EC: adrp x8, __security_cookie ; WINDOWS-ARM64EC: ldr x8, [x8, :lo12:__security_cookie] +; WINDOWS-ARM64EC: sub x8, sp, x8 ; WINDOWS-ARM64EC: str x8, [sp, #8] ; WINDOWS-ARM64EC: bl "#_Z7CapturePi" -; WINDOWS-ARM64EC: ldr x0, [sp, #8] +; WINDOWS-ARM64EC: ldr x8, [sp, #8] +; WINDOWS-ARM64EC: add x0, sp, x8 ; WINDOWS-ARM64EC: bl "#__security_check_cookie_arm64ec"