diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 90e1f8d1eb5e9..edb7d4e0b9480 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -157,6 +157,7 @@ CODEGENOPT(InstrumentForProfiling , 1, 0, Benign) ///< Set when -pg is enabled. CODEGENOPT(CallFEntry , 1, 0, Benign) ///< Set when -mfentry is enabled. CODEGENOPT(MNopMCount , 1, 0, Benign) ///< Set when -mnop-mcount is enabled. CODEGENOPT(RecordMCount , 1, 0, Benign) ///< Set when -mrecord-mcount is enabled. +CODEGENOPT(StackProtectorGuardRecord, 1, 0, Benign) ///< Set when -mstack-protector-guard-record is enabled. CODEGENOPT(PackedStack , 1, 0, Benign) ///< Set when -mpacked-stack is enabled. CODEGENOPT(LessPreciseFPMAD , 1, 0, Benign) ///< Enable less precise MAD instructions to ///< be generated. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 0c9584f1b479f..1af0459e4e4ac 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5728,6 +5728,13 @@ def mstack_protector_guard_reg_EQ : Joined<["-"], "mstack-protector-guard-reg="> Visibility<[ClangOption, CC1Option]>, HelpText<"Use the given reg for addressing the stack-protector guard">, MarshallingInfoString>; +def mstackprotector_guard_record + : Flag<["-"], "mstack-protector-guard-record">, + HelpText<"Generate a __stackprotector_loc section entry for each load of " + "the stackguard address.">, + Visibility<[ClangOption, CC1Option]>, + Group, + MarshallingInfoFlag>; def mfentry : Flag<["-"], "mfentry">, HelpText<"Insert calls to fentry at function entry (x86/SystemZ only)">, Visibility<[ClangOption, CC1Option]>, Group, MarshallingInfoFlag>; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 88628530cf66b..6e35f91cac811 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -1195,6 +1195,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, } } + if (CGM.getCodeGenOpts().StackProtectorGuardRecord) { + if (CGM.getCodeGenOpts().StackProtectorGuard != "global") + CGM.getDiags().Report(diag::err_opt_not_valid_without_opt) + << "-mstack-protector-guard-record" + << "-mstack-protector-guard=global"; + Fn->addFnAttr("mstackprotector-guard-record"); + } + if (CGM.getCodeGenOpts().PackedStack) { if (getContext().getTargetInfo().getTriple().getArch() != llvm::Triple::systemz) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 79edc561c551f..db80662f0dda5 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3433,11 +3433,12 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, StringRef Value = A->getValue(); if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() && !EffectiveTriple.isARM() && !EffectiveTriple.isThumb() && - !EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC()) + !EffectiveTriple.isRISCV() && !EffectiveTriple.isPPC() && + !EffectiveTriple.isSystemZ()) D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) << TripleStr; if ((EffectiveTriple.isX86() || EffectiveTriple.isARM() || - EffectiveTriple.isThumb()) && + EffectiveTriple.isThumb() || EffectiveTriple.isSystemZ()) && Value != "tls" && Value != "global") { D.Diag(diag::err_drv_invalid_value_with_suggestion) << A->getOption().getName() << Value << "tls global"; @@ -3553,6 +3554,10 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, } A->render(Args, CmdArgs); } + + if (Arg *A = Args.getLastArg(options::OPT_mstackprotector_guard_record)) { + A->render(Args, CmdArgs); + } } static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args, diff --git a/clang/test/CodeGen/SystemZ/stack-guard-pseudos.c b/clang/test/CodeGen/SystemZ/stack-guard-pseudos.c new file mode 100644 index 0000000000000..8e8e919e9a348 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/stack-guard-pseudos.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -S -mllvm -stop-after=systemz-isel -stack-protector 1 -triple=s390x-ibm-linux < %s -o - | FileCheck %s + +// CHECK: bb.0.entry: +// CHECK: MOVE_STACK_GUARD %stack.0.StackGuardSlot, 0 +// CHECK: COMPARE_STACK_GUARD %stack.0.StackGuardSlot, implicit-def $cc + +extern char *strcpy (char * D, const char * S); +int main(int argc, char *argv[]) +{ + char Buffer[8] = {0}; + strcpy(Buffer, argv[1]); + return 0; +} diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp index e31d7c6a86476..7156b7d2113ac 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -23,6 +23,7 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/GOFF.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" @@ -740,6 +741,31 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { case SystemZ::EH_SjLj_Setup: return; + case SystemZ::LARL: + case SystemZ::LGRL: { + // If "-mstackprotector-guard-record" was supplied on the command line, + // we need special handling for LARL/LGRL. + if (MF->getFunction().hasFnAttribute("mstackprotector-guard-record")) { + // Obtain the name of the stack guard, and determine if that + // is what we are loading here. + const MachineOperand &Op = MI->getOperand(1); + if (Op.isGlobal() && (Op.getGlobal()->getName() == "__stack_chk_guard")) { + // If so, drop into the __stack_protector_loc section and record + // this locaytion. + MCSymbol *Sym = OutContext.createTempSymbol(); + OutStreamer->pushSection(); + OutStreamer->switchSection(OutContext.getELFSection( + "__stack_protector_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); + OutStreamer->emitSymbolValue(Sym, getDataLayout().getPointerSize()); + OutStreamer->popSection(); + OutStreamer->emitLabel(Sym); + } + } + // Otherwise, keep the MI as it is. + Lower.lower(MI, LoweredMI); + break; + } + default: Lower.lower(MI, LoweredMI); break; diff --git a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index a05fdc74e6366..3196a9d99ad88 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -10,10 +10,13 @@ // //===----------------------------------------------------------------------===// -#include "SystemZTargetMachine.h" +#include "MCTargetDesc/SystemZMCTargetDesc.h" #include "SystemZISelLowering.h" +#include "SystemZTargetMachine.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/KnownBits.h" #include "llvm/Support/raw_ostream.h" @@ -369,7 +372,11 @@ class SystemZDAGToDAGISel : public SelectionDAGISel { if (F.hasFnAttribute("mrecord-mcount")) report_fatal_error("mrecord-mcount only supported with fentry-call"); } - + if (F.getParent()->getStackProtectorGuard() != "global") { + if (F.hasFnAttribute("mstack-protector-guard-record")) + report_fatal_error("mstack-protector-guard-record only supported with " + "mstack-protector-guard=global"); + } Subtarget = &MF.getSubtarget(); return SelectionDAGISel::runOnMachineFunction(MF); } diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index de28faf4908e9..a2ca28086bd76 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -11,21 +11,29 @@ //===----------------------------------------------------------------------===// #include "SystemZISelLowering.h" +#include "MCTargetDesc/SystemZMCTargetDesc.h" #include "SystemZCallingConv.h" #include "SystemZConstantPoolValue.h" #include "SystemZMachineFunctionInfo.h" +#include "SystemZRegisterInfo.h" #include "SystemZTargetMachine.h" #include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsS390.h" +#include "llvm/IR/Module.h" #include "llvm/IR/PatternMatch.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/KnownBits.h" @@ -8177,6 +8185,23 @@ SDValue SystemZTargetLowering::combineSTORE( SN->getMemOperand()); } } + + // combine STORE (LOAD_STACK_GUARD) into MOVE_STACK_GUARD + if (Op1->isMachineOpcode() && + (Op1->getMachineOpcode() == SystemZ::LOAD_STACK_GUARD)) { + // If so, create a MOVE_STACK_GUARD node to subsume the LOAD_STACK_GUARD, + // Store sequence. + int FI = cast(SN->getOperand(2))->getIndex(); + // Dummy Register, FrameIndex, Dummy Displacement + SDValue Ops[] = {DAG.getTargetFrameIndex(FI, MVT::i64), + DAG.getTargetConstant(0, SDLoc(SN), MVT::i64), + SN->getChain()}; + MachineSDNode *Move = DAG.getMachineNode(SystemZ::MOVE_STACK_GUARD, + SDLoc(SN), MVT::Other, Ops); + + return SDValue(Move, 0); + } + // Combine STORE (BSWAP) into STRVH/STRV/STRVG/VSTBR if (!SN->isTruncatingStore() && Op1.getOpcode() == ISD::BSWAP && @@ -9106,6 +9131,41 @@ SDValue SystemZTargetLowering::combineSELECT_CCMASK( return SDValue(); } +SDValue SystemZTargetLowering::combineICMP(SDNode *N, + DAGCombinerInfo &DCI) const { + SelectionDAG &DAG = DCI.DAG; + SDLoc DL(N); + + // Combine icmp (load fi, LOAD_STACK_GUARD) into COMPARE_STACK_GUARD. + + const SDValue &LHS = N->getOperand(0); + const SDValue &RHS = N->getOperand(1); + + if (!ISD::isNormalLoad(RHS.getNode()) || + !(LHS.isMachineOpcode() && + (LHS->getMachineOpcode() == SystemZ::LOAD_STACK_GUARD))) + return SDValue(); + + auto const *StackLoad = cast(RHS.getNode()); + + // The StackLoad will have an outgoing chain that needs to be redirected. + SDValue InChain = StackLoad->getChain(); + SDValue OutChain = SDValue(const_cast(StackLoad), 1); + DAG.ReplaceAllUsesOfValueWith(OutChain, InChain); + + int FI = cast(StackLoad->getOperand(1))->getIndex(); + + // Now, create a COMPARE_STACK_GUARD node to subsume the + // LoadFI, LOAD_STACK_GUARD, Compare sequence. + // Operands are the FrameIndex where the stackguard is stored, and the input + // chain. + SDValue Ops[] = {DAG.getTargetFrameIndex(FI, MVT::i64), InChain}; + MachineSDNode *Move = + DAG.getMachineNode(SystemZ::COMPARE_STACK_GUARD, DL, MVT::i32, Ops); + + return SDValue(Move, 0); +} + SDValue SystemZTargetLowering::combineGET_CCMASK( SDNode *N, DAGCombinerInfo &DCI) const { @@ -9420,6 +9480,8 @@ SDValue SystemZTargetLowering::PerformDAGCombine(SDNode *N, case SystemZISD::BR_CCMASK: return combineBR_CCMASK(N, DCI); case SystemZISD::SELECT_CCMASK: return combineSELECT_CCMASK(N, DCI); case SystemZISD::GET_CCMASK: return combineGET_CCMASK(N, DCI); + case SystemZISD::ICMP: + return combineICMP(N, DCI); case ISD::SRL: case ISD::SRA: return combineShiftToMulAddHigh(N, DCI); case ISD::MUL: return combineMUL(N, DCI); @@ -11088,6 +11150,91 @@ getBackchainAddress(SDValue SP, SelectionDAG &DAG) const { DAG.getIntPtrConstant(TFL->getBackchainOffset(MF), DL)); } +namespace { +// The custom inserters for MOVE_STACK_GUARD and COMPARE_STACK_GUARD both +// need to load the address of the stack guard. This function enables that. +Register emitLoadStackGuard(MachineInstr &MI, MachineBasicBlock *MBB) { + MachineFunction &MF = *MBB->getParent(); + auto *II = MF.getTarget().getMCInstrInfo(); + const Register AddrReg = + MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass); + + Module *M = MF.getFunction().getParent(); + StringRef GuardType = M->getStackProtectorGuard(); + + if (GuardType.empty() || (GuardType == "tls")) { + // TLS-based stack guard loading will be emitted post RA. + // This is so we can more easily guarantee the ear, sllg, ear, load + // sequence. + BuildMI(*MBB, MI, MI.getDebugLoc(), II->get(TargetOpcode::LOAD_STACK_GUARD), + AddrReg); + + } else if (GuardType == "global") { + // Obtain the global value. + const GlobalValue *GV = M->getOrInsertGlobal( + "__stack_chk_guard", PointerType::getUnqual(M->getContext())); + // Emit the move. + if (M->getPICLevel() == PICLevel::NotPIC) { + BuildMI(*MBB, MI, MI.getDebugLoc(), II->get(SystemZ::LARL), AddrReg) + .addGlobalAddress(GV); + } else { + BuildMI(*MBB, MI, MI.getDebugLoc(), II->get(SystemZ::LGRL), AddrReg) + .addGlobalAddress(GV); + } + } else { + llvm_unreachable( + (Twine("Unknown stack protector type \"") + GuardType + "\"") + .str() + .c_str()); + } + return AddrReg; +} +} // namespace + +// Custom Inserter for MOVE_STACK_GUARD. Loads the address of the stack guard, +// then inserts an MVC. +MachineBasicBlock * +SystemZTargetLowering::emitMoveStackGuard(MachineInstr &MI, + MachineBasicBlock *MBB) const { + MachineOperand &FI = MI.getOperand(0); + auto *II = MBB->getParent()->getTarget().getMCInstrInfo(); + Register AddrReg = emitLoadStackGuard(MI, MBB); + + assert(FI.isFI() && "Operand 0 of MOVE_STACK_GUARD is not a frame index."); + + BuildMI(*MBB, MI, MI.getDebugLoc(), II->get(SystemZ::MVC)) + .addFrameIndex(FI.getIndex()) + .addImm(0) + .addImm(8) + .addReg(AddrReg) + .addImm(0); + MI.removeFromParent(); + + return MBB; +} + +// Custom Inserter for COMPARE_STACK_GUARD. Loads the address of the stack +// guard, then inserts a CLC. +MachineBasicBlock * +SystemZTargetLowering::emitCompareStackGuard(MachineInstr &MI, + MachineBasicBlock *MBB) const { + MachineOperand &FI = MI.getOperand(0); + auto *II = MBB->getParent()->getTarget().getMCInstrInfo(); + Register AddrReg = emitLoadStackGuard(MI, MBB); + + assert(FI.isFI() && "Operand 0 of COMPARE_STACK_GUARD is not a frame index."); + + BuildMI(*MBB, MI, MI.getDebugLoc(), II->get(SystemZ::CLC)) + .addFrameIndex(FI.getIndex()) + .addImm(0) + .addImm(8) + .addReg(AddrReg) + .addImm(0); + MI.removeFromParent(); + + return MBB; +} + MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter( MachineInstr &MI, MachineBasicBlock *MBB) const { switch (MI.getOpcode()) { @@ -11241,6 +11388,12 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter( case SystemZ::EH_SjLj_LongJmp: return emitEHSjLjLongJmp(MI, MBB); + case SystemZ::MOVE_STACK_GUARD: + return emitMoveStackGuard(MI, MBB); + + case SystemZ::COMPARE_STACK_GUARD: + return emitCompareStackGuard(MI, MBB); + case TargetOpcode::STACKMAP: case TargetOpcode::PATCHPOINT: return emitPatchPoint(MI, MBB); diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index d5b76031766dd..4aace28a5dd12 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -797,6 +797,7 @@ class SystemZTargetLowering : public TargetLowering { SDValue combineBSWAP(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineSETCC(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineBR_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const; + SDValue combineICMP(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineSELECT_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineGET_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineShiftToMulAddHigh(SDNode *N, DAGCombinerInfo &DCI) const; @@ -851,6 +852,10 @@ class SystemZTargetLowering : public TargetLowering { unsigned Opcode) const; MachineBasicBlock *emitProbedAlloca(MachineInstr &MI, MachineBasicBlock *MBB) const; + MachineBasicBlock *emitMoveStackGuard(MachineInstr &MI, + MachineBasicBlock *MBB) const; + MachineBasicBlock *emitCompareStackGuard(MachineInstr &MI, + MachineBasicBlock *MBB) const; SDValue getBackchainAddress(SDValue SP, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index 2e21f27c9032f..fd34f0cb86b95 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -13,6 +13,7 @@ #include "SystemZInstrInfo.h" #include "MCTargetDesc/SystemZMCTargetDesc.h" #include "SystemZ.h" +#include "SystemZISelLowering.h" #include "SystemZInstrBuilder.h" #include "SystemZSubtarget.h" #include "llvm/ADT/Statistic.h" @@ -33,6 +34,8 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/CodeGen/VirtRegMap.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/BranchProbability.h" @@ -228,35 +231,6 @@ void SystemZInstrInfo::expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode, MI.eraseFromParent(); } -void SystemZInstrInfo::expandLoadStackGuard(MachineInstr *MI) const { - MachineBasicBlock *MBB = MI->getParent(); - MachineFunction &MF = *MBB->getParent(); - const Register Reg64 = MI->getOperand(0).getReg(); - const Register Reg32 = RI.getSubReg(Reg64, SystemZ::subreg_l32); - - // EAR can only load the low subregister so us a shift for %a0 to produce - // the GR containing %a0 and %a1. - - // ear , %a0 - BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32) - .addReg(SystemZ::A0) - .addReg(Reg64, RegState::ImplicitDefine); - - // sllg , , 32 - BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::SLLG), Reg64) - .addReg(Reg64) - .addReg(0) - .addImm(32); - - // ear , %a1 - BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32) - .addReg(SystemZ::A1); - - // lg , 40() - MI->setDesc(get(SystemZ::LG)); - MachineInstrBuilder(MF, MI).addReg(Reg64).addImm(40).addReg(0); -} - // Emit a zero-extending move from 32-bit GPR SrcReg to 32-bit GPR // DestReg before MBBI in MBB. Use LowLowOpcode when both DestReg and SrcReg // are low registers, otherwise use RISB[LH]G. Size is the number of bits @@ -1054,8 +1028,7 @@ void SystemZInstrInfo::loadRegFromStackSlot( // and no index. Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores. static bool isSimpleBD12Move(const MachineInstr *MI, unsigned Flag) { const MCInstrDesc &MCID = MI->getDesc(); - return ((MCID.TSFlags & Flag) && - isUInt<12>(MI->getOperand(2).getImm()) && + return ((MCID.TSFlags & Flag) && isUInt<12>(MI->getOperand(2).getImm()) && MI->getOperand(3).getReg() == 0); } @@ -1812,6 +1785,49 @@ bool SystemZInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { } } +void SystemZInstrInfo::expandLoadStackGuard(MachineInstr *MI) const { + MachineBasicBlock *MBB = MI->getParent(); + MachineFunction &MF = *MBB->getParent(); + const Register Reg64 = MI->getOperand(0).getReg(); + const Register Reg32 = RI.getSubReg(Reg64, SystemZ::subreg_l32); + + Module *M = MF.getFunction().getParent(); + StringRef GuardType = M->getStackProtectorGuard(); + + if (GuardType.empty() || (GuardType == "tls")) { + // EAR can only load the low subregister so use a shift for %a0 to produce + // the GR containing %a0 and %a1. + + // ear , %a0 + BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32) + .addReg(SystemZ::A0) + .addReg(Reg64, RegState::ImplicitDefine); + + // sllg , , 32 + BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::SLLG), Reg64) + .addReg(Reg64) + .addReg(0) + .addImm(32); + + // ear , %a1 + BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32) + .addReg(SystemZ::A1); + + // lg , 40() + MI->setDesc(get(SystemZ::LG)); + MachineInstrBuilder(MF, MI).addReg(Reg64).addImm(40).addReg(0); + } else if (GuardType == "global") { + // Expanding the load of a global stack guard post-RA is an error. + llvm_unreachable( + "global stack guard expansion should have happened during isel."); + } else { + llvm_unreachable( + (Twine("Unknown stack protector type \"") + GuardType + "\"") + .str() + .c_str()); + } +} + unsigned SystemZInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { if (MI.isInlineAsm()) { const MachineFunction *MF = MI.getParent()->getParent(); diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index 4f75e0132610e..4d3f5f1bdac82 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -521,6 +521,14 @@ let SimpleBDXStore = 1, mayStore = 1 in { [(store GR128:$src, bdxaddr20only128:$dst)]>; } } + +let hasNoSchedulingInfo = 1, usesCustomInserter = 1, mayLoad = 1 in { + let mayStore = 1 in def MOVE_STACK_GUARD + : Pseudo<(outs), (ins bdaddr12only:$grdloc), []>; + let Defs = [CC] in def COMPARE_STACK_GUARD + : Pseudo<(outs), (ins bdaddr12only:$grdloc), []>; +} + def STRL : StoreRILPC<"strl", 0xC4F, aligned_store, GR32>; def STGRL : StoreRILPC<"stgrl", 0xC4B, aligned_store, GR64>; diff --git a/llvm/test/CodeGen/SystemZ/stack-guard-global-nopic.ll b/llvm/test/CodeGen/SystemZ/stack-guard-global-nopic.ll new file mode 100644 index 0000000000000..ec9f1b5c0d54a --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/stack-guard-global-nopic.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +define i32 @test_global_stack_guard() #0 { +; CHECK-LABEL: test_global_stack_guard: +; CHECK: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp0 +; CHECK-NEXT: .text +; CHECK-NEXT:.Ltmp0: +; CHECK-NEXT: larl %r13, __stack_chk_guard +; CHECK-NEXT: mvc 1184(8,%r15), 0(%r13) +; CHECK: la %r2, 160(%r15) +; CHECK-NEXT: brasl %r14, foo3@PLT +; CHECK-NEXT: clc 1184(8,%r15), 0(%r13) +; CHECK-NEXT: jlh .LBB0_2 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: lhi %r2, 0 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB0_2: # %entry +; CHECK-NEXT: brasl %r14, __stack_chk_fail@PLT +entry: + %a1 = alloca [256 x i32], align 4 + call void @foo3(ptr %a1) + ret i32 0 +} + +declare void @foo3(ptr) + +attributes #0 = { sspstrong "mstackprotector-guard-record" } + + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"stack-protector-guard", !"global"} diff --git a/llvm/test/CodeGen/SystemZ/stack-guard-global-pic.ll b/llvm/test/CodeGen/SystemZ/stack-guard-global-pic.ll new file mode 100644 index 0000000000000..c354cb086e9d5 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/stack-guard-global-pic.ll @@ -0,0 +1,41 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +define i32 @test_global_stack_guard() #0 { +; CHECK-LABEL: test_global_stack_guard: +; CHECK: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp0 +; CHECK-NEXT: .text +; CHECK-NEXT:.Ltmp0: +; CHECK-NEXT: lgrl %r1, __stack_chk_guard +; CHECK-NEXT: mvc 1184(8,%r15), 0(%r1) +; CHECK: la %r2, 160(%r15) +; CHECK-NEXT: brasl %r14, foo3@PLT +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp1 +; CHECK-NEXT: .text +; CHECK-NEXT:.Ltmp1: +; CHECK-NEXT: lgrl %r1, __stack_chk_guard +; CHECK-NEXT: clc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: jlh .LBB0_2 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: lhi %r2, 0 +; CHECK-NEXT: lmg %r14, %r15, 1304(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB0_2: # %entry +; CHECK-NEXT: brasl %r14, __stack_chk_fail@PLT +entry: + %a1 = alloca [256 x i32], align 4 + call void @foo3(ptr %a1) + ret i32 0 +} + +declare void @foo3(ptr) + +attributes #0 = { sspstrong "mstackprotector-guard-record" } + + +!llvm.module.flags = !{!0, !1, !2} +!0 = !{i32 1, !"stack-protector-guard", !"global"} +!1 = !{i32 8, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} diff --git a/llvm/test/CodeGen/SystemZ/stack-guard-tls.ll b/llvm/test/CodeGen/SystemZ/stack-guard-tls.ll new file mode 100644 index 0000000000000..00d139e84a3b6 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/stack-guard-tls.ll @@ -0,0 +1,33 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +define i32 @test_tls_stack_guard() #0 { +; CHECK-LABEL: test_tls_stack_guard: +; CHECK: ear %r1, %a0 +; CHECK-NEXT: sllg %r1, %r1, 32 +; CHECK-NEXT: ear %r1, %a1 +; CHECK-NEXT: lg %r1, 40(%r1) +; CHECK-NEXT: mvc 1184(8,%r15), 0(%r1) +; CHECK: la %r2, 160(%r15) +; CHECK-NEXT: brasl %r14, foo3@PLT +; CHECK-NEXT: ear %r1, %a0 +; CHECK-NEXT: sllg %r1, %r1, 32 +; CHECK-NEXT: ear %r1, %a1 +; CHECK-NEXT: lg %r1, 40(%r1) +; CHECK-NEXT: clc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: jlh .LBB0_2 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: lhi %r2, 0 +; CHECK-NEXT: lmg %r14, %r15, 1304(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB0_2: # %entry +; CHECK-NEXT: brasl %r14, __stack_chk_fail@PLT +entry: + %a1 = alloca [256 x i32], align 4 + call void @foo3(ptr %a1) + ret i32 0 +} + +declare void @foo3(ptr) + +attributes #0 = { sspstrong } diff --git a/llvm/test/CodeGen/SystemZ/stack-guard.ll b/llvm/test/CodeGen/SystemZ/stack-guard.ll deleted file mode 100644 index 04a87b4632dd2..0000000000000 --- a/llvm/test/CodeGen/SystemZ/stack-guard.ll +++ /dev/null @@ -1,33 +0,0 @@ -; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s - -; CHECK-LABEL: @test_stack_guard -; CHECK: ear [[REG1:%r[1-9][0-9]?]], %a0 -; CHECK: sllg [[REG1]], [[REG1]], 32 -; CHECK: ear [[REG1]], %a1 -; CHECK: lg [[REG1]], 40([[REG1]]) -; CHECK: stg [[REG1]], {{[0-9]*}}(%r15) -; CHECK: brasl %r14, foo3@PLT -; CHECK: ear [[REG2:%r[1-9][0-9]?]], %a0 -; CHECK: sllg [[REG2]], [[REG2]], 32 -; CHECK: ear [[REG2]], %a1 -; CHECK: lg [[REG2]], 40([[REG2]]) -; CHECK: cg [[REG2]], {{[0-9]*}}(%r15) - -define i32 @test_stack_guard() #0 { -entry: - %a1 = alloca [256 x i32], align 4 - call void @llvm.lifetime.start.p0(i64 1024, ptr %a1) - call void @foo3(ptr %a1) - call void @llvm.lifetime.end.p0(i64 1024, ptr %a1) - ret i32 0 -} - -; Function Attrs: nounwind -declare void @llvm.lifetime.start.p0(i64, ptr nocapture) - -declare void @foo3(ptr) - -; Function Attrs: nounwind -declare void @llvm.lifetime.end.p0(i64, ptr nocapture) - -attributes #0 = { sspstrong }