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 (Clang patch)
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt (compiler-rt patch)
- [LLVMdev] [NEW PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt (compiler-rt patch)
- problem (and fix) with -fms-extensions