Steven Newbury
2013-Aug-22  06:04 UTC
[LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt
Hi, I'm working on bringing up complete coverage for a Gentoo x32 "desktop" system. I've been cooking up quite a few patches for various packages to push upstream, but right now, the biggest blocker is the lack of support for building with/codegen targeting x32 in llvm/clang. Since the x32 patches were sent last year, I see support code has landed in LLVM, and basic handling of 32-bit pointers in Clang, but no elf32_x86_64 codegen or support for the -mx32 switch. I've been trying to get x32 ABI support working in Clang and compiler-rt, I based off the previous clang patch, bringing it up to date with the changes in trunk, and hacked together handling of x32 "ARCH" support for compiler-rt. (there must be a better way??) Unfortunately, although the build succeeds as far as beginning to build compiler-rt the resulting clang doesn't seem to respect the fact that the target is x86_64-pc-linux-gnux32, nor that the "-mx32" opt has been supplied. Something is clearly missing. Can somebody please take a look at the patches, and look to see what I'm missing/where I've gone wrong, or otherwise point me to a working patchset/repo if I'm duplicating effort. Patches to follow...
Steven Newbury
2013-Aug-22  06:07 UTC
[LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)
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);
Steven Newbury
2013-Aug-22  06:09 UTC
[LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt (compiler-rt patch)
X32 support patch for compiler-rt.  Applies against current trunk.
--- projects/compiler-rt/make/platform/clang_linux.mk~	2013-08-21
06:27:38.000000000 +0000
+++ projects/compiler-rt/make/platform/clang_linux.mk	2013-08-21
11:16:55.891621025 +0000
@@ -41,7 +41,18 @@
     SupportedArches += x86_64
   endif
 else
-  SupportedArches := x86_64
+  # x86-64 arch has two ABIs 64 bit x86-64 and 32 bit x32
+  ifeq ($(lastword $(subst -gnu, ,$(CompilerTargetTriple))),x32)
+    SupportedArches := x32
+    ifeq ($(call TryCompile,$(CC),$(test_source),-m64),0)
+      SupportedArches += x86_64
+    endif
+  else
+    SupportedArches := x86_64
+    ifeq ($(call TryCompile,$(CC),$(test_source),-mx32),0)
+      SupportedArches += x32
+    endif
+  endif
   ifeq ($(call TryCompile,$(CC),$(test_source),-m32),0)
     SupportedArches += i386
   endif
@@ -74,6 +85,22 @@
 Arch.lsan-x86_64 := x86_64
 endif
 
+# Build runtime libraries for x32.
+ifeq ($(call contains,$(SupportedArches),x32),true)
+Configs += full-x32 profile-x32 san-x32 asan-x32 tsan-x32 \
+           msan-x32 ubsan-x32 ubsan_cxx-x32 dfsan-x32 lsan-x32
+Arch.full-x32 := x32
+Arch.profile-x32 := x32
+Arch.san-x32 := x32
+Arch.asan-x32 := x32
+Arch.tsan-x32 := x32
+Arch.msan-x32 := x32
+Arch.ubsan-x32 := x32
+Arch.ubsan_cxx-x32 := x32
+Arch.dfsan-x32 := x32
+Arch.lsan-x32 := x32
+endif
+
 ifneq ($(LLVM_ANDROID_TOOLCHAIN_DIR),)
 Configs += asan-arm-android
 Arch.asan-arm-android := arm-android
@@ -89,22 +116,33 @@
 
 CFLAGS.full-i386 := $(CFLAGS) -m32
 CFLAGS.full-x86_64 := $(CFLAGS) -m64
+CFLAGS.full-x32 := $(CFLAGS) -mx32
 CFLAGS.profile-i386 := $(CFLAGS) -m32
 CFLAGS.profile-x86_64 := $(CFLAGS) -m64
+CFLAGS.profile-x32 := $(CFLAGS) -mx32
 CFLAGS.san-i386 := $(CFLAGS) -m32 $(SANITIZER_CFLAGS) -fno-rtti
 CFLAGS.san-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS) -fno-rtti
+CFLAGS.san-x32 := $(CFLAGS) -mx32 $(SANITIZER_CFLAGS) -fno-rtti
 CFLAGS.asan-i386 := $(CFLAGS) -m32 $(SANITIZER_CFLAGS) -fno-rtti \
                     -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=1
 CFLAGS.asan-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS) -fno-rtti \
                     -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=1
+CFLAGS.asan-x32 := $(CFLAGS) -mx32 $(SANITIZER_CFLAGS) -fno-rtti \
+                    -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=1
 CFLAGS.tsan-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS) -fno-rtti
+CFLAGS.tsan-x32 := $(CFLAGS) -mx32 $(SANITIZER_CFLAGS) -fno-rtti
 CFLAGS.msan-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS) -fno-rtti
+CFLAGS.msan-x32 := $(CFLAGS) -mx32 $(SANITIZER_CFLAGS) -fno-rtti
 CFLAGS.ubsan-i386 := $(CFLAGS) -m32 $(SANITIZER_CFLAGS) -fno-rtti
 CFLAGS.ubsan-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS) -fno-rtti
+CFLAGS.ubsan-x32 := $(CFLAGS) -mx32 $(SANITIZER_CFLAGS) -fno-rtti
 CFLAGS.ubsan_cxx-i386 := $(CFLAGS) -m32 $(SANITIZER_CFLAGS)
 CFLAGS.ubsan_cxx-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS)
+CFLAGS.ubsan_cxx-x32 := $(CFLAGS) -mx32 $(SANITIZER_CFLAGS)
 CFLAGS.dfsan-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS)
+CFLAGS.dfsan-x32 := $(CFLAGS) -mx32 $(SANITIZER_CFLAGS)
 CFLAGS.lsan-x86_64 := $(CFLAGS) -m64 $(SANITIZER_CFLAGS)
+CFLAGS.lsan-x32 := $(CFLAGS) -mx32 $(SANITIZER_CFLAGS)
 
 SHARED_LIBRARY.asan-arm-android := 1
 ANDROID_COMMON_FLAGS := -target arm-linux-androideabi \
@@ -120,30 +158,45 @@
 # enough support to build the sanitizers or profile runtimes.
 CFLAGS.full-i386 += --sysroot=$(ProjSrcRoot)/SDKs/linux
 CFLAGS.full-x86_64 += --sysroot=$(ProjSrcRoot)/SDKs/linux
+CFLAGS.full-x32 += --sysroot=$(ProjSrcRoot)/SDKs/linux
 
 FUNCTIONS.full-i386 := $(CommonFunctions) $(ArchFunctions.i386)
 FUNCTIONS.full-x86_64 := $(CommonFunctions) $(ArchFunctions.x86_64)
+FUNCTIONS.full-x32 := $(CommonFunctions) $(ArchFunctions.x32)
 FUNCTIONS.profile-i386 := GCDAProfiling
 FUNCTIONS.profile-x86_64 := GCDAProfiling
+FUNCTIONS.profile-x32 := GCDAProfiling
 FUNCTIONS.san-i386 := $(SanitizerCommonFunctions)
 FUNCTIONS.san-x86_64 := $(SanitizerCommonFunctions)
+FUNCTIONS.san-x32 := $(SanitizerCommonFunctions)
 FUNCTIONS.asan-i386 := $(AsanFunctions) $(InterceptionFunctions) \
                                         $(SanitizerCommonFunctions)
 FUNCTIONS.asan-x86_64 := $(AsanFunctions) $(InterceptionFunctions) \
                          $(SanitizerCommonFunctions)
$(LsanCommonFunctions)
+FUNCTIONS.asan-x32 := $(AsanFunctions) $(InterceptionFunctions) \
+                         $(SanitizerCommonFunctions)
$(LsanCommonFunctions)
 FUNCTIONS.asan-arm-android := $(AsanFunctions) $(InterceptionFunctions)
\
                                           $(SanitizerCommonFunctions)
 FUNCTIONS.tsan-x86_64 := $(TsanFunctions) $(InterceptionFunctions) \
                                           $(SanitizerCommonFunctions)
+FUNCTIONS.tsan-x32 := $(TsanFunctions) $(InterceptionFunctions) \
+                                          $(SanitizerCommonFunctions)
 FUNCTIONS.msan-x86_64 := $(MsanFunctions) $(InterceptionFunctions) \
                                           $(SanitizerCommonFunctions)
+FUNCTIONS.msan-x32 := $(MsanFunctions) $(InterceptionFunctions) \
+                                          $(SanitizerCommonFunctions)
 FUNCTIONS.ubsan-i386 := $(UbsanFunctions)
 FUNCTIONS.ubsan-x86_64 := $(UbsanFunctions)
+FUNCTIONS.ubsan-x32 := $(UbsanFunctions)
 FUNCTIONS.ubsan_cxx-i386 := $(UbsanCXXFunctions)
 FUNCTIONS.ubsan_cxx-x86_64 := $(UbsanCXXFunctions)
+FUNCTIONS.ubsan_cxx-x32 := $(UbsanCXXFunctions)
 FUNCTIONS.dfsan-x86_64 := $(DfsanFunctions) $(SanitizerCommonFunctions)
+FUNCTIONS.dfsan-x32 := $(DfsanFunctions) $(SanitizerCommonFunctions)
 FUNCTIONS.lsan-x86_64 := $(LsanFunctions) $(InterceptionFunctions) \
                                           $(SanitizerCommonFunctions)
+FUNCTIONS.lsan-x32 := $(LsanFunctions) $(InterceptionFunctions) \
+                                          $(SanitizerCommonFunctions)
 
 # Always use optimized variants.
 OPTIMIZED := 1
--- tools/clang/runtime/compiler-rt/Makefile.orig	2013-08-21
16:20:43.915932247 +0000
+++ tools/clang/runtime/compiler-rt/Makefile	2013-08-21
17:03:15.856154519 +0000
@@ -96,29 +96,66 @@
     $(1) $$cflags $(2) -o /dev/null > /dev/null 2> /dev/null ; \
     echo $$?)
 
-# We try to build 32-bit runtimes both on 32-bit hosts and 64-bit
hosts.
-Runtime32BitConfigs = \
+# We try to build x86 runtimes both on x86 hosts and 64-bit hosts.
+Runtimex86Configs = \
 	full-i386.a profile-i386.a san-i386.a asan-i386.a ubsan-i386.a \
 	ubsan_cxx-i386.a
 
+Runtime64BitConfigs = \
+	full-x86_64.a profile-x86_64.a san-x86_64.a asan-x86_64.a \
+	tsan-x86_64.a msan-x86_64.a ubsan-x86_64.a ubsan_cxx-x86_64.a \
+	dfsan-x86_64.a lsan-x86_64.a
+
+Runtimex32Configs += \
+	full-x32.a profile-x32.a san-x32.a asan-x32.a \
+	tsan-x32.a msan-x32.a ubsan-x32.a ubsan_cxx-x32.a \
+	dfsan-x32.a lsan-x32.a
+
+
 # We currently only try to generate runtime libraries on x86.
 ifeq ($(ARCH),x86)
-RuntimeLibrary.linux.Configs += $(Runtime32BitConfigs)
+RuntimeLibrary.linux.Configs += $(Runtimex86Configs)
+
+ifneq ($(LLVM_ANDROID_TOOLCHAIN_DIR),)
+RuntimeLibrary.linux.Configs += asan-arm-android.so
+endif
 endif
 
 ifeq ($(ARCH),x86_64)
-RuntimeLibrary.linux.Configs += \
-	full-x86_64.a profile-x86_64.a san-x86_64.a asan-x86_64.a \
-	tsan-x86_64.a msan-x86_64.a ubsan-x86_64.a ubsan_cxx-x86_64.a \
-	dfsan-x86_64.a lsan-x86_64.a
-# We need to build 32-bit ASan/UBsan libraries on 64-bit platform, and
add them
+CompilerTargetTriple := $(shell \
+	$(CC) -v 2>&1 | grep 'Target:' | cut -d' ' -f2)
+ifeq ($(CompilerTargetTriple),)
+$(error "unable to infer compiler target triple for $(CC)")
+endif
+ifeq ($(lastword $(subst -gnu, ,$(CompilerTargetTriple))),x32)
+ARCH=x32
+RuntimeLibrary.linux.Configs += $(Runtimex32Configs)
+# We need to build x86 ASan/UBsan libraries on x32 platform, and add
them
 # to the list of runtime libraries to make
-# "clang -fsanitize=(address|undefined) -m32" work.
-# We check that Clang can produce working 32-bit binaries by compiling
a simple
+# "clang -fsanitize=(address|undefined) -m32/-m64" work.
+# We check that Clang can produce working 32/64-bit binaries by
compiling a simple
 # executable.
 test_source
$(LLVM_SRC_ROOT)/tools/clang/runtime/compiler-rt/clang_linux_test_input.c
+ifeq ($(call TryCompile,$(ToolDir)/clang,$(test_source),-m64),0)
+RuntimeLibrary.linux.Configs += $(Runtime64BitConfigs)
+endif
 ifeq ($(call TryCompile,$(ToolDir)/clang,$(test_source),-m32),0)
-RuntimeLibrary.linux.Configs += $(Runtime32BitConfigs)
+RuntimeLibrary.linux.Configs += $(Runtimex86Configs)
+endif
+else
+RuntimeLibrary.linux.Configs += $(Runtime64BitConfigs)
+# We need to build x86/x32 ASan/UBsan libraries on 64-bit platform, and
add them
+# to the list of runtime libraries to make
+# "clang -fsanitize=(address|undefined) -m32/-mx32" work.
+# We check that Clang can produce working x86 binaries by compiling a
simple
+# executable.
+test_source
$(LLVM_SRC_ROOT)/tools/clang/runtime/compiler-rt/clang_linux_test_input.c
+ifeq ($(call TryCompile,$(ToolDir)/clang,$(test_source),-m32),0)
+RuntimeLibrary.linux.Configs += $(Runtimex86Configs)
+endif
+ifeq ($(call TryCompile,$(ToolDir)/clang,$(test_source),-mx32),0)
+RuntimeLibrary.linux.Configs += $(Runtimex32Configs)
+endif
 endif
 ifneq ($(LLVM_ANDROID_TOOLCHAIN_DIR),)
 RuntimeLibrary.linux.Configs += asan-arm-android.so
Dmitri Gribenko
2013-Aug-22  06:54 UTC
[LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)
On Wed, Aug 21, 2013 at 11:07 PM, Steven Newbury <steve at snewbury.org.uk> wrote:> Clang patch for X32 support. Applies against current trunk.Not a real review, but it seems like this change needs tests -- at least driver tests, and tests for predefined macros. Dmitri -- main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if (j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/
Dmitri Gribenko
2013-Aug-22  06:59 UTC
[LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt
On Wed, Aug 21, 2013 at 11:04 PM, Steven Newbury <steve at snewbury.org.uk> wrote:> I've been trying > to get x32 ABI support working in Clang and compiler-rt, I based off the > previous clang patch, bringing it up to date with the changes in trunk, > and hacked together handling of x32 "ARCH" support for compiler-rt. > (there must be a better way??)If you are just trying to get basic things working, you don't need to port compiler-rt immediately. It is still pretty important (for example, to support features like Address Sanitizer), but not critical -- you will still get a useable Clang without building compiler-rt. Dmitri -- main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if (j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/
Steven Newbury
2013-Aug-22  07:23 UTC
[LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt
On Wed, 2013-08-21 at 23:59 -0700, Dmitri Gribenko wrote:> On Wed, Aug 21, 2013 at 11:04 PM, Steven Newbury <steve at snewbury.org.uk> wrote: > > I've been trying > > to get x32 ABI support working in Clang and compiler-rt, I based off the > > previous clang patch, bringing it up to date with the changes in trunk, > > and hacked together handling of x32 "ARCH" support for compiler-rt. > > (there must be a better way??) > > If you are just trying to get basic things working, you don't need to > port compiler-rt immediately. It is still pretty important (for > example, to support features like Address Sanitizer), but not critical > -- you will still get a useable Clang without building compiler-rt. > > Dmitri >Having Clang working would of course be my primary goal, that said, being able to compile compiler-rt is a pretty good test all is working as it should be! :) It's also built/installed as part of the Gentoo llvm ebuild when the clang useflag is enabled, so from that point of view, I need to get it working.
Alexey Samsonov
2013-Aug-22  07:29 UTC
[LLVMdev] [cfe-dev] [RFC PATCH] X32 ABI support for Clang/compiler-rt
Ah, I've replied in a different thread already. What Dmitri says - If you're interesting in only building the Clang on x32 host, you may avoid checking out compiler-rt repo for now. On Thu, Aug 22, 2013 at 10:59 AM, Dmitri Gribenko <gribozavr at gmail.com>wrote:> On Wed, Aug 21, 2013 at 11:04 PM, Steven Newbury <steve at snewbury.org.uk> > wrote: > > I've been trying > > to get x32 ABI support working in Clang and compiler-rt, I based off the > > previous clang patch, bringing it up to date with the changes in trunk, > > and hacked together handling of x32 "ARCH" support for compiler-rt. > > (there must be a better way??) > > If you are just trying to get basic things working, you don't need to > port compiler-rt immediately. It is still pretty important (for > example, to support features like Address Sanitizer), but not critical > -- you will still get a useable Clang without building compiler-rt. > > Dmitri > > -- > main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if > (j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/ > _______________________________________________ > cfe-dev mailing list > cfe-dev at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev >-- Alexey Samsonov, MSK -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130822/114063e2/attachment.html>
Steven Newbury
2013-Aug-22  14:22 UTC
[LLVMdev] [NEW PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)
This patch is still not creating elf32_x86_64 objects.  No idea
why. :( It does however, fix elf_x86_64 (-m64) code generation on x32
hosts which is nice. :)
--- ./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/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);
--- tools/clang/lib/Driver/Driver.cpp.orig	2013-08-22 14:07:13.397091755
+0000
+++ tools/clang/lib/Driver/Driver.cpp	2013-08-22 14:05:55.275249307
+0000
@@ -1897,6 +1897,8 @@
   // Handle pseudo-target flags '-m32' and '-m64'.
   // FIXME: Should this information be in llvm::Triple?
   if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+    if (Target.getEnvironment() == llvm::Triple::GNUX32)
+      Target.setEnvironment(llvm::Triple::GNU);
     if (A->getOption().matches(options::OPT_m32)) {
       if (Target.getArch() == llvm::Triple::x86_64)
         Target.setArch(llvm::Triple::x86);
@@ -1908,6 +1910,9 @@
       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;
Apparently Analagous Threads
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt
- [LLVMdev] [NEW PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt