Hello,
the attached patch introduces a -mtls-gs command line option for clang
for the x86_64 target.
This option will force the usage of the GS instead of the FS register
for TLS references and
stack canary references.
This is particularly useful for low-level kernel-side development.
Best regards,
Sven Konietzny
diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td
index 4ca57fe..d5c5026 100644
--- a/lib/Target/X86/X86.td
+++ b/lib/Target/X86/X86.td
@@ -245,6 +245,10 @@ def FeatureSlowIncDec : SubtargetFeature<"slow-incdec", "SlowIncDec", "true",
def FeatureSoftFloat
: SubtargetFeature<"soft-float", "UseSoftFloat", "true",
"Use software floating point features.">;
+def FeatureTlsGs
+ : SubtargetFeature<"tls-gs", "UseTlsGS", "true",
+ "Use GS instead of FS in 64-bit mode">;
+
// On some X86 processors, there is no performance hazard to writing only the
// lower parts of a YMM or ZMM register without clearing the upper part.
def FeatureFastPartialYMMorZMMWrite
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 12adb70..0d4a1d2 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1982,7 +1982,8 @@ X86TargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI,
unsigned X86TargetLowering::getAddressSpace() const {
if (Subtarget.is64Bit())
- return (getTargetMachine().getCodeModel() == CodeModel::Kernel) ? 256 : 257;
+ return (getTargetMachine().getCodeModel() == CodeModel::Kernel ||
+ Subtarget.useTlsGS()) ? 256 : 257;
return 256;
}
@@ -2007,8 +2008,8 @@ Value *X86TargetLowering::getIRStackGuard(IRBuilder<> &IRB) const {
// <magenta/tls.h> defines MX_TLS_STACK_GUARD_OFFSET with this value.
return SegmentOffset(IRB, 0x10, getAddressSpace());
} else {
- // %fs:0x28, unless we're using a Kernel code model, in which case
- // it's %gs:0x28. gs:0x14 on i386.
+ // %fs:0x28, unless we're using a Kernel code model or tls-gs is
+ // specified, in which case it's %gs:0x28. gs:0x14 on i386.
unsigned Offset = (Subtarget.is64Bit()) ? 0x28 : 0x14;
return SegmentOffset(IRB, Offset, getAddressSpace());
}
@@ -14825,12 +14826,14 @@ static SDValue LowerToTLSLocalDynamicModel(GlobalAddressSDNode *GA,
// Lower ISD::GlobalTLSAddress using the "initial exec" or "local exec" model.
static SDValue LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
const EVT PtrVT, TLSModel::Model model,
- bool is64Bit, bool isPIC) {
+ bool is64Bit, bool isPIC, bool useGS) {
SDLoc dl(GA);
// Get the Thread Pointer, which is %gs:0 (32-bit) or %fs:0 (64-bit).
- Value *Ptr = Constant::getNullValue(Type::getInt8PtrTy(*DAG.getContext(),
- is64Bit ? 257 : 256));
+ // If useGS is true %gs:0 will be used in 64-bit mode.
+ Value *Ptr =
+ Constant::getNullValue(Type::getInt8PtrTy(*DAG.getContext(),
+ (is64Bit && !useGS) ? 257 : 256));
SDValue ThreadPointer =
DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), DAG.getIntPtrConstant(0, dl),
@@ -14902,7 +14905,7 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
case TLSModel::InitialExec:
case TLSModel::LocalExec:
return LowerToTLSExecModel(GA, DAG, PtrVT, model, Subtarget.is64Bit(),
- PositionIndependent);
+ PositionIndependent, Subtarget.useTlsGS());
}
llvm_unreachable("Unknown TLS model.");
}
@@ -25868,8 +25871,9 @@ X86TargetLowering::EmitLoweredSegAlloca(MachineInstr &MI,
const bool Is64Bit = Subtarget.is64Bit();
const bool IsLP64 = Subtarget.isTarget64BitLP64();
+ const bool UseTlsGS = Subtarget.useTlsGS();
- const unsigned TlsReg = Is64Bit ? X86::FS : X86::GS;
+ const unsigned TlsReg = (Is64Bit && !UseTlsGS) ? X86::FS : X86::GS;
const unsigned TlsOffset = IsLP64 ? 0x70 : Is64Bit ? 0x40 : 0x30;
// BB:
diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp
index 24845be..7ad4d99 100644
--- a/lib/Target/X86/X86Subtarget.cpp
+++ b/lib/Target/X86/X86Subtarget.cpp
@@ -340,6 +340,7 @@ void X86Subtarget::initializeEnvironment() {
// FIXME: this is a known good value for Yonah. How about others?
MaxInlineSizeThreshold = 128;
UseSoftFloat = false;
+ UseTlsGS = false;
}
X86Subtarget &X86Subtarget::initializeSubtargetDependencies(StringRef CPU,
diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h
index fa0afe2..f16bd20 100644
--- a/lib/Target/X86/X86Subtarget.h
+++ b/lib/Target/X86/X86Subtarget.h
@@ -300,6 +300,9 @@ protected:
/// Use software floating point for code generation.
bool UseSoftFloat;
+ /// In 64-bit mode, use GS instead of FS for TLS references.
+ bool UseTlsGS;
+
/// The minimum alignment known to hold of the stack frame on
/// entry to the function and which must be maintained by every function.
unsigned stackAlignment;
@@ -512,6 +515,7 @@ public:
bool isAtom() const { return X86ProcFamily == IntelAtom; }
bool isSLM() const { return X86ProcFamily == IntelSLM; }
bool useSoftFloat() const { return UseSoftFloat; }
+ bool useTlsGS() const { return UseTlsGS; }
/// Use mfence if we have SSE2 or we're on x86-64 (even if we asked for
/// no-sse2). There isn't any reason to disable it if the target processor
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits