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;
Steven Newbury
2013-Aug-22 14:56 UTC
[LLVMdev] [NEW PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)
On Thu, 2013-08-22 at 15:22 +0100, Steven Newbury wrote:> 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. :)I know why. I had assumed Michael Liao (the original patch author) had submitted all the _LLVM_ x32 support as separate patches, and it was just the tests/Clang/compiler-rt support that was missing. It seems not so. Those specific patches he did submit got commited, but many pieces are missing... I should NEVER make such big assumptions! Looks like I'm going to have to go through the original patch and create a new patch series. If I'm going to submit the Clang patch, how should it be submitted? One patch with what's required to get x32 host to work, then another enabling x32 code generation once the required changes to llvm are merged? Would that be sufficient?
Dmitri Gribenko
2013-Aug-22 15:40 UTC
[LLVMdev] [cfe-dev] [NEW PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)
On Thu, Aug 22, 2013 at 7:56 AM, Steven Newbury <steve at snewbury.org.uk> wrote:> If I'm going to submit the Clang patch, how should it be submitted? One > patch with what's required to get x32 host to work, then another > enabling x32 code generation once the required changes to llvm are > merged? Would that be sufficient?Sounds good to me. 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>*/
Eli Bendersky
2013-Aug-22 16:56 UTC
[LLVMdev] [cfe-dev] [NEW PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)
On Thu, Aug 22, 2013 at 7:56 AM, Steven Newbury <steve at snewbury.org.uk>wrote:> On Thu, 2013-08-22 at 15:22 +0100, Steven Newbury wrote: > > 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. :) > > I know why. I had assumed Michael Liao (the original patch author) had > submitted all the _LLVM_ x32 support as separate patches, and it was > just the tests/Clang/compiler-rt support that was missing. It seems not > so. Those specific patches he did submit got commited, but many pieces > are missing... I should NEVER make such big assumptions! > > Looks like I'm going to have to go through the original patch and create > a new patch series. > > If I'm going to submit the Clang patch, how should it be submitted? One > patch with what's required to get x32 host to work, then another > enabling x32 code generation once the required changes to llvm are > merged? Would that be sufficient? >Please note that the bulk of work to make Clang x32-capable is in LLVM. The patches sent by Michael a while back no longer apply because we upstreamed some things since then, but the support is not complete yet (mainly in SelDAG). Please be sure to go over the mailing list archives discussing x32, as well as look at the SVN logs for everything mentioning x32. There's quite a bit of history here and it's important to have a full grasp of things. Eli -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130822/56be254e/attachment.html>
Reasonably Related Threads
- [LLVMdev] [NEW PATCH] X32 ABI support for Clang/compiler-rt (Clang patch)
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt (compiler-rt patch)
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt (compiler-rt patch)
- [LLVMdev] [RFC PATCH] X32 ABI support for Clang/compiler-rt