Hi, Here is the resubmitting of x32 psABI[1] patches against the latest trunk for code review after the patches[2] to LLVM.
* 0001-add-x32-psABI-support.patch add x32 psABI support * 0002-revise-codegen-test-for-x32-psABI.patch revise/add codegen test for x32 psABI Looking forward to your comments. Thanks - Michael ------ [1] https://sites.google.com/site/x32abi/ [2] http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20120709/146180.html
>From c4db8d7ad3f8c918a072707d6ad7e66ebc81564b Mon Sep 17 00:00:00 2001 From: Michael Liao <[email protected]> Date: Mon, 2 Jul 2012 22:58:27 -0700 Subject: [PATCH 1/2] add x32 psABI support - add '-mx32' option - add linker/gcc-runtime support for x32 psABI under x86-64 target, based on whether x32 psABI is turned on or off - populate '_ILP32'/'__ILP32__' or '_LP64/__LP64__' - set correct widths for data types - add special handling of sret where pointer types could be packed with other 32-bit integer types into a single register - detect target directly from target arch from target triple instead of pointer width --- include/clang/Driver/Options.td | 1 + lib/Basic/Targets.cpp | 45 ++++++++++++++++++++++++++------------- lib/CodeGen/TargetInfo.cpp | 25 ++++++++++++++-------- lib/Driver/Driver.cpp | 3 +++ lib/Driver/ToolChains.cpp | 13 ++++++----- lib/Driver/ToolChains.h | 2 +- lib/Driver/Tools.cpp | 13 ++++++++--- 7 files changed, 69 insertions(+), 33 deletions(-) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index a68353a..235d7a5 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -756,6 +756,7 @@ def mqdsp6_compat : Flag<"-mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption, 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>; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 5165193..1fc9862 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -1520,9 +1520,9 @@ public: virtual bool hasFeature(StringRef Feature) const; virtual void HandleTargetFeatures(std::vector<std::string> &Features); virtual const char* getABI() const { - if (PointerWidth == 64 && SSELevel >= AVX) + if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX) return "avx"; - else if (PointerWidth == 32 && MMX3DNowLevel == NoMMX3DNow) + else if (getTriple().getArch() == llvm::Triple::x86 && MMX3DNowLevel == NoMMX3DNow) return "no-mmx"; return ""; } @@ -1616,7 +1616,7 @@ public: case CK_AthlonMP: case CK_Geode: // Only accept certain architectures when compiling in 32-bit mode. - if (PointerWidth != 32) + if (getTriple().getArch() != llvm::Triple::x86) return false; // Fallthrough @@ -1674,7 +1674,7 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { // FIXME: This *really* should not be here. // X86_64 always has SSE2. - if (PointerWidth == 64) + if (getTriple().getArch() == llvm::Triple::x86_64) Features["sse2"] = Features["sse"] = Features["mmx"] = true; switch (CPU) { @@ -2047,10 +2047,14 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) { void X86TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { // Target identification. - if (PointerWidth == 64) { - if (getLongWidth() == 64) { + if (getTriple().getArch() == llvm::Triple::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__"); } Builder.defineMacro("__amd64__"); Builder.defineMacro("__amd64"); @@ -2303,8 +2307,8 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("sse42", SSELevel >= SSE42) .Case("sse4a", HasSSE4a) .Case("x86", true) - .Case("x86_32", PointerWidth == 32) - .Case("x86_64", PointerWidth == 64) + .Case("x86_32", getTriple().getArch() == llvm::Triple::x86) + .Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64) .Case("xop", HasXOP) .Default(false); } @@ -2634,20 +2638,31 @@ namespace { class X86_64TargetInfo : public X86TargetInfo { public: X86_64TargetInfo(const std::string &triple) : X86TargetInfo(triple) { - LongWidth = LongAlign = PointerWidth = PointerAlign = 64; + const bool IsX32 = (getTriple().getEnvironment() == llvm::Triple::X32); + 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); diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 1ff7ed0..b72b20f 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -954,9 +954,11 @@ class X86_64ABIInfo : public ABIInfo { bool HasAVX; + bool isX32; // X32 psABI + public: - X86_64ABIInfo(CodeGen::CodeGenTypes &CGT, bool hasavx) : - ABIInfo(CGT), HasAVX(hasavx) {} + X86_64ABIInfo(CodeGen::CodeGenTypes &CGT, bool hasavx, bool IsX32) : + ABIInfo(CGT), HasAVX(hasavx), isX32(IsX32) {} bool isPassedUsingAVXType(QualType type) const { unsigned neededInt, neededSSE; @@ -992,8 +994,8 @@ public: class X86_64TargetCodeGenInfo : public TargetCodeGenInfo { public: - X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX) - : TargetCodeGenInfo(new X86_64ABIInfo(CGT, HasAVX)) {} + X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX, bool IsX32) + : TargetCodeGenInfo(new X86_64ABIInfo(CGT, HasAVX, IsX32)) {} const X86_64ABIInfo &getABIInfo() const { return static_cast<const X86_64ABIInfo&>(TargetCodeGenInfo::getABIInfo()); @@ -1189,7 +1191,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, } if (Ty->isMemberPointerType()) { - if (Ty->isMemberFunctionPointerType()) + if (Ty->isMemberFunctionPointerType() && !isX32) Lo = Hi = Integer; else Current = Integer; @@ -1700,7 +1702,7 @@ GetINTEGERTypeAtOffset(llvm::Type *IRType, unsigned IROffset, // returning an 8-byte unit starting with it. See if we can safely use it. if (IROffset == 0) { // Pointers and int64's always fill the 8-byte unit. - if (isa<llvm::PointerType>(IRType) || IRType->isIntegerTy(64)) + if ((!isX32 && isa<llvm::PointerType>(IRType)) || IRType->isIntegerTy(64)) return IRType; // If we have a 1/2/4-byte integer, we can use it only if the rest of the @@ -1709,9 +1711,12 @@ GetINTEGERTypeAtOffset(llvm::Type *IRType, unsigned IROffset, // struct{double,int,int} because we wouldn't return the second int. We // have to do this analysis on the source type because we can't depend on // unions being lowered a specific way etc. - if (IRType->isIntegerTy(8) || IRType->isIntegerTy(16) || + if ((isX32 && isa<llvm::PointerType>(IRType)) || + IRType->isIntegerTy(8) || IRType->isIntegerTy(16) || IRType->isIntegerTy(32)) { - unsigned BitWidth = cast<llvm::IntegerType>(IRType)->getBitWidth(); + unsigned BitWidth = 32; + if (!isa<llvm::PointerType>(IRType)) + BitWidth = cast<llvm::IntegerType>(IRType)->getBitWidth(); if (BitsContainNoUserData(SourceTy, SourceOffset*8+BitWidth, SourceOffset*8+64, getContext())) @@ -3761,6 +3766,7 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::x86_64: { bool HasAVX = strcmp(getContext().getTargetInfo().getABI(), "avx") == 0; + bool IsX32 = Triple.getEnvironment() == llvm::Triple::X32; switch (Triple.getOS()) { case llvm::Triple::Win32: @@ -3769,7 +3775,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { return *(TheTargetCodeGenInfo = new WinX86_64TargetCodeGenInfo(Types)); default: return *(TheTargetCodeGenInfo = new X86_64TargetCodeGenInfo(Types, - HasAVX)); + HasAVX, + IsX32)); } } case llvm::Triple::hexagon: diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index a2afb76..dc6edbb 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1708,6 +1708,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::X32); } return Target; diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 93df747..51dc80c 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1029,7 +1029,6 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( llvm::Triple MultiarchTriple = TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant() : TargetTriple.get32BitArchVariant(); - llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); // The library directories which may contain GCC installations. SmallVector<StringRef, 4> CandidateLibDirs, CandidateMultiarchLibDirs; // The compatible GCC triples for this particular architecture. @@ -1067,7 +1066,7 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( if (!llvm::sys::fs::exists(LibDir)) continue; for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetArch, LibDir, CandidateTripleAliases[k]); + ScanLibDirForGCCTriple(TargetTriple, LibDir, CandidateTripleAliases[k]); } for (unsigned j = 0, je = CandidateMultiarchLibDirs.size(); j < je; ++j) { const std::string LibDir @@ -1076,7 +1075,7 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( continue; for (unsigned k = 0, ke = CandidateMultiarchTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetArch, LibDir, + ScanLibDirForGCCTriple(TargetTriple, LibDir, CandidateMultiarchTripleAliases[k], /*NeedsMultiarchSuffix=*/true); } @@ -1252,8 +1251,9 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( } void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( - llvm::Triple::ArchType TargetArch, const std::string &LibDir, + llvm::Triple TargetTriple, const std::string &LibDir, StringRef CandidateTriple, bool NeedsMultiarchSuffix) { + 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. @@ -1299,6 +1299,8 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( TargetArch == llvm::Triple::ppc64 || TargetArch == llvm::Triple::mips64 || TargetArch == llvm::Triple::mips64el) ? "/64" : "/32"; + if (TargetTriple.getEnvironment() == llvm::Triple::X32) + MultiarchSuffix = "/x32"; if (llvm::sys::fs::exists(LI->path() + MultiarchSuffix + "/crtbegin.o")) { GCCMultiarchSuffix = MultiarchSuffix.str(); } else { @@ -2000,7 +2002,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // to the link paths. path_list &Paths = getFilePaths(); - const std::string Multilib = Triple.isArch32Bit() ? "lib32" : "lib64"; + const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::X32; + const std::string Multilib = Triple.isArch32Bit() ? "lib32" : IsX32 ? "libx32" : "lib64"; const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot); // Add the multilib suffixed paths where they are available. diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index 7c163a0..bcb3300 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -110,7 +110,7 @@ protected: SmallVectorImpl<StringRef> &MultiarchLibDirs, SmallVectorImpl<StringRef> &MultiarchTripleAliases); - void ScanLibDirForGCCTriple(llvm::Triple::ArchType TargetArch, + void ScanLibDirForGCCTriple(llvm::Triple TargetTriple, const std::string &LibDir, StringRef CandidateTriple, bool NeedsMultiarchSuffix = false); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 66d792f..f2f8670 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -5452,7 +5452,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (ToolChain.getArch() == llvm::Triple::x86) CmdArgs.push_back("elf_i386"); else if (ToolChain.getArch() == llvm::Triple::arm - || ToolChain.getArch() == llvm::Triple::thumb) + || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("armelf_linux_eabi"); else if (ToolChain.getArch() == llvm::Triple::ppc) CmdArgs.push_back("elf32ppclinux"); @@ -5466,8 +5466,12 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("elf64btsmip"); else if (ToolChain.getArch() == llvm::Triple::mips64el) CmdArgs.push_back("elf64ltsmip"); + else if (ToolChain.getArch() == llvm::Triple::x86_64) + CmdArgs.push_back(ToolChain.getTriple().getEnvironment() == + llvm::Triple::X32 + ? "elf32_x86_64" : "elf_x86_64"); else - CmdArgs.push_back("elf_x86_64"); + llvm_unreachable("unknown arch"); if (Args.hasArg(options::OPT_static)) { if (ToolChain.getArch() == llvm::Triple::arm @@ -5506,7 +5510,10 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, else if (ToolChain.getArch() == llvm::Triple::ppc64) CmdArgs.push_back("/lib64/ld64.so.1"); else - CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2"); + CmdArgs.push_back(ToolChain.getTriple().getEnvironment() == + llvm::Triple::X32 + ? "/libx32/ld-linux-x32.so.2" + : "/lib64/ld-linux-x86-64.so.2"); } CmdArgs.push_back("-o"); -- 1.7.9.5
>From b1aa68fd41abd351d6c37019286ff0ec1ebde4a1 Mon Sep 17 00:00:00 2001 From: Michael Liao <[email protected]> Date: Mon, 2 Jul 2012 23:03:12 -0700 Subject: [PATCH 2/2] revise codegen test for x32 psABI - revise/add test cases where x32ps ABI will generate different code due to pointer size change --- test/CodeGen/sret-x32.c | 20 ++++++++++++++++++++ test/CodeGen/sret.c | 1 + test/CodeGen/sret2-x32.c | 11 +++++++++++ test/CodeGen/sret2.c | 1 + test/CodeGen/x86_64-arguments.c | 3 +++ 5 files changed, 36 insertions(+) create mode 100644 test/CodeGen/sret-x32.c create mode 100644 test/CodeGen/sret2-x32.c diff --git a/test/CodeGen/sret-x32.c b/test/CodeGen/sret-x32.c new file mode 100644 index 0000000..690ed45 --- /dev/null +++ b/test/CodeGen/sret-x32.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -triple=x86_64-gnux32 -emit-llvm -O0 -o - | grep sret | count 1 +// RUN: %clang_cc1 %s -triple=x86_64-gnux32 -emit-llvm -O0 -o - | grep bitcast | count 2 +// RUN: %clang_cc1 %s -triple=x86_64-gnux32 -emit-llvm -O0 -o - | FileCheck %s + +struct abc { + long a; + long b; + long c; +}; + +struct abc foo1(void); +struct abc foo2(); + +void bar() { + struct abc dummy1 = foo1(); + struct abc dummy2 = foo2(); +} + +// CHECK: declare { i64, i32 } @foo1() +// CHECK: declare { i64, i32 } @foo2(...) diff --git a/test/CodeGen/sret.c b/test/CodeGen/sret.c index ed1f9a4..c67c548 100644 --- a/test/CodeGen/sret.c +++ b/test/CodeGen/sret.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -emit-llvm -O0 -o - | grep sret | count 5 +// XFAIL: x32 struct abc { long a; diff --git a/test/CodeGen/sret2-x32.c b/test/CodeGen/sret2-x32.c new file mode 100644 index 0000000..f55f1a9 --- /dev/null +++ b/test/CodeGen/sret2-x32.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -triple=x86_64-gnux32 -emit-llvm -O0 -o - | grep bitcast | count 1 +// RUN: %clang_cc1 %s -triple=x86_64-gnux32 -emit-llvm -O0 -o - | FileCheck %s + +struct abc { + long a; + long b; + long c; +}; + +// CHECK: define { i64, i32 } @foo2() +struct abc foo2(){} diff --git a/test/CodeGen/sret2.c b/test/CodeGen/sret2.c index c96ce4d..68da490 100644 --- a/test/CodeGen/sret2.c +++ b/test/CodeGen/sret2.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -emit-llvm -O0 -o - | grep sret | count 2 +// XFAIL: x32 struct abc { long a; diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c index f73e1f0..1942fb8 100644 --- a/test/CodeGen/x86_64-arguments.c +++ b/test/CodeGen/x86_64-arguments.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s| FileCheck %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -target-feature +avx | FileCheck %s -check-prefix=AVX +// RUN: %clang_cc1 -triple x86_64-gnux32 -emit-llvm -o - %s| FileCheck %s -check-prefix=X32ABI #include <stdarg.h> // CHECK: define signext i8 @f0() @@ -120,6 +121,7 @@ struct StringRef { // rdar://7375902 // CHECK: define i8* @f21(i64 %S.coerce0, i8* %S.coerce1) +// X32ABI: define i8* @f21(i64 %S.coerce) const char *f21(struct StringRef S) { return S.x+S.Ptr; } // PR7567 @@ -171,6 +173,7 @@ struct foo26 { struct foo26 f26(struct foo26 *P) { // CHECK: define { i32*, float* } @f26(%struct.foo26* %P) + // X32ABI: define i64 @f26(%struct.foo26* %P) return *P; } -- 1.7.9.5
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
