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

Reply via email to