diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3161,10 +3161,14 @@ const std::string &TripleStr = EffectiveTriple.getTriple(); if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) { StringRef Value = A->getValue(); - if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64()) + if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() && + !EffectiveTriple.isARM() && !EffectiveTriple.isThumb()) D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) << TripleStr; - if (EffectiveTriple.isX86() && Value != "tls" && Value != "global") { + if ((EffectiveTriple.isX86() || + EffectiveTriple.isARM() || + EffectiveTriple.isThumb()) && + Value != "tls" && Value != "global") { D.Diag(diag::err_drv_invalid_value_with_suggestion) << A->getOption().getName() << Value << "tls global"; return; @@ -3179,7 +3183,8 @@ if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_offset_EQ)) { StringRef Value = A->getValue(); - if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64()) + if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() && + !EffectiveTriple.isARM() && !EffectiveTriple.isThumb()) D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) << TripleStr; int Offset; diff --git a/clang/test/Driver/stack-protector-guard.c b/clang/test/Driver/stack-protector-guard.c --- a/clang/test/Driver/stack-protector-guard.c +++ b/clang/test/Driver/stack-protector-guard.c @@ -15,7 +15,7 @@ // RUN: FileCheck -check-prefix=CHECK-GS %s // Invalid arch -// RUN: not %clang -target arm-eabi-c -mstack-protector-guard=tls %s 2>&1 | \ +// RUN: not %clang -target powerpc64le-linux-gnu -mstack-protector-guard=tls %s 2>&1 | \ // RUN: FileCheck -check-prefix=INVALID-ARCH %s // INVALID-ARCH: unsupported option '-mstack-protector-guard=tls' for target @@ -23,7 +23,7 @@ // RUN: FileCheck -check-prefix=INVALID-ARCH2 %s // INVALID-ARCH2: unsupported option '-mstack-protector-guard-reg=fs' for target -// RUN: not %clang -target arm-linux-gnueabi -mstack-protector-guard-offset=10 %s 2>&1 | \ +// RUN: not %clang -target powerpc64le-linux-gnu -mstack-protector-guard-offset=10 %s 2>&1 | \ // RUN: FileCheck -check-prefix=INVALID-ARCH3 %s // INVALID-ARCH3: unsupported option '-mstack-protector-guard-offset=10' for target diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1682,8 +1682,6 @@ bool ARMBaseInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { if (MI.getOpcode() == TargetOpcode::LOAD_STACK_GUARD) { - assert(getSubtarget().getTargetTriple().isOSBinFormatMachO() && - "LOAD_STACK_GUARD currently supported only for MachO."); expandLoadStackGuard(MI); MI.getParent()->erase(MI); return true; @@ -4884,8 +4882,6 @@ return true; } -// LoadStackGuard has so far only been implemented for MachO. Different code -// sequence is needed for other targets. void ARMBaseInstrInfo::expandLoadStackGuardBase(MachineBasicBlock::iterator MI, unsigned LoadImmOpc, unsigned LoadOpc) const { @@ -4895,27 +4891,48 @@ MachineBasicBlock &MBB = *MI->getParent(); DebugLoc DL = MI->getDebugLoc(); Register Reg = MI->getOperand(0).getReg(); - const GlobalValue *GV = - cast((*MI->memoperands_begin())->getValue()); MachineInstrBuilder MIB; + int Offset = 0; - BuildMI(MBB, MI, DL, get(LoadImmOpc), Reg) - .addGlobalAddress(GV, 0, ARMII::MO_NONLAZY); + if (LoadImmOpc == ARM::MRC || LoadImmOpc == ARM::t2MRC) { + BuildMI(MBB, MI, DL, get(LoadImmOpc), Reg) + .addImm(15) + .addImm(0) + .addImm(13) + .addImm(0) + .addImm(3) + .add(predOps(ARMCC::AL)); - if (Subtarget.isGVIndirectSymbol(GV)) { - MIB = BuildMI(MBB, MI, DL, get(LoadOpc), Reg); - MIB.addReg(Reg, RegState::Kill).addImm(0); - auto Flags = MachineMemOperand::MOLoad | - MachineMemOperand::MODereferenceable | - MachineMemOperand::MOInvariant; - MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand( - MachinePointerInfo::getGOT(*MBB.getParent()), Flags, 4, Align(4)); - MIB.addMemOperand(MMO).add(predOps(ARMCC::AL)); + Module &M = *MBB.getParent()->getFunction().getParent(); + Offset = M.getStackProtectorGuardOffset(); + } else { + const GlobalValue *GV = + cast((*MI->memoperands_begin())->getValue()); + + unsigned TargetFlags = ARMII::MO_NO_FLAG; + if (Subtarget.isTargetMachO()) + TargetFlags |= ARMII::MO_NONLAZY; + else if (Subtarget.isGVInGOT(GV)) + TargetFlags |= ARMII::MO_GOT; + + BuildMI(MBB, MI, DL, get(LoadImmOpc), Reg) + .addGlobalAddress(GV, 0, TargetFlags); + + if (Subtarget.isGVIndirectSymbol(GV)) { + MIB = BuildMI(MBB, MI, DL, get(LoadOpc), Reg); + MIB.addReg(Reg, RegState::Kill).addImm(0); + auto Flags = MachineMemOperand::MOLoad | + MachineMemOperand::MODereferenceable | + MachineMemOperand::MOInvariant; + MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand( + MachinePointerInfo::getGOT(*MBB.getParent()), Flags, 4, Align(4)); + MIB.addMemOperand(MMO).add(predOps(ARMCC::AL)); + } } MIB = BuildMI(MBB, MI, DL, get(LoadOpc), Reg); MIB.addReg(Reg, RegState::Kill) - .addImm(0) + .addImm(Offset) .cloneMemRefs(*MI) .add(predOps(ARMCC::AL)); } diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -20687,9 +20687,8 @@ return InsertFencesForAtomic; } -// This has so far only been implemented for MachO. bool ARMTargetLowering::useLoadStackGuardNode() const { - return Subtarget->isTargetMachO(); + return true; } void ARMTargetLowering::insertSSPDeclarations(Module &M) const { diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.cpp b/llvm/lib/Target/ARM/ARMInstrInfo.cpp --- a/llvm/lib/Target/ARM/ARMInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMInstrInfo.cpp @@ -95,8 +95,18 @@ MachineFunction &MF = *MI->getParent()->getParent(); const ARMSubtarget &Subtarget = MF.getSubtarget(); const TargetMachine &TM = MF.getTarget(); + MachineBasicBlock &MBB = *MI->getParent(); + Module &M = *MBB.getParent()->getFunction().getParent(); + + if (M.getStackProtectorGuard() == "tls") { + expandLoadStackGuardBase(MI, ARM::MRC, ARM::LDRi12); + return; + } - if (!Subtarget.useMovt()) { + const GlobalValue *GV = + cast((*MI->memoperands_begin())->getValue()); + + if (!Subtarget.useMovt() || Subtarget.isGVInGOT(GV)) { if (TM.isPositionIndependent()) expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12); else @@ -109,15 +119,11 @@ return; } - const GlobalValue *GV = - cast((*MI->memoperands_begin())->getValue()); - if (!Subtarget.isGVIndirectSymbol(GV)) { expandLoadStackGuardBase(MI, ARM::MOV_ga_pcrel, ARM::LDRi12); return; } - MachineBasicBlock &MBB = *MI->getParent(); DebugLoc DL = MI->getDebugLoc(); Register Reg = MI->getOperand(0).getReg(); MachineInstrBuilder MIB; diff --git a/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp b/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp --- a/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -250,7 +250,20 @@ void Thumb2InstrInfo::expandLoadStackGuard( MachineBasicBlock::iterator MI) const { MachineFunction &MF = *MI->getParent()->getParent(); - if (MF.getTarget().isPositionIndependent()) + MachineBasicBlock &MBB = *MI->getParent(); + Module &M = *MBB.getParent()->getFunction().getParent(); + + if (M.getStackProtectorGuard() == "tls") { + expandLoadStackGuardBase(MI, ARM::t2MRC, ARM::t2LDRi12); + return; + } + + const GlobalValue *GV = + cast((*MI->memoperands_begin())->getValue()); + + if (MF.getSubtarget().isGVInGOT(GV)) + expandLoadStackGuardBase(MI, ARM::tLDRLIT_ga_pcrel, ARM::t2LDRi12); + else if (MF.getTarget().isPositionIndependent()) expandLoadStackGuardBase(MI, ARM::t2MOV_ga_pcrel, ARM::t2LDRi12); else expandLoadStackGuardBase(MI, ARM::t2MOVi32imm, ARM::t2LDRi12);