summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.cpp13
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.h4
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.cpp16
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.h3
-rw-r--r--llvm/lib/Target/Sparc/SparcSubtarget.cpp2
-rw-r--r--llvm/lib/Target/Sparc/SparcSubtarget.h3
-rw-r--r--llvm/test/CodeGen/SPARC/stack-protector.ll33
7 files changed, 73 insertions, 1 deletions
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 527d052258d..7a1e7538ba0 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -3302,3 +3302,16 @@ void SparcTargetLowering::ReplaceNodeResults(SDNode *N,
}
}
}
+
+// Override to enable LOAD_STACK_GUARD lowering on Linux.
+bool SparcTargetLowering::useLoadStackGuardNode() const {
+ if (!Subtarget->isTargetLinux())
+ return TargetLowering::useLoadStackGuardNode();
+ return true;
+}
+
+// Override to disable global variable loading on Linux.
+void SparcTargetLowering::insertSSPDeclarations(Module &M) const {
+ if (!Subtarget->isTargetLinux())
+ return TargetLowering::insertSSPDeclarations(M);
+}
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index 5eee611bf61..42a71d81518 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -103,6 +103,10 @@ namespace llvm {
return SP::I1;
}
+ /// Override to support customized stack guard loading.
+ bool useLoadStackGuardNode() const override;
+ void insertSSPDeclarations(Module &M) const override;
+
/// getSetCCResultType - Return the ISD::SETCC ValueType
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
EVT VT) const override;
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
index 28b81b608b3..175d4b73d59 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -491,3 +491,19 @@ unsigned SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const
SparcFI->setGlobalBaseReg(GlobalBaseReg);
return GlobalBaseReg;
}
+
+bool SparcInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
+ switch (MI->getOpcode()) {
+ case TargetOpcode::LOAD_STACK_GUARD: {
+ assert(Subtarget->isTargetLinux() &&
+ "Only Linux target is expected to contain LOAD_STACK_GUARD");
+ // offsetof(tcbhead_t, stack_guard) from sysdeps/sparc/nptl/tls.h in glibc.
+ const int64_t Offset = Subtarget.is64Bit() ? 0x28 : 0x14;
+ MI->setDesc(get(Subtarget.is64Bit() ? SP::LDXri : SP::LDri));
+ MachineInstrBuilder(*MI->getParent()->getParent(), MI)
+ .addReg(SP::G7).addImm(Offset);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.h b/llvm/lib/Target/Sparc/SparcInstrInfo.h
index 9de624cc958..52ce4e84749 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.h
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.h
@@ -97,6 +97,9 @@ public:
const TargetRegisterInfo *TRI) const override;
unsigned getGlobalBaseReg(MachineFunction *MF) const;
+
+ // Lower pseudo instructions after register allocation.
+ bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override;
};
}
diff --git a/llvm/lib/Target/Sparc/SparcSubtarget.cpp b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
index 69cf294aeed..3bc22b530f6 100644
--- a/llvm/lib/Target/Sparc/SparcSubtarget.cpp
+++ b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
@@ -52,7 +52,7 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU,
SparcSubtarget::SparcSubtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, TargetMachine &TM,
bool is64Bit)
- : SparcGenSubtargetInfo(TT, CPU, FS), Is64Bit(is64Bit),
+ : SparcGenSubtargetInfo(TT, CPU, FS), TargetTriple(TT), Is64Bit(is64Bit),
InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
FrameLowering(*this) {}
diff --git a/llvm/lib/Target/Sparc/SparcSubtarget.h b/llvm/lib/Target/Sparc/SparcSubtarget.h
index 7db962806a5..31f688e74c6 100644
--- a/llvm/lib/Target/Sparc/SparcSubtarget.h
+++ b/llvm/lib/Target/Sparc/SparcSubtarget.h
@@ -30,6 +30,7 @@ namespace llvm {
class StringRef;
class SparcSubtarget : public SparcGenSubtargetInfo {
+ Triple TargetTriple;
virtual void anchor();
bool IsV9;
bool IsLeon;
@@ -89,6 +90,8 @@ public:
/// returns adjusted framesize which includes space for register window
/// spills and arguments.
int getAdjustedFrameSize(int stackSize) const;
+
+ bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
};
} // end namespace llvm
diff --git a/llvm/test/CodeGen/SPARC/stack-protector.ll b/llvm/test/CodeGen/SPARC/stack-protector.ll
new file mode 100644
index 00000000000..70a73664aa1
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/stack-protector.ll
@@ -0,0 +1,33 @@
+; RUN: llc -mtriple=sparc-unknown-linux < %s | FileCheck %s --check-prefix=LINUX-32
+; RUN: llc -mtriple=sparc64-unknown-linux < %s | FileCheck %s --check-prefix=LINUX-64
+; RUN: llc -mtriple=sparc-unknown-solaris < %s | FileCheck %s --check-prefix=GENERIC
+; RUN: llc -mtriple=sparc64-unknown-solaris < %s | FileCheck %s --check-prefix=GENERIC
+
+; LINUX-32: ld [%g7+20], [[REG1:%[ilo][0-9]*]]
+; LINUX-64: ldx [%g7+40], [[REG1:%[ilo][0-9]*]]
+; LINUX-32-NOT: __stack_chk_guard
+; LINUX-64-NOT: __stack_chk_guard
+; GENERIC: __stack_chk_guard
+
+@"\01LC" = internal constant [11 x i8] c"buf == %s\0A\00" ; <[11 x i8]*> [#uses=1]
+
+define void @test(i8* %a) nounwind ssp {
+entry:
+ %a_addr = alloca i8* ; <i8**> [#uses=2]
+ %buf = alloca [8 x i8] ; <[8 x i8]*> [#uses=2]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ store i8* %a, i8** %a_addr
+ %buf1 = bitcast [8 x i8]* %buf to i8* ; <i8*> [#uses=1]
+ %0 = load i8*, i8** %a_addr, align 4 ; <i8*> [#uses=1]
+ %1 = call i8* @strcpy(i8* %buf1, i8* %0) nounwind ; <i8*> [#uses=0]
+ %buf2 = bitcast [8 x i8]* %buf to i8* ; <i8*> [#uses=1]
+ %2 = call i32 (i8*, ...) @printf(i8* getelementptr ([11 x i8], [11 x i8]* @"\01LC", i32 0, i32 0), i8* %buf2) nounwind ; <i32> [#uses=0]
+ br label %return
+
+return: ; preds = %entry
+ ret void
+}
+
+declare i8* @strcpy(i8*, i8*) nounwind
+
+declare i32 @printf(i8*, ...) nounwind
OpenPOWER on IntegriCloud