[LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)

Steven Newbury steve at snewbury.org.uk
Wed Aug 21 23:07:38 PDT 2013


Clang patch for X32 support.  Applies against current trunk.

--- ./tools/clang/include/clang/Driver/Options.td.orig	2013-05-16
21:51:51.286129820 +0000
+++ ./tools/clang/include/clang/Driver/Options.td	2013-05-16
21:53:24.875004239 +0000
@@ -841,6 +841,7 @@
   HelpText<"Enable hexagon-qdsp6 backward compatibility">;
 def m3dnowa : Flag<["-"], "m3dnowa">, Group<m_x86_Features_Group>;
 def m3dnow : Flag<["-"], "m3dnow">, Group<m_x86_Features_Group>;
+def mx32 : Flag<["-"], "mx32">, Group<m_Group>, Flags<[DriverOption]>;
 def m64 : Flag<["-"], "m64">, Group<m_Group>, Flags<[DriverOption]>;
 def mabi_EQ : Joined<["-"], "mabi=">, Group<m_Group>;
 def march_EQ : Joined<["-"], "march=">, Group<m_Group>;
--- ./tools/clang/lib/Driver/Driver.cpp.orig
+++ ./tools/clang/lib/Driver/Driver.cpp
@@ -1700,6 +1700,9 @@ static llvm::Triple computeTargetTriple(StringRef
DefaultTargetTriple,
       if (Target.getArch() == llvm::Triple::ppc)
         Target.setArch(llvm::Triple::ppc64);
     }
+  } else if (Args.getLastArg(options::OPT_mx32)) {
+    if (Target.getArch() == llvm::Triple::x86_64)
+      Target.setEnvironment(llvm::Triple::GNUX32);
   }
 
   return Target;
--- ./tools/clang/lib/Basic/Targets.cpp.orig	2013-08-18
12:00:04.501402572 +0000
+++ ./tools/clang/lib/Basic/Targets.cpp	2013-08-18 12:08:11.086175660
+0000
@@ -2384,6 +2384,14 @@
     Builder.defineMacro("__amd64");
     Builder.defineMacro("__x86_64");
     Builder.defineMacro("__x86_64__");
+    if (PointerWidth == 64 && getLongWidth() == 64) {
+       Builder.defineMacro("_LP64");
+       Builder.defineMacro("__LP64__");
+    } else if (PointerWidth == 32 && getLongWidth() == 32 &&
+               getIntWidth() == 32) {
+       Builder.defineMacro("_ILP32");
+       Builder.defineMacro("__ILP32__");
+    }
   } else {
     DefineStd(Builder, "i386", Opts);
   }
@@ -3013,20 +3021,31 @@
 class X86_64TargetInfo : public X86TargetInfo {
 public:
   X86_64TargetInfo(const llvm::Triple &Triple) : X86TargetInfo(Triple)
{
-    LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+    const bool IsX32 = (getTriple().getEnvironment() ==
llvm::Triple::GNUX32);
+    LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 :
64;
     LongDoubleWidth = 128;
     LongDoubleAlign = 128;
     LargeArrayMinWidth = 128;
     LargeArrayAlign = 128;
     SuitableAlign = 128;
-    IntMaxType = SignedLong;
-    UIntMaxType = UnsignedLong;
-    Int64Type = SignedLong;
+    if (IsX32) {
+      SizeType = UnsignedInt;
+      PtrDiffType = SignedInt;
+      IntPtrType = SignedInt;
+    } else {
+      IntMaxType = SignedLong;
+      UIntMaxType = UnsignedLong;
+      Int64Type = SignedLong;
+    }
     RegParmMax = 6;
 
-    DescriptionString =
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
-
"i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
-
"a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128";
+    DescriptionString = IsX32 ?
+      "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+      "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
+      "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" :
+      "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+      "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
+      "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128";
 
     // Use fpret only for long double.
     RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble);
--- ./tools/clang/lib/Driver/ToolChains.h.orig	2013-08-18
13:38:36.158022094 +0000
+++ ./tools/clang/lib/Driver/ToolChains.h	2013-08-18 13:39:12.822210498
+0000
@@ -121,7 +121,7 @@
                              SmallVectorImpl<StringRef> &BiarchLibDirs,
                              SmallVectorImpl<StringRef>
&BiarchTripleAliases);
 
-    void ScanLibDirForGCCTriple(llvm::Triple::ArchType TargetArch,
+    void ScanLibDirForGCCTriple(llvm::Triple TargetTriple,
                                 const llvm::opt::ArgList &Args,
                                 const std::string &LibDir,
                                 StringRef CandidateTriple,
--- ./tools/clang/lib/Driver/Tools.cpp.orig	2013-08-18
13:35:35.783789840 +0000
+++ ./tools/clang/lib/Driver/Tools.cpp	2013-08-18 13:42:18.806549941
+0000
@@ -6045,6 +6045,8 @@
            ToolChain.getArch() == llvm::Triple::ppc64le ||
            ToolChain.getArch() == llvm::Triple::systemz)
     return "/lib64/ld64.so.1";
+  else if (ToolChain.getTriple().getEnvironment() ==
llvm::Triple::GNUX32)
+    return "/libx32/ld-linux-x32.so.2";
   else
     return "/lib64/ld-linux-x86-64.so.2";
 }
@@ -6125,8 +6127,12 @@
   }
   else if (ToolChain.getArch() == llvm::Triple::systemz)
     CmdArgs.push_back("elf64_s390");
-  else
-    CmdArgs.push_back("elf_x86_64");
+  else if (ToolChain.getArch() == llvm::Triple::x86_64)
+    CmdArgs.push_back(ToolChain.getTriple().getEnvironment() ==
+                      llvm::Triple::GNUX32
+                      ? "elf32_x86_64" : "elf_x86_64");
+   else
+    llvm_unreachable("unknown arch");
 
   if (Args.hasArg(options::OPT_static)) {
     if (ToolChain.getArch() == llvm::Triple::arm
--- ./tools/clang/lib/Driver/ToolChains.cpp.orig	2013-08-18
14:18:42.527568969 +0000
+++ ./tools/clang/lib/Driver/ToolChains.cpp	2013-08-18
14:20:41.647025183 +0000
@@ -998,7 +998,6 @@
   llvm::Triple BiarchVariantTriple =
       TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant()
                                  : TargetTriple.get32BitArchVariant();
-  llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
   // The library directories which may contain GCC installations.
   SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs;
   // The compatible GCC triples for this particular architecture.
@@ -1035,7 +1034,7 @@
       if (!llvm::sys::fs::exists(LibDir))
         continue;
       for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke;
++k)
-        ScanLibDirForGCCTriple(TargetArch, Args, LibDir,
+        ScanLibDirForGCCTriple(TargetTriple, Args, LibDir,
                                CandidateTripleAliases[k]);
     }
     for (unsigned j = 0, je = CandidateBiarchLibDirs.size(); j < je;
++j) {
@@ -1044,7 +1043,7 @@
         continue;
       for (unsigned k = 0, ke = CandidateBiarchTripleAliases.size(); k
< ke;
            ++k)
-        ScanLibDirForGCCTriple(TargetArch, Args, LibDir,
+        ScanLibDirForGCCTriple(TargetTriple, Args, LibDir,
                                CandidateBiarchTripleAliases[k],
                                /*NeedsBiarchSuffix=*/ true);
     }
@@ -1321,6 +1351,7 @@
 }
 
 static bool findTargetBiarchSuffix(std::string &Suffix, StringRef Path,
+                                   llvm::Triple TargetTriple,
                                    llvm::Triple::ArchType TargetArch,
                                    const ArgList &Args) {
   // FIXME: This routine was only intended to model bi-arch toolchains
which
@@ -1351,6 +1382,8 @@
       TargetArch == llvm::Triple::ppc64 ||
       TargetArch == llvm::Triple::systemz)
     Suffix = "/64";
+  else if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32)
+      Suffix = "/x32";
   else
     Suffix = "/32";
 
@@ -1358,9 +1391,10 @@
 }
 
 void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
-    llvm::Triple::ArchType TargetArch, const ArgList &Args,
+    llvm::Triple TargetTriple, const ArgList &Args,
     const std::string &LibDir, StringRef CandidateTriple,
     bool NeedsBiarchSuffix) {
+  llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
   // There are various different suffixes involving the triple we
   // check for. We also record what is necessary to walk from each back
   // up to the lib directory.
@@ -1413,7 +1447,7 @@
       // crtbegin.o without the subdirectory.
 
       std::string BiarchSuffix;
-      if (findTargetBiarchSuffix(BiarchSuffix, LI->path(), TargetArch,
Args)) {
+      if (findTargetBiarchSuffix(BiarchSuffix, LI->path(),
TargetTriple, TargetArch, Args)) {
         GCCBiarchSuffix = BiarchSuffix;
       } else {
         if (NeedsBiarchSuffix ||
@@ -2186,8 +2220,9 @@
 
 static StringRef getMultilibDir(const llvm::Triple &Triple,
                                 const ArgList &Args) {
+  const bool IsX32 = Triple.getEnvironment() == llvm::Triple::GNUX32;
   if (!isMipsArch(Triple.getArch()))
-    return Triple.isArch32Bit() ? "lib32" : "lib64";
+    return Triple.isArch32Bit() ? "lib32" : IsX32 ? "libx32" : "lib64";
 
   // lib32 directory has a special meaning on MIPS targets.
   // It contains N32 ABI binaries. Use this folder if produce
--- ./lib/Target/X86/X86JITInfo.cpp.orig	2013-08-19 11:38:44.998820677
+0000
+++ ./lib/Target/X86/X86JITInfo.cpp	2013-08-19 11:39:14.769549714 +0000
@@ -396,6 +396,7 @@
     // PC-relative branch instead of loading the actual address.  (This
is
     // considerably shorter than the 64-bit immediate load already
there.)
     // We assume here intptr_t is 64 bits.
+#if defined (__LP64__)
     intptr_t diff = NewVal-RetAddr+7;
     if (diff >= -2147483648LL && diff <= 2147483647LL) {
       *(unsigned char*)(RetAddr-0xc) = 0xE9;
@@ -405,6 +406,11 @@
       ((unsigned char*)RetAddr)[0] = (2 | (4 << 3) | (3 << 6));
     }
     sys::ValgrindDiscardTranslations((void*)(RetAddr-0xc), 0xd);
+#else // If intptr_t is only 32 bits, always use a PC-relative branch.
+    *(unsigned char*)(RetAddr-0xc) = 0xE9;
+    *(intptr_t *)(RetAddr-0xb) = NewVal-RetAddr+7;
+    sys::ValgrindDiscardTranslations((void*)(RetAddr-0xc), 0xd);
+#endif
 #else
     ((unsigned char*)RetAddr)[-1] = 0xE9;
     sys::ValgrindDiscardTranslations((void*)(RetAddr-1), 5);
@@ -442,7 +448,7 @@
 
 void *X86JITInfo::emitGlobalValueIndirectSym(const GlobalValue* GV,
void *ptr,
                                              JITCodeEmitter &JCE) {
-#if defined (X86_64_JIT)
+#if defined (X86_64_JIT) && defined (__LP64__)
   const unsigned Alignment = 8;
   uint8_t Buffer[8];
   uint8_t *Cur = Buffer;
@@ -481,7 +487,7 @@
   JCE.emitAlignment(4);
   void *Result = (void*)JCE.getCurrentPCValue();
   if (NotCC) {
-#if defined (X86_64_JIT)
+#if defined (X86_64_JIT) && defined (__LP64__)
     JCE.emitByte(0x49);          // REX prefix
     JCE.emitByte(0xB8+2);        // movabsq r10
     JCE.emitWordLE((unsigned)(intptr_t)Target);
@@ -496,7 +502,7 @@
     return Result;
   }
 
-#if defined (X86_64_JIT)
+#if defined (X86_64_JIT) && defined (__LP64__)
   JCE.emitByte(0x49);          // REX prefix
   JCE.emitByte(0xB8+2);        // movabsq r10
   JCE.emitWordLE((unsigned)(intptr_t)Target);





More information about the llvm-dev mailing list