diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 52360b67b306c..a1c6597a1c90b 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/Options/Options.td b/clang/include/clang/Options/Options.td index 34a6651d2445c..db6884d734412 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -5749,6 +5749,14 @@ 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 __stack_protector_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 64e594d09067b..150bf6dbe9f3f 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 2f0aec3ec3c37..1b0693d7aa8a7 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3438,22 +3438,24 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, } const std::string &TripleStr = EffectiveTriple.getTriple(); + StringRef GuardValue; if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) { - StringRef Value = A->getValue(); + GuardValue = 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()) && - Value != "tls" && Value != "global") { + EffectiveTriple.isThumb() || EffectiveTriple.isSystemZ()) && + GuardValue != "tls" && GuardValue != "global") { D.Diag(diag::err_drv_invalid_value_with_suggestion) - << A->getOption().getName() << Value << "tls global"; + << A->getOption().getName() << GuardValue << "tls global"; return; } if ((EffectiveTriple.isARM() || EffectiveTriple.isThumb()) && - Value == "tls") { + GuardValue == "tls") { if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) { D.Diag(diag::err_drv_ssp_missing_offset_argument) << A->getAsString(Args); @@ -3477,18 +3479,19 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, CmdArgs.push_back("-target-feature"); CmdArgs.push_back("+read-tp-tpidruro"); } - if (EffectiveTriple.isAArch64() && Value != "sysreg" && Value != "global") { + if (EffectiveTriple.isAArch64() && GuardValue != "sysreg" && + GuardValue != "global") { D.Diag(diag::err_drv_invalid_value_with_suggestion) - << A->getOption().getName() << Value << "sysreg global"; + << A->getOption().getName() << GuardValue << "sysreg global"; return; } if (EffectiveTriple.isRISCV() || EffectiveTriple.isPPC()) { - if (Value != "tls" && Value != "global") { + if (GuardValue != "tls" && GuardValue != "global") { D.Diag(diag::err_drv_invalid_value_with_suggestion) - << A->getOption().getName() << Value << "tls global"; + << A->getOption().getName() << GuardValue << "tls global"; return; } - if (Value == "tls") { + if (GuardValue == "tls") { if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) { D.Diag(diag::err_drv_ssp_missing_offset_argument) << A->getAsString(Args); @@ -3562,6 +3565,21 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, } A->render(Args, CmdArgs); } + + if (Arg *A = Args.getLastArg(options::OPT_mstackprotector_guard_record)) { + if (!EffectiveTriple.isSystemZ()) { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getAsString(Args) << TripleStr; + return; + } + if (GuardValue != "global") { + D.Diag(diag::err_drv_argument_only_allowed_with) + << "-mstack-protector-guard-record" + << "-mstack-protector-guard=global"; + return; + } + 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..b364aa4028ec7 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/stack-guard-pseudos.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -S -mllvm -stop-after=systemz-isel -stack-protector 1 -triple=s390x-ibm-linux < %s -o - | FileCheck -check-prefix=CHECK-PSEUDOS %s +// RUN: not %clang_cc1 -S -stack-protector 1 -mstack-protector-guard-record -triple=s390x-ibm-linux < %s -o - 2>&1 | FileCheck -check-prefix=CHECK-OPTS %s +// CHECK-PSEUDOS: bb.0.entry: +// CHECK-PSEUDOS: %3:addr64bit = LOAD_STACK_GUARD_ADDRESS +// CHECK-PSEUDOS: MOVE_STACK_GUARD %stack.0.StackGuardSlot, 0, %3 +// CHECK-PSEUDOS: COMPARE_STACK_GUARD %stack.0.StackGuardSlot, 0, %3, 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; +} + +// CHECK-OPTS: error: option '-mstack-protector-guard-record' cannot be specified without '-mstack-protector-guard=global' diff --git a/clang/test/Driver/stack-protector-guard.c b/clang/test/Driver/stack-protector-guard.c index 666c83079e519..8c8aacfa574c7 100644 --- a/clang/test/Driver/stack-protector-guard.c +++ b/clang/test/Driver/stack-protector-guard.c @@ -155,3 +155,21 @@ // CHECK-TLS-POWERPC32: "-cc1" {{.*}}"-mstack-protector-guard=tls" "-mstack-protector-guard-offset=24" "-mstack-protector-guard-reg=r2" // INVALID-REG-POWERPC32: error: invalid value 'r3' in 'mstack-protector-guard-reg=', expected one of: r2 + +// RUN: %clang -### -target systemz-unknown-elf -mstack-protector-guard=tls %s 2>&1 | \ +// RUN: FileCheck -check-prefix=CHECK_TLS_SYSTEMZ %s +// CHECK_TLS_SYSTEMZ: "-cc1" {{.*}}"-mstack-protector-guard=tls" + +// RUN: %clang -### -target systemz-unknown-elf -mstack-protector-guard=global %s 2>&1 | \ +// RUN: FileCheck -check-prefix=CHECK_GLOBAL_SYSTEMZ %s +// CHECK_GLOBAL_SYSTEMZ: "-cc1" {{.*}}"-mstack-protector-guard=global" + +// RUN: %clang -### -target systemz-unknown-elf -mstack-protector-guard=global \ +// RUN: -mstack-protector-guard-record %s 2>&1 | \ +// RUN: FileCheck -check-prefix=CHECK_GLOBAL_RECORD_SYSTEMZ %s +// CHECK_GLOBAL_RECORD_SYSTEMZ: "-cc1" {{.*}}"-mstack-protector-guard=global" "-mstack-protector-guard-record" + +// RUN: not %clang -target systemz-unknown-elf -mstack-protector-guard=tls \ +// RUN: -mstack-protector-guard-record %s 2>&1 | \ +// RUN: FileCheck -check-prefix=INVALID_TLS_RECORD_SYSTEMZ %s +// INVALID_TLS_RECORD_SYSTEMZ: error: invalid argument '-mstack-protector-guard-record' only allowed with '-mstack-protector-guard=global' diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp index e31d7c6a86476..ca27ff5d28241 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -24,9 +24,11 @@ #include "llvm/BinaryFormat/GOFF.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" @@ -213,6 +215,16 @@ SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) { return insert(Sym, ADAslotType); } +namespace { +unsigned long getStackGuardOffset(const MachineBasicBlock *MBB) { + // In the TLS (default) case, AddrReg will contain the thread pointer, so we + // need to add 40 bytes to get the actual address of the stack guard. + StringRef GuardType = + MBB->getParent()->getFunction().getParent()->getStackProtectorGuard(); + return (GuardType == "global") ? 0 : 40; +} +} // namespace + void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(), getSubtargetInfo().getFeatureBits()); @@ -740,6 +752,42 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { case SystemZ::EH_SjLj_Setup: return; + case SystemZ::LOAD_STACK_GUARD: { + // If requested, record address of stack guard address load + if (MF->getFunction().hasFnAttribute("mstackprotector-guard-record")) + emitStackProtectorLocEntry(); + Register AddrReg = emitLoadStackGuardAddress(MI); + LoweredMI = MCInstBuilder(SystemZ::LG) + .addReg(AddrReg) + .addImm(getStackGuardOffset(MI->getParent())) + .addReg(0); + } break; + + case SystemZ::LOAD_STACK_GUARD_ADDRESS: + // If requested, record address of stack guard address load + if (MF->getFunction().hasFnAttribute("mstackprotector-guard-record")) + emitStackProtectorLocEntry(); + emitLoadStackGuardAddress(MI); + return; + + case SystemZ::COMPARE_STACK_GUARD: + LoweredMI = MCInstBuilder(SystemZ::CLC) + .addReg(MI->getOperand(0).getReg()) + .addImm(MI->getOperand(1).getImm()) + .addImm(8) + .addReg(MI->getOperand(2).getReg()) + .addImm(getStackGuardOffset(MI->getParent())); + break; + + case SystemZ::MOVE_STACK_GUARD: + LoweredMI = MCInstBuilder(SystemZ::MVC) + .addReg(MI->getOperand(0).getReg()) + .addImm(MI->getOperand(1).getImm()) + .addImm(8) + .addReg(MI->getOperand(2).getReg()) + .addImm(getStackGuardOffset(MI->getParent())); + break; + default: Lower.lower(MI, LoweredMI); break; @@ -747,6 +795,85 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, LoweredMI); } +void SystemZAsmPrinter::emitStackProtectorLocEntry() { + 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); +} + +// Emit the stack guard address load, depending on guard type. +// Return the register the stack guard address was loaded into. +Register SystemZAsmPrinter::emitLoadStackGuardAddress(const MachineInstr *MI) { + const MachineBasicBlock *MBB = MI->getParent(); + const MachineFunction &MF = *MBB->getParent(); + const Register AddrReg = MI->getOperand(0).getReg(); + const MCRegisterInfo &MRI = *TM.getMCRegisterInfo(); + const Register Reg32 = MRI.getSubReg(AddrReg, SystemZ::subreg_l32); + + const 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 + MCInst EAR1 = MCInstBuilder(SystemZ::EAR) + .addReg(Reg32) + .addReg(SystemZ::A0) + .addReg(AddrReg); + + // sllg , , 32 + MCInst SLLG = MCInstBuilder(SystemZ::SLLG) + .addReg(AddrReg) + .addReg(AddrReg) + .addReg(0) + .addImm(32); + + // ear , %a1 + MCInst EAR2 = MCInstBuilder(SystemZ::EAR) + .addReg(Reg32) + .addReg(SystemZ::A1) + .addReg(AddrReg); + + EmitToStreamer(*OutStreamer, EAR1); + EmitToStreamer(*OutStreamer, SLLG); + EmitToStreamer(*OutStreamer, EAR2); + } else if (GuardType == "global") { + // Obtain the global value. + const auto *GV = M->getGlobalVariable( + "__stack_chk_guard", PointerType::getUnqual(M->getContext())); + assert(GV && + "could not create reference to global variable __stack_chk_guard"); + auto *Sym = TM.getSymbol(GV); + // Ref-> + // Emit the address load. + MCInst Load; + if (M->getPICLevel() == PICLevel::NotPIC) { + Load = MCInstBuilder(SystemZ::LARL) + .addReg(AddrReg) + .addExpr(MCSymbolRefExpr::create(Sym, OutContext)); + } else { + Load = + MCInstBuilder(SystemZ::LGRL) + .addReg(AddrReg) + .addExpr(MCSymbolRefExpr::create(Sym, SystemZ::S_GOT, OutContext)) + .addExpr(getGlobalOffsetTable(OutContext)); + } + EmitToStreamer(*OutStreamer, Load); + } else { + llvm_unreachable( + (Twine("Unknown stack protector type \"") + GuardType + "\"") + .str() + .c_str()); + } + return AddrReg; +} + // Emit the largest nop instruction smaller than or equal to NumBytes // bytes. Return the size of nop emitted. static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h index cb101e472824f..22e82a691be64 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h @@ -139,6 +139,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter { void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI, SystemZMCInstLower &Lower); void LowerPATCHABLE_RET(const MachineInstr &MI, SystemZMCInstLower &Lower); + Register emitLoadStackGuardAddress(const MachineInstr *MI); + void emitStackProtectorLocEntry(); void emitAttributes(Module &M); }; } // end namespace llvm diff --git a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index a05fdc74e6366..fa1daa8bf8c54 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -10,10 +10,11 @@ // //===----------------------------------------------------------------------===// -#include "SystemZTargetMachine.h" #include "SystemZISelLowering.h" +#include "SystemZTargetMachine.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/KnownBits.h" #include "llvm/Support/raw_ostream.h" @@ -369,7 +370,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 eb93024bed35c..e1662dbedae51 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -14,12 +14,13 @@ #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/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/IntrinsicInst.h" @@ -8026,6 +8027,25 @@ 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 replace the store, + // and a LOAD_STACK_GUARD_ADDRESS to replace the LOAD_STACK_GUARD + MachineSDNode *LoadAddr = DAG.getMachineNode( + SystemZ::LOAD_STACK_GUARD_ADDRESS, SDLoc(SN), MVT::i64); + int FI = cast(SN->getOperand(2))->getIndex(); + // FrameIndex, Dummy Displacement + SDValue Ops[] = {DAG.getTargetFrameIndex(FI, MVT::i64), + DAG.getTargetConstant(0, SDLoc(SN), MVT::i64), + SDValue(LoadAddr, 0), 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 && @@ -8845,25 +8865,103 @@ SystemZTargetLowering::getJumpConditionMergingParams(Instruction::BinaryOps Opc, return {-1, -1, -1}; } +namespace { +bool isStackGuardCheck(SDNode const *N, int &FI, SDValue &InChain, + SDValue &OutChain, SDValue &StackGuardLoad, + SystemZTargetLowering::DAGCombinerInfo &DCI) { + auto Comp = N->getOperand(4); + if (Comp->getOpcode() != SystemZISD::ICMP) + return false; + + if (!Comp->hasOneUse()) + return false; + + SDValue LHS = Comp->getOperand(0); + SDValue RHS = Comp->getOperand(1); + LoadSDNode *FILoad; + + if (LHS.isMachineOpcode() && + LHS.getMachineOpcode() == SystemZ::LOAD_STACK_GUARD && + ISD::isNormalLoad(RHS.getNode()) && + dyn_cast(RHS.getOperand(1))) { + StackGuardLoad = LHS; + FILoad = cast(RHS); + } else if ((RHS.isMachineOpcode() && + RHS.getMachineOpcode() == SystemZ::LOAD_STACK_GUARD && + ISD::isNormalLoad(LHS.getNode()) && + dyn_cast(LHS.getOperand(1)))) { + StackGuardLoad = RHS; + FILoad = cast(LHS); + } else + return false; + + // Assert that the values of the loads are not used elsewhere. + // Bail for now. TODO: What is the proper response here? + assert( + SDValue(FILoad, 0).hasOneUse() && + "Value of stackguard loaded from stack must be used for compare only!"); + assert(StackGuardLoad.hasOneUse() && + "Value of reference stackguard must be used for compare only!"); + + FI = cast(FILoad->getOperand(1))->getIndex(); + InChain = FILoad->getChain(); + OutChain = SDValue(FILoad, 1); + DCI.AddToWorklist(FILoad); + DCI.AddToWorklist(Comp.getNode()); + return true; +} +} // namespace + SDValue SystemZTargetLowering::combineBR_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; - // Combine BR_CCMASK (ICMP (SELECT_CCMASK)) into a single BR_CCMASK. auto *CCValid = dyn_cast(N->getOperand(1)); auto *CCMask = dyn_cast(N->getOperand(2)); if (!CCValid || !CCMask) return SDValue(); - int CCValidVal = CCValid->getZExtValue(); int CCMaskVal = CCMask->getZExtValue(); SDValue Chain = N->getOperand(0); SDValue CCReg = N->getOperand(4); + SDLoc DL(N); + + // Combine BR_CCMASK (ICMP (Load FI, Load StackGuard)) into BRC + // (COMPARE_STACK_GUARD) + int FI = 0; + SDValue InChain, OutChain, StackGuardLoad; + if (isStackGuardCheck(N, FI, InChain, OutChain, StackGuardLoad, DCI)) { + // Sanity Checks + assert(CCMaskVal == SystemZ::CCMASK_CMP_NE && + "Unexpected branch condition in stack guard check"); + // Handle the load's chain if necessary + DAG.ReplaceAllUsesOfValueWith(OutChain, InChain); + + // Construct the LOAD_STACK_GUARD_ADDRESS node to replace LOAD_STACK_GUARD + auto *LoadAddress = + DAG.getMachineNode(SystemZ::LOAD_STACK_GUARD_ADDRESS, DL, MVT::i64); + + // Construct the COMPARE_STACK_GUARD node + SDVTList CmpVTs = DAG.getVTList(MVT::Other, MVT::Glue); + auto CompOps = {DAG.getTargetFrameIndex(FI, MVT::i64), + DAG.getTargetConstant(0, DL, MVT::i64), + SDValue(LoadAddress, 0), InChain}; + auto *Compare = + DAG.getMachineNode(SystemZ::COMPARE_STACK_GUARD, DL, CmpVTs, CompOps); + // Construct the BRC node using COMPARE_STACK_GUARD's CC result + auto BranchOps = {DAG.getTargetConstant(CCValidVal, DL, MVT::i32), + DAG.getTargetConstant(CCMaskVal, DL, MVT::i32), + N->getOperand(3), SDValue(Compare, 0), + SDValue(Compare, 1)}; + return SDValue(DAG.getMachineNode(SystemZ::BRC, DL, MVT::Other, BranchOps), + 0); + } + + // Combine BR_CCMASK (ICMP (SELECT_CCMASK)) into a single BR_CCMASK. if (combineCCMask(CCReg, CCValidVal, CCMaskVal, DAG)) - return DAG.getNode(SystemZISD::BR_CCMASK, SDLoc(N), N->getValueType(0), - Chain, - DAG.getTargetConstant(CCValidVal, SDLoc(N), MVT::i32), - DAG.getTargetConstant(CCMaskVal, SDLoc(N), MVT::i32), + return DAG.getNode(SystemZISD::BR_CCMASK, DL, N->getValueType(0), Chain, + DAG.getTargetConstant(CCValidVal, DL, MVT::i32), + DAG.getTargetConstant(CCMaskVal, DL, MVT::i32), N->getOperand(3), CCReg); return SDValue(); } @@ -9270,6 +9368,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); diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index 13a1cd1614a53..60a08fef01df2 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -220,8 +220,6 @@ class SystemZTargetLowering : public TargetLowering { /// Override to support customized stack guard loading. bool useLoadStackGuardNode(const Module &M) const override { return true; } - void insertSSPDeclarations(Module &M) const override { - } MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index eb1ce4a2101d7..a5621030395d9 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -33,6 +33,7 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/CodeGen/VirtRegMap.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/BranchProbability.h" @@ -228,35 +229,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 @@ -1056,8 +1028,7 @@ void SystemZInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, // 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); } @@ -1805,10 +1776,6 @@ bool SystemZInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { splitAdjDynAlloc(MI); return true; - case TargetOpcode::LOAD_STACK_GUARD: - expandLoadStackGuard(&MI); - return true; - default: return false; } @@ -1830,6 +1797,28 @@ unsigned SystemZInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { return 18; if (MI.getOpcode() == TargetOpcode::PATCHABLE_RET) return 18 + (MI.getOperand(0).getImm() == SystemZ::CondReturn ? 4 : 0); + if ((MI.getOpcode() == SystemZ::MOVE_STACK_GUARD) || + (MI.getOpcode() == SystemZ::COMPARE_STACK_GUARD)) + return 6; + if ((MI.getOpcode() == SystemZ::LOAD_STACK_GUARD_ADDRESS) || + (MI.getOpcode() == TargetOpcode::LOAD_STACK_GUARD)) { + StringRef GuardType = MI.getParent() + ->getParent() + ->getFunction() + .getParent() + ->getStackProtectorGuard(); + unsigned Size = (MI.getOpcode() == TargetOpcode::LOAD_STACK_GUARD) + ? 6 + : 0; // lg to load value + if (GuardType == "global") + return Size + 6; // larl/lgrl + if (GuardType.empty() || GuardType == "tls") + return Size + 14; // ear,sllg,ear + llvm_unreachable( + (Twine("Unknown stack protector type \"") + GuardType + "\"") + .str() + .c_str()); + } return MI.getDesc().getSize(); } diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h index 4aecdd7498018..99d0c03ef47fe 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h @@ -198,7 +198,6 @@ class SystemZInstrInfo : public SystemZGenInstrInfo { unsigned HighOpcode) const; void expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode, unsigned Size) const; - void expandLoadStackGuard(MachineInstr *MI) const; MachineInstrBuilder emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index 4f75e0132610e..57f399045e4d2 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -521,6 +521,19 @@ let SimpleBDXStore = 1, mayStore = 1 in { [(store GR128:$src, bdxaddr20only128:$dst)]>; } } + +let hasNoSchedulingInfo = 1, hasSideEffects = 1 in { + // LOAD_STACK_GUARD_ADDRESS may not Load, because it has no (official) + // operands. + def LOAD_STACK_GUARD_ADDRESS : Pseudo<(outs ADDR64:$grdaddr), (ins), []>; + let mayLoad = 1 in { + let mayStore = 1 in def MOVE_STACK_GUARD + : Pseudo<(outs), (ins bdaddr12only:$grdloc, ADDR64:$grdaddr), []>; + let Defs = [CC] in def COMPARE_STACK_GUARD + : Pseudo<(outs), (ins bdaddr12only:$grdloc, ADDR64:$grdaddr), []>; + } +} + 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..d1d98537c1df2 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/stack-guard-global-nopic.ll @@ -0,0 +1,157 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -mtriple=s390x-linux-gnu -verify-machineinstrs | FileCheck %s + +define i32 @test_global_stack_guard() #0 { +; CHECK-LABEL: test_global_stack_guard: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -1192 +; CHECK-NEXT: .cfi_def_cfa_offset 1352 +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp0 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: larl %r1, __stack_chk_guard +; CHECK-NEXT: mvc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: 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: larl %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 +} + +define i32 @test_global_stack_guard_branch(i32 %in) #0 { +; CHECK-LABEL: test_global_stack_guard_branch: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r13, %r15, 104(%r15) +; CHECK-NEXT: .cfi_offset %r13, -56 +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -1192 +; CHECK-NEXT: .cfi_def_cfa_offset 1352 +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp2 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp2: +; CHECK-NEXT: larl %r1, __stack_chk_guard +; CHECK-NEXT: mvc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: lr %r13, %r2 +; CHECK-NEXT: la %r2, 160(%r15) +; CHECK-NEXT: brasl %r14, foo3@PLT +; CHECK-NEXT: cije %r13, 1, .LBB1_4 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: cijlh %r13, 0, .LBB1_6 +; CHECK-NEXT: # %bb.2: # %foo +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp3 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp3: +; CHECK-NEXT: larl %r1, __stack_chk_guard +; CHECK-NEXT: clc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: jlh .LBB1_8 +; CHECK-NEXT: # %bb.3: # %foo +; CHECK-NEXT: lhi %r2, 0 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB1_4: # %bar +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp4 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp4: +; CHECK-NEXT: larl %r1, __stack_chk_guard +; CHECK-NEXT: clc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: jlh .LBB1_8 +; CHECK-NEXT: # %bb.5: # %bar +; CHECK-NEXT: lhi %r2, 1 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB1_6: # %else +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp5 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp5: +; CHECK-NEXT: larl %r1, __stack_chk_guard +; CHECK-NEXT: clc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: jlh .LBB1_8 +; CHECK-NEXT: # %bb.7: # %else +; CHECK-NEXT: lhi %r2, 2 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB1_8: # %bar +; CHECK-NEXT: brasl %r14, __stack_chk_fail@PLT +entry: + %a1 = alloca [256 x i32], align 4 + call void @foo3(ptr %a1) + switch i32 %in, label %else [ + i32 0, label %foo + i32 1, label %bar + ] +foo: + ret i32 0 +bar: + ret i32 1 +else: + ret i32 2 +} + +define i32 @test_global_stack_guard_large() #0 { +; CHECK-LABEL: test_global_stack_guard_large: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -8376 +; CHECK-NEXT: .cfi_def_cfa_offset 8536 +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp6 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp6: +; CHECK-NEXT: larl %r1, __stack_chk_guard +; CHECK-NEXT: lay %r2, 8192(%r15) +; CHECK-NEXT: mvc 176(8,%r2), 0(%r1) +; CHECK-NEXT: la %r2, 176(%r15) +; CHECK-NEXT: brasl %r14, foo3@PLT +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp7 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp7: +; CHECK-NEXT: larl %r1, __stack_chk_guard +; CHECK-NEXT: lay %r2, 8192(%r15) +; CHECK-NEXT: clc 176(8,%r2), 0(%r1) +; CHECK-NEXT: jlh .LBB2_2 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: lhi %r2, 0 +; CHECK-NEXT: lmg %r14, %r15, 8488(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB2_2: # %entry +; CHECK-NEXT: brasl %r14, __stack_chk_fail@PLT +entry: + %a1 = alloca [2048 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..fe8b6a7e4214d --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/stack-guard-global-pic.ll @@ -0,0 +1,159 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -mtriple=s390x-linux-gnu -verify-machineinstrs | FileCheck %s + +define i32 @test_global_stack_guard() #0 { +; CHECK-LABEL: test_global_stack_guard: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -1192 +; CHECK-NEXT: .cfi_def_cfa_offset 1352 +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp0 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: lgrl %r1, __stack_chk_guard@GOT +; CHECK-NEXT: mvc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: 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@GOT +; 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 +} + +define i32 @test_global_stack_guard_branch(i32 %in) #0 { +; CHECK-LABEL: test_global_stack_guard_branch: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r13, %r15, 104(%r15) +; CHECK-NEXT: .cfi_offset %r13, -56 +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -1192 +; CHECK-NEXT: .cfi_def_cfa_offset 1352 +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp2 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp2: +; CHECK-NEXT: lgrl %r1, __stack_chk_guard@GOT +; CHECK-NEXT: mvc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: lr %r13, %r2 +; CHECK-NEXT: la %r2, 160(%r15) +; CHECK-NEXT: brasl %r14, foo3@PLT +; CHECK-NEXT: cije %r13, 1, .LBB1_4 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: cijlh %r13, 0, .LBB1_6 +; CHECK-NEXT: # %bb.2: # %foo +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp3 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp3: +; CHECK-NEXT: lgrl %r1, __stack_chk_guard@GOT +; CHECK-NEXT: clc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: jlh .LBB1_8 +; CHECK-NEXT: # %bb.3: # %foo +; CHECK-NEXT: lhi %r2, 0 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB1_4: # %bar +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp4 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp4: +; CHECK-NEXT: lgrl %r1, __stack_chk_guard@GOT +; CHECK-NEXT: clc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: jlh .LBB1_8 +; CHECK-NEXT: # %bb.5: # %bar +; CHECK-NEXT: lhi %r2, 1 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB1_6: # %else +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp5 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp5: +; CHECK-NEXT: lgrl %r1, __stack_chk_guard@GOT +; CHECK-NEXT: clc 1184(8,%r15), 0(%r1) +; CHECK-NEXT: jlh .LBB1_8 +; CHECK-NEXT: # %bb.7: # %else +; CHECK-NEXT: lhi %r2, 2 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB1_8: # %bar +; CHECK-NEXT: brasl %r14, __stack_chk_fail@PLT +entry: + %a1 = alloca [256 x i32], align 4 + call void @foo3(ptr %a1) + switch i32 %in, label %else [ + i32 0, label %foo + i32 1, label %bar + ] +foo: + ret i32 0 +bar: + ret i32 1 +else: + ret i32 2 +} + + +define i32 @test_global_stack_guard_large() #0 { +; CHECK-LABEL: test_global_stack_guard_large: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -8376 +; CHECK-NEXT: .cfi_def_cfa_offset 8536 +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp6 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp6: +; CHECK-NEXT: lgrl %r1, __stack_chk_guard@GOT +; CHECK-NEXT: lay %r2, 8192(%r15) +; CHECK-NEXT: mvc 176(8,%r2), 0(%r1) +; CHECK-NEXT: la %r2, 176(%r15) +; CHECK-NEXT: brasl %r14, foo3@PLT +; CHECK-NEXT: .section __stack_protector_loc,"a",@progbits +; CHECK-NEXT: .quad .Ltmp7 +; CHECK-NEXT: .text +; CHECK-NEXT: .Ltmp7: +; CHECK-NEXT: lgrl %r1, __stack_chk_guard@GOT +; CHECK-NEXT: lay %r2, 8192(%r15) +; CHECK-NEXT: clc 176(8,%r2), 0(%r1) +; CHECK-NEXT: jlh .LBB2_2 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: lhi %r2, 0 +; CHECK-NEXT: lmg %r14, %r15, 8488(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB2_2: # %entry +; CHECK-NEXT: brasl %r14, __stack_chk_fail@PLT +entry: + %a1 = alloca [2048 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..ea5ad0d5429cb --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/stack-guard-tls.ll @@ -0,0 +1,135 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -mtriple=s390x-linux-gnu -verify-machineinstrs | FileCheck %s + +define i32 @test_tls_stack_guard() #0 { +; CHECK-LABEL: test_tls_stack_guard: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -1192 +; CHECK-NEXT: .cfi_def_cfa_offset 1352 +; CHECK-NEXT: ear %r1, %a0 +; CHECK-NEXT: sllg %r1, %r1, 32 +; CHECK-NEXT: ear %r1, %a1 +; CHECK-NEXT: mvc 1184(8,%r15), 40(%r1) +; CHECK-NEXT: 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: clc 1184(8,%r15), 40(%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 +} + + +define i32 @test_global_stack_guard_branch(i32 %in) #0 { +; CHECK-LABEL: test_global_stack_guard_branch: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r13, %r15, 104(%r15) +; CHECK-NEXT: .cfi_offset %r13, -56 +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -1192 +; CHECK-NEXT: .cfi_def_cfa_offset 1352 +; CHECK-NEXT: ear %r1, %a0 +; CHECK-NEXT: sllg %r1, %r1, 32 +; CHECK-NEXT: ear %r1, %a1 +; CHECK-NEXT: mvc 1184(8,%r15), 40(%r1) +; CHECK-NEXT: lr %r13, %r2 +; CHECK-NEXT: la %r2, 160(%r15) +; CHECK-NEXT: brasl %r14, foo3@PLT +; CHECK-NEXT: cije %r13, 1, .LBB1_4 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: cijlh %r13, 0, .LBB1_6 +; CHECK-NEXT: # %bb.2: # %foo +; CHECK-NEXT: ear %r1, %a0 +; CHECK-NEXT: sllg %r1, %r1, 32 +; CHECK-NEXT: ear %r1, %a1 +; CHECK-NEXT: clc 1184(8,%r15), 40(%r1) +; CHECK-NEXT: jlh .LBB1_8 +; CHECK-NEXT: # %bb.3: # %foo +; CHECK-NEXT: lhi %r2, 0 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB1_4: # %bar +; CHECK-NEXT: ear %r1, %a0 +; CHECK-NEXT: sllg %r1, %r1, 32 +; CHECK-NEXT: ear %r1, %a1 +; CHECK-NEXT: clc 1184(8,%r15), 40(%r1) +; CHECK-NEXT: jlh .LBB1_8 +; CHECK-NEXT: # %bb.5: # %bar +; CHECK-NEXT: lhi %r2, 1 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB1_6: # %else +; CHECK-NEXT: ear %r1, %a0 +; CHECK-NEXT: sllg %r1, %r1, 32 +; CHECK-NEXT: ear %r1, %a1 +; CHECK-NEXT: clc 1184(8,%r15), 40(%r1) +; CHECK-NEXT: jlh .LBB1_8 +; CHECK-NEXT: # %bb.7: # %else +; CHECK-NEXT: lhi %r2, 2 +; CHECK-NEXT: lmg %r13, %r15, 1296(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB1_8: # %bar +; CHECK-NEXT: brasl %r14, __stack_chk_fail@PLT +entry: + %a1 = alloca [256 x i32], align 4 + call void @foo3(ptr %a1) + switch i32 %in, label %else [ + i32 0, label %foo + i32 1, label %bar + ] +foo: + ret i32 0 +bar: + ret i32 1 +else: + ret i32 2 +} + +define i32 @test_tls_stack_guard_large() #0 { +; CHECK-LABEL: test_tls_stack_guard_large: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -1192 +; CHECK-NEXT: .cfi_def_cfa_offset 1352 +; CHECK-NEXT: ear %r1, %a0 +; CHECK-NEXT: sllg %r1, %r1, 32 +; CHECK-NEXT: ear %r1, %a1 +; CHECK-NEXT: mvc 1184(8,%r15), 40(%r1) +; CHECK-NEXT: 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: clc 1184(8,%r15), 40(%r1) +; CHECK-NEXT: jlh .LBB2_2 +; CHECK-NEXT: # %bb.1: # %entry +; CHECK-NEXT: lhi %r2, 0 +; CHECK-NEXT: lmg %r14, %r15, 1304(%r15) +; CHECK-NEXT: br %r14 +; CHECK-NEXT: .LBB2_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 }