diff --git a/contrib/llvm/patches/README.TXT b/contrib/llvm/patches/README.TXT new file mode 100644 index 000000000000..b9ad69ca57dc --- /dev/null +++ b/contrib/llvm/patches/README.TXT @@ -0,0 +1,16 @@ +This is a set of individual patches, which contain all the customizations to +llvm/clang currently in the FreeBSD base system. These can be applied in +alphabetical order to a pristine llvm/clang 3.4 release source tree, for example +by doing: + +svn co https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_34/final llvm-3.4-final +svn co https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_34/final llvm-3.4-final/tools/clang +cd llvm-3.4-final +for p in /usr/src/contrib/llvm/patches/patch-*.diff; do + patch -p0 -f -F0 -E -i $p -s || break +done + +A number of these consist of hand-written modifications, specifically for +FreeBSD, while most others are cherry pickings off the llvm and clang trunks. +When a new version of llvm/clang is eventually imported, those latter ones will +largely disappear. diff --git a/contrib/llvm/patches/patch-r208961-clang-version-include.diff b/contrib/llvm/patches/patch-r208961-clang-version-include.diff new file mode 100644 index 000000000000..fb0ac1871689 --- /dev/null +++ b/contrib/llvm/patches/patch-r208961-clang-version-include.diff @@ -0,0 +1,39 @@ +This patch adjusts clang's default include paths to add FreeBSD-specific +directories. + +Introduced here: http://svn.freebsd.org/changeset/base/208961 + +Index: tools/clang/lib/Frontend/InitHeaderSearch.cpp +=================================================================== +--- tools/clang/lib/Frontend/InitHeaderSearch.cpp ++++ tools/clang/lib/Frontend/InitHeaderSearch.cpp +@@ -14,6 +14,7 @@ + #include "clang/Frontend/Utils.h" + #include "clang/Basic/FileManager.h" + #include "clang/Basic/LangOptions.h" ++#include "clang/Basic/Version.h" + #include "clang/Config/config.h" // C_INCLUDE_DIRS + #include "clang/Lex/HeaderSearch.h" + #include "clang/Lex/HeaderSearchOptions.h" +@@ -333,6 +334,9 @@ void InitHeaderSearch::AddDefaultCIncludePaths(con + #endif + } + break; ++ case llvm::Triple::FreeBSD: ++ AddPath("/usr/include/clang/" CLANG_VERSION_STRING, System, false); ++ break; + + default: + break; +@@ -423,11 +427,6 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple + else + AddPath("/usr/include/c++/4.4", CXXSystem, false); + break; +- case llvm::Triple::FreeBSD: +- // FreeBSD 8.0 +- // FreeBSD 7.3 +- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple); +- break; + case llvm::Triple::OpenBSD: { + std::string t = triple.getTriple(); + if (t.substr(0, 6) == "x86_64") diff --git a/contrib/llvm/patches/patch-r208987-format-extensions.diff b/contrib/llvm/patches/patch-r208987-format-extensions.diff new file mode 100644 index 000000000000..b01553e3e5bf --- /dev/null +++ b/contrib/llvm/patches/patch-r208987-format-extensions.diff @@ -0,0 +1,214 @@ +This patch adds support for the FreeBSD-specific -fformat-extension option, +which enables additional printf modifiers for the kernel. + +Introduced here: http://svn.freebsd.org/changeset/base/208987 + +Index: tools/clang/lib/Frontend/CompilerInvocation.cpp +=================================================================== +--- tools/clang/lib/Frontend/CompilerInvocation.cpp ++++ tools/clang/lib/Frontend/CompilerInvocation.cpp +@@ -1319,6 +1319,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgLi + Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); + Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); + Opts.Freestanding = Args.hasArg(OPT_ffreestanding); ++ Opts.FormatExtensions = Args.hasArg(OPT_fformat_extensions); + Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; + Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); + Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); +Index: tools/clang/lib/Analysis/FormatString.cpp +=================================================================== +--- tools/clang/lib/Analysis/FormatString.cpp ++++ tools/clang/lib/Analysis/FormatString.cpp +@@ -548,6 +548,11 @@ const char *ConversionSpecifier::toString() const + // Objective-C specific specifiers. + case ObjCObjArg: return "@"; + ++ // FreeBSD specific specifiers. ++ case FreeBSDbArg: return "b"; ++ case FreeBSDDArg: return "D"; ++ case FreeBSDrArg: return "r"; ++ + // GlibC specific specifiers. + case PrintErrno: return "m"; + } +@@ -626,6 +631,7 @@ bool FormatSpecifier::hasValidLengthModifier(const + case ConversionSpecifier::xArg: + case ConversionSpecifier::XArg: + case ConversionSpecifier::nArg: ++ case ConversionSpecifier::FreeBSDrArg: + return true; + default: + return false; +@@ -654,6 +660,7 @@ bool FormatSpecifier::hasValidLengthModifier(const + case ConversionSpecifier::nArg: + case ConversionSpecifier::cArg: + case ConversionSpecifier::sArg: ++ case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::ScanListArg: + return true; + default: +@@ -774,6 +781,9 @@ bool FormatSpecifier::hasStandardConversionSpecifi + case ConversionSpecifier::SArg: + return LangOpt.ObjC1 || LangOpt.ObjC2; + case ConversionSpecifier::InvalidSpecifier: ++ case ConversionSpecifier::FreeBSDbArg: ++ case ConversionSpecifier::FreeBSDDArg: ++ case ConversionSpecifier::FreeBSDrArg: + case ConversionSpecifier::PrintErrno: + case ConversionSpecifier::DArg: + case ConversionSpecifier::OArg: +Index: tools/clang/lib/Analysis/PrintfFormatString.cpp +=================================================================== +--- tools/clang/lib/Analysis/PrintfFormatString.cpp ++++ tools/clang/lib/Analysis/PrintfFormatString.cpp +@@ -198,10 +198,25 @@ static PrintfSpecifierResult ParsePrintfSpecifier( + case '@': k = ConversionSpecifier::ObjCObjArg; break; + // Glibc specific. + case 'm': k = ConversionSpecifier::PrintErrno; break; ++ // FreeBSD format extensions ++ case 'b': ++ if (LO.FormatExtensions) ++ k = ConversionSpecifier::FreeBSDbArg; // int followed by char * ++ break; ++ case 'r': ++ if (LO.FormatExtensions) ++ k = ConversionSpecifier::FreeBSDrArg; ++ break; ++ case 'y': ++ if (LO.FormatExtensions) ++ k = ConversionSpecifier::iArg; ++ break; + // Apple-specific + case 'D': + if (Target.getTriple().isOSDarwin()) + k = ConversionSpecifier::DArg; ++ else if (LO.FormatExtensions) ++ k = ConversionSpecifier::FreeBSDDArg; // u_char * followed by char * + break; + case 'O': + if (Target.getTriple().isOSDarwin()) +@@ -216,6 +231,10 @@ static PrintfSpecifierResult ParsePrintfSpecifier( + FS.setConversionSpecifier(CS); + if (CS.consumesDataArgument() && !FS.usesPositionalArg()) + FS.setArgIndex(argIndex++); ++ // FreeBSD extension ++ if (k == ConversionSpecifier::FreeBSDbArg || ++ k == ConversionSpecifier::FreeBSDDArg) ++ argIndex++; + + if (k == ConversionSpecifier::InvalidSpecifier) { + // Assume the conversion takes one argument. +@@ -618,6 +637,7 @@ bool PrintfSpecifier::hasValidPlusPrefix() const { + case ConversionSpecifier::GArg: + case ConversionSpecifier::aArg: + case ConversionSpecifier::AArg: ++ case ConversionSpecifier::FreeBSDrArg: + return true; + + default: +@@ -643,6 +663,7 @@ bool PrintfSpecifier::hasValidAlternativeForm() co + case ConversionSpecifier::FArg: + case ConversionSpecifier::gArg: + case ConversionSpecifier::GArg: ++ case ConversionSpecifier::FreeBSDrArg: + return true; + + default: +Index: tools/clang/lib/Sema/SemaChecking.cpp +=================================================================== +--- tools/clang/lib/Sema/SemaChecking.cpp ++++ tools/clang/lib/Sema/SemaChecking.cpp +@@ -2980,6 +2980,40 @@ CheckPrintfHandler::HandlePrintfSpecifier(const an + CoveredArgs.set(argIndex); + } + ++ // FreeBSD extensions ++ if (CS.getKind() == ConversionSpecifier::FreeBSDbArg || ++ CS.getKind() == ConversionSpecifier::FreeBSDDArg) { ++ // claim the second argument ++ CoveredArgs.set(argIndex + 1); ++ ++ // Now type check the data expression that matches the ++ // format specifier. ++ const Expr *Ex = getDataArg(argIndex); ++ const analyze_printf::ArgType &AT = ++ (CS.getKind() == ConversionSpecifier::FreeBSDbArg) ? ++ ArgType(S.Context.IntTy) : ArgType::CStrTy; ++ if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) ++ S.Diag(getLocationOfByte(CS.getStart()), ++ diag::warn_printf_conversion_argument_type_mismatch) ++ << AT.getRepresentativeType(S.Context) << Ex->getType() ++ << getSpecifierRange(startSpecifier, specifierLen) ++ << Ex->getSourceRange(); ++ ++ // Now type check the data expression that matches the ++ // format specifier. ++ Ex = getDataArg(argIndex + 1); ++ const analyze_printf::ArgType &AT2 = ArgType::CStrTy; ++ if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType())) ++ S.Diag(getLocationOfByte(CS.getStart()), ++ diag::warn_printf_conversion_argument_type_mismatch) ++ << AT2.getRepresentativeType(S.Context) << Ex->getType() ++ << getSpecifierRange(startSpecifier, specifierLen) ++ << Ex->getSourceRange(); ++ ++ return true; ++ } ++ // END OF FREEBSD EXTENSIONS ++ + // Check for using an Objective-C specific conversion specifier + // in a non-ObjC literal. + if (!ObjCContext && CS.isObjCArg()) { +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -2991,6 +2991,7 @@ void Clang::ConstructJob(Compilation &C, const Job + + // Forward -f (flag) options which we can pass directly. + Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls); ++ Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions); + Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); + Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info); + Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info); +Index: tools/clang/include/clang/Basic/LangOptions.def +=================================================================== +--- tools/clang/include/clang/Basic/LangOptions.def ++++ tools/clang/include/clang/Basic/LangOptions.def +@@ -84,6 +84,7 @@ LANGOPT(TraditionalCPP , 1, 0, "traditional CPP + LANGOPT(RTTI , 1, 1, "run-time type information") + LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout") + LANGOPT(Freestanding, 1, 0, "freestanding implementation") ++LANGOPT(FormatExtensions , 1, 0, "FreeBSD format extensions") + LANGOPT(NoBuiltin , 1, 0, "disable builtin functions") + LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions") + +Index: tools/clang/include/clang/Analysis/Analyses/FormatString.h +=================================================================== +--- tools/clang/include/clang/Analysis/Analyses/FormatString.h ++++ tools/clang/include/clang/Analysis/Analyses/FormatString.h +@@ -158,6 +158,11 @@ class ConversionSpecifier { + ObjCObjArg, // '@' + ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg, + ++ // FreeBSD specific specifiers ++ FreeBSDbArg, ++ FreeBSDDArg, ++ FreeBSDrArg, ++ + // GlibC specific specifiers. + PrintErrno, // 'm' + +Index: tools/clang/include/clang/Driver/Options.td +=================================================================== +--- tools/clang/include/clang/Driver/Options.td ++++ tools/clang/include/clang/Driver/Options.td +@@ -530,6 +530,8 @@ def fno_rewrite_includes : Flag<["-"], "fno-rewrit + + def ffreestanding : Flag<["-"], "ffreestanding">, Group, Flags<[CC1Option]>, + HelpText<"Assert that the compilation takes place in a freestanding environment">; ++def fformat_extensions: Flag<["-"], "fformat-extensions">, Group, Flags<[CC1Option]>, ++ HelpText<"Enable FreeBSD kernel specific format string extensions">; + def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group, Flags<[CC1Option]>, + HelpText<"Allow GNU-extension keywords regardless of language standard">; + def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group, Flags<[CC1Option]>, diff --git a/contrib/llvm/patches/patch-r209107-clang-vendor-suffix.diff b/contrib/llvm/patches/patch-r209107-clang-vendor-suffix.diff new file mode 100644 index 000000000000..d761f786b06a --- /dev/null +++ b/contrib/llvm/patches/patch-r209107-clang-vendor-suffix.diff @@ -0,0 +1,22 @@ +This patch adds a FreeBSD-specific suffix to clang's version string. This is +usually of the form "(yyyyddmm)", representing the date when the compiler was +last updated. + +Introduced here: http://svn.freebsd.org/changeset/base/209107 + +Index: tools/clang/lib/Basic/Version.cpp +=================================================================== +--- tools/clang/lib/Basic/Version.cpp ++++ tools/clang/lib/Basic/Version.cpp +@@ -124,8 +124,10 @@ std::string getClangFullVersion() { + OS << "clang version " CLANG_VERSION_STRING " " + << getClangFullRepositoryVersion(); + ++#ifdef CLANG_VENDOR_SUFFIX ++ OS << CLANG_VENDOR_SUFFIX; ++#elif defined(CLANG_VENDOR) + // If vendor supplied, include the base LLVM version as well. +-#ifdef CLANG_VENDOR + OS << " (based on LLVM " << PACKAGE_VERSION << ")"; + #endif + diff --git a/contrib/llvm/patches/patch-r213492-amd64-multi-os-dot.diff b/contrib/llvm/patches/patch-r213492-amd64-multi-os-dot.diff new file mode 100644 index 000000000000..36bf3177f6d0 --- /dev/null +++ b/contrib/llvm/patches/patch-r213492-amd64-multi-os-dot.diff @@ -0,0 +1,18 @@ +This patch makes "clang -print-multi-os-directory" print "." on amd64, which is +required by certain ports. + +Introduced here: http://svn.freebsd.org/changeset/base/213492 + +Index: tools/clang/lib/Driver/Driver.cpp +=================================================================== +--- tools/clang/lib/Driver/Driver.cpp ++++ tools/clang/lib/Driver/Driver.cpp +@@ -780,7 +780,7 @@ bool Driver::HandleImmediateArgs(const Compilation + break; + + case llvm::Triple::x86_64: +- llvm::outs() << "x86_64" << "\n"; ++ llvm::outs() << "." << "\n"; + break; + + case llvm::Triple::ppc64: diff --git a/contrib/llvm/patches/patch-r221503-default-target-triple.diff b/contrib/llvm/patches/patch-r221503-default-target-triple.diff new file mode 100644 index 000000000000..d59cce9ff264 --- /dev/null +++ b/contrib/llvm/patches/patch-r221503-default-target-triple.diff @@ -0,0 +1,26 @@ +This patch ensures the target triple that is passed during the compiler build is +respected, instead of mangling it. + +Introduced here: http://svn.freebsd.org/changeset/base/221503 + +Index: lib/Support/Unix/Host.inc +=================================================================== +--- lib/Support/Unix/Host.inc ++++ lib/Support/Unix/Host.inc +@@ -26,6 +26,11 @@ + + using namespace llvm; + ++#ifdef __FreeBSD__ ++std::string sys::getDefaultTargetTriple() { ++ return LLVM_DEFAULT_TARGET_TRIPLE; ++} ++#else // __FreeBSD__ + static std::string getOSVersion() { + struct utsname info; + +@@ -61,3 +66,4 @@ std::string sys::getDefaultTargetTriple() { + + return Triple; + } ++#endif // __FreeBSD__ diff --git a/contrib/llvm/patches/patch-r243830-arm-disable-clear-cache.diff b/contrib/llvm/patches/patch-r243830-arm-disable-clear-cache.diff new file mode 100644 index 000000000000..b5a43425a88c --- /dev/null +++ b/contrib/llvm/patches/patch-r243830-arm-disable-clear-cache.diff @@ -0,0 +1,19 @@ +This patch ensures __clear_cache is not called on arm. In earlier versions of +clang, this special builtin was emitted as a function call, leading to link +errors. + +Introduced here: http://svn.freebsd.org/changeset/base/243830 + +Index: lib/Support/Unix/Memory.inc +=================================================================== +--- lib/Support/Unix/Memory.inc ++++ lib/Support/Unix/Memory.inc +@@ -332,7 +332,7 @@ void Memory::InvalidateInstructionCache(const void + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("icbi 0, %0" : : "r"(Line)); + asm volatile("isync"); +-# elif (defined(__arm__) || defined(__aarch64__)) && defined(__GNUC__) ++# elif (defined(__arm__) || defined(__aarch64__)) && defined(__GNUC__) && !defined(__FreeBSD__) + // FIXME: Can we safely always call this for __GNUC__ everywhere? + const char *Start = static_cast(Addr); + const char *End = Start + Len; diff --git a/contrib/llvm/patches/patch-r252503-arm-transient-stack-alignment.diff b/contrib/llvm/patches/patch-r252503-arm-transient-stack-alignment.diff new file mode 100644 index 000000000000..a046858069a1 --- /dev/null +++ b/contrib/llvm/patches/patch-r252503-arm-transient-stack-alignment.diff @@ -0,0 +1,79 @@ +This patch applies a workaround for an ARM EABI issue, where clang would +sometimes incorrectly align the stack in a leaf function that uses TLS. + +Introduced here: http://svn.freebsd.org/changeset/base/252503 + +Index: test/CodeGen/Thumb2/large-stack.ll +=================================================================== +--- test/CodeGen/Thumb2/large-stack.ll ++++ test/CodeGen/Thumb2/large-stack.ll +@@ -13,7 +13,7 @@ define void @test1() { + define void @test2() { + ; DARWIN-LABEL: test2: + ; DARWIN: sub.w sp, sp, #4160 +-; DARWIN: sub sp, #8 ++; DARWIN: sub sp, #12 + ; LINUX-LABEL: test2: + ; LINUX: sub.w sp, sp, #4160 + ; LINUX: sub sp, #8 +Index: test/CodeGen/ARM/2009-10-30.ll +=================================================================== +--- test/CodeGen/ARM/2009-10-30.ll ++++ test/CodeGen/ARM/2009-10-30.ll +@@ -4,9 +4,10 @@ + + define void @f(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, ...) { + entry: +-;CHECK: sub sp, sp, #4 +-;CHECK: add r{{[0-9]+}}, sp, #8 +-;CHECK: str r{{[0-9]+}}, [sp], #4 ++;CHECK: sub sp, sp, #8 ++;CHECK: add r{{[0-9]+}}, sp, #12 ++;CHECK: str r{{[0-9]+}}, [sp, #4] ++;CHECK: add sp, sp, #8 + ;CHECK: bx lr + %ap = alloca i8*, align 4 + %ap1 = bitcast i8** %ap to i8* +Index: test/CodeGen/ARM/vargs_align.ll +=================================================================== +--- test/CodeGen/ARM/vargs_align.ll ++++ test/CodeGen/ARM/vargs_align.ll +@@ -15,8 +15,8 @@ entry: + return: ; preds = %entry + %retval2 = load i32* %retval ; [#uses=1] + ret i32 %retval2 +-; EABI: add sp, sp, #12 + ; EABI: add sp, sp, #16 ++; EABI: add sp, sp, #16 ++; OABI: add sp, sp, #16 + ; OABI: add sp, sp, #12 +-; OABI: add sp, sp, #12 + } +Index: test/CodeGen/ARM/prefetch-thumb.ll +=================================================================== +--- test/CodeGen/ARM/prefetch-thumb.ll ++++ test/CodeGen/ARM/prefetch-thumb.ll +@@ -10,8 +10,8 @@ entry: + ;ARM: pld [sp, #50] + + ;THUMB2: t6: +-;THUMB2: pld [sp] +-;THUMB2: pld [sp, #50] ++;THUMB2: pld [sp, #4] ++;THUMB2: pld [sp, #54] + + %red = alloca [100 x i8], align 1 + %0 = getelementptr inbounds [100 x i8]* %red, i32 0, i32 0 +Index: lib/Target/ARM/ARMFrameLowering.h +=================================================================== +--- lib/Target/ARM/ARMFrameLowering.h ++++ lib/Target/ARM/ARMFrameLowering.h +@@ -27,7 +27,7 @@ class ARMFrameLowering : public TargetFrameLowerin + + public: + explicit ARMFrameLowering(const ARMSubtarget &sti) +- : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, 4), ++ : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, 8), + STI(sti) { + } + diff --git a/contrib/llvm/patches/patch-r257109-add-CC-aliases.diff b/contrib/llvm/patches/patch-r257109-add-CC-aliases.diff new file mode 100644 index 000000000000..686210bb71c0 --- /dev/null +++ b/contrib/llvm/patches/patch-r257109-add-CC-aliases.diff @@ -0,0 +1,25 @@ +This patch adds "CC" and "clang-CC" to the list of program name aliases which +invoke the C++ compiler. + +Introduced here: http://svn.freebsd.org/changeset/base/257109 + +Index: tools/clang/tools/driver/driver.cpp +=================================================================== +--- tools/clang/tools/driver/driver.cpp ++++ tools/clang/tools/driver/driver.cpp +@@ -215,6 +215,7 @@ static void ParseProgName(SmallVectorImpl CandidateGCCInstallPaths; + + public: +- GCCInstallationDetector(const Driver &D, const llvm::Triple &TargetTriple, +- const llvm::opt::ArgList &Args); ++ GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {} ++ void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args); + + /// \brief Check whether we detected a valid GCC install. + bool isValid() const { return IsValid; } diff --git a/contrib/llvm/patches/patch-r259498-add-fxsave.diff b/contrib/llvm/patches/patch-r259498-add-fxsave.diff new file mode 100644 index 000000000000..311be1e1f41e --- /dev/null +++ b/contrib/llvm/patches/patch-r259498-add-fxsave.diff @@ -0,0 +1,16 @@ +This patch adds the alias bit_FXSAVE for bit_FXSR to cpuid.h. + +Introduced here: http://svn.freebsd.org/changeset/base/259498 + +Index: tools/clang/lib/Headers/cpuid.h +=================================================================== +--- tools/clang/lib/Headers/cpuid.h ++++ tools/clang/lib/Headers/cpuid.h +@@ -79,6 +79,7 @@ + #define bit_ACPI 0x00400000 + #define bit_MMX 0x00800000 + #define bit_FXSR 0x01000000 ++#define bit_FXSAVE bit_FXSR /* for gcc compat */ + #define bit_SSE 0x02000000 + #define bit_SSE2 0x04000000 + #define bit_SS 0x08000000 diff --git a/contrib/llvm/patches/patch-r261680-clang-r200899-fix-security-quantis.diff b/contrib/llvm/patches/patch-r261680-clang-r200899-fix-security-quantis.diff new file mode 100644 index 000000000000..be810510dcfc --- /dev/null +++ b/contrib/llvm/patches/patch-r261680-clang-r200899-fix-security-quantis.diff @@ -0,0 +1,63 @@ +Pull in r200899 from upstream clang trunk (by Serge Pavlov): + + Allow transformation of VariableArray to ConstantArray. + + In the following code: + + struct A { static const int sz; }; + template void f() { T arr[A::sz]; } + + the array 'arr' is represented as a variable size array in the template. + If 'A::sz' gets value below in the translation unit, the array in + instantiation can turn into constant size array. + + This change fixes PR18633. + + Differential Revision: http://llvm-reviews.chandlerc.com/D2688 + +Introduced here: http://svn.freebsd.org/changeset/base/261680 + +Index: tools/clang/test/SemaCXX/c99-variable-length-array.cpp +=================================================================== +--- tools/clang/test/SemaCXX/c99-variable-length-array.cpp ++++ tools/clang/test/SemaCXX/c99-variable-length-array.cpp +@@ -140,3 +140,24 @@ namespace PR11744 { + } + int test = f(0); // expected-note {{instantiation of}} + } ++ ++namespace pr18633 { ++ struct A1 { ++ static const int sz; ++ static const int sz2; ++ }; ++ const int A1::sz2 = 11; ++ template ++ void func () { ++ int arr[A1::sz]; // expected-warning{{variable length arrays are a C99 feature}} ++ } ++ template ++ void func2 () { ++ int arr[A1::sz2]; ++ } ++ const int A1::sz = 12; ++ void func2() { ++ func(); ++ func2(); ++ } ++} +Index: tools/clang/lib/Sema/TreeTransform.h +=================================================================== +--- tools/clang/lib/Sema/TreeTransform.h ++++ tools/clang/lib/Sema/TreeTransform.h +@@ -3966,7 +3966,9 @@ TreeTransform::TransformVariableArrayType + return QualType(); + } + +- VariableArrayTypeLoc NewTL = TLB.push(Result); ++ // We might have constant size array now, but fortunately it has the same ++ // location layout. ++ ArrayTypeLoc NewTL = TLB.push(Result); + NewTL.setLBracketLoc(TL.getLBracketLoc()); + NewTL.setRBracketLoc(TL.getRBracketLoc()); + NewTL.setSizeExpr(Size); diff --git a/contrib/llvm/patches/patch-r261991-llvm-r195391-fix-dwarf2.diff b/contrib/llvm/patches/patch-r261991-llvm-r195391-fix-dwarf2.diff new file mode 100644 index 000000000000..0a1af3e42ae8 --- /dev/null +++ b/contrib/llvm/patches/patch-r261991-llvm-r195391-fix-dwarf2.diff @@ -0,0 +1,540 @@ +Pull in r195391 from upstream llvm trunk (by Eric Christopher): + + In Dwarf 3 (and Dwarf 2) attributes whose value are offsets into a + section use the form DW_FORM_data4 whilst in Dwarf 4 and later they + use the form DW_FORM_sec_offset. + + This patch updates the places where such attributes are generated to + use the appropriate form depending on the Dwarf version. The DIE entries + affected have the following tags: + DW_AT_stmt_list, DW_AT_ranges, DW_AT_location, DW_AT_GNU_pubnames, + DW_AT_GNU_pubtypes, DW_AT_GNU_addr_base, DW_AT_GNU_ranges_base + + It also adds a hidden command line option "--dwarf-version=" + to llc which allows the version of Dwarf to be generated to override + what is specified in the metadata; this makes it possible to update + existing tests to check the debugging information generated for both + Dwarf 4 (the default) and Dwarf 3 using the same metadata. + + Patch (slightly modified) by Keith Walker! + +Introduced here: http://svn.freebsd.org/changeset/base/261991 + +Index: lib/CodeGen/AsmPrinter/DIE.cpp +=================================================================== +--- lib/CodeGen/AsmPrinter/DIE.cpp ++++ lib/CodeGen/AsmPrinter/DIE.cpp +@@ -338,6 +338,7 @@ void DIEDelta::EmitValue(AsmPrinter *AP, dwarf::Fo + /// + unsigned DIEDelta::SizeOf(AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; ++ if (Form == dwarf::DW_FORM_sec_offset) return 4; + if (Form == dwarf::DW_FORM_strp) return 4; + return AP->getDataLayout().getPointerSize(); + } +Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp +=================================================================== +--- lib/CodeGen/AsmPrinter/DwarfDebug.cpp ++++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp +@@ -105,6 +105,11 @@ DwarfPubSections("generate-dwarf-pub-sections", cl + clEnumVal(Disable, "Disabled"), clEnumValEnd), + cl::init(Default)); + ++static cl::opt ++DwarfVersionNumber("dwarf-version", cl::Hidden, ++ cl::desc("Generate DWARF for dwarf version."), ++ cl::init(0)); ++ + static const char *const DWARFGroupName = "DWARF Emission"; + static const char *const DbgTimerName = "DWARF Debug Writer"; + +@@ -215,7 +220,9 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) + else + HasDwarfPubSections = DwarfPubSections == Enable; + +- DwarfVersion = getDwarfVersionFromModule(MMI->getModule()); ++ DwarfVersion = DwarfVersionNumber ++ ? DwarfVersionNumber ++ : getDwarfVersionFromModule(MMI->getModule()); + + { + NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); +@@ -470,9 +477,9 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileU + // .debug_range section has not been laid out yet. Emit offset in + // .debug_range as a uint, size 4, for now. emitDIE will handle + // DW_AT_ranges appropriately. +- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, +- DebugRangeSymbols.size() +- * Asm->getDataLayout().getPointerSize()); ++ TheCU->addSectionOffset(ScopeDIE, dwarf::DW_AT_ranges, ++ DebugRangeSymbols.size() * ++ Asm->getDataLayout().getPointerSize()); + for (SmallVectorImpl::const_iterator RI = Ranges.begin(), + RE = Ranges.end(); RI != RE; ++RI) { + DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); +@@ -525,9 +532,9 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileU + // .debug_range section has not been laid out yet. Emit offset in + // .debug_range as a uint, size 4, for now. emitDIE will handle + // DW_AT_ranges appropriately. +- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, +- DebugRangeSymbols.size() +- * Asm->getDataLayout().getPointerSize()); ++ TheCU->addSectionOffset(ScopeDIE, dwarf::DW_AT_ranges, ++ DebugRangeSymbols.size() * ++ Asm->getDataLayout().getPointerSize()); + for (SmallVectorImpl::const_iterator RI = Ranges.begin(), + RE = Ranges.end(); RI != RE; ++RI) { + DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); +@@ -758,14 +765,15 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICo + // The line table entries are not always emitted in assembly, so it + // is not okay to use line_table_start here. + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) +- NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, +- UseTheFirstCU ? Asm->GetTempSymbol("section_line") +- : LineTableStartSym); ++ NewCU->addSectionLabel( ++ Die, dwarf::DW_AT_stmt_list, ++ UseTheFirstCU ? Asm->GetTempSymbol("section_line") ++ : LineTableStartSym); + else if (UseTheFirstCU) +- NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); ++ NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0); + else +- NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, +- LineTableStartSym, DwarfLineSectionSym); ++ NewCU->addSectionDelta(Die, dwarf::DW_AT_stmt_list, ++ LineTableStartSym, DwarfLineSectionSym); + + // If we're using split dwarf the compilation dir is going to be in the + // skeleton CU and so we don't need to duplicate it here. +@@ -776,26 +784,24 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICo + // emit it here if we don't have a skeleton CU for split dwarf. + if (GenerateGnuPubSections) { + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) +- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubnames, +- dwarf::DW_FORM_sec_offset, +- Asm->GetTempSymbol("gnu_pubnames", +- NewCU->getUniqueID())); ++ NewCU->addSectionLabel( ++ Die, dwarf::DW_AT_GNU_pubnames, ++ Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID())); + else +- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4, +- Asm->GetTempSymbol("gnu_pubnames", +- NewCU->getUniqueID()), +- DwarfGnuPubNamesSectionSym); ++ NewCU->addSectionDelta( ++ Die, dwarf::DW_AT_GNU_pubnames, ++ Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()), ++ DwarfGnuPubNamesSectionSym); + + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) +- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubtypes, +- dwarf::DW_FORM_sec_offset, +- Asm->GetTempSymbol("gnu_pubtypes", +- NewCU->getUniqueID())); ++ NewCU->addSectionLabel( ++ Die, dwarf::DW_AT_GNU_pubtypes, ++ Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID())); + else +- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4, +- Asm->GetTempSymbol("gnu_pubtypes", +- NewCU->getUniqueID()), +- DwarfGnuPubTypesSectionSym); ++ NewCU->addSectionDelta( ++ Die, dwarf::DW_AT_GNU_pubtypes, ++ Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()), ++ DwarfGnuPubTypesSectionSym); + } + } + +@@ -2956,11 +2962,10 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const + // Relocate to the beginning of the addr_base section, else 0 for the + // beginning of the one for this compile unit. + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) +- NewCU->addLabel(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset, +- DwarfAddrSectionSym); ++ NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_addr_base, ++ DwarfAddrSectionSym); + else +- NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base, +- dwarf::DW_FORM_sec_offset, 0); ++ NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0); + + // 2.17.1 requires that we use DW_AT_low_pc for a single entry point + // into an entity. We're using 0, or a NULL label for this. +@@ -2970,10 +2975,10 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const + // compile unit in debug_line section. + // FIXME: Should handle multiple compile units. + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) +- NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, +- DwarfLineSectionSym); ++ NewCU->addSectionLabel(Die, dwarf::DW_AT_stmt_list, ++ DwarfLineSectionSym); + else +- NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, 0); ++ NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0); + + if (!CompilationDir.empty()) + NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); +@@ -2981,27 +2986,31 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const + // Flags to let the linker know we have emitted new style pubnames. + if (GenerateGnuPubSections) { + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) +- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_sec_offset, +- Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID())); ++ NewCU->addSectionLabel( ++ Die, dwarf::DW_AT_GNU_pubnames, ++ Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID())); + else +- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4, +- Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()), +- DwarfGnuPubNamesSectionSym); ++ NewCU->addSectionDelta( ++ Die, dwarf::DW_AT_GNU_pubnames, ++ Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()), ++ DwarfGnuPubNamesSectionSym); + + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) +- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_sec_offset, +- Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID())); ++ NewCU->addSectionLabel( ++ Die, dwarf::DW_AT_GNU_pubtypes, ++ Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID())); + else +- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4, +- Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()), +- DwarfGnuPubTypesSectionSym); ++ NewCU->addSectionDelta( ++ Die, dwarf::DW_AT_GNU_pubtypes, ++ Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()), ++ DwarfGnuPubTypesSectionSym); + } + + // Flag if we've emitted any ranges and their location for the compile unit. + if (DebugRangeSymbols.size()) { + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) +- NewCU->addLabel(Die, dwarf::DW_AT_GNU_ranges_base, +- dwarf::DW_FORM_sec_offset, DwarfDebugRangeSectionSym); ++ NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_ranges_base, ++ DwarfDebugRangeSectionSym); + else + NewCU->addUInt(Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4, + 0); +Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +=================================================================== +--- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp ++++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +@@ -227,6 +227,26 @@ void CompileUnit::addLabel(DIEBlock *Die, dwarf::F + addLabel(Die, (dwarf::Attribute)0, Form, Label); + } + ++/// addSectionLabel - Add a Dwarf section label attribute data and value. ++/// ++void CompileUnit::addSectionLabel(DIE *Die, dwarf::Attribute Attribute, ++ const MCSymbol *Label) { ++ if (DD->getDwarfVersion() >= 4) ++ addLabel(Die, Attribute, dwarf::DW_FORM_sec_offset, Label); ++ else ++ addLabel(Die, Attribute, dwarf::DW_FORM_data4, Label); ++} ++ ++/// addSectionOffset - Add an offset into a section attribute data and value. ++/// ++void CompileUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute, ++ uint64_t Integer) { ++ if (DD->getDwarfVersion() >= 4) ++ addUInt(Die, Attribute, dwarf::DW_FORM_sec_offset, Integer); ++ else ++ addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer); ++} ++ + /// addLabelAddress - Add a dwarf label attribute data and value using + /// DW_FORM_addr or DW_FORM_GNU_addr_index. + /// +@@ -264,13 +284,15 @@ void CompileUnit::addOpAddress(DIEBlock *Die, cons + } + } + +-/// addDelta - Add a label delta attribute data and value. ++/// addSectionDelta - Add a section label delta attribute data and value. + /// +-void CompileUnit::addDelta(DIE *Die, dwarf::Attribute Attribute, +- dwarf::Form Form, const MCSymbol *Hi, +- const MCSymbol *Lo) { ++void CompileUnit::addSectionDelta(DIE *Die, dwarf::Attribute Attribute, ++ const MCSymbol *Hi, const MCSymbol *Lo) { + DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); +- Die->addValue(Attribute, Form, Value); ++ if (DD->getDwarfVersion() >= 4) ++ Die->addValue(Attribute, dwarf::DW_FORM_sec_offset, Value); ++ else ++ Die->addValue(Attribute, dwarf::DW_FORM_data4, Value); + } + + /// addDIEEntry - Add a DIE attribute data and value. +@@ -1768,10 +1790,8 @@ DIE *CompileUnit::constructVariableDIE(DbgVariable + + unsigned Offset = DV.getDotDebugLocOffset(); + if (Offset != ~0U) { +- addLabel(VariableDie, dwarf::DW_AT_location, +- DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset +- : dwarf::DW_FORM_data4, +- Asm->GetTempSymbol("debug_loc", Offset)); ++ addSectionLabel(VariableDie, dwarf::DW_AT_location, ++ Asm->GetTempSymbol("debug_loc", Offset)); + DV.setDIE(VariableDie); + return VariableDie; + } +Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +=================================================================== +--- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h ++++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +@@ -209,6 +209,14 @@ class CompileUnit { + + void addLabel(DIEBlock *Die, dwarf::Form Form, const MCSymbol *Label); + ++ /// addSectionLabel - Add a Dwarf section label attribute data and value. ++ /// ++ void addSectionLabel(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Label); ++ ++ /// addSectionOffset - Add an offset into a section attribute data and value. ++ /// ++ void addSectionOffset(DIE *Die, dwarf::Attribute Attribute, uint64_t Integer); ++ + /// addLabelAddress - Add a dwarf label attribute data and value using + /// either DW_FORM_addr or DW_FORM_GNU_addr_index. + /// +@@ -219,10 +227,9 @@ class CompileUnit { + /// + void addOpAddress(DIEBlock *Die, const MCSymbol *Label); + +- /// addDelta - Add a label delta attribute data and value. +- /// +- void addDelta(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, const MCSymbol *Hi, +- const MCSymbol *Lo); ++ /// addSectionDelta - Add a label delta attribute data and value. ++ void addSectionDelta(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Hi, ++ const MCSymbol *Lo); + + /// addDIEEntry - Add a DIE attribute data and value. + /// +Index: test/DebugInfo/X86/gnu-public-names.ll +=================================================================== +--- test/DebugInfo/X86/gnu-public-names.ll ++++ test/DebugInfo/X86/gnu-public-names.ll +@@ -1,5 +1,6 @@ + ; RUN: llc -mtriple=x86_64-pc-linux-gnu -generate-gnu-dwarf-pub-sections < %s | FileCheck -check-prefix=ASM %s + ; RUN: llc -mtriple=x86_64-pc-linux-gnu -generate-gnu-dwarf-pub-sections -filetype=obj < %s | llvm-dwarfdump - | FileCheck %s ++; RUN: llc -mtriple=x86_64-pc-linux-gnu -generate-gnu-dwarf-pub-sections -filetype=obj -dwarf-version=3 < %s | llvm-dwarfdump - | FileCheck %s -check-prefix=DWARF3 + ; ModuleID = 'dwarf-public-names.cpp' + ; + ; Generated from: +@@ -123,6 +124,85 @@ + ; CHECK-DAG: [[D]] EXTERNAL TYPE "ns::D" + ; CHECK-DAG: [[INT]] STATIC TYPE "int" + ++; DWARF3: .debug_info contents: ++; DWARF3: DW_AT_GNU_pubnames [DW_FORM_data4] (0x00000000) ++; DWARF3: DW_AT_GNU_pubtypes [DW_FORM_data4] (0x00000000) ++ ++; DWARF3: [[C:[0-9a-f]+]]: DW_TAG_structure_type ++; DWARF3-NEXT: DW_AT_name {{.*}} "C" ++ ++; DWARF3: [[STATIC_MEM_DECL:[0-9a-f]+]]: DW_TAG_member ++; DWARF3-NEXT: DW_AT_name {{.*}} "static_member_variable" ++ ++; DWARF3: [[MEM_FUNC_DECL:[0-9a-f]+]]: DW_TAG_subprogram ++; DWARF3-NEXT: DW_AT_MIPS_linkage_name ++; DWARF3-NEXT: DW_AT_name {{.*}} "member_function" ++ ++; DWARF3: [[STATIC_MEM_FUNC_DECL:[0-9a-f]+]]: DW_TAG_subprogram ++; DWARF3-NEXT: DW_AT_MIPS_linkage_name ++; DWARF3-NEXT: DW_AT_name {{.*}} "static_member_function" ++ ++; DWARF3: [[INT:[0-9a-f]+]]: DW_TAG_base_type ++; DWARF3-NEXT: DW_AT_name {{.*}} "int" ++ ++; DWARF3: [[STATIC_MEM_VAR:[0-9a-f]+]]: DW_TAG_variable ++; DWARF3-NEXT: DW_AT_specification {{.*}}[[STATIC_MEM_DECL]] ++ ++; DWARF3: [[GLOB_VAR:[0-9a-f]+]]: DW_TAG_variable ++; DWARF3-NEXT: DW_AT_name {{.*}} "global_variable" ++ ++; DWARF3: [[NS:[0-9a-f]+]]: DW_TAG_namespace ++; DWARF3-NEXT: DW_AT_name {{.*}} "ns" ++ ++; DWARF3: [[GLOB_NS_VAR_DECL:[0-9a-f]+]]: DW_TAG_variable ++; DWARF3-NEXT: DW_AT_name {{.*}} "global_namespace_variable" ++ ++; DWARF3: [[D_VAR_DECL:[0-9a-f]+]]: DW_TAG_variable ++; DWARF3-NEXT: DW_AT_name {{.*}} "d" ++ ++; DWARF3: [[D:[0-9a-f]+]]: DW_TAG_structure_type ++; DWARF3-NEXT: DW_AT_name {{.*}} "D" ++ ++; DWARF3: [[GLOB_NS_FUNC:[0-9a-f]+]]: DW_TAG_subprogram ++; DWARF3-NEXT: DW_AT_MIPS_linkage_name ++; DWARF3-NEXT: DW_AT_name {{.*}} "global_namespace_function" ++ ++; DWARF3: [[GLOB_NS_VAR:[0-9a-f]+]]: DW_TAG_variable ++; DWARF3-NEXT: DW_AT_specification {{.*}}[[GLOB_NS_VAR_DECL]] ++ ++; DWARF3: [[D_VAR:[0-9a-f]+]]: DW_TAG_variable ++; DWARF3-NEXT: DW_AT_specification {{.*}}[[D_VAR_DECL]] ++ ++; DWARF3: [[MEM_FUNC:[0-9a-f]+]]: DW_TAG_subprogram ++; DWARF3-NEXT: DW_AT_specification {{.*}}[[MEM_FUNC_DECL]] ++ ++; DWARF3: [[STATIC_MEM_FUNC:[0-9a-f]+]]: DW_TAG_subprogram ++; DWARF3-NEXT: DW_AT_specification {{.*}}[[STATIC_MEM_FUNC_DECL]] ++ ++; DWARF3: [[GLOBAL_FUNC:[0-9a-f]+]]: DW_TAG_subprogram ++; DWARF3-NEXT: DW_AT_MIPS_linkage_name ++; DWARF3-NEXT: DW_AT_name {{.*}} "global_function" ++ ++; DWARF3-LABEL: .debug_gnu_pubnames contents: ++; DWARF3-NEXT: length = 0x000000e7 version = 0x0002 unit_offset = 0x00000000 unit_size = 0x0000018b ++; DWARF3-NEXT: Offset Linkage Kind Name ++; DWARF3-DAG: [[GLOBAL_FUNC]] EXTERNAL FUNCTION "global_function" ++; DWARF3-DAG: [[NS]] EXTERNAL TYPE "ns" ++; DWARF3-DAG: [[MEM_FUNC]] EXTERNAL FUNCTION "C::member_function" ++; DWARF3-DAG: [[GLOB_VAR]] EXTERNAL VARIABLE "global_variable" ++; DWARF3-DAG: [[GLOB_NS_VAR]] EXTERNAL VARIABLE "ns::global_namespace_variable" ++; DWARF3-DAG: [[GLOB_NS_FUNC]] EXTERNAL FUNCTION "ns::global_namespace_function" ++; DWARF3-DAG: [[D_VAR]] EXTERNAL VARIABLE "ns::d" ++; DWARF3-DAG: [[STATIC_MEM_VAR]] EXTERNAL VARIABLE "C::static_member_variable" ++; DWARF3-DAG: [[STATIC_MEM_FUNC]] EXTERNAL FUNCTION "C::static_member_function" ++ ++ ++; DWARF3-LABEL: debug_gnu_pubtypes contents: ++; DWARF3: Offset Linkage Kind Name ++; DWARF3-DAG: [[C]] EXTERNAL TYPE "C" ++; DWARF3-DAG: [[D]] EXTERNAL TYPE "ns::D" ++; DWARF3-DAG: [[INT]] STATIC TYPE "int" ++ + %struct.C = type { i8 } + %"struct.ns::D" = type { i32 } + +Index: test/DebugInfo/X86/stmt-list-multiple-compile-units.ll +=================================================================== +--- test/DebugInfo/X86/stmt-list-multiple-compile-units.ll ++++ test/DebugInfo/X86/stmt-list-multiple-compile-units.ll +@@ -1,5 +1,7 @@ + ; RUN: llc -O0 %s -mtriple=x86_64-apple-darwin -filetype=obj -o %t + ; RUN: llvm-dwarfdump %t | FileCheck %s ++; RUN: llc -O0 %s -mtriple=x86_64-apple-darwin -filetype=obj -o %t -dwarf-version=3 ++; RUN: llvm-dwarfdump %t | FileCheck %s -check-prefix=DWARF3 + ; RUN: llc < %s -O0 -mtriple=x86_64-apple-macosx10.7 | FileCheck %s -check-prefix=ASM + + ; rdar://13067005 +@@ -6,11 +8,11 @@ + ; CHECK: .debug_info contents: + ; CHECK: DW_TAG_compile_unit + ; CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) +-; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x00000000) ++; CHECK: DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000) + + ; CHECK: DW_TAG_compile_unit + ; CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) +-; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x0000003c) ++; CHECK: DW_AT_stmt_list [DW_FORM_sec_offset] (0x0000003c) + + ; CHECK: .debug_line contents: + ; CHECK-NEXT: Line table prologue: +@@ -21,6 +23,24 @@ + ; CHECK: file_names[ 1] 0 0x00000000 0x00000000 simple2.c + ; CHECK-NOT: file_names + ++; DWARF3: .debug_info contents: ++; DWARF3: DW_TAG_compile_unit ++; DWARF3: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) ++; DWARF3: DW_AT_stmt_list [DW_FORM_data4] (0x00000000) ++ ++; DWARF3: DW_TAG_compile_unit ++; DWARF3: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) ++; DWARF3: DW_AT_stmt_list [DW_FORM_data4] (0x0000003c) ++ ++; DWARF3: .debug_line contents: ++; DWARF3-NEXT: Line table prologue: ++; DWARF3-NEXT: total_length: 0x00000038 ++; DWARF3: file_names[ 1] 0 0x00000000 0x00000000 simple.c ++; DWARF3: Line table prologue: ++; DWARF3-NEXT: total_length: 0x00000039 ++; DWARF3: file_names[ 1] 0 0x00000000 0x00000000 simple2.c ++; DWARF3-NOT: file_names ++ + ; PR15408 + ; ASM: L__DWARF__debug_info_begin0: + ; ASM: .long 0 ## DW_AT_stmt_list +Index: test/DebugInfo/X86/block-capture.ll +=================================================================== +--- test/DebugInfo/X86/block-capture.ll ++++ test/DebugInfo/X86/block-capture.ll +@@ -1,5 +1,7 @@ + ; RUN: llc -mtriple=x86_64-apple-darwin %s -o %t -filetype=obj + ; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s ++; RUN: llc -mtriple=x86_64-apple-darwin %s -o %t -filetype=obj -dwarf-version=3 ++; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s -check-prefix=DWARF3 + + ; Checks that we emit debug info for the block variable declare. + ; CHECK: DW_TAG_subprogram [3] +@@ -7,6 +9,11 @@ + ; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "block") + ; CHECK: DW_AT_location [DW_FORM_sec_offset] ({{.*}}) + ++; DWARF3: DW_TAG_subprogram [3] ++; DWARF3: DW_TAG_variable [5] ++; DWARF3: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "block") ++; DWARF3: DW_AT_location [DW_FORM_data4] ({{.*}}) ++ + %struct.__block_descriptor = type { i64, i64 } + %struct.__block_literal_generic = type { i8*, i32, i32, i8*, %struct.__block_descriptor* } + +Index: test/DebugInfo/X86/op_deref.ll +=================================================================== +--- test/DebugInfo/X86/op_deref.ll ++++ test/DebugInfo/X86/op_deref.ll +@@ -1,5 +1,7 @@ + ; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o %t -filetype=obj + ; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s -check-prefix=DW-CHECK ++; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o %t -filetype=obj -dwarf-version=3 ++; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s -check-prefix=DWARF3 + + ; DW-CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000067] = "vla") + ; FIXME: The location here needs to be fixed, but llvm-dwarfdump doesn't handle +@@ -6,6 +8,11 @@ + ; DW_AT_location lists yet. + ; DW-CHECK: DW_AT_location [DW_FORM_sec_offset] (0x00000000) + ++; DWARF3: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000067] = "vla") ++; FIXME: The location here needs to be fixed, but llvm-dwarfdump doesn't handle ++; DW_AT_location lists yet. ++; DWARF3: DW_AT_location [DW_FORM_data4] (0x00000000) ++ + ; Unfortunately llvm-dwarfdump can't unparse a list of DW_AT_locations + ; right now, so we check the asm output: + ; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o - -filetype=asm | FileCheck %s -check-prefix=ASM-CHECK +Index: test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll +=================================================================== +--- test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll ++++ test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll +@@ -1,7 +1,10 @@ + ; RUN: llc -mtriple=i686-w64-mingw32 -o %t -filetype=obj %s + ; RUN: llvm-dwarfdump -debug-dump=all %t | FileCheck %s ++; RUN: llc -mtriple=i686-w64-mingw32 -o %t -filetype=obj -dwarf-version=3 %s ++; RUN: llvm-dwarfdump -debug-dump=all %t | FileCheck %s -check-prefix=DWARF3 + + ; CHECK: DW_AT_stmt_list [DW_FORM_sec_offset] ++; DWARF3: DW_AT_stmt_list [DW_FORM_data4] + ; + ; generated from: + ; clang -g -S -emit-llvm test.c -o test.ll +@@ -36,6 +39,6 @@ attributes #0 = { nounwind "less-precise-fpmad"="f + !6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] + !7 = metadata !{metadata !8} + !8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +-!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 3} ++!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} + !10 = metadata !{i32 3, i32 0, metadata !4, null} + !11 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} diff --git a/contrib/llvm/patches/patch-r261991-llvm-r198385-fix-dwarf2.diff b/contrib/llvm/patches/patch-r261991-llvm-r198385-fix-dwarf2.diff new file mode 100644 index 000000000000..375f66252963 --- /dev/null +++ b/contrib/llvm/patches/patch-r261991-llvm-r198385-fix-dwarf2.diff @@ -0,0 +1,91 @@ +Pull in r198385 from upstream llvm trunk (by David Blaikie): + + Reverting r193835 due to weirdness with Go... + + Apologies for the noise - we're seeing some Go failures with cgo + interacting with Clang's debug info due to this change. + +Introduced here: http://svn.freebsd.org/changeset/base/261991 + +Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +=================================================================== +--- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp ++++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +@@ -1845,9 +1845,6 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, + + addSourceLine(MemberDie, DT); + +- DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); +- addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); +- + if (DT.getTag() == dwarf::DW_TAG_inheritance && DT.isVirtual()) { + + // For C++, virtual base classes are not at fixed offset. Use following +@@ -1892,7 +1889,11 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, + } else + // This is not a bitfield. + OffsetInBytes = DT.getOffsetInBits() >> 3; +- addUInt(MemberDie, dwarf::DW_AT_data_member_location, None, OffsetInBytes); ++ ++ DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); ++ addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); ++ addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes); ++ addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie); + } + + if (DT.isProtected()) +Index: test/DebugInfo/X86/data_member_location.ll +=================================================================== +--- test/DebugInfo/X86/data_member_location.ll ++++ test/DebugInfo/X86/data_member_location.ll +@@ -11,11 +11,11 @@ + + ; CHECK: DW_AT_name {{.*}} "c" + ; CHECK-NOT: DW_TAG +-; CHECK: DW_AT_data_member_location {{.*}} (0x00) ++; CHECK: DW_AT_data_member_location {{.*}} (<0x02> 23 00 ) + + ; CHECK: DW_AT_name {{.*}} "i" + ; CHECK-NOT: DW_TAG +-; CHECK: DW_AT_data_member_location {{.*}} (0x04) ++; CHECK: DW_AT_data_member_location {{.*}} (<0x02> 23 04 ) + + %struct.foo = type { i8, i32 } + +Index: test/DebugInfo/X86/concrete_out_of_line.ll +=================================================================== +--- test/DebugInfo/X86/concrete_out_of_line.ll ++++ test/DebugInfo/X86/concrete_out_of_line.ll +@@ -7,7 +7,7 @@ + ; first check that we have a TAG_subprogram at a given offset and it has + ; AT_inline. + +-; CHECK: 0x0000011c: DW_TAG_subprogram [17] ++; CHECK: 0x0000011e: DW_TAG_subprogram [17] + ; CHECK-NEXT: DW_AT_specification + ; CHECK-NEXT: DW_AT_inline + +@@ -14,8 +14,8 @@ + + ; and then that a TAG_subprogram refers to it with AT_abstract_origin. + +-; CHECK: 0x0000015d: DW_TAG_subprogram [19] +-; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x011c => {0x0000011c}) ++; CHECK: 0x0000015f: DW_TAG_subprogram [19] ++; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x011e => {0x0000011e}) + + define i32 @_ZN17nsAutoRefCnt7ReleaseEv() { + entry: +Index: test/DebugInfo/X86/generate-odr-hash.ll +=================================================================== +--- test/DebugInfo/X86/generate-odr-hash.ll ++++ test/DebugInfo/X86/generate-odr-hash.ll +@@ -1,5 +1,8 @@ + ; REQUIRES: object-emission + ++; Fail while investigating problem with non-block representations of member offsets. ++; XFAIL: * ++ + ; RUN: llc %s -o %t -filetype=obj -O0 -generate-odr-hash -mtriple=x86_64-unknown-linux-gnu + ; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s + ; diff --git a/contrib/llvm/patches/patch-r261991-llvm-r198389-fix-dwarf2.diff b/contrib/llvm/patches/patch-r261991-llvm-r198389-fix-dwarf2.diff new file mode 100644 index 000000000000..a4a00a9e8c65 --- /dev/null +++ b/contrib/llvm/patches/patch-r261991-llvm-r198389-fix-dwarf2.diff @@ -0,0 +1,105 @@ +Pull in r198389 from upstream llvm trunk (by David Blaikie): + + Revert "Reverting r193835 due to weirdness with Go..." + + The cgo problem was that it wants dwarf2 which doesn't support direct + constant encoding of the location. So let's add support for dwarf2 + encoding (using a location expression) of data member locations. + + This reverts commit r198385. + +Introduced here: http://svn.freebsd.org/changeset/base/261991 + +Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +=================================================================== +--- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp ++++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +@@ -1890,10 +1890,14 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, + // This is not a bitfield. + OffsetInBytes = DT.getOffsetInBits() >> 3; + +- DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); +- addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); +- addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes); +- addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie); ++ if (DD->getDwarfVersion() <= 2) { ++ DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); ++ addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); ++ addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes); ++ addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie); ++ } else ++ addUInt(MemberDie, dwarf::DW_AT_data_member_location, None, ++ OffsetInBytes); + } + + if (DT.isProtected()) +Index: test/DebugInfo/X86/data_member_location.ll +=================================================================== +--- test/DebugInfo/X86/data_member_location.ll ++++ test/DebugInfo/X86/data_member_location.ll +@@ -1,4 +1,5 @@ + ; RUN: llc -mtriple=x86_64-linux -O0 -o - -filetype=obj < %s | llvm-dwarfdump -debug-dump=info -| FileCheck %s ++; RUN: llc -mtriple=x86_64-linux -dwarf-version=2 -O0 -o - -filetype=obj < %s | llvm-dwarfdump -debug-dump=info -| FileCheck -check-prefix=DWARF2 %s + + ; Generated from Clang with the following source: + ; +@@ -11,12 +12,20 @@ + + ; CHECK: DW_AT_name {{.*}} "c" + ; CHECK-NOT: DW_TAG +-; CHECK: DW_AT_data_member_location {{.*}} (<0x02> 23 00 ) ++; CHECK: DW_AT_data_member_location {{.*}} (0x00) + + ; CHECK: DW_AT_name {{.*}} "i" + ; CHECK-NOT: DW_TAG +-; CHECK: DW_AT_data_member_location {{.*}} (<0x02> 23 04 ) ++; CHECK: DW_AT_data_member_location {{.*}} (0x04) + ++; DWARF2: DW_AT_name {{.*}} "c" ++; DWARF2-NOT: DW_TAG ++; DWARF2: DW_AT_data_member_location {{.*}} (<0x02> 23 00 ) ++ ++; DWARF2: DW_AT_name {{.*}} "i" ++; DWARF2-NOT: DW_TAG ++; DWARF2: DW_AT_data_member_location {{.*}} (<0x02> 23 04 ) ++ + %struct.foo = type { i8, i32 } + + @f = global %struct.foo zeroinitializer, align 4 +Index: test/DebugInfo/X86/concrete_out_of_line.ll +=================================================================== +--- test/DebugInfo/X86/concrete_out_of_line.ll ++++ test/DebugInfo/X86/concrete_out_of_line.ll +@@ -7,7 +7,7 @@ + ; first check that we have a TAG_subprogram at a given offset and it has + ; AT_inline. + +-; CHECK: 0x0000011e: DW_TAG_subprogram [17] ++; CHECK: 0x0000011c: DW_TAG_subprogram [17] + ; CHECK-NEXT: DW_AT_specification + ; CHECK-NEXT: DW_AT_inline + +@@ -14,8 +14,8 @@ + + ; and then that a TAG_subprogram refers to it with AT_abstract_origin. + +-; CHECK: 0x0000015f: DW_TAG_subprogram [19] +-; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x011e => {0x0000011e}) ++; CHECK: 0x0000015d: DW_TAG_subprogram [19] ++; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x011c => {0x0000011c}) + + define i32 @_ZN17nsAutoRefCnt7ReleaseEv() { + entry: +Index: test/DebugInfo/X86/generate-odr-hash.ll +=================================================================== +--- test/DebugInfo/X86/generate-odr-hash.ll ++++ test/DebugInfo/X86/generate-odr-hash.ll +@@ -1,8 +1,5 @@ + ; REQUIRES: object-emission + +-; Fail while investigating problem with non-block representations of member offsets. +-; XFAIL: * +- + ; RUN: llc %s -o %t -filetype=obj -O0 -generate-odr-hash -mtriple=x86_64-unknown-linux-gnu + ; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s + ; diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198028-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198028-sparc.diff new file mode 100644 index 000000000000..b4fb92915b37 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198028-sparc.diff @@ -0,0 +1,258 @@ +Pull in r198028 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add MCInstPrinter implementation for SPARC. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/InstPrinter/LLVMBuild.txt +=================================================================== +--- lib/Target/Sparc/InstPrinter/LLVMBuild.txt ++++ lib/Target/Sparc/InstPrinter/LLVMBuild.txt +@@ -0,0 +1,23 @@ ++;===- ./lib/Target/Sparc/InstPrinter/LLVMBuild.txt -------------*- Conf -*--===; ++; ++; The LLVM Compiler Infrastructure ++; ++; This file is distributed under the University of Illinois Open Source ++; License. See LICENSE.TXT for details. ++; ++;===------------------------------------------------------------------------===; ++; ++; This is an LLVMBuild description file for the components in this subdirectory. ++; ++; For more information on the LLVMBuild system, please see: ++; ++; http://llvm.org/docs/LLVMBuild.html ++; ++;===------------------------------------------------------------------------===; ++ ++[component_0] ++type = Library ++name = SparcAsmPrinter ++parent = Sparc ++required_libraries = MC Support ++add_to_library_groups = Sparc +Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +=================================================================== +--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp ++++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +@@ -0,0 +1,95 @@ ++//===-- SparcInstPrinter.cpp - Convert Sparc MCInst to assembly syntax -----==// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This class prints an Sparc MCInst to a .s file. ++// ++//===----------------------------------------------------------------------===// ++ ++#define DEBUG_TYPE "asm-printer" ++#include "SparcInstPrinter.h" ++ ++#include "Sparc.h" ++#include "MCTargetDesc/SparcBaseInfo.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/MC/MCSymbol.h" ++#include "llvm/Support/raw_ostream.h" ++using namespace llvm; ++ ++#define GET_INSTRUCTION_NAME ++// Uncomment the following line once we are ready to use MCAsmWriter. ++//#include "SparcGenAsmWriter.inc" ++ ++void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const ++{ ++ OS << '%' << StringRef(getRegisterName(RegNo)).lower(); ++} ++ ++void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O, ++ StringRef Annot) ++{ ++ printInstruction(MI, O); ++ printAnnotation(O, Annot); ++} ++ ++void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, ++ raw_ostream &O) ++{ ++ const MCOperand &MO = MI->getOperand (opNum); ++ ++ if (MO.isReg()) { ++ printRegName(O, MO.getReg()); ++ return ; ++ } ++ ++ if (MO.isImm()) { ++ O << (int)MO.getImm(); ++ return; ++ } ++ ++ assert(MO.isExpr() && "Unknown operand kind in printOperand"); ++ MO.getExpr()->print(O); ++} ++ ++void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum, ++ raw_ostream &O, const char *Modifier) ++{ ++ printOperand(MI, opNum, O); ++ ++ // If this is an ADD operand, emit it like normal operands. ++ if (Modifier && !strcmp(Modifier, "arith")) { ++ O << ", "; ++ printOperand(MI, opNum+1, O); ++ return; ++ } ++ const MCOperand &MO = MI->getOperand(opNum+1); ++ ++ if (MO.isReg() && MO.getReg() == SP::G0) ++ return; // don't print "+%g0" ++ if (MO.isImm() && MO.getImm() == 0) ++ return; // don't print "+0" ++ ++ O << "+"; ++ ++ printOperand(MI, opNum+1, O); ++} ++ ++void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, ++ raw_ostream &O) ++{ ++ int CC = (int)MI->getOperand(opNum).getImm(); ++ O << SPARCCondCodeToString((SPCC::CondCodes)CC); ++} ++ ++bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum, ++ raw_ostream &O) ++{ ++ assert(0 && "FIXME: Implement SparcInstPrinter::printGetPCX."); ++ return true; ++} +Index: lib/Target/Sparc/InstPrinter/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/InstPrinter/CMakeLists.txt ++++ lib/Target/Sparc/InstPrinter/CMakeLists.txt +@@ -0,0 +1,3 @@ ++add_llvm_library(LLVMSparcAsmPrinter ++ SparcInstPrinter.cpp ++ ) +Index: lib/Target/Sparc/InstPrinter/Makefile +=================================================================== +--- lib/Target/Sparc/InstPrinter/Makefile ++++ lib/Target/Sparc/InstPrinter/Makefile +@@ -0,0 +1,16 @@ ++##===- lib/Target/Sparc/InstPrinter/Makefile ---------------*- Makefile -*-===## ++# ++# The LLVM Compiler Infrastructure ++# ++# This file is distributed under the University of Illinois Open Source ++# License. See LICENSE.TXT for details. ++# ++##===----------------------------------------------------------------------===## ++ ++LEVEL = ../../../.. ++LIBRARYNAME = LLVMSparcAsmPrinter ++ ++# Hack: we need to include 'main' target directory to grab private headers ++CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. ++ ++include $(LEVEL)/Makefile.common +Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.h +=================================================================== +--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h ++++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.h +@@ -0,0 +1,46 @@ ++//===-- SparcInstPrinter.h - Convert Sparc MCInst to assembly syntax ------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This class prints an Sparc MCInst to a .s file. ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef SparcINSTPRINTER_H ++#define SparcINSTPRINTER_H ++ ++#include "llvm/MC/MCInstPrinter.h" ++ ++namespace llvm { ++ ++class MCOperand; ++ ++class SparcInstPrinter : public MCInstPrinter { ++public: ++ SparcInstPrinter(const MCAsmInfo &MAI, ++ const MCInstrInfo &MII, ++ const MCRegisterInfo &MRI) ++ : MCInstPrinter(MAI, MII, MRI) {} ++ ++ virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; ++ virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); ++ ++ // Autogenerated by tblgen. ++ void printInstruction(const MCInst *MI, raw_ostream &O); ++ static const char *getRegisterName(unsigned RegNo); ++ ++ void printOperand(const MCInst *MI, int opNum, raw_ostream &OS); ++ void printMemOperand(const MCInst *MI, int opNum, raw_ostream &OS, ++ const char *Modifier = 0); ++ void printCCOperand(const MCInst *MI, int opNum, raw_ostream &OS); ++ bool printGetPCX(const MCInst *MI, unsigned OpNo, raw_ostream &OS); ++ ++}; ++} // end namespace llvm ++ ++#endif +Index: lib/Target/Sparc/LLVMBuild.txt +=================================================================== +--- lib/Target/Sparc/LLVMBuild.txt ++++ lib/Target/Sparc/LLVMBuild.txt +@@ -16,7 +16,7 @@ + ;===------------------------------------------------------------------------===; + + [common] +-subdirectories = MCTargetDesc TargetInfo ++subdirectories = InstPrinter MCTargetDesc TargetInfo + + [component_0] + type = TargetGroup +@@ -29,6 +29,6 @@ has_jit = 1 + type = Library + name = SparcCodeGen + parent = Sparc +-required_libraries = AsmPrinter CodeGen Core MC SelectionDAG SparcDesc +- SparcInfo Support Target ++required_libraries = AsmPrinter CodeGen Core MC SelectionDAG SparcAsmPrinter ++ SparcDesc SparcInfo Support Target + add_to_library_groups = Sparc +Index: lib/Target/Sparc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/CMakeLists.txt ++++ lib/Target/Sparc/CMakeLists.txt +@@ -29,3 +29,4 @@ add_dependencies(LLVMSparcCodeGen SparcCommonTable + + add_subdirectory(TargetInfo) + add_subdirectory(MCTargetDesc) ++add_subdirectory(InstPrinter) +Index: lib/Target/Sparc/Makefile +=================================================================== +--- lib/Target/Sparc/Makefile ++++ lib/Target/Sparc/Makefile +@@ -17,7 +17,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenI + SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \ + SparcGenCodeEmitter.inc + +-DIRS = TargetInfo MCTargetDesc ++DIRS = InstPrinter TargetInfo MCTargetDesc + + include $(LEVEL)/Makefile.common + diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198029-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198029-sparc.diff new file mode 100644 index 000000000000..6656bce19538 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198029-sparc.diff @@ -0,0 +1,210 @@ +Pull in r198029 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add target specific MCExpr class to handle sparc specific modifiers like %hi, %lo, etc., + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +@@ -0,0 +1,84 @@ ++//===-- SparcMCExpr.cpp - Sparc specific MC expression classes --------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file contains the implementation of the assembly expression modifiers ++// accepted by the Sparc architecture (e.g. "%hi", "%lo", ...). ++// ++//===----------------------------------------------------------------------===// ++ ++#define DEBUG_TYPE "sparcmcexpr" ++#include "SparcMCExpr.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCAssembler.h" ++#include "llvm/MC/MCELF.h" ++#include "llvm/Object/ELF.h" ++ ++ ++using namespace llvm; ++ ++const SparcMCExpr* ++SparcMCExpr::Create(VariantKind Kind, const MCExpr *Expr, ++ MCContext &Ctx) { ++ return new (Ctx) SparcMCExpr(Kind, Expr); ++} ++ ++ ++void SparcMCExpr::PrintImpl(raw_ostream &OS) const ++{ ++ bool closeParen = true; ++ switch (Kind) { ++ case VK_Sparc_None: closeParen = false; break; ++ case VK_Sparc_LO: OS << "%lo("; break; ++ case VK_Sparc_HI: OS << "%hi("; break; ++ case VK_Sparc_H44: OS << "%h44("; break; ++ case VK_Sparc_M44: OS << "%m44("; break; ++ case VK_Sparc_L44: OS << "%l44("; break; ++ case VK_Sparc_HH: OS << "%hh("; break; ++ case VK_Sparc_HM: OS << "%hm("; break; ++ case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break; ++ case VK_Sparc_TLS_GD_LO10: OS << "%tgd_lo10("; break; ++ case VK_Sparc_TLS_GD_ADD: OS << "%tgd_add("; break; ++ case VK_Sparc_TLS_GD_CALL: OS << "%tgd_call("; break; ++ case VK_Sparc_TLS_LDM_HI22: OS << "%tldm_hi22("; break; ++ case VK_Sparc_TLS_LDM_LO10: OS << "%tldm_lo10("; break; ++ case VK_Sparc_TLS_LDM_ADD: OS << "%tldm_add("; break; ++ case VK_Sparc_TLS_LDM_CALL: OS << "%tldm_call("; break; ++ case VK_Sparc_TLS_LDO_HIX22: OS << "%tldo_hix22("; break; ++ case VK_Sparc_TLS_LDO_LOX10: OS << "%tldo_lox10("; break; ++ case VK_Sparc_TLS_LDO_ADD: OS << "%tldo_add("; break; ++ case VK_Sparc_TLS_IE_HI22: OS << "%tie_hi22("; break; ++ case VK_Sparc_TLS_IE_LO10: OS << "%tie_lo10("; break; ++ case VK_Sparc_TLS_IE_LD: OS << "%tie_ld("; break; ++ case VK_Sparc_TLS_IE_LDX: OS << "%tie_ldx("; break; ++ case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; break; ++ case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; break; ++ case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; break; ++ } ++ ++ const MCExpr *Expr = getSubExpr(); ++ Expr->print(OS); ++ if (closeParen) ++ OS << ')'; ++} ++ ++bool ++SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, ++ const MCAsmLayout *Layout) const { ++ assert(0 && "FIXME: Implement SparcMCExpr::EvaluateAsRelocatableImpl"); ++ return getSubExpr()->EvaluateAsRelocatable(Res, *Layout); ++} ++ ++ ++void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { ++ assert(0 && "FIXME: Implement SparcMCExpr::fixELFSymbolsInTLSFixups"); ++} ++ ++void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const { ++ assert(0 && "FIXME: Implement SparcMCExpr::AddValueSymbols"); ++} +Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt ++++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +@@ -1,6 +1,7 @@ + add_llvm_library(LLVMSparcDesc + SparcMCTargetDesc.cpp + SparcMCAsmInfo.cpp ++ SparcMCExpr.cpp + ) + + add_dependencies(LLVMSparcDesc SparcCommonTableGen) +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +@@ -0,0 +1,98 @@ ++//====- SparcMCExpr.h - Sparc specific MC expression classes --*- C++ -*-=====// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file describes Sparc-specific MCExprs, used for modifiers like ++// "%hi" or "%lo" etc., ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_SPARCMCEXPR_H ++#define LLVM_SPARCMCEXPR_H ++ ++#include "llvm/MC/MCExpr.h" ++ ++namespace llvm { ++ ++class SparcMCExpr : public MCTargetExpr { ++public: ++ enum VariantKind { ++ VK_Sparc_None, ++ VK_Sparc_LO, ++ VK_Sparc_HI, ++ VK_Sparc_H44, ++ VK_Sparc_M44, ++ VK_Sparc_L44, ++ VK_Sparc_HH, ++ VK_Sparc_HM, ++ VK_Sparc_TLS_GD_HI22, ++ VK_Sparc_TLS_GD_LO10, ++ VK_Sparc_TLS_GD_ADD, ++ VK_Sparc_TLS_GD_CALL, ++ VK_Sparc_TLS_LDM_HI22, ++ VK_Sparc_TLS_LDM_LO10, ++ VK_Sparc_TLS_LDM_ADD, ++ VK_Sparc_TLS_LDM_CALL, ++ VK_Sparc_TLS_LDO_HIX22, ++ VK_Sparc_TLS_LDO_LOX10, ++ VK_Sparc_TLS_LDO_ADD, ++ VK_Sparc_TLS_IE_HI22, ++ VK_Sparc_TLS_IE_LO10, ++ VK_Sparc_TLS_IE_LD, ++ VK_Sparc_TLS_IE_LDX, ++ VK_Sparc_TLS_IE_ADD, ++ VK_Sparc_TLS_LE_HIX22, ++ VK_Sparc_TLS_LE_LOX10 ++ }; ++ ++private: ++ const VariantKind Kind; ++ const MCExpr *Expr; ++ ++ explicit SparcMCExpr(VariantKind _Kind, const MCExpr *_Expr) ++ : Kind(_Kind), Expr(_Expr) {} ++ ++public: ++ /// @name Construction ++ /// @{ ++ ++ static const SparcMCExpr *Create(VariantKind Kind, const MCExpr *Expr, ++ MCContext &Ctx); ++ /// @} ++ /// @name Accessors ++ /// @{ ++ ++ /// getOpcode - Get the kind of this expression. ++ VariantKind getKind() const { return Kind; } ++ ++ /// getSubExpr - Get the child of this expression. ++ const MCExpr *getSubExpr() const { return Expr; } ++ ++ /// @} ++ void PrintImpl(raw_ostream &OS) const; ++ bool EvaluateAsRelocatableImpl(MCValue &Res, ++ const MCAsmLayout *Layout) const; ++ void AddValueSymbols(MCAssembler *) const; ++ const MCSection *FindAssociatedSection() const { ++ return getSubExpr()->FindAssociatedSection(); ++ } ++ ++ void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const; ++ ++ static bool classof(const MCExpr *E) { ++ return E->getKind() == MCExpr::Target; ++ } ++ ++ static bool classof(const SparcMCExpr *) { return true; } ++ ++ ++}; ++ ++} // end namespace llvm. ++ ++#endif diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198030-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198030-sparc.diff new file mode 100644 index 000000000000..7ab42913f061 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198030-sparc.diff @@ -0,0 +1,678 @@ +Pull in r198030 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Lower and MachineInstr to MC and print assembly using MCInstPrinter. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp +@@ -0,0 +1,40 @@ ++//===-- SparcTargetStreamer.cpp - Sparc Target Streamer Methods -----------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file provides Sparc specific target streamer methods. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "SparcTargetStreamer.h" ++#include "InstPrinter/SparcInstPrinter.h" ++#include "llvm/Support/FormattedStream.h" ++ ++using namespace llvm; ++ ++// pin vtable to this file ++void SparcTargetStreamer::anchor() {} ++ ++SparcTargetAsmStreamer::SparcTargetAsmStreamer(formatted_raw_ostream &OS) ++ : OS(OS) {} ++ ++void SparcTargetAsmStreamer::emitSparcRegisterIgnore(unsigned reg) { ++ OS << "\t.register " ++ << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower() ++ << ", #ignore\n"; ++} ++ ++void SparcTargetAsmStreamer::emitSparcRegisterScratch(unsigned reg) { ++ OS << "\t.register " ++ << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower() ++ << ", #scratch\n"; ++} ++ ++MCELFStreamer &SparcTargetELFStreamer::getStreamer() { ++ return static_cast(*Streamer); ++} +Index: lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt ++++ lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt +@@ -19,5 +19,5 @@ + type = Library + name = SparcDesc + parent = Sparc +-required_libraries = MC SparcInfo Support ++required_libraries = MC SparcAsmPrinter SparcInfo Support + add_to_library_groups = Sparc +Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt ++++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +@@ -2,6 +2,7 @@ add_llvm_library(LLVMSparcDesc + SparcMCTargetDesc.cpp + SparcMCAsmInfo.cpp + SparcMCExpr.cpp ++ SparcTargetStreamer.cpp + ) + + add_dependencies(LLVMSparcDesc SparcCommonTableGen) +Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +@@ -13,6 +13,8 @@ + + #include "SparcMCTargetDesc.h" + #include "SparcMCAsmInfo.h" ++#include "SparcTargetStreamer.h" ++#include "InstPrinter/SparcInstPrinter.h" + #include "llvm/MC/MCCodeGenInfo.h" + #include "llvm/MC/MCInstrInfo.h" + #include "llvm/MC/MCRegisterInfo.h" +@@ -86,6 +88,28 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(S + X->InitMCCodeGenInfo(RM, CM, OL); + return X; + } ++ ++static MCStreamer * ++createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, ++ bool isVerboseAsm, bool useLoc, bool useCFI, ++ bool useDwarfDirectory, MCInstPrinter *InstPrint, ++ MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) { ++ SparcTargetAsmStreamer *S = new SparcTargetAsmStreamer(OS); ++ ++ return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI, ++ useDwarfDirectory, InstPrint, CE, TAB, ++ ShowInst); ++} ++ ++static MCInstPrinter *createSparcMCInstPrinter(const Target &T, ++ unsigned SyntaxVariant, ++ const MCAsmInfo &MAI, ++ const MCInstrInfo &MII, ++ const MCRegisterInfo &MRI, ++ const MCSubtargetInfo &STI) { ++ return new SparcInstPrinter(MAI, MII, MRI); ++} ++ + extern "C" void LLVMInitializeSparcTargetMC() { + // Register the MC asm info. + RegisterMCAsmInfo X(TheSparcTarget); +@@ -106,4 +130,15 @@ extern "C" void LLVMInitializeSparcTargetMC() { + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget, + createSparcMCSubtargetInfo); ++ ++ TargetRegistry::RegisterAsmStreamer(TheSparcTarget, ++ createMCAsmStreamer); ++ TargetRegistry::RegisterAsmStreamer(TheSparcV9Target, ++ createMCAsmStreamer); ++ ++ // Register the MCInstPrinter ++ TargetRegistry::RegisterMCInstPrinter(TheSparcTarget, ++ createSparcMCInstPrinter); ++ TargetRegistry::RegisterMCInstPrinter(TheSparcV9Target, ++ createSparcMCInstPrinter); + } +Index: lib/Target/Sparc/SparcTargetStreamer.h +=================================================================== +--- lib/Target/Sparc/SparcTargetStreamer.h ++++ lib/Target/Sparc/SparcTargetStreamer.h +@@ -0,0 +1,47 @@ ++//===-- SparcTargetStreamer.h - Sparc Target Streamer ----------*- C++ -*--===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef SPARCTARGETSTREAMER_H ++#define SPARCTARGETSTREAMER_H ++ ++#include "llvm/MC/MCELFStreamer.h" ++#include "llvm/MC/MCStreamer.h" ++ ++namespace llvm { ++class SparcTargetStreamer : public MCTargetStreamer { ++ virtual void anchor(); ++ ++public: ++ /// Emit ".register , #ignore". ++ virtual void emitSparcRegisterIgnore(unsigned reg) = 0; ++ /// Emit ".register , #scratch". ++ virtual void emitSparcRegisterScratch(unsigned reg) = 0; ++}; ++ ++// This part is for ascii assembly output ++class SparcTargetAsmStreamer : public SparcTargetStreamer { ++ formatted_raw_ostream &OS; ++ ++public: ++ SparcTargetAsmStreamer(formatted_raw_ostream &OS); ++ virtual void emitSparcRegisterIgnore(unsigned reg); ++ virtual void emitSparcRegisterScratch(unsigned reg); ++ ++}; ++ ++// This part is for ELF object output ++class SparcTargetELFStreamer : public SparcTargetStreamer { ++public: ++ MCELFStreamer &getStreamer(); ++ virtual void emitSparcRegisterIgnore(unsigned reg) {} ++ virtual void emitSparcRegisterScratch(unsigned reg) {} ++}; ++} // end namespace llvm ++ ++#endif +Index: lib/Target/Sparc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/CMakeLists.txt ++++ lib/Target/Sparc/CMakeLists.txt +@@ -23,6 +23,7 @@ add_llvm_target(SparcCodeGen + SparcSelectionDAGInfo.cpp + SparcJITInfo.cpp + SparcCodeEmitter.cpp ++ SparcMCInstLower.cpp + ) + + add_dependencies(LLVMSparcCodeGen SparcCommonTableGen intrinsics_gen) +Index: lib/Target/Sparc/Sparc.td +=================================================================== +--- lib/Target/Sparc/Sparc.td ++++ lib/Target/Sparc/Sparc.td +@@ -65,6 +65,10 @@ def : Proc<"ultrasparc", [FeatureV9, FeatureV + def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>; + def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>; + ++def SparcAsmWriter : AsmWriter { ++ string AsmWriterClassName = "InstPrinter"; ++ bit isMCAsmWriter = 1; ++} + + //===----------------------------------------------------------------------===// + // Declare the target which we are implementing +@@ -73,4 +77,6 @@ def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV + def Sparc : Target { + // Pull in Instruction Info: + let InstructionSet = SparcInstrInfo; ++ ++ let AssemblyWriters = [SparcAsmWriter]; + } +Index: lib/Target/Sparc/SparcMCInstLower.cpp +=================================================================== +--- lib/Target/Sparc/SparcMCInstLower.cpp ++++ lib/Target/Sparc/SparcMCInstLower.cpp +@@ -0,0 +1,141 @@ ++//===-- SparcMCInstLower.cpp - Convert Sparc MachineInstr to MCInst -------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file contains code to lower Sparc MachineInstrs to their corresponding ++// MCInst records. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "Sparc.h" ++#include "MCTargetDesc/SparcBaseInfo.h" ++#include "MCTargetDesc/SparcMCExpr.h" ++#include "llvm/CodeGen/AsmPrinter.h" ++#include "llvm/CodeGen/MachineFunction.h" ++#include "llvm/CodeGen/MachineInstr.h" ++#include "llvm/CodeGen/MachineOperand.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCAsmInfo.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/Target/Mangler.h" ++#include "llvm/ADT/SmallString.h" ++ ++using namespace llvm; ++ ++ ++static MCOperand LowerSymbolOperand(const MachineInstr *MI, ++ const MachineOperand &MO, ++ AsmPrinter &AP) { ++ ++ SparcMCExpr::VariantKind Kind; ++ const MCSymbol *Symbol = 0; ++ ++ unsigned TF = MO.getTargetFlags(); ++ ++ switch(TF) { ++ default: llvm_unreachable("Unknown target flags on operand"); ++ case SPII::MO_NO_FLAG: Kind = SparcMCExpr::VK_Sparc_None; break; ++ case SPII::MO_LO: Kind = SparcMCExpr::VK_Sparc_LO; break; ++ case SPII::MO_HI: Kind = SparcMCExpr::VK_Sparc_HI; break; ++ case SPII::MO_H44: Kind = SparcMCExpr::VK_Sparc_H44; break; ++ case SPII::MO_M44: Kind = SparcMCExpr::VK_Sparc_M44; break; ++ case SPII::MO_L44: Kind = SparcMCExpr::VK_Sparc_L44; break; ++ case SPII::MO_HH: Kind = SparcMCExpr::VK_Sparc_HH; break; ++ case SPII::MO_HM: Kind = SparcMCExpr::VK_Sparc_HM; break; ++ case SPII::MO_TLS_GD_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_GD_HI22; break; ++ case SPII::MO_TLS_GD_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_GD_LO10; break; ++ case SPII::MO_TLS_GD_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_GD_ADD; break; ++ case SPII::MO_TLS_GD_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_GD_CALL; break; ++ case SPII::MO_TLS_LDM_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_HI22; break; ++ case SPII::MO_TLS_LDM_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_LO10; break; ++ case SPII::MO_TLS_LDM_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_ADD; break; ++ case SPII::MO_TLS_LDM_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_CALL; break; ++ case SPII::MO_TLS_LDO_HIX22:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_HIX22; break; ++ case SPII::MO_TLS_LDO_LOX10:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_LOX10; break; ++ case SPII::MO_TLS_LDO_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDO_ADD; break; ++ case SPII::MO_TLS_IE_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_IE_HI22; break; ++ case SPII::MO_TLS_IE_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LO10; break; ++ case SPII::MO_TLS_IE_LD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LD; break; ++ case SPII::MO_TLS_IE_LDX: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LDX; break; ++ case SPII::MO_TLS_IE_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_ADD; break; ++ case SPII::MO_TLS_LE_HIX22: Kind = SparcMCExpr::VK_Sparc_TLS_LE_HIX22; break; ++ case SPII::MO_TLS_LE_LOX10: Kind = SparcMCExpr::VK_Sparc_TLS_LE_LOX10; break; ++ } ++ ++ switch(MO.getType()) { ++ default: llvm_unreachable("Unknown type in LowerSymbolOperand"); ++ case MachineOperand::MO_MachineBasicBlock: ++ Symbol = MO.getMBB()->getSymbol(); ++ break; ++ ++ case MachineOperand::MO_GlobalAddress: ++ Symbol = AP.getSymbol(MO.getGlobal()); ++ break; ++ ++ case MachineOperand::MO_BlockAddress: ++ Symbol = AP.GetBlockAddressSymbol(MO.getBlockAddress()); ++ break; ++ ++ case MachineOperand::MO_ExternalSymbol: ++ Symbol = AP.GetExternalSymbolSymbol(MO.getSymbolName()); ++ break; ++ ++ case MachineOperand::MO_ConstantPoolIndex: ++ Symbol = AP.GetCPISymbol(MO.getIndex()); ++ break; ++ } ++ ++ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, ++ AP.OutContext); ++ const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, ++ AP.OutContext); ++ return MCOperand::CreateExpr(expr); ++} ++ ++static MCOperand LowerOperand(const MachineInstr *MI, ++ const MachineOperand &MO, ++ AsmPrinter &AP) { ++ switch(MO.getType()) { ++ default: llvm_unreachable("unknown operand type"); break; ++ case MachineOperand::MO_Register: ++ if (MO.isImplicit()) ++ break; ++ return MCOperand::CreateReg(MO.getReg()); ++ ++ case MachineOperand::MO_Immediate: ++ return MCOperand::CreateImm(MO.getImm()); ++ ++ case MachineOperand::MO_MachineBasicBlock: ++ case MachineOperand::MO_GlobalAddress: ++ case MachineOperand::MO_BlockAddress: ++ case MachineOperand::MO_ExternalSymbol: ++ case MachineOperand::MO_ConstantPoolIndex: ++ return LowerSymbolOperand(MI, MO, AP); ++ ++ case MachineOperand::MO_RegisterMask: break; ++ ++ } ++ return MCOperand(); ++} ++ ++void llvm::LowerSparcMachineInstrToMCInst(const MachineInstr *MI, ++ MCInst &OutMI, ++ AsmPrinter &AP) ++{ ++ ++ OutMI.setOpcode(MI->getOpcode()); ++ ++ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { ++ const MachineOperand &MO = MI->getOperand(i); ++ MCOperand MCOp = LowerOperand(MI, MO, AP); ++ ++ if (MCOp.isValid()) ++ OutMI.addOperand(MCOp); ++ } ++} +Index: lib/Target/Sparc/Sparc.h +=================================================================== +--- lib/Target/Sparc/Sparc.h ++++ lib/Target/Sparc/Sparc.h +@@ -23,6 +23,9 @@ namespace llvm { + class FunctionPass; + class SparcTargetMachine; + class formatted_raw_ostream; ++ class AsmPrinter; ++ class MCInst; ++ class MachineInstr; + + FunctionPass *createSparcISelDag(SparcTargetMachine &TM); + FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM); +@@ -29,6 +32,9 @@ namespace llvm { + FunctionPass *createSparcJITCodeEmitterPass(SparcTargetMachine &TM, + JITCodeEmitter &JCE); + ++ void LowerSparcMachineInstrToMCInst(const MachineInstr *MI, ++ MCInst &OutMI, ++ AsmPrinter &AP); + } // end namespace llvm; + + namespace llvm { +Index: lib/Target/Sparc/SparcAsmPrinter.cpp +=================================================================== +--- lib/Target/Sparc/SparcAsmPrinter.cpp ++++ lib/Target/Sparc/SparcAsmPrinter.cpp +@@ -16,12 +16,17 @@ + #include "Sparc.h" + #include "SparcInstrInfo.h" + #include "SparcTargetMachine.h" ++#include "SparcTargetStreamer.h" ++#include "InstPrinter/SparcInstPrinter.h" + #include "MCTargetDesc/SparcBaseInfo.h" ++#include "MCTargetDesc/SparcMCExpr.h" + #include "llvm/ADT/SmallString.h" + #include "llvm/CodeGen/AsmPrinter.h" + #include "llvm/CodeGen/MachineInstr.h" + #include "llvm/CodeGen/MachineRegisterInfo.h" + #include "llvm/MC/MCAsmInfo.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCInst.h" + #include "llvm/MC/MCStreamer.h" + #include "llvm/MC/MCSymbol.h" + #include "llvm/Support/TargetRegistry.h" +@@ -31,6 +36,9 @@ using namespace llvm; + + namespace { + class SparcAsmPrinter : public AsmPrinter { ++ SparcTargetStreamer &getTargetStreamer() { ++ return static_cast(OutStreamer.getTargetStreamer()); ++ } + public: + explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} +@@ -45,14 +53,11 @@ namespace { + void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); + + virtual void EmitFunctionBodyStart(); +- virtual void EmitInstruction(const MachineInstr *MI) { +- SmallString<128> Str; +- raw_svector_ostream OS(Str); +- printInstruction(MI, OS); +- OutStreamer.EmitRawText(OS.str()); ++ virtual void EmitInstruction(const MachineInstr *MI); ++ ++ static const char *getRegisterName(unsigned RegNo) { ++ return SparcInstPrinter::getRegisterName(RegNo); + } +- void printInstruction(const MachineInstr *MI, raw_ostream &OS);// autogen'd. +- static const char *getRegisterName(unsigned RegNo); + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, +@@ -61,25 +66,139 @@ namespace { + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + +- bool printGetPCX(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS); +- + virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) + const; +- void EmitGlobalRegisterDecl(unsigned reg) { +- SmallString<128> Str; +- raw_svector_ostream OS(Str); +- OS << "\t.register " +- << "%" << StringRef(getRegisterName(reg)).lower() +- << ", " +- << ((reg == SP::G6 || reg == SP::G7)? "#ignore" : "#scratch"); +- OutStreamer.EmitRawText(OS.str()); +- } + + }; + } // end of anonymous namespace + +-#include "SparcGenAsmWriter.inc" ++static MCOperand createPCXCallOP(MCSymbol *Label, ++ MCContext &OutContext) ++{ ++ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label, ++ OutContext); ++ const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None, ++ MCSym, OutContext); ++ return MCOperand::CreateExpr(expr); ++} + ++static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, ++ MCSymbol *GOTLabel, MCSymbol *StartLabel, ++ MCSymbol *CurLabel, ++ MCContext &OutContext) ++{ ++ const MCSymbolRefExpr *GOT = MCSymbolRefExpr::Create(GOTLabel, OutContext); ++ const MCSymbolRefExpr *Start = MCSymbolRefExpr::Create(StartLabel, ++ OutContext); ++ const MCSymbolRefExpr *Cur = MCSymbolRefExpr::Create(CurLabel, ++ OutContext); ++ ++ const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Cur, Start, OutContext); ++ const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(GOT, Sub, OutContext); ++ const SparcMCExpr *expr = SparcMCExpr::Create(Kind, ++ Add, OutContext); ++ return MCOperand::CreateExpr(expr); ++} ++ ++static void EmitCall(MCStreamer &OutStreamer, ++ MCOperand &Callee) ++{ ++ MCInst CallInst; ++ CallInst.setOpcode(SP::CALL); ++ CallInst.addOperand(Callee); ++ OutStreamer.EmitInstruction(CallInst); ++} ++ ++static void EmitSETHI(MCStreamer &OutStreamer, ++ MCOperand &Imm, MCOperand &RD) ++{ ++ MCInst SETHIInst; ++ SETHIInst.setOpcode(SP::SETHIi); ++ SETHIInst.addOperand(RD); ++ SETHIInst.addOperand(Imm); ++ OutStreamer.EmitInstruction(SETHIInst); ++} ++ ++static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, ++ MCOperand &Imm, MCOperand &RD) ++{ ++ MCInst ORInst; ++ ORInst.setOpcode(SP::ORri); ++ ORInst.addOperand(RD); ++ ORInst.addOperand(RS1); ++ ORInst.addOperand(Imm); ++ OutStreamer.EmitInstruction(ORInst); ++} ++ ++void EmitADD(MCStreamer &OutStreamer, ++ MCOperand &RS1, MCOperand &RS2, MCOperand &RD) ++{ ++ MCInst ADDInst; ++ ADDInst.setOpcode(SP::ADDrr); ++ ADDInst.addOperand(RD); ++ ADDInst.addOperand(RS1); ++ ADDInst.addOperand(RS2); ++ OutStreamer.EmitInstruction(ADDInst); ++} ++ ++static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, ++ MCStreamer &OutStreamer, ++ MCContext &OutContext) ++{ ++ const MachineOperand &MO = MI->getOperand(0); ++ MCSymbol *StartLabel = OutContext.CreateTempSymbol(); ++ MCSymbol *EndLabel = OutContext.CreateTempSymbol(); ++ MCSymbol *SethiLabel = OutContext.CreateTempSymbol(); ++ MCSymbol *GOTLabel = ++ OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); ++ ++ assert(MO.getReg() != SP::O7 && ++ "%o7 is assigned as destination for getpcx!"); ++ ++ MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg()); ++ MCOperand RegO7 = MCOperand::CreateReg(SP::O7); ++ ++ // : ++ // call ++ // : ++ // sethi %hi(_GLOBAL_OFFSET_TABLE_+(-)), ++ // : ++ // or , %lo(_GLOBAL_OFFSET_TABLE_+(-))), ++ // add , %o7, ++ ++ OutStreamer.EmitLabel(StartLabel); ++ MCOperand Callee = createPCXCallOP(EndLabel, OutContext); ++ EmitCall(OutStreamer, Callee); ++ OutStreamer.EmitLabel(SethiLabel); ++ MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_HI, ++ GOTLabel, StartLabel, SethiLabel, ++ OutContext); ++ EmitSETHI(OutStreamer, hiImm, MCRegOP); ++ OutStreamer.EmitLabel(EndLabel); ++ MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO, ++ GOTLabel, StartLabel, EndLabel, ++ OutContext); ++ EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP); ++ EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP); ++} ++ ++void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI) ++{ ++ MCInst TmpInst; ++ ++ switch (MI->getOpcode()) { ++ default: break; ++ case TargetOpcode::DBG_VALUE: ++ // FIXME: Debug Value. ++ return; ++ case SP::GETPCX: ++ LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext); ++ return; ++ } ++ LowerSparcMachineInstrToMCInst(MI, TmpInst, *this); ++ OutStreamer.EmitInstruction(TmpInst); ++} ++ + void SparcAsmPrinter::EmitFunctionBodyStart() { + if (!TM.getSubtarget().is64Bit()) + return; +@@ -90,7 +209,11 @@ void SparcAsmPrinter::EmitFunctionBodyStart() { + unsigned reg = globalRegs[i]; + if (MRI.use_empty(reg)) + continue; +- EmitGlobalRegisterDecl(reg); ++ ++ if (reg == SP::G6 || reg == SP::G7) ++ getTargetStreamer().emitSparcRegisterIgnore(reg); ++ else ++ getTargetStreamer().emitSparcRegisterScratch(reg); + } + } + +@@ -226,46 +349,6 @@ void SparcAsmPrinter::printMemOperand(const Machin + printOperand(MI, opNum+1, O); + } + +-bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum, +- raw_ostream &O) { +- std::string operand = ""; +- const MachineOperand &MO = MI->getOperand(opNum); +- switch (MO.getType()) { +- default: llvm_unreachable("Operand is not a register"); +- case MachineOperand::MO_Register: +- assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && +- "Operand is not a physical register "); +- assert(MO.getReg() != SP::O7 && +- "%o7 is assigned as destination for getpcx!"); +- operand = "%" + StringRef(getRegisterName(MO.getReg())).lower(); +- break; +- } +- +- unsigned mfNum = MI->getParent()->getParent()->getFunctionNumber(); +- unsigned bbNum = MI->getParent()->getNumber(); +- +- O << '\n' << ".LLGETPCH" << mfNum << '_' << bbNum << ":\n"; +- O << "\tcall\t.LLGETPC" << mfNum << '_' << bbNum << '\n' ; +- +- O << "\t sethi\t" +- << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum +- << ")), " << operand << '\n' ; +- +- O << ".LLGETPC" << mfNum << '_' << bbNum << ":\n" ; +- O << "\tor\t" << operand +- << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum +- << ")), " << operand << '\n'; +- O << "\tadd\t" << operand << ", %o7, " << operand << '\n'; +- +- return true; +-} +- +-void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum, +- raw_ostream &O) { +- int CC = (int)MI->getOperand(opNum).getImm(); +- O << SPARCCondCodeToString((SPCC::CondCodes)CC); +-} +- + /// PrintAsmOperand - Print out an operand for an inline asm expression. + /// + bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, +Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +=================================================================== +--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp ++++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +@@ -23,8 +23,7 @@ + using namespace llvm; + + #define GET_INSTRUCTION_NAME +-// Uncomment the following line once we are ready to use MCAsmWriter. +-//#include "SparcGenAsmWriter.inc" ++#include "SparcGenAsmWriter.inc" + + void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const + { +Index: test/CodeGen/SPARC/exception.ll +=================================================================== +--- test/CodeGen/SPARC/exception.ll ++++ test/CodeGen/SPARC/exception.ll +@@ -11,7 +11,7 @@ + + ; CHECK-LABEL: main: + ; CHECK: .cfi_startproc +-; CHECK: .cfi_def_cfa_register 30 ++; CHECK: .cfi_def_cfa_register {{30|%fp}} + ; CHECK: .cfi_window_save + ; CHECK: .cfi_register 15, 31 + diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198145-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198145-sparc.diff new file mode 100644 index 000000000000..2429e5248d70 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198145-sparc.diff @@ -0,0 +1,166 @@ +Pull in r198145 from upstream llvm trunk (by Venkatraman Govindaraju): + + [SparcV9]: Implement lowering of long double (fp128) arguments in Sparc64 ABI. + Also, pass fp128 arguments to varargs through integer registers if necessary. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/CodeGen/SPARC/64abi.ll +=================================================================== +--- test/CodeGen/SPARC/64abi.ll ++++ test/CodeGen/SPARC/64abi.ll +@@ -411,3 +411,33 @@ entry: + } + + declare i32 @use_buf(i32, i8*) ++ ++; CHECK-LABEL: test_fp128_args ++; CHECK-DAG: std %f0, [%fp+{{.+}}] ++; CHECK-DAG: std %f2, [%fp+{{.+}}] ++; CHECK-DAG: std %f6, [%fp+{{.+}}] ++; CHECK-DAG: std %f4, [%fp+{{.+}}] ++; CHECK: add %fp, [[Offset:[0-9]+]], %o0 ++; CHECK: call _Qp_add ++; CHECK: ldd [%fp+[[Offset]]], %f0 ++define fp128 @test_fp128_args(fp128 %a, fp128 %b) { ++entry: ++ %0 = fadd fp128 %a, %b ++ ret fp128 %0 ++} ++ ++declare i64 @receive_fp128(i64 %a, ...) ++ ++; CHECK-LABEL: test_fp128_variable_args ++; CHECK-DAG: std %f4, [%sp+[[Offset0:[0-9]+]]] ++; CHECK-DAG: std %f6, [%sp+[[Offset1:[0-9]+]]] ++; CHECK-DAG: ldx [%sp+[[Offset0]]], %o2 ++; CHECK-DAG: ldx [%sp+[[Offset1]]], %o3 ++; CHECK: call receive_fp128 ++define i64 @test_fp128_variable_args(i64 %a, fp128 %b) { ++entry: ++ %0 = call i64 (i64, ...)* @receive_fp128(i64 %a, fp128 %b) ++ ret i64 %0 ++} ++ ++ +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -80,11 +80,14 @@ static bool CC_Sparc_Assign_f64(unsigned &ValNo, M + static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, + MVT &LocVT, CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { +- assert((LocVT == MVT::f32 || LocVT.getSizeInBits() == 64) && ++ assert((LocVT == MVT::f32 || LocVT == MVT::f128 ++ || LocVT.getSizeInBits() == 64) && + "Can't handle non-64 bits locations"); + + // Stack space is allocated for all arguments starting from [%fp+BIAS+128]. +- unsigned Offset = State.AllocateStack(8, 8); ++ unsigned size = (LocVT == MVT::f128) ? 16 : 8; ++ unsigned alignment = (LocVT == MVT::f128) ? 16 : 8; ++ unsigned Offset = State.AllocateStack(size, alignment); + unsigned Reg = 0; + + if (LocVT == MVT::i64 && Offset < 6*8) +@@ -96,6 +99,9 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT & + else if (LocVT == MVT::f32 && Offset < 16*8) + // Promote floats to %f1, %f3, ... + Reg = SP::F1 + Offset/4; ++ else if (LocVT == MVT::f128 && Offset < 16*8) ++ // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7). ++ Reg = SP::Q0 + Offset/16; + + // Promote to register when possible, otherwise use the stack slot. + if (Reg) { +@@ -998,9 +1004,10 @@ static void fixupVariableFloatArgs(SmallVectorImpl + ArrayRef Outs) { + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + const CCValAssign &VA = ArgLocs[i]; ++ MVT ValTy = VA.getLocVT(); + // FIXME: What about f32 arguments? C promotes them to f64 when calling + // varargs functions. +- if (!VA.isRegLoc() || VA.getLocVT() != MVT::f64) ++ if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128)) + continue; + // The fixed arguments to a varargs function still go in FP registers. + if (Outs[VA.getValNo()].IsFixed) +@@ -1010,15 +1017,25 @@ static void fixupVariableFloatArgs(SmallVectorImpl + CCValAssign NewVA; + + // Determine the offset into the argument array. +- unsigned Offset = 8 * (VA.getLocReg() - SP::D0); ++ unsigned firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0; ++ unsigned argSize = (ValTy == MVT::f64) ? 8 : 16; ++ unsigned Offset = argSize * (VA.getLocReg() - firstReg); + assert(Offset < 16*8 && "Offset out of range, bad register enum?"); + + if (Offset < 6*8) { + // This argument should go in %i0-%i5. + unsigned IReg = SP::I0 + Offset/8; +- // Full register, just bitconvert into i64. +- NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), +- IReg, MVT::i64, CCValAssign::BCvt); ++ if (ValTy == MVT::f64) ++ // Full register, just bitconvert into i64. ++ NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), ++ IReg, MVT::i64, CCValAssign::BCvt); ++ else { ++ assert(ValTy == MVT::f128 && "Unexpected type!"); ++ // Full register, just bitconvert into i128 -- We will lower this into ++ // two i64s in LowerCall_64. ++ NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), ++ IReg, MVT::i128, CCValAssign::BCvt); ++ } + } else { + // This needs to go to memory, we're out of integer registers. + NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), +@@ -1094,11 +1111,46 @@ SparcTargetLowering::LowerCall_64(TargetLowering:: + Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg); + break; + case CCValAssign::BCvt: +- Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg); ++ // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But ++ // SPARC does not support i128 natively. Lower it into two i64, see below. ++ if (!VA.needsCustom() || VA.getValVT() != MVT::f128 ++ || VA.getLocVT() != MVT::i128) ++ Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg); + break; + } + + if (VA.isRegLoc()) { ++ if (VA.needsCustom() && VA.getValVT() == MVT::f128 ++ && VA.getLocVT() == MVT::i128) { ++ // Store and reload into the interger register reg and reg+1. ++ unsigned Offset = 8 * (VA.getLocReg() - SP::I0); ++ unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128; ++ SDValue StackPtr = DAG.getRegister(SP::O6, getPointerTy()); ++ SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset); ++ HiPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr, ++ HiPtrOff); ++ SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8); ++ LoPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr, ++ LoPtrOff); ++ ++ // Store to %sp+BIAS+128+Offset ++ SDValue Store = DAG.getStore(Chain, DL, Arg, HiPtrOff, ++ MachinePointerInfo(), ++ false, false, 0); ++ // Load into Reg and Reg+1 ++ SDValue Hi64 = DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, ++ MachinePointerInfo(), ++ false, false, false, 0); ++ SDValue Lo64 = DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, ++ MachinePointerInfo(), ++ false, false, false, 0); ++ RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), ++ Hi64)); ++ RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1), ++ Lo64)); ++ continue; ++ } ++ + // The custom bit on an i32 return value indicates that it should be + // passed in the high bits of the register. + if (VA.getValVT() == MVT::i32 && VA.needsCustom()) { diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198149-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198149-sparc.diff new file mode 100644 index 000000000000..912daf38eb8e --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198149-sparc.diff @@ -0,0 +1,54 @@ +Pull in r198149 from upstream llvm trunk (by Venkatraman Govindaraju): + + [SparcV9] For codegen generated library calls that return float, set inreg flag manually in LowerCall(). + This makes the sparc backend to generate Sparc64 ABI compliant code. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -1252,6 +1252,12 @@ SparcTargetLowering::LowerCall_64(TargetLowering:: + SmallVector RVLocs; + CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), + DAG.getTarget(), RVLocs, *DAG.getContext()); ++ ++ // Set inreg flag manually for codegen generated library calls that ++ // return float. ++ if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && CLI.CS == 0) ++ CLI.Ins[0].Flags.setInReg(); ++ + RVInfo.AnalyzeCallResult(CLI.Ins, CC_Sparc64); + + // Copy all of the result registers out of their specified physreg. +Index: test/CodeGen/SPARC/64abi.ll +=================================================================== +--- test/CodeGen/SPARC/64abi.ll ++++ test/CodeGen/SPARC/64abi.ll +@@ -440,4 +440,25 @@ entry: + ret i64 %0 + } + ++; CHECK-LABEL: test_call_libfunc ++; CHECK: st %f1, [%fp+[[Offset0:[0-9]+]]] ++; CHECK: fmovs %f3, %f1 ++; CHECK: call cosf ++; CHECK: st %f0, [%fp+[[Offset1:[0-9]+]]] ++; CHECK: ld [%fp+[[Offset0]]], %f1 ++; CHECK: call sinf ++; CHECK: ld [%fp+[[Offset1]]], %f1 ++; CHECK: fmuls %f1, %f0, %f0 + ++define inreg float @test_call_libfunc(float %arg0, float %arg1) { ++entry: ++ %0 = tail call inreg float @cosf(float %arg1) ++ %1 = tail call inreg float @sinf(float %arg0) ++ %2 = fmul float %0, %1 ++ ret float %2 ++} ++ ++declare inreg float @cosf(float %arg) readnone nounwind ++declare inreg float @sinf(float %arg) readnone nounwind ++ ++ diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198157-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198157-sparc.diff new file mode 100644 index 000000000000..42ef3db601ed --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198157-sparc.diff @@ -0,0 +1,368 @@ +Pull in r198157 from upstream llvm trunk (by Venkatraman Govindaraju): + + [SparcV9] Use separate instruction patterns for 64 bit arithmetic instructions instead of reusing 32 bit instruction patterns. + This is done to avoid spilling the result of the 64-bit instructions to a 4-byte slot. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcAsmPrinter.cpp +=================================================================== +--- lib/Target/Sparc/SparcAsmPrinter.cpp ++++ lib/Target/Sparc/SparcAsmPrinter.cpp +@@ -227,7 +227,7 @@ void SparcAsmPrinter::printOperand(const MachineIn + if (MI->getOpcode() == SP::CALL) + assert(TF == SPII::MO_NO_FLAG && + "Cannot handle target flags on call address"); +- else if (MI->getOpcode() == SP::SETHIi) ++ else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi) + assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH + || TF == SPII::MO_TLS_GD_HI22 + || TF == SPII::MO_TLS_LDM_HI22 +@@ -250,7 +250,7 @@ void SparcAsmPrinter::printOperand(const MachineIn + else if (MI->getOpcode() == SP::TLS_LDXrr) + assert(TF == SPII::MO_TLS_IE_LDX && + "Cannot handle target flags on ldx for TLS"); +- else if (MI->getOpcode() == SP::XORri) ++ else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri) + assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) && + "Cannot handle target flags on xor for TLS"); + else +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -141,32 +141,36 @@ def : Pat<(i64 imm:$val), + let Predicates = [Is64Bit] in { + + // Register-register instructions. ++defm ANDX : F3_12<"and", 0b000001, and, I64Regs, i64, i64imm>; ++defm ORX : F3_12<"or", 0b000010, or, I64Regs, i64, i64imm>; ++defm XORX : F3_12<"xor", 0b000011, xor, I64Regs, i64, i64imm>; + +-def : Pat<(and i64:$a, i64:$b), (ANDrr $a, $b)>; +-def : Pat<(or i64:$a, i64:$b), (ORrr $a, $b)>; +-def : Pat<(xor i64:$a, i64:$b), (XORrr $a, $b)>; ++def ANDXNrr : F3_1<2, 0b000101, ++ (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c), ++ "andn $b, $c, $dst", ++ [(set i64:$dst, (and i64:$b, (not i64:$c)))]>; ++def ORXNrr : F3_1<2, 0b000110, ++ (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c), ++ "orn $b, $c, $dst", ++ [(set i64:$dst, (or i64:$b, (not i64:$c)))]>; ++def XNORXrr : F3_1<2, 0b000111, ++ (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c), ++ "xnor $b, $c, $dst", ++ [(set i64:$dst, (not (xor i64:$b, i64:$c)))]>; + +-def : Pat<(and i64:$a, (not i64:$b)), (ANDNrr $a, $b)>; +-def : Pat<(or i64:$a, (not i64:$b)), (ORNrr $a, $b)>; +-def : Pat<(xor i64:$a, (not i64:$b)), (XNORrr $a, $b)>; ++defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>; ++defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>; + +-def : Pat<(add i64:$a, i64:$b), (ADDrr $a, $b)>; +-def : Pat<(sub i64:$a, i64:$b), (SUBrr $a, $b)>; +- + def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>; + +-def : Pat<(tlsadd i64:$a, i64:$b, tglobaltlsaddr:$sym), +- (TLS_ADDrr $a, $b, $sym)>; ++def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd), ++ (ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym), ++ "add $rs1, $rs2, $rd, $sym", ++ [(set i64:$rd, ++ (tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>; + + // Register-immediate instructions. + +-def : Pat<(and i64:$a, (i64 simm13:$b)), (ANDri $a, (as_i32imm $b))>; +-def : Pat<(or i64:$a, (i64 simm13:$b)), (ORri $a, (as_i32imm $b))>; +-def : Pat<(xor i64:$a, (i64 simm13:$b)), (XORri $a, (as_i32imm $b))>; +- +-def : Pat<(add i64:$a, (i64 simm13:$b)), (ADDri $a, (as_i32imm $b))>; +-def : Pat<(sub i64:$a, (i64 simm13:$b)), (SUBri $a, (as_i32imm $b))>; +- + def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>; + + def : Pat<(ctpop i64:$src), (POPCrr $src)>; +@@ -402,3 +406,38 @@ def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, im + (MOVFCCri (as_i32imm $t), $f, imm:$cond)>; + + } // Predicates = [Is64Bit] ++ ++ ++// 64 bit SETHI ++let Predicates = [Is64Bit] in { ++def SETHIXi : F2_1<0b100, ++ (outs IntRegs:$rd), (ins i64imm:$imm22), ++ "sethi $imm22, $rd", ++ [(set i64:$rd, SETHIimm:$imm22)]>; ++} ++// Global addresses, constant pool entries ++let Predicates = [Is64Bit] in { ++ ++def : Pat<(SPhi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>; ++def : Pat<(SPlo tglobaladdr:$in), (ORXri (i64 G0), tglobaladdr:$in)>; ++def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>; ++def : Pat<(SPlo tconstpool:$in), (ORXri (i64 G0), tconstpool:$in)>; ++ ++// GlobalTLS addresses ++def : Pat<(SPhi tglobaltlsaddr:$in), (SETHIi tglobaltlsaddr:$in)>; ++def : Pat<(SPlo tglobaltlsaddr:$in), (ORXri (i64 G0), tglobaltlsaddr:$in)>; ++def : Pat<(add (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)), ++ (ADDXri (SETHIXi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>; ++def : Pat<(xor (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)), ++ (XORXri (SETHIXi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>; ++ ++// Blockaddress ++def : Pat<(SPhi tblockaddress:$in), (SETHIi tblockaddress:$in)>; ++def : Pat<(SPlo tblockaddress:$in), (ORXri (i64 G0), tblockaddress:$in)>; ++ ++// Add reg, lo. This is used when taking the addr of a global/constpool entry. ++def : Pat<(add iPTR:$r, (SPlo tglobaladdr:$in)), (ADDXri $r, tglobaladdr:$in)>; ++def : Pat<(add iPTR:$r, (SPlo tconstpool:$in)), (ADDXri $r, tconstpool:$in)>; ++def : Pat<(add iPTR:$r, (SPlo tblockaddress:$in)), ++ (ADDXri $r, tblockaddress:$in)>; ++} +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -210,15 +210,16 @@ def FCC_O : FCC_VAL<29>; // Ordered + //===----------------------------------------------------------------------===// + + /// F3_12 multiclass - Define a normal F3_1/F3_2 pattern in one shot. +-multiclass F3_12 Op3Val, SDNode OpNode> { ++multiclass F3_12 Op3Val, SDNode OpNode, ++ RegisterClass RC, ValueType Ty, Operand immOp> { + def rr : F3_1<2, Op3Val, +- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), ++ (outs RC:$dst), (ins RC:$b, RC:$c), + !strconcat(OpcStr, " $b, $c, $dst"), +- [(set i32:$dst, (OpNode i32:$b, i32:$c))]>; ++ [(set Ty:$dst, (OpNode Ty:$b, Ty:$c))]>; + def ri : F3_2<2, Op3Val, +- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), ++ (outs RC:$dst), (ins RC:$b, immOp:$c), + !strconcat(OpcStr, " $b, $c, $dst"), +- [(set i32:$dst, (OpNode i32:$b, (i32 simm13:$c)))]>; ++ [(set Ty:$dst, (OpNode Ty:$b, (Ty simm13:$c)))]>; + } + + /// F3_12np multiclass - Define a normal F3_1/F3_2 pattern in one shot, with no +@@ -464,7 +465,7 @@ let rd = 0, imm22 = 0 in + def NOP : F2_1<0b100, (outs), (ins), "nop", []>; + + // Section B.11 - Logical Instructions, p. 106 +-defm AND : F3_12<"and", 0b000001, and>; ++defm AND : F3_12<"and", 0b000001, and, IntRegs, i32, i32imm>; + + def ANDNrr : F3_1<2, 0b000101, + (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), +@@ -474,7 +475,7 @@ def ANDNri : F3_2<2, 0b000101, + (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), + "andn $b, $c, $dst", []>; + +-defm OR : F3_12<"or", 0b000010, or>; ++defm OR : F3_12<"or", 0b000010, or, IntRegs, i32, i32imm>; + + def ORNrr : F3_1<2, 0b000110, + (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), +@@ -483,7 +484,7 @@ def ORNrr : F3_1<2, 0b000110, + def ORNri : F3_2<2, 0b000110, + (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), + "orn $b, $c, $dst", []>; +-defm XOR : F3_12<"xor", 0b000011, xor>; ++defm XOR : F3_12<"xor", 0b000011, xor, IntRegs, i32, i32imm>; + + def XNORrr : F3_1<2, 0b000111, + (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), +@@ -494,12 +495,12 @@ def XNORri : F3_2<2, 0b000111, + "xnor $b, $c, $dst", []>; + + // Section B.12 - Shift Instructions, p. 107 +-defm SLL : F3_12<"sll", 0b100101, shl>; +-defm SRL : F3_12<"srl", 0b100110, srl>; +-defm SRA : F3_12<"sra", 0b100111, sra>; ++defm SLL : F3_12<"sll", 0b100101, shl, IntRegs, i32, i32imm>; ++defm SRL : F3_12<"srl", 0b100110, srl, IntRegs, i32, i32imm>; ++defm SRA : F3_12<"sra", 0b100111, sra, IntRegs, i32, i32imm>; + + // Section B.13 - Add Instructions, p. 108 +-defm ADD : F3_12<"add", 0b000000, add>; ++defm ADD : F3_12<"add", 0b000000, add, IntRegs, i32, i32imm>; + + // "LEA" forms of add (patterns to make tblgen happy) + let Predicates = [Is32Bit] in +@@ -509,18 +510,18 @@ let Predicates = [Is32Bit] in + [(set iPTR:$dst, ADDRri:$addr)]>; + + let Defs = [ICC] in +- defm ADDCC : F3_12<"addcc", 0b010000, addc>; ++ defm ADDCC : F3_12<"addcc", 0b010000, addc, IntRegs, i32, i32imm>; + + let Uses = [ICC], Defs = [ICC] in +- defm ADDX : F3_12<"addxcc", 0b011000, adde>; ++ defm ADDE : F3_12<"addxcc", 0b011000, adde, IntRegs, i32, i32imm>; + + // Section B.15 - Subtract Instructions, p. 110 +-defm SUB : F3_12 <"sub" , 0b000100, sub>; ++defm SUB : F3_12 <"sub" , 0b000100, sub, IntRegs, i32, i32imm>; + let Uses = [ICC], Defs = [ICC] in +- defm SUBX : F3_12 <"subxcc" , 0b011100, sube>; ++ defm SUBE : F3_12 <"subxcc" , 0b011100, sube, IntRegs, i32, i32imm>; + + let Defs = [ICC] in +- defm SUBCC : F3_12 <"subcc", 0b010100, subc>; ++ defm SUBCC : F3_12 <"subcc", 0b010100, subc, IntRegs, i32, i32imm>; + + let Defs = [ICC], rd = 0 in { + def CMPrr : F3_1<2, 0b010100, +@@ -542,7 +543,7 @@ let Uses = [ICC], Defs = [ICC] in + // Section B.18 - Multiply Instructions, p. 113 + let Defs = [Y] in { + defm UMUL : F3_12np<"umul", 0b001010>; +- defm SMUL : F3_12 <"smul", 0b001011, mul>; ++ defm SMUL : F3_12 <"smul", 0b001011, mul, IntRegs, i32, i32imm>; + } + + // Section B.19 - Divide Instructions, p. 115 +@@ -987,6 +988,8 @@ def : Pat<(i32 imm:$val), + + + // Global addresses, constant pool entries ++let Predicates = [Is32Bit] in { ++ + def : Pat<(SPhi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>; + def : Pat<(SPlo tglobaladdr:$in), (ORri (i32 G0), tglobaladdr:$in)>; + def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>; +@@ -1009,6 +1012,7 @@ def : Pat<(add iPTR:$r, (SPlo tglobaladdr:$in)), ( + def : Pat<(add iPTR:$r, (SPlo tconstpool:$in)), (ADDri $r, tconstpool:$in)>; + def : Pat<(add iPTR:$r, (SPlo tblockaddress:$in)), + (ADDri $r, tblockaddress:$in)>; ++} + + // Calls: + def : Pat<(call tglobaladdr:$dst), +Index: test/CodeGen/SPARC/64spill.ll +=================================================================== +--- test/CodeGen/SPARC/64spill.ll ++++ test/CodeGen/SPARC/64spill.ll +@@ -0,0 +1,116 @@ ++; RUN: llc < %s -march=sparcv9 | FileCheck %s ++ ++target datalayout = "E-i64:64-n32:64-S128" ++target triple = "sparc64-sun-sparc" ++ ++; CHECK-LABEL: test_and_spill ++; CHECK: and %i0, %i1, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_and_spill(i64 %a, i64 %b) { ++entry: ++ %r0 = and i64 %a, %b ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ ++; CHECK-LABEL: test_or_spill ++; CHECK: or %i0, %i1, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_or_spill(i64 %a, i64 %b) { ++entry: ++ %r0 = or i64 %a, %b ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ ++; CHECK-LABEL: test_xor_spill ++; CHECK: xor %i0, %i1, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_xor_spill(i64 %a, i64 %b) { ++entry: ++ %r0 = xor i64 %a, %b ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ ++ ++; CHECK-LABEL: test_add_spill ++; CHECK: add %i0, %i1, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_add_spill(i64 %a, i64 %b) { ++entry: ++ %r0 = add i64 %a, %b ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ ++; CHECK-LABEL: test_sub_spill ++; CHECK: sub %i0, %i1, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_sub_spill(i64 %a, i64 %b) { ++entry: ++ %r0 = sub i64 %a, %b ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ ++; CHECK-LABEL: test_andi_spill ++; CHECK: and %i0, 1729, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_andi_spill(i64 %a) { ++entry: ++ %r0 = and i64 %a, 1729 ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ ++; CHECK-LABEL: test_ori_spill ++; CHECK: or %i0, 1729, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_ori_spill(i64 %a) { ++entry: ++ %r0 = or i64 %a, 1729 ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ ++; CHECK-LABEL: test_xori_spill ++; CHECK: xor %i0, 1729, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_xori_spill(i64 %a) { ++entry: ++ %r0 = xor i64 %a, 1729 ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ ++; CHECK-LABEL: test_addi_spill ++; CHECK: add %i0, 1729, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_addi_spill(i64 %a) { ++entry: ++ %r0 = add i64 %a, 1729 ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ ++; CHECK-LABEL: test_subi_spill ++; CHECK: add %i0, -1729, [[R:%[gilo][0-7]]] ++; CHECK: stx [[R]], [%fp+{{.+}}] ++; CHECK: ldx [%fp+{{.+}}, %i0 ++define i64 @test_subi_spill(i64 %a) { ++entry: ++ %r0 = sub i64 %a, 1729 ++ %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0) ++ ret i64 %r0 ++} ++ diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198280-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198280-sparc.diff new file mode 100644 index 000000000000..f75d9fc6f9ae --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198280-sparc.diff @@ -0,0 +1,55 @@ +Pull in r198280 from upstream llvm trunk (by Venkatraman Govindaraju): + + [SparcV9]: Use SRL instead of SLL to clear top 32-bits in ctpop:i32. SLL does not clear top 32 bit, only SRL does. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -967,13 +967,13 @@ let Predicates = [HasV9] in { + } + + // POPCrr - This does a ctpop of a 64-bit register. As such, we have to clear +-// the top 32-bits before using it. To do this clearing, we use a SLLri X,0. ++// the top 32-bits before using it. To do this clearing, we use a SRLri X,0. + let rs1 = 0 in + def POPCrr : F3_1<2, 0b101110, + (outs IntRegs:$dst), (ins IntRegs:$src), + "popc $src, $dst", []>, Requires<[HasV9]>; + def : Pat<(ctpop i32:$src), +- (POPCrr (SLLri $src, 0))>; ++ (POPCrr (SRLri $src, 0))>; + + //===----------------------------------------------------------------------===// + // Non-Instruction Patterns +Index: test/CodeGen/SPARC/ctpop.ll +=================================================================== +--- test/CodeGen/SPARC/ctpop.ll ++++ test/CodeGen/SPARC/ctpop.ll +@@ -1,8 +1,22 @@ +-; RUN: llc < %s -march=sparc -mattr=-v9 | not grep popc +-; RUN: llc < %s -march=sparc -mattr=+v9 | grep popc ++; RUN: llc < %s -march=sparc -mattr=-v9 | FileCheck %s -check-prefix=V8 ++; RUN: llc < %s -march=sparc -mattr=+v9 | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparcv9 | FileCheck %s -check-prefix=SPARC64 + + declare i32 @llvm.ctpop.i32(i32) + ++; V8-LABEL: test ++; V8-NOT : popc ++ ++; V9-LABEL: test ++; V9: srl %o0, 0, %o0 ++; V9-NEXT: jmp %o7+8 ++; V9-NEXT: popc %o0, %o0 ++ ++; SPARC64-LABEL: test ++; SPARC64: srl %o0, 0, %o0 ++; SPARC64: jmp %o7+8 ++; SPARC64: popc %o0, %o0 ++ + define i32 @test(i32 %X) { + %Y = call i32 @llvm.ctpop.i32( i32 %X ) ; [#uses=1] + ret i32 %Y diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198281-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198281-sparc.diff new file mode 100644 index 000000000000..0af21f41330a --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198281-sparc.diff @@ -0,0 +1,99 @@ +Pull in r198281 from upstream llvm trunk (by Venkatraman Govindaraju): + + [SparcV9]: Custom lower UMULO/SMULO so that the arguments are send to __multi3() in correct order. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -1525,6 +1525,9 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::MULHU, MVT::i64, Expand); + setOperationAction(ISD::MULHS, MVT::i64, Expand); ++ ++ setOperationAction(ISD::UMULO, MVT::i64, Custom); ++ setOperationAction(ISD::SMULO, MVT::i64, Custom); + } + + // VASTART needs to be custom lowered to use the VarArgsFrameIndex. +@@ -2673,6 +2676,53 @@ static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op + return DAG.getMergeValues(Ops, 2, dl); + } + ++// Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode() ++// in LegalizeDAG.cpp except the order of arguments to the library function. ++static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG, ++ const SparcTargetLowering &TLI) ++{ ++ unsigned opcode = Op.getOpcode(); ++ assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode."); ++ ++ bool isSigned = (opcode == ISD::SMULO); ++ EVT VT = MVT::i64; ++ EVT WideVT = MVT::i128; ++ SDLoc dl(Op); ++ SDValue LHS = Op.getOperand(0); ++ ++ if (LHS.getValueType() != VT) ++ return Op; ++ ++ SDValue ShiftAmt = DAG.getConstant(63, VT); ++ ++ SDValue RHS = Op.getOperand(1); ++ SDValue HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt); ++ SDValue HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt); ++ SDValue Args[] = { HiLHS, LHS, HiRHS, RHS }; ++ ++ SDValue MulResult = TLI.makeLibCall(DAG, ++ RTLIB::MUL_I128, WideVT, ++ Args, 4, isSigned, dl).first; ++ SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, ++ MulResult, DAG.getIntPtrConstant(0)); ++ SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, ++ MulResult, DAG.getIntPtrConstant(1)); ++ if (isSigned) { ++ SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt); ++ TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE); ++ } else { ++ TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, VT), ++ ISD::SETNE); ++ } ++ // MulResult is a node with an illegal type. Because such things are not ++ // generally permitted during this phase of legalization, delete the ++ // node. The above EXTRACT_ELEMENT nodes should have been folded. ++ DAG.DeleteNode(MulResult.getNode()); ++ ++ SDValue Ops[2] = { BottomHalf, TopHalf } ; ++ return DAG.getMergeValues(Ops, 2, dl); ++} ++ + SDValue SparcTargetLowering:: + LowerOperation(SDValue Op, SelectionDAG &DAG) const { + +@@ -2726,6 +2776,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons + case ISD::ADDE: + case ISD::SUBC: + case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); ++ case ISD::UMULO: ++ case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this); + } + } + +Index: test/CodeGen/SPARC/64cond.ll +=================================================================== +--- test/CodeGen/SPARC/64cond.ll ++++ test/CodeGen/SPARC/64cond.ll +@@ -111,6 +111,11 @@ entry: + } + + ; CHECK-LABEL: setcc_resultty ++; CHECK-DAG: srax %i0, 63, %o0 ++; CHECK-DAG: or %g0, %i0, %o1 ++; CHECK-DAG: or %g0, 0, %o2 ++; CHECK-DAG: or %g0, 32, %o3 ++; CHECK-DAG: call __multi3 + ; CHECK: cmp + ; CHECK: movne %xcc, 1, [[R:%[gilo][0-7]]] + ; CHECK: or [[R]], %i1, %i0 diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198286-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198286-sparc.diff new file mode 100644 index 000000000000..041e263e23a2 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198286-sparc.diff @@ -0,0 +1,231 @@ +Pull in r198286 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Handle atomic loads/stores in sparc backend. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -975,6 +975,33 @@ let rs1 = 0 in + def : Pat<(ctpop i32:$src), + (POPCrr (SRLri $src, 0))>; + ++// Atomic swap. ++let hasSideEffects =1, rd = 0, rs1 = 0b01111, rs2 = 0 in ++ def STBAR : F3_1<2, 0b101000, (outs), (ins), "stbar", []>; ++ ++let Predicates = [HasV9], hasSideEffects = 1, rd = 0, rs1 = 0b01111 in ++ def MEMBARi : F3_2<2, 0b101000, (outs), (ins i32imm:$simm13), ++ "membar $simm13", []>; ++ ++let Constraints = "$val = $rd" in { ++ def SWAPrr : F3_1<3, 0b001111, ++ (outs IntRegs:$rd), (ins IntRegs:$val, MEMrr:$addr), ++ "swap [$addr], $rd", ++ [(set i32:$rd, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>; ++ def SWAPri : F3_2<3, 0b001111, ++ (outs IntRegs:$rd), (ins IntRegs:$val, MEMri:$addr), ++ "swap [$addr], $rd", ++ [(set i32:$rd, (atomic_swap_32 ADDRri:$addr, i32:$val))]>; ++} ++ ++let Predicates = [HasV9], Constraints = "$swap = $rd" in ++ def CASrr: F3_1<3, 0b111100, ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, ++ IntRegs:$swap), ++ "cas [$rs1], $rs2, $rd", ++ [(set i32:$rd, ++ (atomic_cmp_swap iPTR:$rs1, i32:$rs2, i32:$swap))]>; ++ + //===----------------------------------------------------------------------===// + // Non-Instruction Patterns + //===----------------------------------------------------------------------===// +@@ -1036,4 +1063,17 @@ def : Pat<(i32 (zextloadi1 ADDRri:$src)), (LDUBri + def : Pat<(store (i32 0), ADDRrr:$dst), (STrr ADDRrr:$dst, (i32 G0))>; + def : Pat<(store (i32 0), ADDRri:$dst), (STri ADDRri:$dst, (i32 G0))>; + ++// store bar for all atomic_fence in V8. ++let Predicates = [HasNoV9] in ++ def : Pat<(atomic_fence imm, imm), (STBAR)>; ++ ++// atomic_load_32 addr -> load addr ++def : Pat<(i32 (atomic_load ADDRrr:$src)), (LDrr ADDRrr:$src)>; ++def : Pat<(i32 (atomic_load ADDRri:$src)), (LDri ADDRri:$src)>; ++ ++// atomic_store_32 val, addr -> store val, addr ++def : Pat<(atomic_store ADDRrr:$dst, i32:$val), (STrr ADDRrr:$dst, $val)>; ++def : Pat<(atomic_store ADDRri:$dst, i32:$val), (STri ADDRri:$dst, $val)>; ++ ++ + include "SparcInstr64Bit.td" +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -1472,10 +1472,30 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); + } + +- // FIXME: There are instructions available for ATOMIC_FENCE +- // on SparcV8 and later. +- setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); ++ // ATOMICs. ++ // FIXME: We insert fences for each atomics and generate sub-optimal code ++ // for PSO/TSO. Also, implement other atomicrmw operations. + ++ setInsertFencesForAtomic(true); ++ ++ setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal); ++ setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, ++ (Subtarget->isV9() ? Legal: Expand)); ++ ++ ++ setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal); ++ ++ // Custom Lower Atomic LOAD/STORE ++ setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); ++ setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); ++ ++ if (Subtarget->is64Bit()) { ++ setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal); ++ setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Expand); ++ setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom); ++ setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom); ++ } ++ + if (!Subtarget->isV9()) { + // SparcV8 does not have FNEGD and FABSD. + setOperationAction(ISD::FNEG, MVT::f64, Custom); +@@ -2723,6 +2743,16 @@ static SDValue LowerUMULO_SMULO(SDValue Op, Select + return DAG.getMergeValues(Ops, 2, dl); + } + ++static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) { ++ // Monotonic load/stores are legal. ++ if (cast(Op)->getOrdering() <= Monotonic) ++ return Op; ++ ++ // Otherwise, expand with a fence. ++ return SDValue(); ++} ++ ++ + SDValue SparcTargetLowering:: + LowerOperation(SDValue Op, SelectionDAG &DAG) const { + +@@ -2778,6 +2808,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons + case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); + case ISD::UMULO: + case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this); ++ case ISD::ATOMIC_LOAD: ++ case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG); + } + } + +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -415,6 +415,32 @@ def SETHIXi : F2_1<0b100, + "sethi $imm22, $rd", + [(set i64:$rd, SETHIimm:$imm22)]>; + } ++ ++// ATOMICS. ++let Predicates = [Is64Bit], Constraints = "$swap = $rd" in { ++ def CASXrr: F3_1<3, 0b111110, ++ (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2, ++ I64Regs:$swap), ++ "casx [$rs1], $rs2, $rd", ++ [(set i64:$rd, ++ (atomic_cmp_swap i64:$rs1, i64:$rs2, i64:$swap))]>; ++ ++} // Predicates = [Is64Bit], Constraints = ... ++ ++let Predicates = [Is64Bit] in { ++ ++def : Pat<(atomic_fence imm, imm), (MEMBARi 0xf)>; ++ ++// atomic_load_64 addr -> load addr ++def : Pat<(i64 (atomic_load ADDRrr:$src)), (LDXrr ADDRrr:$src)>; ++def : Pat<(i64 (atomic_load ADDRri:$src)), (LDXri ADDRri:$src)>; ++ ++// atomic_store_64 val, addr -> store val, addr ++def : Pat<(atomic_store ADDRrr:$dst, i64:$val), (STXrr ADDRrr:$dst, $val)>; ++def : Pat<(atomic_store ADDRri:$dst, i64:$val), (STXri ADDRri:$dst, $val)>; ++ ++} // Predicates = [Is64Bit] ++ + // Global addresses, constant pool entries + let Predicates = [Is64Bit] in { + +Index: test/CodeGen/SPARC/atomics.ll +=================================================================== +--- test/CodeGen/SPARC/atomics.ll ++++ test/CodeGen/SPARC/atomics.ll +@@ -0,0 +1,63 @@ ++; RUN: llc < %s -march=sparcv9 | FileCheck %s ++ ++; CHECK-LABEL: test_atomic_i32 ++; CHECK: ld [%o0] ++; CHECK: membar ++; CHECK: ld [%o1] ++; CHECK: membar ++; CHECK: membar ++; CHECK: st {{.+}}, [%o2] ++define i32 @test_atomic_i32(i32* %ptr1, i32* %ptr2, i32* %ptr3) { ++entry: ++ %0 = load atomic i32* %ptr1 acquire, align 8 ++ %1 = load atomic i32* %ptr2 acquire, align 8 ++ %2 = add i32 %0, %1 ++ store atomic i32 %2, i32* %ptr3 release, align 8 ++ ret i32 %2 ++} ++ ++; CHECK-LABEL: test_atomic_i64 ++; CHECK: ldx [%o0] ++; CHECK: membar ++; CHECK: ldx [%o1] ++; CHECK: membar ++; CHECK: membar ++; CHECK: stx {{.+}}, [%o2] ++define i64 @test_atomic_i64(i64* %ptr1, i64* %ptr2, i64* %ptr3) { ++entry: ++ %0 = load atomic i64* %ptr1 acquire, align 8 ++ %1 = load atomic i64* %ptr2 acquire, align 8 ++ %2 = add i64 %0, %1 ++ store atomic i64 %2, i64* %ptr3 release, align 8 ++ ret i64 %2 ++} ++ ++; CHECK-LABEL: test_cmpxchg_i32 ++; CHECK: or %g0, 123, [[R:%[gilo][0-7]]] ++; CHECK: cas [%o1], %o0, [[R]] ++ ++define i32 @test_cmpxchg_i32(i32 %a, i32* %ptr) { ++entry: ++ %b = cmpxchg i32* %ptr, i32 %a, i32 123 monotonic ++ ret i32 %b ++} ++ ++; CHECK-LABEL: test_cmpxchg_i64 ++; CHECK: or %g0, 123, [[R:%[gilo][0-7]]] ++; CHECK: casx [%o1], %o0, [[R]] ++ ++define i64 @test_cmpxchg_i64(i64 %a, i64* %ptr) { ++entry: ++ %b = cmpxchg i64* %ptr, i64 %a, i64 123 monotonic ++ ret i64 %b ++} ++ ++; CHECK-LABEL: test_swap_i32 ++; CHECK: or %g0, 42, [[R:%[gilo][0-7]]] ++; CHECK: swap [%o1], [[R]] ++ ++define i32 @test_swap_i32(i32 %a, i32* %ptr) { ++entry: ++ %b = atomicrmw xchg i32* %ptr, i32 42 monotonic ++ ret i32 %b ++} diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198480-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198480-sparc.diff new file mode 100644 index 000000000000..b3e13627c23d --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198480-sparc.diff @@ -0,0 +1,213 @@ +Pull in r198480 from upstream llvm trunk (by Venkatraman Govindaraju): + + [SparcV9]: Implement RETURNADDR and FRAMEADDR lowering in SPARC64. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -2415,7 +2415,8 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG + return Chain; + } + +-static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { ++static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG, ++ const SparcSubtarget *Subtarget) { + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MFI->setFrameAddressIsTaken(true); + +@@ -2422,32 +2423,49 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG + EVT VT = Op.getValueType(); + SDLoc dl(Op); + unsigned FrameReg = SP::I6; ++ unsigned stackBias = Subtarget->getStackPointerBias(); + +- uint64_t depth = Op.getConstantOperandVal(0); ++ SDValue FrameAddr; + +- SDValue FrameAddr; +- if (depth == 0) ++ if (depth == 0) { + FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); +- else { +- // flush first to make sure the windowed registers' values are in stack +- SDValue Chain = getFLUSHW(Op, DAG); +- FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT); ++ if (Subtarget->is64Bit()) ++ FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, ++ DAG.getIntPtrConstant(stackBias)); ++ return FrameAddr; ++ } + +- for (uint64_t i = 0; i != depth; ++i) { +- SDValue Ptr = DAG.getNode(ISD::ADD, +- dl, MVT::i32, +- FrameAddr, DAG.getIntPtrConstant(56)); +- FrameAddr = DAG.getLoad(MVT::i32, dl, +- Chain, +- Ptr, +- MachinePointerInfo(), false, false, false, 0); +- } ++ // flush first to make sure the windowed registers' values are in stack ++ SDValue Chain = getFLUSHW(Op, DAG); ++ FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT); ++ ++ unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56; ++ ++ while (depth--) { ++ SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, ++ DAG.getIntPtrConstant(Offset)); ++ FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo(), ++ false, false, false, 0); + } ++ if (Subtarget->is64Bit()) ++ FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, ++ DAG.getIntPtrConstant(stackBias)); + return FrameAddr; + } + ++ ++static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, ++ const SparcSubtarget *Subtarget) { ++ ++ uint64_t depth = Op.getConstantOperandVal(0); ++ ++ return getFRAMEADDR(depth, Op, DAG, Subtarget); ++ ++} ++ + static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG, +- const SparcTargetLowering &TLI) { ++ const SparcTargetLowering &TLI, ++ const SparcSubtarget *Subtarget) { + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MFI->setReturnAddressIsTaken(true); +@@ -2461,25 +2479,20 @@ static SDValue LowerRETURNADDR(SDValue Op, Selecti + unsigned RetReg = MF.addLiveIn(SP::I7, + TLI.getRegClassFor(TLI.getPointerTy())); + RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT); +- } else { +- // Need frame address to find return address of the caller. +- MFI->setFrameAddressIsTaken(true); ++ return RetAddr; ++ } + +- // flush first to make sure the windowed registers' values are in stack +- SDValue Chain = getFLUSHW(Op, DAG); +- RetAddr = DAG.getCopyFromReg(Chain, dl, SP::I6, VT); ++ // Need frame address to find return address of the caller. ++ SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget); + +- for (uint64_t i = 0; i != depth; ++i) { +- SDValue Ptr = DAG.getNode(ISD::ADD, +- dl, MVT::i32, +- RetAddr, +- DAG.getIntPtrConstant((i == depth-1)?60:56)); +- RetAddr = DAG.getLoad(MVT::i32, dl, +- Chain, +- Ptr, +- MachinePointerInfo(), false, false, false, 0); +- } +- } ++ unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60; ++ SDValue Ptr = DAG.getNode(ISD::ADD, ++ dl, VT, ++ FrameAddr, ++ DAG.getIntPtrConstant(Offset)); ++ RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, ++ MachinePointerInfo(), false, false, false, 0); ++ + return RetAddr; + } + +@@ -2763,8 +2776,10 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons + switch (Op.getOpcode()) { + default: llvm_unreachable("Should not custom lower this!"); + +- case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this); +- case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); ++ case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this, ++ Subtarget); ++ case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG, ++ Subtarget); + case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); + case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); +Index: test/CodeGen/SPARC/2011-01-11-FrameAddr.ll +=================================================================== +--- test/CodeGen/SPARC/2011-01-11-FrameAddr.ll ++++ test/CodeGen/SPARC/2011-01-11-FrameAddr.ll +@@ -2,6 +2,7 @@ + ;RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9 + ;RUN: llc -march=sparc -regalloc=basic < %s | FileCheck %s -check-prefix=V8 + ;RUN: llc -march=sparc -regalloc=basic -mattr=v9 < %s | FileCheck %s -check-prefix=V9 ++;RUN: llc -march=sparcv9 < %s | FileCheck %s -check-prefix=SPARC64 + + + define i8* @frameaddr() nounwind readnone { +@@ -15,6 +16,13 @@ entry: + ;V9: save %sp, -96, %sp + ;V9: jmp %i7+8 + ;V9: restore %g0, %fp, %o0 ++ ++;SPARC64-LABEL: frameaddr ++;SPARC64: save %sp, -128, %sp ++;SPARC64: add %fp, 2047, %i0 ++;SPARC64: jmp %i7+8 ++;SPARC64: restore %g0, %g0, %g0 ++ + %0 = tail call i8* @llvm.frameaddress(i32 0) + ret i8* %0 + } +@@ -32,6 +40,14 @@ entry: + ;V9: ld [%fp+56], {{.+}} + ;V9: ld [{{.+}}+56], {{.+}} + ;V9: ld [{{.+}}+56], {{.+}} ++ ++;SPARC64-LABEL: frameaddr2 ++;SPARC64: flushw ++;SPARC64: ldx [%fp+2159], %[[R0:[goli][0-7]]] ++;SPARC64: ldx [%[[R0]]+2159], %[[R1:[goli][0-7]]] ++;SPARC64: ldx [%[[R1]]+2159], %[[R2:[goli][0-7]]] ++;SPARC64: add %[[R2]], 2047, {{.+}} ++ + %0 = tail call i8* @llvm.frameaddress(i32 3) + ret i8* %0 + } +@@ -48,6 +64,9 @@ entry: + ;V9-LABEL: retaddr: + ;V9: or %g0, %o7, {{.+}} + ++;SPARC64-LABEL: retaddr ++;SPARC64: or %g0, %o7, {{.+}} ++ + %0 = tail call i8* @llvm.returnaddress(i32 0) + ret i8* %0 + } +@@ -66,18 +85,12 @@ entry: + ;V9: ld [{{.+}}+56], {{.+}} + ;V9: ld [{{.+}}+60], {{.+}} + +-;V8LEAF-LABEL: retaddr2: +-;V8LEAF: ta 3 +-;V8LEAF: ld [%fp+56], %[[R:[goli][0-7]]] +-;V8LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]] +-;V8LEAF: ld [%[[R1]]+60], {{.+}} ++;SPARC64-LABEL: retaddr2 ++;SPARC64: flushw ++;SPARC64: ldx [%fp+2159], %[[R0:[goli][0-7]]] ++;SPARC64: ldx [%[[R0]]+2159], %[[R1:[goli][0-7]]] ++;SPARC64: ldx [%[[R1]]+2167], {{.+}} + +-;V9LEAF-LABEL: retaddr2: +-;V9LEAF: flushw +-;V9LEAF: ld [%fp+56], %[[R:[goli][0-7]]] +-;V9LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]] +-;V9LEAF: ld [%[[R1]]+60], {{.+}} +- + %0 = tail call i8* @llvm.returnaddress(i32 3) + ret i8* %0 + } diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198484-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198484-sparc.diff new file mode 100644 index 000000000000..3bfb7d5d9643 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198484-sparc.diff @@ -0,0 +1,844 @@ +Pull in r198484 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add the initial implementation of an asm parser for sparc/sparcv9. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +@@ -123,13 +123,18 @@ extern "C" void LLVMInitializeSparcTargetMC() { + + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(TheSparcTarget, createSparcMCInstrInfo); ++ TargetRegistry::RegisterMCInstrInfo(TheSparcV9Target, createSparcMCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(TheSparcTarget, createSparcMCRegisterInfo); ++ TargetRegistry::RegisterMCRegInfo(TheSparcV9Target, ++ createSparcMCRegisterInfo); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget, + createSparcMCSubtargetInfo); ++ TargetRegistry::RegisterMCSubtargetInfo(TheSparcV9Target, ++ createSparcMCSubtargetInfo); + + TargetRegistry::RegisterAsmStreamer(TheSparcTarget, + createMCAsmStreamer); +Index: lib/Target/Sparc/LLVMBuild.txt +=================================================================== +--- lib/Target/Sparc/LLVMBuild.txt ++++ lib/Target/Sparc/LLVMBuild.txt +@@ -16,7 +16,7 @@ + ;===------------------------------------------------------------------------===; + + [common] +-subdirectories = InstPrinter MCTargetDesc TargetInfo ++subdirectories = AsmParser InstPrinter MCTargetDesc TargetInfo + + [component_0] + type = TargetGroup +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -76,13 +76,25 @@ def ADDRrr : ComplexPattern; + + // Address operands ++def SparcMEMrrAsmOperand : AsmOperandClass { ++ let Name = "MEMrr"; ++ let ParserMethod = "parseMEMrrOperand"; ++} ++ ++def SparcMEMriAsmOperand : AsmOperandClass { ++ let Name = "MEMri"; ++ let ParserMethod = "parseMEMriOperand"; ++} ++ + def MEMrr : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops ptr_rc, ptr_rc); ++ let ParserMatchClass = SparcMEMrrAsmOperand; + } + def MEMri : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops ptr_rc, i32imm); ++ let ParserMatchClass = SparcMEMriAsmOperand; + } + + def TLSSym : Operand; +@@ -239,7 +251,10 @@ multiclass F3_12np Op3Val> + + // Pseudo instructions. + class Pseudo pattern> +- : InstSP; ++ : InstSP { ++ let isCodeGenOnly = 1; ++ let isPseudo = 1; ++} + + // GETPCX for PIC + let Defs = [O7] in { +@@ -503,7 +518,7 @@ defm SRA : F3_12<"sra", 0b100111, sra, IntRegs, i3 + defm ADD : F3_12<"add", 0b000000, add, IntRegs, i32, i32imm>; + + // "LEA" forms of add (patterns to make tblgen happy) +-let Predicates = [Is32Bit] in ++let Predicates = [Is32Bit], isCodeGenOnly = 1 in + def LEA_ADDri : F3_2<2, 0b000000, + (outs IntRegs:$dst), (ins MEMri:$addr), + "add ${addr:arith}, $dst", +Index: lib/Target/Sparc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/CMakeLists.txt ++++ lib/Target/Sparc/CMakeLists.txt +@@ -4,6 +4,7 @@ tablegen(LLVM SparcGenRegisterInfo.inc -gen-regist + tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info) + tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter) + tablegen(LLVM SparcGenAsmWriter.inc -gen-asm-writer) ++tablegen(LLVM SparcGenAsmMatcher.inc -gen-asm-matcher) + tablegen(LLVM SparcGenDAGISel.inc -gen-dag-isel) + tablegen(LLVM SparcGenSubtargetInfo.inc -gen-subtarget) + tablegen(LLVM SparcGenCallingConv.inc -gen-callingconv) +@@ -31,3 +32,4 @@ add_dependencies(LLVMSparcCodeGen SparcCommonTable + add_subdirectory(TargetInfo) + add_subdirectory(MCTargetDesc) + add_subdirectory(InstPrinter) ++add_subdirectory(AsmParser) +Index: lib/Target/Sparc/Makefile +=================================================================== +--- lib/Target/Sparc/Makefile ++++ lib/Target/Sparc/Makefile +@@ -13,11 +13,12 @@ TARGET = Sparc + + # Make sure that tblgen is run, first thing. + BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \ +- SparcGenAsmWriter.inc SparcGenDAGISel.inc \ ++ SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \ ++ SparcGenDAGISel.inc \ + SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \ + SparcGenCodeEmitter.inc + +-DIRS = InstPrinter TargetInfo MCTargetDesc ++DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc + + include $(LEVEL)/Makefile.common + +Index: lib/Target/Sparc/Sparc.td +=================================================================== +--- lib/Target/Sparc/Sparc.td ++++ lib/Target/Sparc/Sparc.td +@@ -44,6 +44,10 @@ include "SparcInstrInfo.td" + + def SparcInstrInfo : InstrInfo; + ++def SparcAsmParser : AsmParser { ++ bit ShouldEmitMatchRegisterName = 0; ++} ++ + //===----------------------------------------------------------------------===// + // SPARC processors supported. + //===----------------------------------------------------------------------===// +@@ -77,6 +81,7 @@ def SparcAsmWriter : AsmWriter { + def Sparc : Target { + // Pull in Instruction Info: + let InstructionSet = SparcInstrInfo; ++ let AssemblyParsers = [SparcAsmParser]; + + let AssemblyWriters = [SparcAsmWriter]; + } +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -0,0 +1,614 @@ ++//===-- SparcAsmParser.cpp - Parse Sparc assembly to MCInst instructions --===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "MCTargetDesc/SparcMCTargetDesc.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/MC/MCParser/MCParsedAsmOperand.h" ++#include "llvm/MC/MCStreamer.h" ++#include "llvm/MC/MCSubtargetInfo.h" ++#include "llvm/MC/MCTargetAsmParser.h" ++#include "llvm/Support/TargetRegistry.h" ++ ++using namespace llvm; ++ ++// The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target ++// namespace. But SPARC backend uses "SP" as its namespace. ++namespace llvm { ++ namespace Sparc { ++ using namespace SP; ++ } ++} ++ ++namespace { ++class SparcAsmParser : public MCTargetAsmParser { ++ ++ MCSubtargetInfo &STI; ++ MCAsmParser &Parser; ++ ++ /// @name Auto-generated Match Functions ++ /// { ++ ++#define GET_ASSEMBLER_HEADER ++#include "SparcGenAsmMatcher.inc" ++ ++ /// } ++ ++ // public interface of the MCTargetAsmParser. ++ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, ++ SmallVectorImpl &Operands, ++ MCStreamer &Out, unsigned &ErrorInfo, ++ bool MatchingInlineAsm); ++ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); ++ bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, ++ SMLoc NameLoc, ++ SmallVectorImpl &Operands); ++ bool ParseDirective(AsmToken DirectiveID); ++ ++ ++ // Custom parse functions for Sparc specific operands. ++ OperandMatchResultTy ++ parseMEMrrOperand(SmallVectorImpl &Operands); ++ OperandMatchResultTy ++ parseMEMriOperand(SmallVectorImpl &Operands); ++ ++ OperandMatchResultTy ++ parseMEMOperand(SmallVectorImpl &Operands, ++ int ImmOffsetOrReg); ++ ++ OperandMatchResultTy ++ parseOperand(SmallVectorImpl &Operands, ++ StringRef Name); ++ ++ // returns true if Tok is matched to a register and returns register in RegNo. ++ bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP, ++ bool isQFP); ++ ++public: ++ SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, ++ const MCInstrInfo &MII) ++ : MCTargetAsmParser(), STI(sti), Parser(parser) { ++ // Initialize the set of available features. ++ setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); ++ } ++ ++}; ++ ++ static unsigned IntRegs[32] = { ++ Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3, ++ Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7, ++ Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3, ++ Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7, ++ Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3, ++ Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7, ++ Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3, ++ Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 }; ++ ++ static unsigned FloatRegs[32] = { ++ Sparc::F0, Sparc::F1, Sparc::F2, Sparc::F3, ++ Sparc::F4, Sparc::F5, Sparc::F6, Sparc::F7, ++ Sparc::F8, Sparc::F9, Sparc::F10, Sparc::F11, ++ Sparc::F12, Sparc::F13, Sparc::F14, Sparc::F15, ++ Sparc::F16, Sparc::F17, Sparc::F18, Sparc::F19, ++ Sparc::F20, Sparc::F21, Sparc::F22, Sparc::F23, ++ Sparc::F24, Sparc::F25, Sparc::F26, Sparc::F27, ++ Sparc::F28, Sparc::F29, Sparc::F30, Sparc::F31 }; ++ ++ static unsigned DoubleRegs[32] = { ++ Sparc::D0, Sparc::D1, Sparc::D2, Sparc::D3, ++ Sparc::D4, Sparc::D5, Sparc::D6, Sparc::D7, ++ Sparc::D8, Sparc::D7, Sparc::D8, Sparc::D9, ++ Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15, ++ Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19, ++ Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23, ++ Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27, ++ Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 }; ++ ++ static unsigned QuadFPRegs[32] = { ++ Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3, ++ Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7, ++ Sparc::Q8, Sparc::Q7, Sparc::Q8, Sparc::Q9, ++ Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 }; ++ ++ ++/// SparcOperand - Instances of this class represent a parsed Sparc machine ++/// instruction. ++class SparcOperand : public MCParsedAsmOperand { ++public: ++ enum RegisterKind { ++ rk_None, ++ rk_IntReg, ++ rk_FloatReg, ++ rk_DoubleReg, ++ rk_QuadReg, ++ rk_CCReg, ++ rk_Y ++ }; ++private: ++ enum KindTy { ++ k_Token, ++ k_Register, ++ k_Immediate, ++ k_MemoryReg, ++ k_MemoryImm ++ } Kind; ++ ++ SMLoc StartLoc, EndLoc; ++ ++ SparcOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} ++ ++ struct Token { ++ const char *Data; ++ unsigned Length; ++ }; ++ ++ struct RegOp { ++ unsigned RegNum; ++ RegisterKind Kind; ++ }; ++ ++ struct ImmOp { ++ const MCExpr *Val; ++ }; ++ ++ struct MemOp { ++ unsigned Base; ++ unsigned OffsetReg; ++ const MCExpr *Off; ++ }; ++ ++ union { ++ struct Token Tok; ++ struct RegOp Reg; ++ struct ImmOp Imm; ++ struct MemOp Mem; ++ }; ++public: ++ bool isToken() const { return Kind == k_Token; } ++ bool isReg() const { return Kind == k_Register; } ++ bool isImm() const { return Kind == k_Immediate; } ++ bool isMem() const { return isMEMrr() || isMEMri(); } ++ bool isMEMrr() const { return Kind == k_MemoryReg; } ++ bool isMEMri() const { return Kind == k_MemoryImm; } ++ ++ StringRef getToken() const { ++ assert(Kind == k_Token && "Invalid access!"); ++ return StringRef(Tok.Data, Tok.Length); ++ } ++ ++ unsigned getReg() const { ++ assert((Kind == k_Register) && "Invalid access!"); ++ return Reg.RegNum; ++ } ++ ++ const MCExpr *getImm() const { ++ assert((Kind == k_Immediate) && "Invalid access!"); ++ return Imm.Val; ++ } ++ ++ unsigned getMemBase() const { ++ assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!"); ++ return Mem.Base; ++ } ++ ++ unsigned getMemOffsetReg() const { ++ assert((Kind == k_MemoryReg) && "Invalid access!"); ++ return Mem.OffsetReg; ++ } ++ ++ const MCExpr *getMemOff() const { ++ assert((Kind == k_MemoryImm) && "Invalid access!"); ++ return Mem.Off; ++ } ++ ++ /// getStartLoc - Get the location of the first token of this operand. ++ SMLoc getStartLoc() const { ++ return StartLoc; ++ } ++ /// getEndLoc - Get the location of the last token of this operand. ++ SMLoc getEndLoc() const { ++ return EndLoc; ++ } ++ ++ virtual void print(raw_ostream &OS) const { ++ switch (Kind) { ++ case k_Token: OS << "Token: " << getToken() << "\n"; break; ++ case k_Register: OS << "Reg: #" << getReg() << "\n"; break; ++ case k_Immediate: OS << "Imm: " << getImm() << "\n"; break; ++ case k_MemoryReg: OS << "Mem: " << getMemBase() << "+" ++ << getMemOffsetReg() << "\n"; break; ++ case k_MemoryImm: assert(getMemOff() != 0); ++ OS << "Mem: " << getMemBase() ++ << "+" << *getMemOff() ++ << "\n"; break; ++ } ++ } ++ ++ void addRegOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ Inst.addOperand(MCOperand::CreateReg(getReg())); ++ } ++ ++ void addImmOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 1 && "Invalid number of operands!"); ++ const MCExpr *Expr = getImm(); ++ addExpr(Inst, Expr); ++ } ++ ++ void addExpr(MCInst &Inst, const MCExpr *Expr) const{ ++ // Add as immediate when possible. Null MCExpr = 0. ++ if (Expr == 0) ++ Inst.addOperand(MCOperand::CreateImm(0)); ++ else if (const MCConstantExpr *CE = dyn_cast(Expr)) ++ Inst.addOperand(MCOperand::CreateImm(CE->getValue())); ++ else ++ Inst.addOperand(MCOperand::CreateExpr(Expr)); ++ } ++ ++ void addMEMrrOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 2 && "Invalid number of operands!"); ++ ++ Inst.addOperand(MCOperand::CreateReg(getMemBase())); ++ ++ assert(getMemOffsetReg() != 0 && "Invalid offset"); ++ Inst.addOperand(MCOperand::CreateReg(getMemOffsetReg())); ++ } ++ ++ void addMEMriOperands(MCInst &Inst, unsigned N) const { ++ assert(N == 2 && "Invalid number of operands!"); ++ ++ Inst.addOperand(MCOperand::CreateReg(getMemBase())); ++ ++ const MCExpr *Expr = getMemOff(); ++ addExpr(Inst, Expr); ++ } ++ ++ static SparcOperand *CreateToken(StringRef Str, SMLoc S) { ++ SparcOperand *Op = new SparcOperand(k_Token); ++ Op->Tok.Data = Str.data(); ++ Op->Tok.Length = Str.size(); ++ Op->StartLoc = S; ++ Op->EndLoc = S; ++ return Op; ++ } ++ ++ static SparcOperand *CreateReg(unsigned RegNum, ++ SparcOperand::RegisterKind Kind, ++ SMLoc S, SMLoc E) { ++ SparcOperand *Op = new SparcOperand(k_Register); ++ Op->Reg.RegNum = RegNum; ++ Op->Reg.Kind = Kind; ++ Op->StartLoc = S; ++ Op->EndLoc = E; ++ return Op; ++ } ++ ++ static SparcOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { ++ SparcOperand *Op = new SparcOperand(k_Immediate); ++ Op->Imm.Val = Val; ++ Op->StartLoc = S; ++ Op->EndLoc = E; ++ return Op; ++ } ++ ++ ++}; ++ ++} // end namespace ++ ++bool SparcAsmParser:: ++MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, ++ SmallVectorImpl &Operands, ++ MCStreamer &Out, unsigned &ErrorInfo, ++ bool MatchingInlineAsm) { ++ MCInst Inst; ++ SmallVector Instructions; ++ unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, ++ MatchingInlineAsm); ++ switch (MatchResult) { ++ default: ++ break; ++ ++ case Match_Success: { ++ Inst.setLoc(IDLoc); ++ Out.EmitInstruction(Inst); ++ return false; ++ } ++ ++ case Match_MissingFeature: ++ return Error(IDLoc, ++ "instruction requires a CPU feature not currently enabled"); ++ ++ case Match_InvalidOperand: { ++ SMLoc ErrorLoc = IDLoc; ++ if (ErrorInfo != ~0U) { ++ if (ErrorInfo >= Operands.size()) ++ return Error(IDLoc, "too few operands for instruction"); ++ ++ ErrorLoc = ((SparcOperand*) Operands[ErrorInfo])->getStartLoc(); ++ if (ErrorLoc == SMLoc()) ++ ErrorLoc = IDLoc; ++ } ++ ++ return Error(ErrorLoc, "invalid operand for instruction"); ++ } ++ case Match_MnemonicFail: ++ return Error(IDLoc, "invalid instruction"); ++ } ++ return true; ++} ++ ++bool SparcAsmParser:: ++ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) ++{ ++ const AsmToken &Tok = Parser.getTok(); ++ StartLoc = Tok.getLoc(); ++ EndLoc = Tok.getEndLoc(); ++ RegNo = 0; ++ if (getLexer().getKind() != AsmToken::Percent) ++ return false; ++ Parser.Lex(); ++ if (matchRegisterName(Tok, RegNo, false, false)) { ++ Parser.Lex(); ++ return false; ++ } ++ ++ return Error(StartLoc, "invalid register name"); ++} ++ ++bool SparcAsmParser:: ++ParseInstruction(ParseInstructionInfo &Info, StringRef Name, ++ SMLoc NameLoc, ++ SmallVectorImpl &Operands) ++{ ++ // Check if we have valid mnemonic. ++ if (!mnemonicIsValid(Name, 0)) { ++ Parser.eatToEndOfStatement(); ++ return Error(NameLoc, "Unknown instruction"); ++ } ++ // First operand in MCInst is instruction mnemonic. ++ Operands.push_back(SparcOperand::CreateToken(Name, NameLoc)); ++ ++ if (getLexer().isNot(AsmToken::EndOfStatement)) { ++ // Read the first operand. ++ if (parseOperand(Operands, Name) != MatchOperand_Success) { ++ SMLoc Loc = getLexer().getLoc(); ++ Parser.eatToEndOfStatement(); ++ return Error(Loc, "unexpected token"); ++ } ++ ++ while (getLexer().is(AsmToken::Comma)) { ++ Parser.Lex(); // Eat the comma. ++ // Parse and remember the operand. ++ if (parseOperand(Operands, Name) != MatchOperand_Success) { ++ SMLoc Loc = getLexer().getLoc(); ++ Parser.eatToEndOfStatement(); ++ return Error(Loc, "unexpected token"); ++ } ++ } ++ } ++ if (getLexer().isNot(AsmToken::EndOfStatement)) { ++ SMLoc Loc = getLexer().getLoc(); ++ Parser.eatToEndOfStatement(); ++ return Error(Loc, "unexpected token"); ++ } ++ Parser.Lex(); // Consume the EndOfStatement. ++ return false; ++} ++ ++bool SparcAsmParser:: ++ParseDirective(AsmToken DirectiveID) ++{ ++ // Ignore all directives for now. ++ Parser.eatToEndOfStatement(); ++ return false; ++} ++ ++SparcAsmParser::OperandMatchResultTy SparcAsmParser:: ++parseMEMOperand(SmallVectorImpl &Operands, ++ int ImmOffsetOrReg) ++{ ++ // FIXME: Implement memory operand parsing here. ++ return MatchOperand_NoMatch; ++} ++ ++SparcAsmParser::OperandMatchResultTy SparcAsmParser:: ++parseMEMrrOperand(SmallVectorImpl &Operands) ++{ ++ return parseMEMOperand(Operands, 2); ++} ++ ++SparcAsmParser::OperandMatchResultTy SparcAsmParser:: ++parseMEMriOperand(SmallVectorImpl &Operands) ++{ ++ return parseMEMOperand(Operands, 1); ++} ++ ++SparcAsmParser::OperandMatchResultTy SparcAsmParser:: ++parseOperand(SmallVectorImpl &Operands, ++ StringRef Mnemonic) ++{ ++ OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); ++ if (ResTy == MatchOperand_Success) ++ return ResTy; ++ // If there wasn't a custom match, try the generic matcher below. Otherwise, ++ // there was a match, but an error occurred, in which case, just return that ++ // the operand parsing failed. ++ if (ResTy == MatchOperand_ParseFail) ++ return ResTy; ++ ++ SMLoc S = Parser.getTok().getLoc(); ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); ++ const MCExpr *EVal; ++ SparcOperand *Op; ++ switch (getLexer().getKind()) { ++ case AsmToken::Percent: ++ Parser.Lex(); // Eat the '%'. ++ unsigned RegNo; ++ if (matchRegisterName(Parser.getTok(), RegNo, false, false)) { ++ Parser.Lex(); // Eat the identifier token. ++ Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E); ++ break; ++ } ++ // FIXME: Handle modifiers like %hi, %lo etc., ++ return MatchOperand_ParseFail; ++ ++ case AsmToken::Minus: ++ case AsmToken::Integer: ++ if (getParser().parseExpression(EVal)) ++ return MatchOperand_ParseFail; ++ ++ Op = SparcOperand::CreateImm(EVal, S, E); ++ break; ++ ++ case AsmToken::Identifier: { ++ StringRef Identifier; ++ if (getParser().parseIdentifier(Identifier)) ++ return MatchOperand_ParseFail; ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); ++ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); ++ ++ // Otherwise create a symbol reference. ++ const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, ++ getContext()); ++ ++ Op = SparcOperand::CreateImm(Res, S, E); ++ break; ++ } ++ ++ case AsmToken::LBrac: // handle [ ++ return parseMEMOperand(Operands, 0); ++ ++ default: ++ return MatchOperand_ParseFail; ++ } ++ // Push the parsed operand into the list of operands ++ Operands.push_back(Op); ++ return MatchOperand_Success; ++} ++ ++bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, ++ unsigned &RegNo, ++ bool isDFP, ++ bool isQFP) ++{ ++ int64_t intVal = 0; ++ RegNo = 0; ++ if (Tok.is(AsmToken::Identifier)) { ++ StringRef name = Tok.getString(); ++ ++ // %fp ++ if (name.equals("fp")) { ++ RegNo = Sparc::I6; ++ return true; ++ } ++ // %sp ++ if (name.equals("sp")) { ++ RegNo = Sparc::O6; ++ return true; ++ } ++ ++ if (name.equals("y")) { ++ RegNo = Sparc::Y; ++ return true; ++ } ++ ++ if (name.equals("icc")) { ++ RegNo = Sparc::ICC; ++ return true; ++ } ++ ++ if (name.equals("xcc")) { ++ // FIXME:: check 64bit. ++ RegNo = Sparc::ICC; ++ return true; ++ } ++ ++ // %fcc0 - %fcc3 ++ if (name.substr(0, 3).equals_lower("fcc") ++ && !name.substr(3).getAsInteger(10, intVal) ++ && intVal < 4) { ++ // FIXME: check 64bit and handle %fcc1 - %fcc3 ++ RegNo = Sparc::FCC; ++ return true; ++ } ++ ++ // %g0 - %g7 ++ if (name.substr(0, 1).equals_lower("g") ++ && !name.substr(1).getAsInteger(10, intVal) ++ && intVal < 8) { ++ RegNo = IntRegs[intVal]; ++ return true; ++ } ++ // %o0 - %o7 ++ if (name.substr(0, 1).equals_lower("o") ++ && !name.substr(1).getAsInteger(10, intVal) ++ && intVal < 8) { ++ RegNo = IntRegs[8 + intVal]; ++ return true; ++ } ++ if (name.substr(0, 1).equals_lower("l") ++ && !name.substr(1).getAsInteger(10, intVal) ++ && intVal < 8) { ++ RegNo = IntRegs[16 + intVal]; ++ return true; ++ } ++ if (name.substr(0, 1).equals_lower("i") ++ && !name.substr(1).getAsInteger(10, intVal) ++ && intVal < 8) { ++ RegNo = IntRegs[24 + intVal]; ++ return true; ++ } ++ // %f0 - %f31 ++ if (name.substr(0, 1).equals_lower("f") ++ && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) { ++ if (isDFP && (intVal%2 == 0)) { ++ RegNo = DoubleRegs[intVal/2]; ++ } else if (isQFP && (intVal%4 == 0)) { ++ RegNo = QuadFPRegs[intVal/4]; ++ } else { ++ RegNo = FloatRegs[intVal]; ++ } ++ return true; ++ } ++ // %f32 - %f62 ++ if (name.substr(0, 1).equals_lower("f") ++ && !name.substr(1, 2).getAsInteger(10, intVal) ++ && intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) { ++ if (isDFP) { ++ RegNo = DoubleRegs[16 + intVal/2]; ++ } else if (isQFP && (intVal % 4 == 0)) { ++ RegNo = QuadFPRegs[8 + intVal/4]; ++ } else { ++ return false; ++ } ++ return true; ++ } ++ ++ // %r0 - %r31 ++ if (name.substr(0, 1).equals_lower("r") ++ && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) { ++ RegNo = IntRegs[intVal]; ++ return true; ++ } ++ } ++ return false; ++} ++ ++ ++ ++extern "C" void LLVMInitializeSparcAsmParser() { ++ RegisterMCAsmParser A(TheSparcTarget); ++ RegisterMCAsmParser B(TheSparcV9Target); ++} ++ ++#define GET_REGISTER_MATCHER ++#define GET_MATCHER_IMPLEMENTATION ++#include "SparcGenAsmMatcher.inc" +Index: lib/Target/Sparc/AsmParser/LLVMBuild.txt +=================================================================== +--- lib/Target/Sparc/AsmParser/LLVMBuild.txt ++++ lib/Target/Sparc/AsmParser/LLVMBuild.txt +@@ -0,0 +1,23 @@ ++;===- ./lib/Target/Sparc/AsmParser/LLVMBuild.txt ---------------*- Conf -*--===; ++; ++; The LLVM Compiler Infrastructure ++; ++; This file is distributed under the University of Illinois Open Source ++; License. See LICENSE.TXT for details. ++; ++;===------------------------------------------------------------------------===; ++; ++; This is an LLVMBuild description file for the components in this subdirectory. ++; ++; For more information on the LLVMBuild system, please see: ++; ++; http://llvm.org/docs/LLVMBuild.html ++; ++;===------------------------------------------------------------------------===; ++ ++[component_0] ++type = Library ++name = SparcAsmParser ++parent = Sparc ++required_libraries = MC MCParser Support SparcDesc SparcInfo ++add_to_library_groups = Sparc +Index: lib/Target/Sparc/AsmParser/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/AsmParser/CMakeLists.txt ++++ lib/Target/Sparc/AsmParser/CMakeLists.txt +@@ -0,0 +1,3 @@ ++add_llvm_library(LLVMSparcAsmParser ++ SparcAsmParser.cpp ++ ) +Index: lib/Target/Sparc/AsmParser/Makefile +=================================================================== +--- lib/Target/Sparc/AsmParser/Makefile ++++ lib/Target/Sparc/AsmParser/Makefile +@@ -0,0 +1,15 @@ ++##===- lib/Target/Sparc/AsmParser/Makefile ------------------*- Makefile-*-===## ++# ++# The LLVM Compiler Infrastructure ++# ++# This file is distributed under the University of Illinois Open Source ++# License. See LICENSE.TXT for details. ++# ++##===----------------------------------------------------------------------===## ++LEVEL = ../../../.. ++LIBRARYNAME = LLVMSparcAsmParser ++ ++# Hack: we need to include 'main' Sparc target directory to grab private headers ++CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. ++ ++include $(LEVEL)/Makefile.common +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -176,11 +176,11 @@ def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMP + def : Pat<(ctpop i64:$src), (POPCrr $src)>; + + // "LEA" form of add ++let isCodeGenOnly = 1 in + def LEAX_ADDri : F3_2<2, 0b000000, + (outs I64Regs:$dst), (ins MEMri:$addr), + "add ${addr:arith}, $dst", + [(set iPTR:$dst, ADDRri:$addr)]>; +- + } // Predicates = [Is64Bit] + + diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198533-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198533-sparc.diff new file mode 100644 index 000000000000..d6e65dad0693 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198533-sparc.diff @@ -0,0 +1,516 @@ +Pull in r198533 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add initial implementation of MC Code emitter for sparc. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -100,9 +100,14 @@ def MEMri : Operand { + def TLSSym : Operand; + + // Branch targets have OtherVT type. +-def brtarget : Operand; +-def calltarget : Operand; ++def brtarget : Operand { ++ let EncoderMethod = "getBranchTargetOpValue"; ++} + ++def calltarget : Operand { ++ let EncoderMethod = "getCallTargetOpValue"; ++} ++ + // Operand for printing out a condition code. + let PrintMethod = "printCCOperand" in + def CCOp : Operand; +Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt ++++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +@@ -1,6 +1,8 @@ + add_llvm_library(LLVMSparcDesc ++ SparcAsmBackend.cpp ++ SparcMCAsmInfo.cpp ++ SparcMCCodeEmitter.cpp + SparcMCTargetDesc.cpp +- SparcMCAsmInfo.cpp + SparcMCExpr.cpp + SparcTargetStreamer.cpp + ) +Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +@@ -0,0 +1,131 @@ ++//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file implements the SparcMCCodeEmitter class. ++// ++//===----------------------------------------------------------------------===// ++ ++#define DEBUG_TYPE "mccodeemitter" ++#include "SparcMCTargetDesc.h" ++#include "MCTargetDesc/SparcFixupKinds.h" ++#include "llvm/MC/MCCodeEmitter.h" ++#include "llvm/MC/MCContext.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCInst.h" ++#include "llvm/MC/MCRegisterInfo.h" ++#include "llvm/ADT/Statistic.h" ++#include "llvm/Support/raw_ostream.h" ++ ++using namespace llvm; ++ ++STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); ++ ++namespace { ++class SparcMCCodeEmitter : public MCCodeEmitter { ++ SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION; ++ void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION; ++ MCContext &Ctx; ++ ++public: ++ SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {} ++ ++ ~SparcMCCodeEmitter() {} ++ ++ void EncodeInstruction(const MCInst &MI, raw_ostream &OS, ++ SmallVectorImpl &Fixups) const; ++ ++ // getBinaryCodeForInstr - TableGen'erated function for getting the ++ // binary encoding for an instruction. ++ uint64_t getBinaryCodeForInstr(const MCInst &MI, ++ SmallVectorImpl &Fixups) const; ++ ++ /// getMachineOpValue - Return binary encoding of operand. If the machine ++ /// operand requires relocation, record the relocation and return zero. ++ unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, ++ SmallVectorImpl &Fixups) const; ++ ++ unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups) const; ++ unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups) const; ++ ++}; ++} // end anonymous namespace ++ ++MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII, ++ const MCRegisterInfo &MRI, ++ const MCSubtargetInfo &STI, ++ MCContext &Ctx) { ++ return new SparcMCCodeEmitter(Ctx); ++} ++ ++void SparcMCCodeEmitter:: ++EncodeInstruction(const MCInst &MI, raw_ostream &OS, ++ SmallVectorImpl &Fixups) const { ++ unsigned Bits = getBinaryCodeForInstr(MI, Fixups); ++ ++ // Output the constant in big endian byte order. ++ for (unsigned i = 0; i != 4; ++i) { ++ OS << (char)(Bits >> 24); ++ Bits <<= 8; ++ } ++ ++ ++MCNumEmitted; // Keep track of the # of mi's emitted. ++} ++ ++ ++unsigned SparcMCCodeEmitter:: ++getMachineOpValue(const MCInst &MI, const MCOperand &MO, ++ SmallVectorImpl &Fixups) const { ++ ++ if (MO.isReg()) ++ return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); ++ ++ if (MO.isImm()) ++ return MO.getImm(); ++ ++ assert(MO.isExpr()); ++ const MCExpr *Expr = MO.getExpr(); ++ int64_t Res; ++ if (Expr->EvaluateAsAbsolute(Res)) ++ return Res; ++ ++ assert(0 && "Unhandled expression!"); ++ return 0; ++} ++ ++unsigned SparcMCCodeEmitter:: ++getCallTargetOpValue(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups) const { ++ const MCOperand &MO = MI.getOperand(OpNo); ++ if (MO.isReg() || MO.isImm()) ++ return getMachineOpValue(MI, MO, Fixups); ++ ++ Fixups.push_back(MCFixup::Create(0, MO.getExpr(), ++ (MCFixupKind)Sparc::fixup_sparc_call30)); ++ return 0; ++} ++ ++unsigned SparcMCCodeEmitter:: ++getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, ++ SmallVectorImpl &Fixups) const { ++ const MCOperand &MO = MI.getOperand(OpNo); ++ if (MO.isReg() || MO.isImm()) ++ return getMachineOpValue(MI, MO, Fixups); ++ ++ Sparc::Fixups fixup = Sparc::fixup_sparc_br22; ++ if (MI.getOpcode() == SP::BPXCC) ++ fixup = Sparc::fixup_sparc_br19; ++ ++ Fixups.push_back(MCFixup::Create(0, MO.getExpr(), ++ (MCFixupKind)fixup)); ++ return 0; ++} ++ ++#include "SparcGenMCCodeEmitter.inc" +Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +@@ -136,6 +136,18 @@ extern "C" void LLVMInitializeSparcTargetMC() { + TargetRegistry::RegisterMCSubtargetInfo(TheSparcV9Target, + createSparcMCSubtargetInfo); + ++ // Register the MC Code Emitter. ++ TargetRegistry::RegisterMCCodeEmitter(TheSparcTarget, ++ createSparcMCCodeEmitter); ++ TargetRegistry::RegisterMCCodeEmitter(TheSparcV9Target, ++ createSparcMCCodeEmitter); ++ ++ //Register the asm backend. ++ TargetRegistry::RegisterMCAsmBackend(TheSparcTarget, ++ createSparcAsmBackend); ++ TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target, ++ createSparcAsmBackend); ++ + TargetRegistry::RegisterAsmStreamer(TheSparcTarget, + createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheSparcV9Target, +Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +@@ -0,0 +1,101 @@ ++//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "llvm/MC/MCAsmBackend.h" ++#include "MCTargetDesc/SparcMCTargetDesc.h" ++#include "MCTargetDesc/SparcFixupKinds.h" ++#include "llvm/MC/MCFixupKindInfo.h" ++#include "llvm/MC/MCObjectWriter.h" ++#include "llvm/Support/TargetRegistry.h" ++ ++using namespace llvm; ++ ++namespace { ++ class SparcAsmBackend : public MCAsmBackend { ++ ++ public: ++ SparcAsmBackend(const Target &T) : MCAsmBackend() {} ++ ++ unsigned getNumFixupKinds() const { ++ return Sparc::NumTargetFixupKinds; ++ } ++ ++ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { ++ const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = { ++ // name offset bits flags ++ { "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, ++ { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, ++ { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel } ++ }; ++ ++ if (Kind < FirstTargetFixupKind) ++ return MCAsmBackend::getFixupKindInfo(Kind); ++ ++ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && ++ "Invalid kind!"); ++ return Infos[Kind - FirstTargetFixupKind]; ++ } ++ ++ bool mayNeedRelaxation(const MCInst &Inst) const { ++ // FIXME. ++ return false; ++ } ++ ++ /// fixupNeedsRelaxation - Target specific predicate for whether a given ++ /// fixup requires the associated instruction to be relaxed. ++ bool fixupNeedsRelaxation(const MCFixup &Fixup, ++ uint64_t Value, ++ const MCRelaxableFragment *DF, ++ const MCAsmLayout &Layout) const { ++ // FIXME. ++ assert(0 && "fixupNeedsRelaxation() unimplemented"); ++ return false; ++ } ++ void relaxInstruction(const MCInst &Inst, MCInst &Res) const { ++ // FIXME. ++ assert(0 && "relaxInstruction() unimplemented"); ++ } ++ ++ bool writeNopData(uint64_t Count, MCObjectWriter *OW) const { ++ // FIXME: Zero fill for now. ++ for (uint64_t i = 0; i != Count; ++i) ++ OW->Write8(0); ++ return true; ++ } ++ }; ++ ++ class ELFSparcAsmBackend : public SparcAsmBackend { ++ public: ++ ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) : ++ SparcAsmBackend(T) { } ++ ++ void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, ++ uint64_t Value) const { ++ assert(0 && "applyFixup not implemented yet"); ++ } ++ ++ MCObjectWriter *createObjectWriter(raw_ostream &OS) const { ++ assert(0 && "Object Writer not implemented yet"); ++ return 0; ++ } ++ ++ virtual bool doesSectionRequireSymbols(const MCSection &Section) const { ++ return false; ++ } ++ }; ++ ++} // end anonymous namespace ++ ++ ++MCAsmBackend *llvm::createSparcAsmBackend(const Target &T, ++ const MCRegisterInfo &MRI, ++ StringRef TT, ++ StringRef CPU) { ++ return new ELFSparcAsmBackend(T, Triple(TT).getOS()); ++} +Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h ++++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +@@ -0,0 +1,36 @@ ++//===-- SparcFixupKinds.h - Sparc Specific Fixup Entries --------*- C++ -*-===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_SPARC_FIXUPKINDS_H ++#define LLVM_SPARC_FIXUPKINDS_H ++ ++#include "llvm/MC/MCFixup.h" ++ ++namespace llvm { ++ namespace Sparc { ++ enum Fixups { ++ // fixup_sparc_call30 - 30-bit PC relative relocation for call ++ fixup_sparc_call30 = FirstTargetFixupKind, ++ ++ /// fixup_sparc_br22 - 22-bit PC relative relocation for ++ /// branches ++ fixup_sparc_br22, ++ ++ /// fixup_sparc_br22 - 22-bit PC relative relocation for ++ /// branches on icc/xcc ++ fixup_sparc_br19, ++ ++ // Marker ++ LastTargetFixupKind, ++ NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind ++ }; ++ } ++} ++ ++#endif +Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h ++++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +@@ -15,11 +15,27 @@ + #define SPARCMCTARGETDESC_H + + namespace llvm { ++class MCAsmBackend; ++class MCCodeEmitter; ++class MCContext; ++class MCInstrInfo; ++class MCRegisterInfo; ++class MCSubtargetInfo; + class Target; ++class StringRef; + + extern Target TheSparcTarget; + extern Target TheSparcV9Target; + ++MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII, ++ const MCRegisterInfo &MRI, ++ const MCSubtargetInfo &STI, ++ MCContext &Ctx); ++MCAsmBackend *createSparcAsmBackend(const Target &T, ++ const MCRegisterInfo &MRI, ++ StringRef TT, ++ StringRef CPU); ++ + } // End llvm namespace + + // Defines symbolic names for Sparc registers. This defines a mapping from +Index: lib/Target/Sparc/Makefile +=================================================================== +--- lib/Target/Sparc/Makefile ++++ lib/Target/Sparc/Makefile +@@ -16,7 +16,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenI + SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \ + SparcGenDAGISel.inc \ + SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \ +- SparcGenCodeEmitter.inc ++ SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc + + DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc + +Index: lib/Target/Sparc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/CMakeLists.txt ++++ lib/Target/Sparc/CMakeLists.txt +@@ -3,6 +3,7 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td) + tablegen(LLVM SparcGenRegisterInfo.inc -gen-register-info) + tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info) + tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter) ++tablegen(LLVM SparcGenMCCodeEmitter.inc -gen-emitter -mc-emitter) + tablegen(LLVM SparcGenAsmWriter.inc -gen-asm-writer) + tablegen(LLVM SparcGenAsmMatcher.inc -gen-asm-matcher) + tablegen(LLVM SparcGenDAGISel.inc -gen-dag-isel) +Index: lib/Target/Sparc/SparcCodeEmitter.cpp +=================================================================== +--- lib/Target/Sparc/SparcCodeEmitter.cpp ++++ lib/Target/Sparc/SparcCodeEmitter.cpp +@@ -72,6 +72,11 @@ class SparcCodeEmitter : public MachineFunctionPas + unsigned getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) const; + ++ unsigned getCallTargetOpValue(const MachineInstr &MI, ++ unsigned) const; ++ unsigned getBranchTargetOpValue(const MachineInstr &MI, ++ unsigned) const; ++ + void emitWord(unsigned Word); + + unsigned getRelocation(const MachineInstr &MI, +@@ -181,6 +186,18 @@ unsigned SparcCodeEmitter::getMachineOpValue(const + llvm_unreachable("Unable to encode MachineOperand!"); + return 0; + } ++unsigned SparcCodeEmitter::getCallTargetOpValue(const MachineInstr &MI, ++ unsigned opIdx) const { ++ const MachineOperand MO = MI.getOperand(opIdx); ++ return getMachineOpValue(MI, MO); ++} ++ ++unsigned SparcCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI, ++ unsigned opIdx) const { ++ const MachineOperand MO = MI.getOperand(opIdx); ++ return getMachineOpValue(MI, MO); ++} ++ + unsigned SparcCodeEmitter::getRelocation(const MachineInstr &MI, + const MachineOperand &MO) const { + +Index: test/MC/Sparc/sparc-alu-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-alu-instructions.s ++++ test/MC/Sparc/sparc-alu-instructions.s +@@ -0,0 +1,72 @@ ++! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s ++! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s ++ ++ ! CHECK: add %g0, %g0, %g0 ! encoding: [0x80,0x00,0x00,0x00] ++ add %g0, %g0, %g0 ++ ! CHECK: add %g1, %g2, %g3 ! encoding: [0x86,0x00,0x40,0x02] ++ add %g1, %g2, %g3 ++ ! CHECK: add %o0, %o1, %l0 ! encoding: [0xa0,0x02,0x00,0x09] ++ add %r8, %r9, %l0 ++ ! CHECK: add %o0, 10, %l0 ! encoding: [0xa0,0x02,0x20,0x0a] ++ add %o0, 10, %l0 ++ ++ ! CHECK: addcc %g1, %g2, %g3 ! encoding: [0x86,0x80,0x40,0x02] ++ addcc %g1, %g2, %g3 ++ ++ ! CHECK: addxcc %g1, %g2, %g3 ! encoding: [0x86,0xc0,0x40,0x02] ++ addxcc %g1, %g2, %g3 ++ ++ ! CHECK: udiv %g1, %g2, %g3 ! encoding: [0x86,0x70,0x40,0x02] ++ udiv %g1, %g2, %g3 ++ ++ ! CHECK: sdiv %g1, %g2, %g3 ! encoding: [0x86,0x78,0x40,0x02] ++ sdiv %g1, %g2, %g3 ++ ++ ! CHECK: and %g1, %g2, %g3 ! encoding: [0x86,0x08,0x40,0x02] ++ and %g1, %g2, %g3 ++ ! CHECK: andn %g1, %g2, %g3 ! encoding: [0x86,0x28,0x40,0x02] ++ andn %g1, %g2, %g3 ++ ! CHECK: or %g1, %g2, %g3 ! encoding: [0x86,0x10,0x40,0x02] ++ or %g1, %g2, %g3 ++ ! CHECK: orn %g1, %g2, %g3 ! encoding: [0x86,0x30,0x40,0x02] ++ orn %g1, %g2, %g3 ++ ! CHECK: xor %g1, %g2, %g3 ! encoding: [0x86,0x18,0x40,0x02] ++ xor %g1, %g2, %g3 ++ ! CHECK: xnor %g1, %g2, %g3 ! encoding: [0x86,0x38,0x40,0x02] ++ xnor %g1, %g2, %g3 ++ ++ ! CHECK: umul %g1, %g2, %g3 ! encoding: [0x86,0x50,0x40,0x02] ++ umul %g1, %g2, %g3 ++ ++ ! CHECK: smul %g1, %g2, %g3 ! encoding: [0x86,0x58,0x40,0x02] ++ smul %g1, %g2, %g3 ++ ++ ! CHECK: nop ! encoding: [0x01,0x00,0x00,0x00] ++ nop ++ ++ ! CHECK: sethi 10, %l0 ! encoding: [0x21,0x00,0x00,0x0a] ++ sethi 10, %l0 ++ ++ ! CHECK: sll %g1, %g2, %g3 ! encoding: [0x87,0x28,0x40,0x02] ++ sll %g1, %g2, %g3 ++ ! CHECK: sll %g1, 31, %g3 ! encoding: [0x87,0x28,0x60,0x1f] ++ sll %g1, 31, %g3 ++ ++ ! CHECK: srl %g1, %g2, %g3 ! encoding: [0x87,0x30,0x40,0x02] ++ srl %g1, %g2, %g3 ++ ! CHECK: srl %g1, 31, %g3 ! encoding: [0x87,0x30,0x60,0x1f] ++ srl %g1, 31, %g3 ++ ++ ! CHECK: sra %g1, %g2, %g3 ! encoding: [0x87,0x38,0x40,0x02] ++ sra %g1, %g2, %g3 ++ ! CHECK: sra %g1, 31, %g3 ! encoding: [0x87,0x38,0x60,0x1f] ++ sra %g1, 31, %g3 ++ ++ ! CHECK: sub %g1, %g2, %g3 ! encoding: [0x86,0x20,0x40,0x02] ++ sub %g1, %g2, %g3 ++ ! CHECK: subcc %g1, %g2, %g3 ! encoding: [0x86,0xa0,0x40,0x02] ++ subcc %g1, %g2, %g3 ++ ++ ! CHECK: subxcc %g1, %g2, %g3 ! encoding: [0x86,0xe0,0x40,0x02] ++ subxcc %g1, %g2, %g3 ++ diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198565-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198565-sparc.diff new file mode 100644 index 000000000000..cf32440f5a5b --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198565-sparc.diff @@ -0,0 +1,76 @@ +Pull in r198565 from upstream llvm trunk (by Venkatraman Govindaraju): + + ELF relocation types for sparc. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: include/llvm/Support/ELF.h +=================================================================== +--- include/llvm/Support/ELF.h ++++ include/llvm/Support/ELF.h +@@ -1087,6 +1087,65 @@ enum { + R_390_IRELATIVE = 61 + }; + ++// ELF Relocation type for Sparc. ++enum { ++ R_SPARC_NONE = 0, ++ R_SPARC_8 = 1, ++ R_SPARC_16 = 2, ++ R_SPARC_32 = 3, ++ R_SPARC_DISP8 = 4, ++ R_SPARC_DISP16 = 5, ++ R_SPARC_DISP32 = 6, ++ R_SPARC_WDISP30 = 7, ++ R_SPARC_WDISP22 = 8, ++ R_SPARC_HI22 = 9, ++ R_SPARC_22 = 10, ++ R_SPARC_13 = 11, ++ R_SPARC_LO10 = 12, ++ R_SPARC_GOT10 = 13, ++ R_SPARC_GOT13 = 14, ++ R_SPARC_GOT22 = 15, ++ R_SPARC_PC10 = 16, ++ R_SPARC_PC22 = 17, ++ R_SPARC_WPLT30 = 18, ++ R_SPARC_COPY = 19, ++ R_SPARC_GLOB_DAT = 20, ++ R_SPARC_JMP_SLOT = 21, ++ R_SPARC_RELATIVE = 22, ++ R_SPARC_UA32 = 23, ++ R_SPARC_PLT32 = 24, ++ R_SPARC_HIPLT22 = 25, ++ R_SPARC_LOPLT10 = 26, ++ R_SPARC_PCPLT32 = 27, ++ R_SPARC_PCPLT22 = 28, ++ R_SPARC_PCPLT10 = 29, ++ R_SPARC_10 = 30, ++ R_SPARC_11 = 31, ++ R_SPARC_64 = 32, ++ R_SPARC_OLO10 = 33, ++ R_SPARC_HH22 = 34, ++ R_SPARC_HM10 = 35, ++ R_SPARC_LM22 = 36, ++ R_SPARC_PC_HH22 = 37, ++ R_SPARC_PC_HM10 = 38, ++ R_SPARC_PC_LM22 = 39, ++ R_SPARC_WDISP16 = 40, ++ R_SPARC_WDISP19 = 41, ++ R_SPARC_7 = 43, ++ R_SPARC_5 = 44, ++ R_SPARC_6 = 45, ++ R_SPARC_DISP64 = 46, ++ R_SPARC_PLT64 = 47, ++ R_SPARC_HIX22 = 48, ++ R_SPARC_LOX10 = 49, ++ R_SPARC_H44 = 50, ++ R_SPARC_M44 = 51, ++ R_SPARC_L44 = 52, ++ R_SPARC_REGISTER = 53, ++ R_SPARC_UA64 = 54, ++ R_SPARC_UA16 = 55 ++}; ++ + // Section header. + struct Elf32_Shdr { + Elf32_Word sh_name; // Section name (index into string table) diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198567-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198567-sparc.diff new file mode 100644 index 000000000000..0ce6863d8041 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198567-sparc.diff @@ -0,0 +1,21 @@ +Pull in r198567 from upstream llvm trunk (by Benjamin Kramer): + + SPARC: Make helper function static. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcAsmPrinter.cpp +=================================================================== +--- lib/Target/Sparc/SparcAsmPrinter.cpp ++++ lib/Target/Sparc/SparcAsmPrinter.cpp +@@ -130,8 +130,8 @@ static void EmitOR(MCStreamer &OutStreamer, MCOper + OutStreamer.EmitInstruction(ORInst); + } + +-void EmitADD(MCStreamer &OutStreamer, +- MCOperand &RS1, MCOperand &RS2, MCOperand &RD) ++static void EmitADD(MCStreamer &OutStreamer, ++ MCOperand &RS1, MCOperand &RS2, MCOperand &RD) + { + MCInst ADDInst; + ADDInst.setOpcode(SP::ADDrr); diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198580-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198580-sparc.diff new file mode 100644 index 000000000000..e30cbb290181 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198580-sparc.diff @@ -0,0 +1,460 @@ +Pull in r198580 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add ELF Object Writer for Sparc. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +@@ -12,6 +12,7 @@ + //===----------------------------------------------------------------------===// + + #define DEBUG_TYPE "mccodeemitter" ++#include "SparcMCExpr.h" + #include "SparcMCTargetDesc.h" + #include "MCTargetDesc/SparcFixupKinds.h" + #include "llvm/MC/MCCodeEmitter.h" +@@ -92,6 +93,41 @@ getMachineOpValue(const MCInst &MI, const MCOperan + + assert(MO.isExpr()); + const MCExpr *Expr = MO.getExpr(); ++ if (const SparcMCExpr *SExpr = dyn_cast(Expr)) { ++ switch(SExpr->getKind()) { ++ default: assert(0 && "Unhandled sparc expression!"); break; ++ case SparcMCExpr::VK_Sparc_LO: ++ Fixups.push_back(MCFixup::Create(0, Expr, ++ (MCFixupKind)Sparc::fixup_sparc_lo10)); ++ break; ++ case SparcMCExpr::VK_Sparc_HI: ++ Fixups.push_back(MCFixup::Create(0, Expr, ++ (MCFixupKind)Sparc::fixup_sparc_hi22)); ++ break; ++ case SparcMCExpr::VK_Sparc_H44: ++ Fixups.push_back(MCFixup::Create(0, Expr, ++ (MCFixupKind)Sparc::fixup_sparc_h44)); ++ break; ++ case SparcMCExpr::VK_Sparc_M44: ++ Fixups.push_back(MCFixup::Create(0, Expr, ++ (MCFixupKind)Sparc::fixup_sparc_m44)); ++ break; ++ case SparcMCExpr::VK_Sparc_L44: ++ Fixups.push_back(MCFixup::Create(0, Expr, ++ (MCFixupKind)Sparc::fixup_sparc_l44)); ++ break; ++ case SparcMCExpr::VK_Sparc_HH: ++ Fixups.push_back(MCFixup::Create(0, Expr, ++ (MCFixupKind)Sparc::fixup_sparc_hh)); ++ break; ++ case SparcMCExpr::VK_Sparc_HM: ++ Fixups.push_back(MCFixup::Create(0, Expr, ++ (MCFixupKind)Sparc::fixup_sparc_hm)); ++ break; ++ } ++ return 0; ++ } ++ + int64_t Res; + if (Expr->EvaluateAsAbsolute(Res)) + return Res; +Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +@@ -89,6 +89,14 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(S + return X; + } + ++static MCStreamer *createMCStreamer(const Target &T, StringRef TT, ++ MCContext &Context, MCAsmBackend &MAB, ++ raw_ostream &OS, MCCodeEmitter *Emitter, ++ bool RelaxAll, bool NoExecStack) { ++ SparcTargetELFStreamer *S = new SparcTargetELFStreamer(); ++ return createELFStreamer(Context, S, MAB, OS, Emitter, RelaxAll, NoExecStack); ++} ++ + static MCStreamer * + createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, bool useLoc, bool useCFI, +@@ -148,6 +156,13 @@ extern "C" void LLVMInitializeSparcTargetMC() { + TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target, + createSparcAsmBackend); + ++ // Register the object streamer. ++ TargetRegistry::RegisterMCObjectStreamer(TheSparcTarget, ++ createMCStreamer); ++ TargetRegistry::RegisterMCObjectStreamer(TheSparcV9Target, ++ createMCStreamer); ++ ++ // Register the asm streamer. + TargetRegistry::RegisterAsmStreamer(TheSparcTarget, + createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheSparcV9Target, +Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +@@ -10,6 +10,7 @@ + #include "llvm/MC/MCAsmBackend.h" + #include "MCTargetDesc/SparcMCTargetDesc.h" + #include "MCTargetDesc/SparcFixupKinds.h" ++#include "llvm/MC/MCELFObjectWriter.h" + #include "llvm/MC/MCFixupKindInfo.h" + #include "llvm/MC/MCObjectWriter.h" + #include "llvm/Support/TargetRegistry.h" +@@ -16,11 +17,43 @@ + + using namespace llvm; + ++static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { ++ switch (Kind) { ++ default: ++ llvm_unreachable("Unknown fixup kind!"); ++ case FK_Data_1: ++ case FK_Data_2: ++ case FK_Data_4: ++ case FK_Data_8: ++ return Value; ++ case Sparc::fixup_sparc_call30: ++ return Value & 0x3fffffff; ++ case Sparc::fixup_sparc_br22: ++ return Value & 0x3fffff; ++ case Sparc::fixup_sparc_br19: ++ return Value & 0x1ffff; ++ case Sparc::fixup_sparc_hi22: ++ return (Value >> 10) & 0x3fffff; ++ case Sparc::fixup_sparc_lo10: ++ return Value & 0x3ff; ++ case Sparc::fixup_sparc_h44: ++ return (Value >> 22) & 0x3fffff; ++ case Sparc::fixup_sparc_m44: ++ return (Value >> 12) & 0x3ff; ++ case Sparc::fixup_sparc_l44: ++ return Value & 0xfff; ++ case Sparc::fixup_sparc_hh: ++ return (Value >> 42) & 0x3fffff; ++ case Sparc::fixup_sparc_hm: ++ return (Value >>32) & 0x3ff; ++ } ++} ++ + namespace { + class SparcAsmBackend : public MCAsmBackend { +- ++ const Target &TheTarget; + public: +- SparcAsmBackend(const Target &T) : MCAsmBackend() {} ++ SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {} + + unsigned getNumFixupKinds() const { + return Sparc::NumTargetFixupKinds; +@@ -31,7 +64,14 @@ namespace { + // name offset bits flags + { "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, +- { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel } ++ { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, ++ { "fixup_sparc_hi22", 0, 22, 0 }, ++ { "fixup_sparc_lo10", 0, 10, 0 }, ++ { "fixup_sparc_h44", 0, 22, 0 }, ++ { "fixup_sparc_m44", 0, 10, 0 }, ++ { "fixup_sparc_l44", 0, 12, 0 }, ++ { "fixup_sparc_hh", 0, 21, 0 }, ++ { "fixup_sparc_hm", 0, 10, 0 }, + }; + + if (Kind < FirstTargetFixupKind) +@@ -68,21 +108,38 @@ namespace { + OW->Write8(0); + return true; + } ++ ++ bool is64Bit() const { ++ StringRef name = TheTarget.getName(); ++ return name == "sparcv9"; ++ } + }; + + class ELFSparcAsmBackend : public SparcAsmBackend { ++ Triple::OSType OSType; + public: + ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) : +- SparcAsmBackend(T) { } ++ SparcAsmBackend(T), OSType(OSType) { } + + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value) const { +- assert(0 && "applyFixup not implemented yet"); ++ ++ Value = adjustFixupValue(Fixup.getKind(), Value); ++ if (!Value) return; // Doesn't change encoding. ++ ++ unsigned Offset = Fixup.getOffset(); ++ ++ // For each byte of the fragment that the fixup touches, mask in the bits ++ // from the fixup value. The Value has been "split up" into the ++ // appropriate bitfields above. ++ for (unsigned i = 0; i != 4; ++i) ++ Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff); ++ + } + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { +- assert(0 && "Object Writer not implemented yet"); +- return 0; ++ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); ++ return createSparcELFObjectWriter(OS, is64Bit(), OSABI); + } + + virtual bool doesSectionRequireSymbols(const MCSection &Section) const { +Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h ++++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +@@ -22,10 +22,32 @@ namespace llvm { + /// branches + fixup_sparc_br22, + +- /// fixup_sparc_br22 - 22-bit PC relative relocation for ++ /// fixup_sparc_br19 - 19-bit PC relative relocation for + /// branches on icc/xcc + fixup_sparc_br19, + ++ /// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo) ++ /// for sethi ++ fixup_sparc_hi22, ++ ++ /// fixup_sparc_lo10 - 10-bit fixup corresponding to %lo(foo) ++ fixup_sparc_lo10, ++ ++ /// fixup_sparc_h44 - 22-bit fixup corresponding to %h44(foo) ++ fixup_sparc_h44, ++ ++ /// fixup_sparc_m44 - 10-bit fixup corresponding to %m44(foo) ++ fixup_sparc_m44, ++ ++ /// fixup_sparc_l44 - 12-bit fixup corresponding to %l44(foo) ++ fixup_sparc_l44, ++ ++ /// fixup_sparc_hh - 22-bit fixup corresponding to %hh(foo) ++ fixup_sparc_hh, ++ ++ /// fixup_sparc_hm - 10-bit fixup corresponding to %hm(foo) ++ fixup_sparc_hm, ++ + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind +Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +@@ -0,0 +1,86 @@ ++//===-- SparcELFObjectWriter.cpp - Sparc ELF Writer -----------------------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "MCTargetDesc/SparcMCTargetDesc.h" ++#include "MCTargetDesc/SparcFixupKinds.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/MC/MCELFObjectWriter.h" ++#include "llvm/MC/MCExpr.h" ++#include "llvm/MC/MCValue.h" ++#include "llvm/Support/ErrorHandling.h" ++ ++using namespace llvm; ++ ++namespace { ++ class SparcELFObjectWriter : public MCELFObjectTargetWriter { ++ public: ++ SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI) ++ : MCELFObjectTargetWriter(Is64Bit, OSABI, ++ Is64Bit ? ELF::EM_SPARCV9 : ELF::EM_SPARC, ++ /*HasRelocationAddend*/ true) {} ++ ++ virtual ~SparcELFObjectWriter() {} ++ protected: ++ virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, ++ bool IsPCRel, bool IsRelocWithSymbol, ++ int64_t Addend) const; ++ ++ }; ++} ++ ++ ++unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, ++ const MCFixup &Fixup, ++ bool IsPCRel, ++ bool IsRelocWithSymbol, ++ int64_t Addend) const { ++ if (IsPCRel) { ++ switch((unsigned)Fixup.getKind()) { ++ default: ++ llvm_unreachable("Unimplemented fixup -> relocation"); ++ case FK_Data_1: return ELF::R_SPARC_DISP8; ++ case FK_Data_2: return ELF::R_SPARC_DISP16; ++ case FK_Data_4: return ELF::R_SPARC_DISP32; ++ case FK_Data_8: return ELF::R_SPARC_DISP64; ++ case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30; ++ case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22; ++ case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19; ++ } ++ } ++ ++ switch((unsigned)Fixup.getKind()) { ++ default: ++ llvm_unreachable("Unimplemented fixup -> relocation"); ++ case FK_Data_1: return ELF::R_SPARC_8; ++ case FK_Data_2: return ((Fixup.getOffset() % 2) ++ ? ELF::R_SPARC_UA16 ++ : ELF::R_SPARC_16); ++ case FK_Data_4: return ((Fixup.getOffset() % 4) ++ ? ELF::R_SPARC_UA32 ++ : ELF::R_SPARC_32); ++ case FK_Data_8: return ((Fixup.getOffset() % 8) ++ ? ELF::R_SPARC_UA64 ++ : ELF::R_SPARC_64); ++ case Sparc::fixup_sparc_hi22: return ELF::R_SPARC_HI22; ++ case Sparc::fixup_sparc_lo10: return ELF::R_SPARC_LO10; ++ case Sparc::fixup_sparc_h44: return ELF::R_SPARC_H44; ++ case Sparc::fixup_sparc_m44: return ELF::R_SPARC_M44; ++ case Sparc::fixup_sparc_l44: return ELF::R_SPARC_L44; ++ case Sparc::fixup_sparc_hh: return ELF::R_SPARC_HH22; ++ case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10; ++ } ++ return ELF::R_SPARC_NONE; ++} ++ ++MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS, ++ bool Is64Bit, ++ uint8_t OSABI) { ++ MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI); ++ return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); ++} +Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h ++++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +@@ -14,15 +14,19 @@ + #ifndef SPARCMCTARGETDESC_H + #define SPARCMCTARGETDESC_H + ++#include "llvm/Support/DataTypes.h" ++ + namespace llvm { + class MCAsmBackend; + class MCCodeEmitter; + class MCContext; + class MCInstrInfo; ++class MCObjectWriter; + class MCRegisterInfo; + class MCSubtargetInfo; + class Target; + class StringRef; ++class raw_ostream; + + extern Target TheSparcTarget; + extern Target TheSparcV9Target; +@@ -35,7 +39,9 @@ MCAsmBackend *createSparcAsmBackend(const Target & + const MCRegisterInfo &MRI, + StringRef TT, + StringRef CPU); +- ++MCObjectWriter *createSparcELFObjectWriter(raw_ostream &OS, ++ bool Is64Bit, ++ uint8_t OSABI); + } // End llvm namespace + + // Defines symbolic names for Sparc registers. This defines a mapping from +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +@@ -70,15 +70,67 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const + bool + SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const { +- assert(0 && "FIXME: Implement SparcMCExpr::EvaluateAsRelocatableImpl"); + return getSubExpr()->EvaluateAsRelocatable(Res, *Layout); + } + ++static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { ++ assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!"); ++} + + void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { +- assert(0 && "FIXME: Implement SparcMCExpr::fixELFSymbolsInTLSFixups"); ++ switch(getKind()) { ++ default: return; ++ case VK_Sparc_TLS_GD_HI22: ++ case VK_Sparc_TLS_GD_LO10: ++ case VK_Sparc_TLS_GD_ADD: ++ case VK_Sparc_TLS_GD_CALL: ++ case VK_Sparc_TLS_LDM_HI22: ++ case VK_Sparc_TLS_LDM_LO10: ++ case VK_Sparc_TLS_LDM_ADD: ++ case VK_Sparc_TLS_LDM_CALL: ++ case VK_Sparc_TLS_LDO_HIX22: ++ case VK_Sparc_TLS_LDO_LOX10: ++ case VK_Sparc_TLS_LDO_ADD: ++ case VK_Sparc_TLS_IE_HI22: ++ case VK_Sparc_TLS_IE_LO10: ++ case VK_Sparc_TLS_IE_LD: ++ case VK_Sparc_TLS_IE_LDX: ++ case VK_Sparc_TLS_IE_ADD: ++ case VK_Sparc_TLS_LE_HIX22: ++ case VK_Sparc_TLS_LE_LOX10: break; ++ } ++ fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); + } + ++// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps ++// that method should be made public? ++// FIXME: really do above: now that at least three other backends are using it. ++static void AddValueSymbolsImpl(const MCExpr *Value, MCAssembler *Asm) { ++ switch (Value->getKind()) { ++ case MCExpr::Target: ++ llvm_unreachable("Can't handle nested target expr!"); ++ break; ++ ++ case MCExpr::Constant: ++ break; ++ ++ case MCExpr::Binary: { ++ const MCBinaryExpr *BE = cast(Value); ++ AddValueSymbolsImpl(BE->getLHS(), Asm); ++ AddValueSymbolsImpl(BE->getRHS(), Asm); ++ break; ++ } ++ ++ case MCExpr::SymbolRef: ++ Asm->getOrCreateSymbolData(cast(Value)->getSymbol()); ++ break; ++ ++ case MCExpr::Unary: ++ AddValueSymbolsImpl(cast(Value)->getSubExpr(), Asm); ++ break; ++ } ++} ++ + void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const { +- assert(0 && "FIXME: Implement SparcMCExpr::AddValueSymbols"); ++ AddValueSymbolsImpl(getSubExpr(), Asm); + } +Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt ++++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +@@ -1,5 +1,6 @@ + add_llvm_library(LLVMSparcDesc + SparcAsmBackend.cpp ++ SparcELFObjectWriter.cpp + SparcMCAsmInfo.cpp + SparcMCCodeEmitter.cpp + SparcMCTargetDesc.cpp diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198591-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198591-sparc.diff new file mode 100644 index 000000000000..056cb34c53a3 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198591-sparc.diff @@ -0,0 +1,762 @@ +Pull in r198591 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add initial implementation of disassembler for sparc + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcInstrFormats.td +=================================================================== +--- lib/Target/Sparc/SparcInstrFormats.td ++++ lib/Target/Sparc/SparcInstrFormats.td +@@ -12,6 +12,7 @@ class InstSP Inst; + + let Namespace = "SP"; ++ let Size = 4; + + bits<2> op; + let Inst{31-30} = op; // Top two bits are the 'op' field +@@ -20,6 +21,9 @@ class InstSP SoftFail = 0; + } + + //===----------------------------------------------------------------------===// +@@ -58,6 +62,27 @@ class F2_2 op2Val, dag outs, dag ins, stri + let Inst{28-25} = cond; + } + ++class F2_3 op2Val, bits<2> ccVal, dag outs, dag ins, string asmstr, ++ list pattern> ++ : InstSP { ++ bit annul; ++ bits<4> cond; ++ bit pred; ++ bits<19> imm19; ++ ++ let op = 0; // op = 0 ++ ++ bit annul = 0; // currently unused ++ let pred = 1; // default is predict taken ++ ++ let Inst{29} = annul; ++ let Inst{28-25} = cond; ++ let Inst{24-22} = op2Val; ++ let Inst{21-20} = ccVal; ++ let Inst{19} = pred; ++ let Inst{18-0} = imm19; ++} ++ + //===----------------------------------------------------------------------===// + // Format #3 instruction classes in the Sparc + //===----------------------------------------------------------------------===// +Index: lib/Target/Sparc/LLVMBuild.txt +=================================================================== +--- lib/Target/Sparc/LLVMBuild.txt ++++ lib/Target/Sparc/LLVMBuild.txt +@@ -16,13 +16,15 @@ + ;===------------------------------------------------------------------------===; + + [common] +-subdirectories = AsmParser InstPrinter MCTargetDesc TargetInfo ++subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo + + [component_0] + type = TargetGroup + name = Sparc + parent = Target ++has_asmparser = 1 + has_asmprinter = 1 ++has_disassembler = 1 + has_jit = 1 + + [component_1] +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -230,13 +230,13 @@ def FCC_O : FCC_VAL<29>; // Ordered + multiclass F3_12 Op3Val, SDNode OpNode, + RegisterClass RC, ValueType Ty, Operand immOp> { + def rr : F3_1<2, Op3Val, +- (outs RC:$dst), (ins RC:$b, RC:$c), +- !strconcat(OpcStr, " $b, $c, $dst"), +- [(set Ty:$dst, (OpNode Ty:$b, Ty:$c))]>; ++ (outs RC:$rd), (ins RC:$rs1, RC:$rs2), ++ !strconcat(OpcStr, " $rs1, $rs2, $rd"), ++ [(set Ty:$rd, (OpNode Ty:$rs1, Ty:$rs2))]>; + def ri : F3_2<2, Op3Val, +- (outs RC:$dst), (ins RC:$b, immOp:$c), +- !strconcat(OpcStr, " $b, $c, $dst"), +- [(set Ty:$dst, (OpNode Ty:$b, (Ty simm13:$c)))]>; ++ (outs RC:$rd), (ins RC:$rs1, immOp:$simm13), ++ !strconcat(OpcStr, " $rs1, $simm13, $rd"), ++ [(set Ty:$rd, (OpNode Ty:$rs1, (Ty simm13:$simm13)))]>; + } + + /// F3_12np multiclass - Define a normal F3_1/F3_2 pattern in one shot, with no +@@ -243,11 +243,11 @@ multiclass F3_12 Op3Val, SD + /// pattern. + multiclass F3_12np Op3Val> { + def rr : F3_1<2, Op3Val, +- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), +- !strconcat(OpcStr, " $b, $c, $dst"), []>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), ++ !strconcat(OpcStr, " $rs1, $rs2, $rd"), []>; + def ri : F3_2<2, Op3Val, +- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), +- !strconcat(OpcStr, " $b, $c, $dst"), []>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13), ++ !strconcat(OpcStr, " $rs1, $simm13, $rd"), []>; + } + + //===----------------------------------------------------------------------===// +@@ -488,31 +488,31 @@ let rd = 0, imm22 = 0 in + defm AND : F3_12<"and", 0b000001, and, IntRegs, i32, i32imm>; + + def ANDNrr : F3_1<2, 0b000101, +- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), +- "andn $b, $c, $dst", +- [(set i32:$dst, (and i32:$b, (not i32:$c)))]>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), ++ "andn $rs1, $rs2, $rd", ++ [(set i32:$rd, (and i32:$rs1, (not i32:$rs2)))]>; + def ANDNri : F3_2<2, 0b000101, +- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), +- "andn $b, $c, $dst", []>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13), ++ "andn $rs1, $simm13, $rd", []>; + + defm OR : F3_12<"or", 0b000010, or, IntRegs, i32, i32imm>; + + def ORNrr : F3_1<2, 0b000110, +- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), +- "orn $b, $c, $dst", +- [(set i32:$dst, (or i32:$b, (not i32:$c)))]>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), ++ "orn $rs1, $rs2, $rd", ++ [(set i32:$rd, (or i32:$rs1, (not i32:$rs2)))]>; + def ORNri : F3_2<2, 0b000110, +- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), +- "orn $b, $c, $dst", []>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13), ++ "orn $rs1, $simm13, $rd", []>; + defm XOR : F3_12<"xor", 0b000011, xor, IntRegs, i32, i32imm>; + + def XNORrr : F3_1<2, 0b000111, +- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), +- "xnor $b, $c, $dst", +- [(set i32:$dst, (not (xor i32:$b, i32:$c)))]>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), ++ "xnor $rs1, $rs2, $rd", ++ [(set i32:$rd, (not (xor i32:$rs1, i32:$rs2)))]>; + def XNORri : F3_2<2, 0b000111, +- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), +- "xnor $b, $c, $dst", []>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13), ++ "xnor $rs1, $simm13, $rd", []>; + + // Section B.12 - Shift Instructions, p. 107 + defm SLL : F3_12<"sll", 0b100101, shl, IntRegs, i32, i32imm>; +@@ -545,21 +545,15 @@ let Defs = [ICC] in + + let Defs = [ICC], rd = 0 in { + def CMPrr : F3_1<2, 0b010100, +- (outs), (ins IntRegs:$b, IntRegs:$c), +- "cmp $b, $c", +- [(SPcmpicc i32:$b, i32:$c)]>; ++ (outs), (ins IntRegs:$rs1, IntRegs:$rs2), ++ "cmp $rs1, $rs2", ++ [(SPcmpicc i32:$rs1, i32:$rs2)]>; + def CMPri : F3_2<2, 0b010100, +- (outs), (ins IntRegs:$b, i32imm:$c), +- "cmp $b, $c", +- [(SPcmpicc i32:$b, (i32 simm13:$c))]>; ++ (outs), (ins IntRegs:$rs1, i32imm:$simm13), ++ "cmp $rs1, $simm13", ++ [(SPcmpicc i32:$rs1, (i32 simm13:$simm13))]>; + } + +-let Uses = [ICC], Defs = [ICC] in +- def SUBXCCrr: F3_1<2, 0b011100, +- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), +- "subxcc $b, $c, $dst", []>; +- +- + // Section B.18 - Multiply Instructions, p. 113 + let Defs = [Y] in { + defm UMUL : F3_12np<"umul", 0b001010>; +@@ -858,7 +852,7 @@ let Defs = [FCC] in { + //===----------------------------------------------------------------------===// + // Instructions for Thread Local Storage(TLS). + //===----------------------------------------------------------------------===// +- ++let isCodeGenOnly = 1, isAsmParserOnly = 1 in { + def TLS_ADDrr : F3_1<2, 0b000000, + (outs IntRegs:$rd), + (ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym), +@@ -882,6 +876,7 @@ let Uses = [O6], isCall = 1, hasDelaySlot = 1 in + let op = 1; + let Inst{29-0} = disp; + } ++} + + //===----------------------------------------------------------------------===// + // V9 Instructions +Index: lib/Target/Sparc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/CMakeLists.txt ++++ lib/Target/Sparc/CMakeLists.txt +@@ -3,6 +3,7 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td) + tablegen(LLVM SparcGenRegisterInfo.inc -gen-register-info) + tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info) + tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter) ++tablegen(LLVM SparcGenDisassemblerTables.inc -gen-disassembler) + tablegen(LLVM SparcGenMCCodeEmitter.inc -gen-emitter -mc-emitter) + tablegen(LLVM SparcGenAsmWriter.inc -gen-asm-writer) + tablegen(LLVM SparcGenAsmMatcher.inc -gen-asm-matcher) +@@ -34,3 +35,4 @@ add_subdirectory(TargetInfo) + add_subdirectory(MCTargetDesc) + add_subdirectory(InstPrinter) + add_subdirectory(AsmParser) ++add_subdirectory(Disassembler) +Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +=================================================================== +--- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp ++++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +@@ -0,0 +1,228 @@ ++//===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- C++ -*-===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file is part of the Sparc Disassembler. ++// ++//===----------------------------------------------------------------------===// ++ ++#define DEBUG_TYPE "sparc-disassembler" ++ ++#include "Sparc.h" ++#include "SparcRegisterInfo.h" ++#include "SparcSubtarget.h" ++#include "llvm/MC/MCDisassembler.h" ++#include "llvm/MC/MCFixedLenDisassembler.h" ++#include "llvm/Support/MemoryObject.h" ++#include "llvm/Support/TargetRegistry.h" ++ ++using namespace llvm; ++ ++typedef MCDisassembler::DecodeStatus DecodeStatus; ++ ++namespace { ++ ++/// SparcDisassembler - a disassembler class for Sparc. ++class SparcDisassembler : public MCDisassembler { ++public: ++ /// Constructor - Initializes the disassembler. ++ /// ++ SparcDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info) : ++ MCDisassembler(STI), RegInfo(Info) ++ {} ++ virtual ~SparcDisassembler() {} ++ ++ const MCRegisterInfo *getRegInfo() const { return RegInfo.get(); } ++ ++ /// getInstruction - See MCDisassembler. ++ virtual DecodeStatus getInstruction(MCInst &instr, ++ uint64_t &size, ++ const MemoryObject ®ion, ++ uint64_t address, ++ raw_ostream &vStream, ++ raw_ostream &cStream) const; ++private: ++ OwningPtr RegInfo; ++}; ++ ++} ++ ++namespace llvm { ++ extern Target TheSparcTarget, TheSparcV9Target; ++} ++ ++static MCDisassembler *createSparcDisassembler( ++ const Target &T, ++ const MCSubtargetInfo &STI) { ++ return new SparcDisassembler(STI, T.createMCRegInfo("")); ++} ++ ++ ++extern "C" void LLVMInitializeSparcDisassembler() { ++ // Register the disassembler. ++ TargetRegistry::RegisterMCDisassembler(TheSparcTarget, ++ createSparcDisassembler); ++ TargetRegistry::RegisterMCDisassembler(TheSparcV9Target, ++ createSparcDisassembler); ++} ++ ++ ++ ++static const unsigned IntRegDecoderTable[] = { ++ SP::G0, SP::G1, SP::G2, SP::G3, ++ SP::G4, SP::G5, SP::G6, SP::G7, ++ SP::O0, SP::O1, SP::O2, SP::O3, ++ SP::O4, SP::O5, SP::O6, SP::O7, ++ SP::L0, SP::L1, SP::L2, SP::L3, ++ SP::L4, SP::L5, SP::L6, SP::L7, ++ SP::I0, SP::I1, SP::I2, SP::I3, ++ SP::I4, SP::I5, SP::I6, SP::I7 }; ++ ++static const unsigned FPRegDecoderTable[] = { ++ SP::F0, SP::F1, SP::F2, SP::F3, ++ SP::F4, SP::F5, SP::F6, SP::F7, ++ SP::F8, SP::F9, SP::F10, SP::F11, ++ SP::F12, SP::F13, SP::F14, SP::F15, ++ SP::F16, SP::F17, SP::F18, SP::F19, ++ SP::F20, SP::F21, SP::F22, SP::F23, ++ SP::F24, SP::F25, SP::F26, SP::F27, ++ SP::F28, SP::F29, SP::F30, SP::F31 }; ++ ++static const unsigned DFPRegDecoderTable[] = { ++ SP::D0, SP::D16, SP::D1, SP::D17, ++ SP::D2, SP::D18, SP::D3, SP::D19, ++ SP::D4, SP::D20, SP::D5, SP::D21, ++ SP::D6, SP::D22, SP::D7, SP::D23, ++ SP::D8, SP::D24, SP::D9, SP::D25, ++ SP::D10, SP::D26, SP::D11, SP::D27, ++ SP::D12, SP::D28, SP::D13, SP::D29, ++ SP::D14, SP::D30, SP::D15, SP::D31 }; ++ ++static const unsigned QFPRegDecoderTable[] = { ++ SP::Q0, SP::Q8, -1, -1, ++ SP::Q1, SP::Q9, -1, -1, ++ SP::Q2, SP::Q10, -1, -1, ++ SP::Q3, SP::Q11, -1, -1, ++ SP::Q4, SP::Q12, -1, -1, ++ SP::Q5, SP::Q13, -1, -1, ++ SP::Q6, SP::Q14, -1, -1, ++ SP::Q7, SP::Q15, -1, -1 } ; ++ ++static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = IntRegDecoderTable[RegNo]; ++ Inst.addOperand(MCOperand::CreateReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++static DecodeStatus DecodeI64RegsRegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = IntRegDecoderTable[RegNo]; ++ Inst.addOperand(MCOperand::CreateReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++ ++static DecodeStatus DecodeFPRegsRegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = FPRegDecoderTable[RegNo]; ++ Inst.addOperand(MCOperand::CreateReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++ ++static DecodeStatus DecodeDFPRegsRegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ unsigned Reg = DFPRegDecoderTable[RegNo]; ++ Inst.addOperand(MCOperand::CreateReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++ ++static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst, ++ unsigned RegNo, ++ uint64_t Address, ++ const void *Decoder) { ++ if (RegNo > 31) ++ return MCDisassembler::Fail; ++ ++ unsigned Reg = QFPRegDecoderTable[RegNo]; ++ if (Reg == (unsigned)-1) ++ return MCDisassembler::Fail; ++ Inst.addOperand(MCOperand::CreateReg(Reg)); ++ return MCDisassembler::Success; ++} ++ ++ ++#include "SparcGenDisassemblerTables.inc" ++ ++/// readInstruction - read four bytes from the MemoryObject ++/// and return 32 bit word. ++static DecodeStatus readInstruction32(const MemoryObject ®ion, ++ uint64_t address, ++ uint64_t &size, ++ uint32_t &insn) { ++ uint8_t Bytes[4]; ++ ++ // We want to read exactly 4 Bytes of data. ++ if (region.readBytes(address, 4, Bytes) == -1) { ++ size = 0; ++ return MCDisassembler::Fail; ++ } ++ ++ // Encoded as a big-endian 32-bit word in the stream. ++ insn = (Bytes[3] << 0) | ++ (Bytes[2] << 8) | ++ (Bytes[1] << 16) | ++ (Bytes[0] << 24); ++ ++ return MCDisassembler::Success; ++} ++ ++ ++DecodeStatus ++SparcDisassembler::getInstruction(MCInst &instr, ++ uint64_t &Size, ++ const MemoryObject &Region, ++ uint64_t Address, ++ raw_ostream &vStream, ++ raw_ostream &cStream) const { ++ uint32_t Insn; ++ ++ DecodeStatus Result = readInstruction32(Region, Address, Size, Insn); ++ if (Result == MCDisassembler::Fail) ++ return MCDisassembler::Fail; ++ ++ ++ // Calling the auto-generated decoder function. ++ Result = decodeInstruction(DecoderTableSparc32, instr, Insn, Address, ++ this, STI); ++ ++ if (Result != MCDisassembler::Fail) { ++ Size = 4; ++ return Result; ++ } ++ ++ return MCDisassembler::Fail; ++} +Index: lib/Target/Sparc/Disassembler/LLVMBuild.txt +=================================================================== +--- lib/Target/Sparc/Disassembler/LLVMBuild.txt ++++ lib/Target/Sparc/Disassembler/LLVMBuild.txt +@@ -0,0 +1,23 @@ ++;===- ./lib/Target/Sparc/Disassembler/LLVMBuild.txt ------------*- Conf -*--===; ++; ++; The LLVM Compiler Infrastructure ++; ++; This file is distributed under the University of Illinois Open Source ++; License. See LICENSE.TXT for details. ++; ++;===------------------------------------------------------------------------===; ++; ++; This is an LLVMBuild description file for the components in this subdirectory. ++; ++; For more information on the LLVMBuild system, please see: ++; ++; http://llvm.org/docs/LLVMBuild.html ++; ++;===------------------------------------------------------------------------===; ++ ++[component_0] ++type = Library ++name = SparcDisassembler ++parent = Sparc ++required_libraries = MC Support SparcInfo ++add_to_library_groups = Sparc +Index: lib/Target/Sparc/Disassembler/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/Disassembler/CMakeLists.txt ++++ lib/Target/Sparc/Disassembler/CMakeLists.txt +@@ -0,0 +1,12 @@ ++add_llvm_library(LLVMSparcDisassembler ++ SparcDisassembler.cpp ++ ) ++ ++# workaround for hanging compilation on MSVC9 and 10 ++if( MSVC_VERSION EQUAL 1400 OR MSVC_VERSION EQUAL 1500 ++ OR MSVC_VERSION EQUAL 1600 ) ++set_property( ++ SOURCE SparcDisassembler.cpp ++ PROPERTY COMPILE_FLAGS "/Od" ++ ) ++endif() +Index: lib/Target/Sparc/Disassembler/Makefile +=================================================================== +--- lib/Target/Sparc/Disassembler/Makefile ++++ lib/Target/Sparc/Disassembler/Makefile +@@ -0,0 +1,16 @@ ++##===- lib/Target/Sparc/Disassembler/Makefile --------------*- Makefile -*-===## ++# ++# The LLVM Compiler Infrastructure ++# ++# This file is distributed under the University of Illinois Open Source ++# License. See LICENSE.TXT for details. ++# ++##===----------------------------------------------------------------------===## ++ ++LEVEL = ../../../.. ++LIBRARYNAME = LLVMSparcDisassembler ++ ++# Hack: we need to include 'main' Sparc target directory to grab private headers ++CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. ++ ++include $(LEVEL)/Makefile.common +Index: lib/Target/Sparc/Makefile +=================================================================== +--- lib/Target/Sparc/Makefile ++++ lib/Target/Sparc/Makefile +@@ -14,11 +14,11 @@ TARGET = Sparc + # Make sure that tblgen is run, first thing. + BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \ + SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \ +- SparcGenDAGISel.inc \ ++ SparcGenDAGISel.inc SparcGenDisassemblerTables.inc \ + SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \ + SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc + +-DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc ++DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc + + include $(LEVEL)/Makefile.common + +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -141,6 +141,7 @@ def : Pat<(i64 imm:$val), + let Predicates = [Is64Bit] in { + + // Register-register instructions. ++let isCodeGenOnly = 1 in { + defm ANDX : F3_12<"and", 0b000001, and, I64Regs, i64, i64imm>; + defm ORX : F3_12<"or", 0b000010, or, I64Regs, i64, i64imm>; + defm XORX : F3_12<"xor", 0b000011, xor, I64Regs, i64, i64imm>; +@@ -161,8 +162,6 @@ def XNORXrr : F3_1<2, 0b000111, + defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>; + defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>; + +-def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>; +- + def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd), + (ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym), + "add $rs1, $rs2, $rd, $sym", +@@ -169,18 +168,17 @@ def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$ + [(set i64:$rd, + (tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>; + +-// Register-immediate instructions. +- +-def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>; +- +-def : Pat<(ctpop i64:$src), (POPCrr $src)>; +- + // "LEA" form of add +-let isCodeGenOnly = 1 in + def LEAX_ADDri : F3_2<2, 0b000000, + (outs I64Regs:$dst), (ins MEMri:$addr), + "add ${addr:arith}, $dst", + [(set iPTR:$dst, ADDRri:$addr)]>; ++} ++ ++def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>; ++def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>; ++def : Pat<(ctpop i64:$src), (POPCrr $src)>; ++ + } // Predicates = [Is64Bit] + + +@@ -245,7 +243,7 @@ def LDXri : F3_2<3, 0b001011, + (outs I64Regs:$dst), (ins MEMri:$addr), + "ldx [$addr], $dst", + [(set i64:$dst, (load ADDRri:$addr))]>; +-let mayLoad = 1 in ++let mayLoad = 1, isCodeGenOnly = 1, isAsmParserOnly = 1 in + def TLS_LDXrr : F3_1<3, 0b001011, + (outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym), + "ldx [$addr], $dst, $sym", +@@ -278,11 +276,11 @@ def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr + def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>; + + // Sign-extending load of i32 into i64 is a new SPARC v9 instruction. +-def LDSWrr : F3_1<3, 0b001011, ++def LDSWrr : F3_1<3, 0b001000, + (outs I64Regs:$dst), (ins MEMrr:$addr), + "ldsw [$addr], $dst", + [(set i64:$dst, (sextloadi32 ADDRrr:$addr))]>; +-def LDSWri : F3_2<3, 0b001011, ++def LDSWri : F3_2<3, 0b001000, + (outs I64Regs:$dst), (ins MEMri:$addr), + "ldsw [$addr], $dst", + [(set i64:$dst, (sextloadi32 ADDRri:$addr))]>; +@@ -289,13 +287,13 @@ def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri + + // 64-bit stores. + def STXrr : F3_1<3, 0b001110, +- (outs), (ins MEMrr:$addr, I64Regs:$src), +- "stx $src, [$addr]", +- [(store i64:$src, ADDRrr:$addr)]>; ++ (outs), (ins MEMrr:$addr, I64Regs:$rd), ++ "stx $rd, [$addr]", ++ [(store i64:$rd, ADDRrr:$addr)]>; + def STXri : F3_2<3, 0b001110, +- (outs), (ins MEMri:$addr, I64Regs:$src), +- "stx $src, [$addr]", +- [(store i64:$src, ADDRri:$addr)]>; ++ (outs), (ins MEMri:$addr, I64Regs:$rd), ++ "stx $rd, [$addr]", ++ [(store i64:$rd, ADDRri:$addr)]>; + + // Truncating stores from i64 are identical to the i32 stores. + def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>; +@@ -315,6 +313,15 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADD + //===----------------------------------------------------------------------===// + // 64-bit Conditionals. + //===----------------------------------------------------------------------===// ++ ++// Conditional branch class on %xcc: ++class XBranchSP pattern> ++ : F2_3<0b001, 0b10, (outs), ins, asmstr, pattern> { ++ let isBranch = 1; ++ let isTerminator = 1; ++ let hasDelaySlot = 1; ++} ++ + // + // Flag-setting instructions like subcc and addcc set both icc and xcc flags. + // The icc flags correspond to the 32-bit result, and the xcc are for the +@@ -326,7 +333,7 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADD + let Predicates = [Is64Bit] in { + + let Uses = [ICC] in +-def BPXCC : BranchSP<(ins brtarget:$imm22, CCOp:$cond), ++def BPXCC : XBranchSP<(ins brtarget:$imm22, CCOp:$cond), + "b$cond %xcc, $imm22", + [(SPbrxcc bb:$imm22, imm:$cond)]>; + +@@ -409,7 +416,7 @@ def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, im + + + // 64 bit SETHI +-let Predicates = [Is64Bit] in { ++let Predicates = [Is64Bit], isCodeGenOnly = 1 in { + def SETHIXi : F2_1<0b100, + (outs IntRegs:$rd), (ins i64imm:$imm22), + "sethi $imm22, $rd", +Index: test/MC/Disassembler/Sparc/lit.local.cfg +=================================================================== +--- test/MC/Disassembler/Sparc/lit.local.cfg ++++ test/MC/Disassembler/Sparc/lit.local.cfg +@@ -0,0 +1,4 @@ ++targets = set(config.root.targets_to_build.split()) ++if not 'Sparc' in targets: ++ config.unsupported = True ++ +Index: test/MC/Disassembler/Sparc/sparc.txt +=================================================================== +--- test/MC/Disassembler/Sparc/sparc.txt ++++ test/MC/Disassembler/Sparc/sparc.txt +@@ -0,0 +1,82 @@ ++# RUN: llvm-mc --disassemble %s -triple=sparc-unknown-linux | FileCheck %s ++ ++# CHECK: add %g0, %g0, %g0 ++0x80 0x00 0x00 0x00 ++ ++# CHECK: add %g1, %g2, %g3 ++0x86 0x00 0x40 0x02 ++ ++# CHECK: add %o0, %o1, %l0 ++0xa0 0x02 0x00 0x09 ++ ++# CHECK: add %o0, 10, %l0 ++0xa0 0x02 0x20 0x0a ++ ++# CHECK: addcc %g1, %g2, %g3 ++0x86 0x80 0x40 0x02 ++ ++# CHECK: addxcc %g1, %g2, %g3 ++0x86 0xc0 0x40 0x02 ++ ++# CHECK: udiv %g1, %g2, %g3 ++0x86 0x70 0x40 0x02 ++ ++# CHECK: sdiv %g1, %g2, %g3 ++0x86 0x78 0x40 0x02 ++ ++# CHECK: and %g1, %g2, %g3 ++0x86 0x08 0x40 0x02 ++ ++# CHECK: andn %g1, %g2, %g3 ++0x86 0x28 0x40 0x02 ++ ++# CHECK: or %g1, %g2, %g3 ++0x86 0x10 0x40 0x02 ++ ++# CHECK: orn %g1, %g2, %g3 ++0x86 0x30 0x40 0x02 ++ ++# CHECK: xor %g1, %g2, %g3 ++0x86 0x18 0x40 0x02 ++ ++# CHECK: xnor %g1, %g2, %g3 ++0x86 0x38 0x40 0x02 ++ ++# CHECK: umul %g1, %g2, %g3 ++0x86 0x50 0x40 0x02 ++ ++# CHECK: smul %g1, %g2, %g3 ++0x86 0x58 0x40 0x02 ++ ++# CHECK: nop ++0x01 0x00 0x00 0x00 ++ ++# CHECK: sethi 10, %l0 ++0x21 0x00 0x00 0x0a ++ ++# CHECK: sll %g1, %g2, %g3 ++0x87 0x28 0x40 0x02 ++ ++# CHECK: sll %g1, 31, %g3 ++0x87 0x28 0x60 0x1f ++ ++# CHECK: srl %g1, %g2, %g3 ++0x87 0x30 0x40 0x02 ++ ++# CHECK: srl %g1, 31, %g3 ++0x87 0x30 0x60 0x1f ++ ++# CHECK: sra %g1, %g2, %g3 ++0x87 0x38 0x40 0x02 ++ ++# CHECK: sra %g1, 31, %g3 ++0x87 0x38 0x60 0x1f ++ ++# CHECK: sub %g1, %g2, %g3 ++0x86 0x20 0x40 0x02 ++ ++# CHECK: subcc %g1, %g2, %g3 ++0x86 0xa0 0x40 0x02 ++ ++# CHECK: subxcc %g1, %g2, %g3 ++0x86 0xe0 0x40 0x02 diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198592-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198592-sparc.diff new file mode 100644 index 000000000000..722290ed5f5c --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198592-sparc.diff @@ -0,0 +1,33 @@ +Pull in r198592 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Explicitly cast -1 to unsigned to fix buildbot errors. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +=================================================================== +--- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp ++++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +@@ -104,14 +104,14 @@ static const unsigned DFPRegDecoderTable[] = { + SP::D14, SP::D30, SP::D15, SP::D31 }; + + static const unsigned QFPRegDecoderTable[] = { +- SP::Q0, SP::Q8, -1, -1, +- SP::Q1, SP::Q9, -1, -1, +- SP::Q2, SP::Q10, -1, -1, +- SP::Q3, SP::Q11, -1, -1, +- SP::Q4, SP::Q12, -1, -1, +- SP::Q5, SP::Q13, -1, -1, +- SP::Q6, SP::Q14, -1, -1, +- SP::Q7, SP::Q15, -1, -1 } ; ++ SP::Q0, SP::Q8, (unsigned)-1, (unsigned)-1, ++ SP::Q1, SP::Q9, (unsigned)-1, (unsigned)-1, ++ SP::Q2, SP::Q10, (unsigned)-1, (unsigned)-1, ++ SP::Q3, SP::Q11, (unsigned)-1, (unsigned)-1, ++ SP::Q4, SP::Q12, (unsigned)-1, (unsigned)-1, ++ SP::Q5, SP::Q13, (unsigned)-1, (unsigned)-1, ++ SP::Q6, SP::Q14, (unsigned)-1, (unsigned)-1, ++ SP::Q7, SP::Q15, (unsigned)-1, (unsigned)-1 } ; + + static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, + unsigned RegNo, diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198658-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198658-sparc.diff new file mode 100644 index 000000000000..b7eb2a283a06 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198658-sparc.diff @@ -0,0 +1,359 @@ +Pull in r198658 from upstream llvm trunk: + + [Sparc] Add support for parsing memory operands in sparc AsmParser. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/MC/Sparc/sparc-ctrl-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-ctrl-instructions.s ++++ test/MC/Sparc/sparc-ctrl-instructions.s +@@ -0,0 +1,23 @@ ++! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s ++! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s ++ ++ ! CHECK: call foo ++ call foo ++ ++ ! CHECK: call %g1+%i2 ++ call %g1 + %i2 ++ ++ ! CHECK: call %o1+8 ++ call %o1 + 8 ++ ++ ! CHECK: call %g1 ++ call %g1 ++ ++ ! CHECK: jmp %g1+%i2 ++ jmp %g1 + %i2 ++ ++ ! CHECK: jmp %o1+8 ++ jmp %o1 + 8 ++ ++ ! CHECK: jmp %g1 ++ jmp %g1 +Index: test/MC/Sparc/sparc-mem-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-mem-instructions.s ++++ test/MC/Sparc/sparc-mem-instructions.s +@@ -0,0 +1,58 @@ ++! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s ++! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s ++ ++ ! CHECK: ldsb [%i0+%l6], %o2 ! encoding: [0xd4,0x4e,0x00,0x16] ++ ldsb [%i0 + %l6], %o2 ++ ! CHECK: ldsb [%i0+32], %o2 ! encoding: [0xd4,0x4e,0x20,0x20] ++ ldsb [%i0 + 32], %o2 ++ ! CHECK: ldsb [%g1], %o4 ! encoding: [0xd8,0x48,0x60,0x00] ++ ldsb [%g1], %o4 ++ ++ ! CHECK: ldsh [%i0+%l6], %o2 ! encoding: [0xd4,0x56,0x00,0x16] ++ ldsh [%i0 + %l6], %o2 ++ ! CHECK: ldsh [%i0+32], %o2 ! encoding: [0xd4,0x56,0x20,0x20] ++ ldsh [%i0 + 32], %o2 ++ ! CHECK: ldsh [%g1], %o4 ! encoding: [0xd8,0x50,0x60,0x00] ++ ldsh [%g1], %o4 ++ ++ ! CHECK: ldub [%i0+%l6], %o2 ! encoding: [0xd4,0x0e,0x00,0x16] ++ ldub [%i0 + %l6], %o2 ++ ! CHECK: ldub [%i0+32], %o2 ! encoding: [0xd4,0x0e,0x20,0x20] ++ ldub [%i0 + 32], %o2 ++ ! CHECK: ldub [%g1], %o2 ! encoding: [0xd4,0x08,0x60,0x00] ++ ldub [%g1], %o2 ++ ++ ! CHECK: lduh [%i0+%l6], %o2 ! encoding: [0xd4,0x16,0x00,0x16] ++ lduh [%i0 + %l6], %o2 ++ ! CHECK: lduh [%i0+32], %o2 ! encoding: [0xd4,0x16,0x20,0x20] ++ lduh [%i0 + 32], %o2 ++ ! CHECK: lduh [%g1], %o2 ! encoding: [0xd4,0x10,0x60,0x00] ++ lduh [%g1], %o2 ++ ++ ! CHECK: ld [%i0+%l6], %o2 ! encoding: [0xd4,0x06,0x00,0x16] ++ ld [%i0 + %l6], %o2 ++ ! CHECK: ld [%i0+32], %o2 ! encoding: [0xd4,0x06,0x20,0x20] ++ ld [%i0 + 32], %o2 ++ ! CHECK: ld [%g1], %o2 ! encoding: [0xd4,0x00,0x60,0x00] ++ ld [%g1], %o2 ++ ++ ! CHECK: stb %o2, [%i0+%l6] ! encoding: [0xd4,0x2e,0x00,0x16] ++ stb %o2, [%i0 + %l6] ++ ! CHECK: stb %o2, [%i0+32] ! encoding: [0xd4,0x2e,0x20,0x20] ++ stb %o2, [%i0 + 32] ++ ! CHECK: stb %o2, [%g1] ! encoding: [0xd4,0x28,0x60,0x00] ++ stb %o2, [%g1] ++ ++ ! CHECK: sth %o2, [%i0+%l6] ! encoding: [0xd4,0x36,0x00,0x16] ++ sth %o2, [%i0 + %l6] ++ ! CHECK: sth %o2, [%i0+32] ! encoding: [0xd4,0x36,0x20,0x20] ++ sth %o2, [%i0 + 32] ++ ! CHECK: sth %o2, [%g1] ! encoding: [0xd4,0x30,0x60,0x00] ++ sth %o2, [%g1] ++ ++ ! CHECK: st %o2, [%i0+%l6] ! encoding: [0xd4,0x26,0x00,0x16] ++ st %o2, [%i0 + %l6] ++ ! CHECK: st %o2, [%i0+32] ! encoding: [0xd4,0x26,0x20,0x20] ++ st %o2, [%i0 + 32] ++ ! CHECK: st %o2, [%g1] ! encoding: [0xd4,0x20,0x60,0x00] ++ st %o2, [%g1] +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -28,6 +28,7 @@ namespace llvm { + } + + namespace { ++class SparcOperand; + class SparcAsmParser : public MCTargetAsmParser { + + MCSubtargetInfo &STI; +@@ -55,18 +56,15 @@ class SparcAsmParser : public MCTargetAsmParser { + + // Custom parse functions for Sparc specific operands. + OperandMatchResultTy +- parseMEMrrOperand(SmallVectorImpl &Operands); +- OperandMatchResultTy +- parseMEMriOperand(SmallVectorImpl &Operands); ++ parseMEMOperand(SmallVectorImpl &Operands); + + OperandMatchResultTy +- parseMEMOperand(SmallVectorImpl &Operands, +- int ImmOffsetOrReg); +- +- OperandMatchResultTy + parseOperand(SmallVectorImpl &Operands, + StringRef Name); + ++ OperandMatchResultTy ++ parseSparcAsmOperand(SparcOperand *&Operand); ++ + // returns true if Tok is matched to a register and returns register in RegNo. + bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP, + bool isQFP); +@@ -298,7 +296,35 @@ class SparcOperand : public MCParsedAsmOperand { + return Op; + } + ++ static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) { ++ unsigned offsetReg = Op->getReg(); ++ Op->Kind = k_MemoryReg; ++ Op->Mem.Base = Base; ++ Op->Mem.OffsetReg = offsetReg; ++ Op->Mem.Off = 0; ++ return Op; ++ } + ++ static SparcOperand *CreateMEMri(unsigned Base, ++ const MCExpr *Off, ++ SMLoc S, SMLoc E) { ++ SparcOperand *Op = new SparcOperand(k_MemoryImm); ++ Op->Mem.Base = Base; ++ Op->Mem.OffsetReg = 0; ++ Op->Mem.Off = Off; ++ Op->StartLoc = S; ++ Op->EndLoc = E; ++ return Op; ++ } ++ ++ static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) { ++ const MCExpr *Imm = Op->getImm(); ++ Op->Kind = k_MemoryImm; ++ Op->Mem.Base = Base; ++ Op->Mem.OffsetReg = 0; ++ Op->Mem.Off = Imm; ++ return Op; ++ } + }; + + } // end namespace +@@ -412,23 +438,42 @@ ParseDirective(AsmToken DirectiveID) + } + + SparcAsmParser::OperandMatchResultTy SparcAsmParser:: +-parseMEMOperand(SmallVectorImpl &Operands, +- int ImmOffsetOrReg) ++parseMEMOperand(SmallVectorImpl &Operands) + { +- // FIXME: Implement memory operand parsing here. +- return MatchOperand_NoMatch; +-} + +-SparcAsmParser::OperandMatchResultTy SparcAsmParser:: +-parseMEMrrOperand(SmallVectorImpl &Operands) +-{ +- return parseMEMOperand(Operands, 2); +-} ++ SMLoc S, E; ++ unsigned BaseReg = 0; + +-SparcAsmParser::OperandMatchResultTy SparcAsmParser:: +-parseMEMriOperand(SmallVectorImpl &Operands) +-{ +- return parseMEMOperand(Operands, 1); ++ if (ParseRegister(BaseReg, S, E)) { ++ return MatchOperand_NoMatch; ++ } ++ ++ switch (getLexer().getKind()) { ++ default: return MatchOperand_NoMatch; ++ ++ case AsmToken::RBrac: ++ case AsmToken::EndOfStatement: ++ Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E)); ++ return MatchOperand_Success; ++ ++ case AsmToken:: Plus: ++ Parser.Lex(); // Eat the '+' ++ break; ++ case AsmToken::Minus: ++ break; ++ } ++ ++ SparcOperand *Offset = 0; ++ OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset); ++ if (ResTy != MatchOperand_Success || !Offset) ++ return MatchOperand_NoMatch; ++ ++ Offset = (Offset->isImm() ++ ? SparcOperand::MorphToMEMri(BaseReg, Offset) ++ : SparcOperand::MorphToMEMrr(BaseReg, Offset)); ++ ++ Operands.push_back(Offset); ++ return MatchOperand_Success; + } + + SparcAsmParser::OperandMatchResultTy SparcAsmParser:: +@@ -435,20 +480,57 @@ SparcAsmParser::OperandMatchResultTy SparcAsmParse + parseOperand(SmallVectorImpl &Operands, + StringRef Mnemonic) + { ++ + OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); +- if (ResTy == MatchOperand_Success) +- return ResTy; ++ + // If there wasn't a custom match, try the generic matcher below. Otherwise, + // there was a match, but an error occurred, in which case, just return that + // the operand parsing failed. +- if (ResTy == MatchOperand_ParseFail) ++ if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail) + return ResTy; + ++ if (getLexer().is(AsmToken::LBrac)) { ++ // Memory operand ++ Operands.push_back(SparcOperand::CreateToken("[", ++ Parser.getTok().getLoc())); ++ Parser.Lex(); // Eat the [ ++ ++ ResTy = parseMEMOperand(Operands); ++ if (ResTy != MatchOperand_Success) ++ return ResTy; ++ ++ if (!getLexer().is(AsmToken::RBrac)) ++ return MatchOperand_ParseFail; ++ ++ Operands.push_back(SparcOperand::CreateToken("]", ++ Parser.getTok().getLoc())); ++ Parser.Lex(); // Eat the ] ++ return MatchOperand_Success; ++ } ++ ++ SparcOperand *Op = 0; ++ ResTy = parseSparcAsmOperand(Op); ++ if (ResTy != MatchOperand_Success || !Op) ++ return MatchOperand_ParseFail; ++ ++ // Push the parsed operand into the list of operands ++ Operands.push_back(Op); ++ ++ return MatchOperand_Success; ++} ++ ++SparcAsmParser::OperandMatchResultTy ++SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op) ++{ ++ + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + const MCExpr *EVal; +- SparcOperand *Op; ++ ++ Op = 0; + switch (getLexer().getKind()) { ++ default: break; ++ + case AsmToken::Percent: + Parser.Lex(); // Eat the '%'. + unsigned RegNo; +@@ -458,40 +540,30 @@ parseOperand(SmallVectorImpl + break; + } + // FIXME: Handle modifiers like %hi, %lo etc., +- return MatchOperand_ParseFail; ++ break; + + case AsmToken::Minus: + case AsmToken::Integer: +- if (getParser().parseExpression(EVal)) +- return MatchOperand_ParseFail; +- +- Op = SparcOperand::CreateImm(EVal, S, E); ++ if (!getParser().parseExpression(EVal)) ++ Op = SparcOperand::CreateImm(EVal, S, E); + break; + + case AsmToken::Identifier: { + StringRef Identifier; +- if (getParser().parseIdentifier(Identifier)) +- return MatchOperand_ParseFail; +- SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); +- MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); ++ if (!getParser().parseIdentifier(Identifier)) { ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok(). ++ getLoc().getPointer() - 1); ++ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); + +- // Otherwise create a symbol reference. +- const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, +- getContext()); ++ const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, ++ getContext()); + +- Op = SparcOperand::CreateImm(Res, S, E); ++ Op = SparcOperand::CreateImm(Res, S, E); ++ } + break; + } +- +- case AsmToken::LBrac: // handle [ +- return parseMEMOperand(Operands, 0); +- +- default: +- return MatchOperand_ParseFail; + } +- // Push the parsed operand into the list of operands +- Operands.push_back(Op); +- return MatchOperand_Success; ++ return (Op) ? MatchOperand_Success : MatchOperand_ParseFail; + } + + bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -78,12 +78,12 @@ def ADDRri : ComplexPattern { diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198681-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198681-sparc.diff new file mode 100644 index 000000000000..4bd12d264ae4 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198681-sparc.diff @@ -0,0 +1,298 @@ +Pull in r198681 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add support for parsing sparc asm modifiers such as %hi, %lo etc., + Also, correct the offsets for FixupsKindInfo. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +@@ -27,11 +27,11 @@ static unsigned adjustFixupValue(unsigned Kind, ui + case FK_Data_8: + return Value; + case Sparc::fixup_sparc_call30: +- return Value & 0x3fffffff; ++ return (Value >> 2) & 0x3fffffff; + case Sparc::fixup_sparc_br22: +- return Value & 0x3fffff; ++ return (Value >> 2) & 0x3fffff; + case Sparc::fixup_sparc_br19: +- return Value & 0x1ffff; ++ return (Value >> 2) & 0x1ffff; + case Sparc::fixup_sparc_hi22: + return (Value >> 10) & 0x3fffff; + case Sparc::fixup_sparc_lo10: +@@ -45,7 +45,7 @@ static unsigned adjustFixupValue(unsigned Kind, ui + case Sparc::fixup_sparc_hh: + return (Value >> 42) & 0x3fffff; + case Sparc::fixup_sparc_hm: +- return (Value >>32) & 0x3ff; ++ return (Value >> 32) & 0x3ff; + } + } + +@@ -62,16 +62,16 @@ namespace { + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = { + // name offset bits flags +- { "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, +- { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, +- { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, +- { "fixup_sparc_hi22", 0, 22, 0 }, +- { "fixup_sparc_lo10", 0, 10, 0 }, +- { "fixup_sparc_h44", 0, 22, 0 }, +- { "fixup_sparc_m44", 0, 10, 0 }, +- { "fixup_sparc_l44", 0, 12, 0 }, +- { "fixup_sparc_hh", 0, 21, 0 }, +- { "fixup_sparc_hm", 0, 10, 0 }, ++ { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, ++ { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, ++ { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel }, ++ { "fixup_sparc_hi22", 10, 22, 0 }, ++ { "fixup_sparc_lo10", 22, 10, 0 }, ++ { "fixup_sparc_h44", 10, 22, 0 }, ++ { "fixup_sparc_m44", 22, 10, 0 }, ++ { "fixup_sparc_l44", 20, 12, 0 }, ++ { "fixup_sparc_hh", 10, 22, 0 }, ++ { "fixup_sparc_hm", 22, 10, 0 }, + }; + + if (Kind < FirstTargetFixupKind) +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +@@ -67,6 +67,37 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const + OS << ')'; + } + ++SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name) ++{ ++ return StringSwitch(name) ++ .Case("lo", VK_Sparc_LO) ++ .Case("hi", VK_Sparc_HI) ++ .Case("h44", VK_Sparc_H44) ++ .Case("m44", VK_Sparc_M44) ++ .Case("l44", VK_Sparc_L44) ++ .Case("hh", VK_Sparc_HH) ++ .Case("hm", VK_Sparc_HM) ++ .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22) ++ .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10) ++ .Case("tgd_add", VK_Sparc_TLS_GD_ADD) ++ .Case("tgd_call", VK_Sparc_TLS_GD_CALL) ++ .Case("tldm_hi22", VK_Sparc_TLS_LDM_HI22) ++ .Case("tldm_lo10", VK_Sparc_TLS_LDM_LO10) ++ .Case("tldm_add", VK_Sparc_TLS_LDM_ADD) ++ .Case("tldm_call", VK_Sparc_TLS_LDM_CALL) ++ .Case("tldo_hix22", VK_Sparc_TLS_LDO_HIX22) ++ .Case("tldo_lox10", VK_Sparc_TLS_LDO_LOX10) ++ .Case("tldo_add", VK_Sparc_TLS_LDO_ADD) ++ .Case("tie_hi22", VK_Sparc_TLS_IE_HI22) ++ .Case("tie_lo10", VK_Sparc_TLS_IE_LO10) ++ .Case("tie_ld", VK_Sparc_TLS_IE_LD) ++ .Case("tie_ldx", VK_Sparc_TLS_IE_LDX) ++ .Case("tie_add", VK_Sparc_TLS_IE_ADD) ++ .Case("tle_hix22", VK_Sparc_TLS_LE_HIX22) ++ .Case("tle_lox10", VK_Sparc_TLS_LE_LOX10) ++ .Default(VK_Sparc_None); ++} ++ + bool + SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const { +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +@@ -19,6 +19,7 @@ + + namespace llvm { + ++class StringRef; + class SparcMCExpr : public MCTargetExpr { + public: + enum VariantKind { +@@ -90,6 +91,7 @@ class SparcMCExpr : public MCTargetExpr { + + static bool classof(const SparcMCExpr *) { return true; } + ++ static VariantKind parseVariantKind(StringRef name); + + }; + +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -8,6 +8,7 @@ + //===----------------------------------------------------------------------===// + + #include "MCTargetDesc/SparcMCTargetDesc.h" ++#include "MCTargetDesc/SparcMCExpr.h" + #include "llvm/ADT/STLExtras.h" + #include "llvm/MC/MCContext.h" + #include "llvm/MC/MCInst.h" +@@ -68,6 +69,7 @@ class SparcAsmParser : public MCTargetAsmParser { + // returns true if Tok is matched to a register and returns register in RegNo. + bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP, + bool isQFP); ++ bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc); + + public: + SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, +@@ -536,15 +538,19 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand + unsigned RegNo; + if (matchRegisterName(Parser.getTok(), RegNo, false, false)) { + Parser.Lex(); // Eat the identifier token. ++ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E); + break; + } +- // FIXME: Handle modifiers like %hi, %lo etc., ++ if (matchSparcAsmModifiers(EVal, E)) { ++ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); ++ Op = SparcOperand::CreateImm(EVal, S, E); ++ } + break; + + case AsmToken::Minus: + case AsmToken::Integer: +- if (!getParser().parseExpression(EVal)) ++ if (!getParser().parseExpression(EVal, E)) + Op = SparcOperand::CreateImm(EVal, S, E); + break; + +@@ -551,13 +557,11 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand + case AsmToken::Identifier: { + StringRef Identifier; + if (!getParser().parseIdentifier(Identifier)) { +- SMLoc E = SMLoc::getFromPointer(Parser.getTok(). +- getLoc().getPointer() - 1); ++ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); + + const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, + getContext()); +- + Op = SparcOperand::CreateImm(Res, S, E); + } + break; +@@ -675,7 +679,33 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + } + + ++bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal, ++ SMLoc &EndLoc) ++{ ++ AsmToken Tok = Parser.getTok(); ++ if (!Tok.is(AsmToken::Identifier)) ++ return false; + ++ StringRef name = Tok.getString(); ++ ++ SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name); ++ ++ if (VK == SparcMCExpr::VK_Sparc_None) ++ return false; ++ ++ Parser.Lex(); // Eat the identifier. ++ if (Parser.getTok().getKind() != AsmToken::LParen) ++ return false; ++ ++ Parser.Lex(); // Eat the LParen token. ++ const MCExpr *subExpr; ++ if (Parser.parseParenExpression(subExpr, EndLoc)) ++ return false; ++ EVal = SparcMCExpr::Create(VK, subExpr, getContext()); ++ return true; ++} ++ ++ + extern "C" void LLVMInitializeSparcAsmParser() { + RegisterMCAsmParser A(TheSparcTarget); + RegisterMCAsmParser B(TheSparcV9Target); +Index: test/MC/Sparc/sparc-relocations.s +=================================================================== +--- test/MC/Sparc/sparc-relocations.s ++++ test/MC/Sparc/sparc-relocations.s +@@ -0,0 +1,33 @@ ++! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s ++ ++ ! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A] ++ ! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30 ++ call foo ++ ++ ! CHECK: or %g1, %lo(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A] ++ ! CHECK-NEXT ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 ++ or %g1, %lo(sym), %g3 ++ ++ ! CHECK: sethi %hi(sym), %l0 ! encoding: [0x21,0b00AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: %hi(sym), kind: fixup_sparc_hi22 ++ sethi %hi(sym), %l0 ++ ++ ! CHECK: sethi %h44(sym), %l0 ! encoding: [0x21,0b00AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: %h44(sym), kind: fixup_sparc_h44 ++ sethi %h44(sym), %l0 ++ ++ ! CHECK: or %g1, %m44(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A] ++ ! CHECK-NEXT ! fixup A - offset: 0, value: %m44(sym), kind: fixup_sparc_m44 ++ or %g1, %m44(sym), %g3 ++ ++ ! CHECK: or %g1, %l44(sym), %g3 ! encoding: [0x86,0x10,0b0110AAAA,A] ++ ! CHECK-NEXT ! fixup A - offset: 0, value: %l44(sym), kind: fixup_sparc_l44 ++ or %g1, %l44(sym), %g3 ++ ++ ! CHECK: sethi %hh(sym), %l0 ! encoding: [0x21,0b00AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: %hh(sym), kind: fixup_sparc_hh ++ sethi %hh(sym), %l0 ++ ++ ! CHECK: or %g1, %hm(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A] ++ ! CHECK-NEXT ! fixup A - offset: 0, value: %hm(sym), kind: fixup_sparc_hm ++ or %g1, %hm(sym), %g3 +Index: test/MC/Sparc/sparc-ctrl-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-ctrl-instructions.s ++++ test/MC/Sparc/sparc-ctrl-instructions.s +@@ -1,23 +1,33 @@ + ! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s + ! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s + +- ! CHECK: call foo ++ ! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A] ++ ! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30 + call foo + +- ! CHECK: call %g1+%i2 ++ ! CHECK: call %g1+%i2 ! encoding: [0x9f,0xc0,0x40,0x1a] + call %g1 + %i2 + +- ! CHECK: call %o1+8 ++ ! CHECK: call %o1+8 ! encoding: [0x9f,0xc2,0x60,0x08] + call %o1 + 8 + +- ! CHECK: call %g1 ++ ! CHECK: call %g1 ! encoding: [0x9f,0xc0,0x60,0x00] + call %g1 + +- ! CHECK: jmp %g1+%i2 ++ ! CHECK: call %g1+%lo(sym) ! encoding: [0x9f,0xc0,0b011000AA,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 ++ call %g1+%lo(sym) ++ ++ ! CHECK: jmp %g1+%i2 ! encoding: [0x81,0xc0,0x40,0x1a] + jmp %g1 + %i2 + +- ! CHECK: jmp %o1+8 ++ ! CHECK: jmp %o1+8 ! encoding: [0x81,0xc2,0x60,0x08] + jmp %o1 + 8 + +- ! CHECK: jmp %g1 ++ ! CHECK: jmp %g1 ! encoding: [0x81,0xc0,0x60,0x00] + jmp %g1 ++ ++ ! CHECK: jmp %g1+%lo(sym) ! encoding: [0x81,0xc0,0b011000AA,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 ++ jmp %g1+%lo(sym) ++ diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198738-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198738-sparc.diff new file mode 100644 index 000000000000..87637a7fc188 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198738-sparc.diff @@ -0,0 +1,734 @@ +Pull in r198738 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add support for parsing branch instructions and conditional moves. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/MC/Disassembler/Sparc/sparc.txt +=================================================================== +--- test/MC/Disassembler/Sparc/sparc.txt ++++ test/MC/Disassembler/Sparc/sparc.txt +@@ -80,3 +80,90 @@ + + # CHECK: subxcc %g1, %g2, %g3 + 0x86 0xe0 0x40 0x02 ++ ++# CHECK: ba 4194303 ++0x10 0xbf 0xff 0xff ++ ++# CHECK: bne 4194303 ++0x12 0xbf 0xff 0xff ++ ++# CHECK: be 4194303 ++0x02 0xbf 0xff 0xff ++ ++# CHECK: bg 4194303 ++0x14 0xbf 0xff 0xff ++ ++# CHECK: ble 4194303 ++0x04 0xbf 0xff 0xff ++ ++# CHECK: bge 4194303 ++0x16 0xbf 0xff 0xff ++ ++# CHECK: bl 4194303 ++0x06 0xbf 0xff 0xff ++ ++# CHECK: bgu 4194303 ++0x18 0xbf 0xff 0xff ++ ++# CHECK: bleu 4194303 ++0x08 0xbf 0xff 0xff ++ ++# CHECK: bcc 4194303 ++0x1a 0xbf 0xff 0xff ++ ++# CHECK: bcs 4194303 ++0x0a 0xbf 0xff 0xff ++ ++# CHECK: bpos 4194303 ++0x1c 0xbf 0xff 0xff ++ ++# CHECK: bneg 4194303 ++0x0c 0xbf 0xff 0xff ++ ++# CHECK: bvc 4194303 ++0x1e 0xbf 0xff 0xff ++ ++# CHECK: bvs 4194303 ++0x0e 0xbf 0xff 0xff ++ ++# CHECK: fbu 4194303 ++0x0f 0xbf 0xff 0xff ++ ++# CHECK: fbg 4194303 ++0x0d 0xbf 0xff 0xff ++ ++# CHECK: fbug 4194303 ++0x0b 0xbf 0xff 0xff ++ ++# CHECK: fbl 4194303 ++0x09 0xbf 0xff 0xff ++ ++# CHECK: fbul 4194303 ++0x07 0xbf 0xff 0xff ++ ++# CHECK: fblg 4194303 ++0x05 0xbf 0xff 0xff ++ ++# CHECK: fbne 4194303 ++0x03 0xbf 0xff 0xff ++ ++# CHECK: fbe 4194303 ++0x13 0xbf 0xff 0xff ++ ++# CHECK: fbue 4194303 ++0x15 0xbf 0xff 0xff ++ ++# CHECK: fbge 4194303 ++0x17 0xbf 0xff 0xff ++ ++# CHECK: fbuge 4194303 ++0x19 0xbf 0xff 0xff ++ ++# CHECK: fble 4194303 ++0x1b 0xbf 0xff 0xff ++ ++# CHECK: fbule 4194303 ++0x1d 0xbf 0xff 0xff ++ ++# CHECK: fbo 4194303 ++0x1f 0xbf 0xff 0xff +Index: test/MC/Sparc/sparc-ctrl-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-ctrl-instructions.s ++++ test/MC/Sparc/sparc-ctrl-instructions.s +@@ -31,3 +31,117 @@ + ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 + jmp %g1+%lo(sym) + ++ ! CHECK: ba .BB0 ! encoding: [0x10,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ ba .BB0 ++ ++ ! CHECK: bne .BB0 ! encoding: [0x12,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bne .BB0 ++ ++ ! CHECK: be .BB0 ! encoding: [0x02,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ be .BB0 ++ ++ ! CHECK: bg .BB0 ! encoding: [0x14,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bg .BB0 ++ ++ ! CHECK: ble .BB0 ! encoding: [0x04,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ ble .BB0 ++ ++ ! CHECK: bge .BB0 ! encoding: [0x16,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bge .BB0 ++ ++ ! CHECK: bl .BB0 ! encoding: [0x06,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bl .BB0 ++ ++ ! CHECK: bgu .BB0 ! encoding: [0x18,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bgu .BB0 ++ ++ ! CHECK: bleu .BB0 ! encoding: [0x08,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bleu .BB0 ++ ++ ! CHECK: bcc .BB0 ! encoding: [0x1a,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bcc .BB0 ++ ++ ! CHECK: bcs .BB0 ! encoding: [0x0a,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bcs .BB0 ++ ++ ! CHECK: bpos .BB0 ! encoding: [0x1c,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bpos .BB0 ++ ++ ! CHECK: bneg .BB0 ! encoding: [0x0c,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bneg .BB0 ++ ++ ! CHECK: bvc .BB0 ! encoding: [0x1e,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bvc .BB0 ++ ++ ! CHECK: bvs .BB0 ! encoding: [0x0e,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ bvs .BB0 ++ ++ ! CHECK: fbu .BB0 ! encoding: [0x0f,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbu .BB0 ++ ++ ! CHECK: fbg .BB0 ! encoding: [0x0d,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbg .BB0 ++ ! CHECK: fbug .BB0 ! encoding: [0x0b,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbug .BB0 ++ ++ ! CHECK: fbl .BB0 ! encoding: [0x09,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbl .BB0 ++ ++ ! CHECK: fbul .BB0 ! encoding: [0x07,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbul .BB0 ++ ++ ! CHECK: fblg .BB0 ! encoding: [0x05,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fblg .BB0 ++ ++ ! CHECK: fbne .BB0 ! encoding: [0x03,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbne .BB0 ++ ++ ! CHECK: fbe .BB0 ! encoding: [0x13,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbe .BB0 ++ ++ ! CHECK: fbue .BB0 ! encoding: [0x15,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbue .BB0 ++ ++ ! CHECK: fbge .BB0 ! encoding: [0x17,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbge .BB0 ++ ++ ! CHECK: fbuge .BB0 ! encoding: [0x19,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbuge .BB0 ++ ++ ! CHECK: fble .BB0 ! encoding: [0x1b,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fble .BB0 ++ ++ ! CHECK: fbule .BB0 ! encoding: [0x1d,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbule .BB0 ++ ++ ! CHECK: fbo .BB0 ! encoding: [0x1f,0b10AAAAAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 ++ fbo .BB0 +Index: test/MC/Sparc/sparc64-ctrl-instructions.s +=================================================================== +--- test/MC/Sparc/sparc64-ctrl-instructions.s ++++ test/MC/Sparc/sparc64-ctrl-instructions.s +@@ -0,0 +1,235 @@ ++! RUN: llvm-mc %s -triple=sparc64-unknown-linux-gnu -show-encoding | FileCheck %s ++ ++ ++ ! CHECK: bne %xcc, .BB0 ! encoding: [0x12,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bne %xcc, .BB0 ++ ++ ! CHECK: be %xcc, .BB0 ! encoding: [0x02,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ be %xcc, .BB0 ++ ++ ! CHECK: bg %xcc, .BB0 ! encoding: [0x14,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bg %xcc, .BB0 ++ ++ ! CHECK: ble %xcc, .BB0 ! encoding: [0x04,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ ble %xcc, .BB0 ++ ++ ! CHECK: bge %xcc, .BB0 ! encoding: [0x16,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bge %xcc, .BB0 ++ ++ ! CHECK: bl %xcc, .BB0 ! encoding: [0x06,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bl %xcc, .BB0 ++ ++ ! CHECK: bgu %xcc, .BB0 ! encoding: [0x18,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bgu %xcc, .BB0 ++ ++ ! CHECK: bleu %xcc, .BB0 ! encoding: [0x08,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bleu %xcc, .BB0 ++ ++ ! CHECK: bcc %xcc, .BB0 ! encoding: [0x1a,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bcc %xcc, .BB0 ++ ++ ! CHECK: bcs %xcc, .BB0 ! encoding: [0x0a,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bcs %xcc, .BB0 ++ ++ ! CHECK: bpos %xcc, .BB0 ! encoding: [0x1c,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bpos %xcc, .BB0 ++ ++ ! CHECK: bneg %xcc, .BB0 ! encoding: [0x0c,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bneg %xcc, .BB0 ++ ++ ! CHECK: bvc %xcc, .BB0 ! encoding: [0x1e,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bvc %xcc, .BB0 ++ ++ ! CHECK: bvs %xcc, .BB0 ! encoding: [0x0e,0b01101AAA,A,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 ++ bvs %xcc, .BB0 ++ ++ ++ ! CHECK: movne %icc, %g1, %g2 ! encoding: [0x85,0x66,0x40,0x01] ++ ! CHECK: move %icc, %g1, %g2 ! encoding: [0x85,0x64,0x40,0x01] ++ ! CHECK: movg %icc, %g1, %g2 ! encoding: [0x85,0x66,0x80,0x01] ++ ! CHECK: movle %icc, %g1, %g2 ! encoding: [0x85,0x64,0x80,0x01] ++ ! CHECK: movge %icc, %g1, %g2 ! encoding: [0x85,0x66,0xc0,0x01] ++ ! CHECK: movl %icc, %g1, %g2 ! encoding: [0x85,0x64,0xc0,0x01] ++ ! CHECK: movgu %icc, %g1, %g2 ! encoding: [0x85,0x67,0x00,0x01] ++ ! CHECK: movleu %icc, %g1, %g2 ! encoding: [0x85,0x65,0x00,0x01] ++ ! CHECK: movcc %icc, %g1, %g2 ! encoding: [0x85,0x67,0x40,0x01] ++ ! CHECK: movcs %icc, %g1, %g2 ! encoding: [0x85,0x65,0x40,0x01] ++ ! CHECK: movpos %icc, %g1, %g2 ! encoding: [0x85,0x67,0x80,0x01] ++ ! CHECK: movneg %icc, %g1, %g2 ! encoding: [0x85,0x65,0x80,0x01] ++ ! CHECK: movvc %icc, %g1, %g2 ! encoding: [0x85,0x67,0xc0,0x01] ++ ! CHECK: movvs %icc, %g1, %g2 ! encoding: [0x85,0x65,0xc0,0x01] ++ movne %icc, %g1, %g2 ++ move %icc, %g1, %g2 ++ movg %icc, %g1, %g2 ++ movle %icc, %g1, %g2 ++ movge %icc, %g1, %g2 ++ movl %icc, %g1, %g2 ++ movgu %icc, %g1, %g2 ++ movleu %icc, %g1, %g2 ++ movcc %icc, %g1, %g2 ++ movcs %icc, %g1, %g2 ++ movpos %icc, %g1, %g2 ++ movneg %icc, %g1, %g2 ++ movvc %icc, %g1, %g2 ++ movvs %icc, %g1, %g2 ++ ++ ! CHECK: movne %xcc, %g1, %g2 ! encoding: [0x85,0x66,0x50,0x01] ++ ! CHECK: move %xcc, %g1, %g2 ! encoding: [0x85,0x64,0x50,0x01] ++ ! CHECK: movg %xcc, %g1, %g2 ! encoding: [0x85,0x66,0x90,0x01] ++ ! CHECK: movle %xcc, %g1, %g2 ! encoding: [0x85,0x64,0x90,0x01] ++ ! CHECK: movge %xcc, %g1, %g2 ! encoding: [0x85,0x66,0xd0,0x01] ++ ! CHECK: movl %xcc, %g1, %g2 ! encoding: [0x85,0x64,0xd0,0x01] ++ ! CHECK: movgu %xcc, %g1, %g2 ! encoding: [0x85,0x67,0x10,0x01] ++ ! CHECK: movleu %xcc, %g1, %g2 ! encoding: [0x85,0x65,0x10,0x01] ++ ! CHECK: movcc %xcc, %g1, %g2 ! encoding: [0x85,0x67,0x50,0x01] ++ ! CHECK: movcs %xcc, %g1, %g2 ! encoding: [0x85,0x65,0x50,0x01] ++ ! CHECK: movpos %xcc, %g1, %g2 ! encoding: [0x85,0x67,0x90,0x01] ++ ! CHECK: movneg %xcc, %g1, %g2 ! encoding: [0x85,0x65,0x90,0x01] ++ ! CHECK: movvc %xcc, %g1, %g2 ! encoding: [0x85,0x67,0xd0,0x01] ++ ! CHECK: movvs %xcc, %g1, %g2 ! encoding: [0x85,0x65,0xd0,0x01] ++ movne %xcc, %g1, %g2 ++ move %xcc, %g1, %g2 ++ movg %xcc, %g1, %g2 ++ movle %xcc, %g1, %g2 ++ movge %xcc, %g1, %g2 ++ movl %xcc, %g1, %g2 ++ movgu %xcc, %g1, %g2 ++ movleu %xcc, %g1, %g2 ++ movcc %xcc, %g1, %g2 ++ movcs %xcc, %g1, %g2 ++ movpos %xcc, %g1, %g2 ++ movneg %xcc, %g1, %g2 ++ movvc %xcc, %g1, %g2 ++ movvs %xcc, %g1, %g2 ++ ++ ! CHECK: movu %fcc0, %g1, %g2 ! encoding: [0x85,0x61,0xc0,0x01] ++ ! CHECK: movg %fcc0, %g1, %g2 ! encoding: [0x85,0x61,0x80,0x01] ++ ! CHECK: movug %fcc0, %g1, %g2 ! encoding: [0x85,0x61,0x40,0x01] ++ ! CHECK: movl %fcc0, %g1, %g2 ! encoding: [0x85,0x61,0x00,0x01] ++ ! CHECK: movul %fcc0, %g1, %g2 ! encoding: [0x85,0x60,0xc0,0x01] ++ ! CHECK: movlg %fcc0, %g1, %g2 ! encoding: [0x85,0x60,0x80,0x01] ++ ! CHECK: movne %fcc0, %g1, %g2 ! encoding: [0x85,0x60,0x40,0x01] ++ ! CHECK: move %fcc0, %g1, %g2 ! encoding: [0x85,0x62,0x40,0x01] ++ ! CHECK: movue %fcc0, %g1, %g2 ! encoding: [0x85,0x62,0x80,0x01] ++ ! CHECK: movge %fcc0, %g1, %g2 ! encoding: [0x85,0x62,0xc0,0x01] ++ ! CHECK: movuge %fcc0, %g1, %g2 ! encoding: [0x85,0x63,0x00,0x01] ++ ! CHECK: movle %fcc0, %g1, %g2 ! encoding: [0x85,0x63,0x40,0x01] ++ ! CHECK: movule %fcc0, %g1, %g2 ! encoding: [0x85,0x63,0x80,0x01] ++ ! CHECK: movo %fcc0, %g1, %g2 ! encoding: [0x85,0x63,0xc0,0x01] ++ movu %fcc0, %g1, %g2 ++ movg %fcc0, %g1, %g2 ++ movug %fcc0, %g1, %g2 ++ movl %fcc0, %g1, %g2 ++ movul %fcc0, %g1, %g2 ++ movlg %fcc0, %g1, %g2 ++ movne %fcc0, %g1, %g2 ++ move %fcc0, %g1, %g2 ++ movue %fcc0, %g1, %g2 ++ movge %fcc0, %g1, %g2 ++ movuge %fcc0, %g1, %g2 ++ movle %fcc0, %g1, %g2 ++ movule %fcc0, %g1, %g2 ++ movo %fcc0, %g1, %g2 ++ ++ ++ ! CHECK fmovsne %icc, %f1, %f2 ! encoding: [0x85,0xaa,0x60,0x21] ++ ! CHECK fmovse %icc, %f1, %f2 ! encoding: [0x85,0xa8,0x60,0x21] ++ ! CHECK fmovsg %icc, %f1, %f2 ! encoding: [0x85,0xaa,0xa0,0x21] ++ ! CHECK fmovsle %icc, %f1, %f2 ! encoding: [0x85,0xa8,0xa0,0x21] ++ ! CHECK fmovsge %icc, %f1, %f2 ! encoding: [0x85,0xaa,0xe0,0x21] ++ ! CHECK fmovsl %icc, %f1, %f2 ! encoding: [0x85,0xa8,0xe0,0x21] ++ ! CHECK fmovsgu %icc, %f1, %f2 ! encoding: [0x85,0xab,0x20,0x21] ++ ! CHECK fmovsleu %icc, %f1, %f2 ! encoding: [0x85,0xa9,0x20,0x21] ++ ! CHECK fmovscc %icc, %f1, %f2 ! encoding: [0x85,0xab,0x60,0x21] ++ ! CHECK fmovscs %icc, %f1, %f2 ! encoding: [0x85,0xa9,0x60,0x21] ++ ! CHECK fmovspos %icc, %f1, %f2 ! encoding: [0x85,0xab,0xa0,0x21] ++ ! CHECK fmovsneg %icc, %f1, %f2 ! encoding: [0x85,0xa9,0xa0,0x21] ++ ! CHECK fmovsvc %icc, %f1, %f2 ! encoding: [0x85,0xab,0xe0,0x21] ++ ! CHECK fmovsvs %icc, %f1, %f2 ! encoding: [0x85,0xa9,0xe0,0x21] ++ fmovsne %icc, %f1, %f2 ++ fmovse %icc, %f1, %f2 ++ fmovsg %icc, %f1, %f2 ++ fmovsle %icc, %f1, %f2 ++ fmovsge %icc, %f1, %f2 ++ fmovsl %icc, %f1, %f2 ++ fmovsgu %icc, %f1, %f2 ++ fmovsleu %icc, %f1, %f2 ++ fmovscc %icc, %f1, %f2 ++ fmovscs %icc, %f1, %f2 ++ fmovspos %icc, %f1, %f2 ++ fmovsneg %icc, %f1, %f2 ++ fmovsvc %icc, %f1, %f2 ++ fmovsvs %icc, %f1, %f2 ++ ++ ! CHECK fmovsne %xcc, %f1, %f2 ! encoding: [0x85,0xaa,0x70,0x21] ++ ! CHECK fmovse %xcc, %f1, %f2 ! encoding: [0x85,0xa8,0x70,0x21] ++ ! CHECK fmovsg %xcc, %f1, %f2 ! encoding: [0x85,0xaa,0xb0,0x21] ++ ! CHECK fmovsle %xcc, %f1, %f2 ! encoding: [0x85,0xa8,0xb0,0x21] ++ ! CHECK fmovsge %xcc, %f1, %f2 ! encoding: [0x85,0xaa,0xf0,0x21] ++ ! CHECK fmovsl %xcc, %f1, %f2 ! encoding: [0x85,0xa8,0xf0,0x21] ++ ! CHECK fmovsgu %xcc, %f1, %f2 ! encoding: [0x85,0xab,0x30,0x21] ++ ! CHECK fmovsleu %xcc, %f1, %f2 ! encoding: [0x85,0xa9,0x30,0x21] ++ ! CHECK fmovscc %xcc, %f1, %f2 ! encoding: [0x85,0xab,0x70,0x21] ++ ! CHECK fmovscs %xcc, %f1, %f2 ! encoding: [0x85,0xa9,0x70,0x21] ++ ! CHECK fmovspos %xcc, %f1, %f2 ! encoding: [0x85,0xab,0xb0,0x21] ++ ! CHECK fmovsneg %xcc, %f1, %f2 ! encoding: [0x85,0xa9,0xb0,0x21] ++ ! CHECK fmovsvc %xcc, %f1, %f2 ! encoding: [0x85,0xab,0xf0,0x21] ++ ! CHECK fmovsvs %xcc, %f1, %f2 ! encoding: [0x85,0xa9,0xf0,0x21] ++ fmovsne %xcc, %f1, %f2 ++ fmovse %xcc, %f1, %f2 ++ fmovsg %xcc, %f1, %f2 ++ fmovsle %xcc, %f1, %f2 ++ fmovsge %xcc, %f1, %f2 ++ fmovsl %xcc, %f1, %f2 ++ fmovsgu %xcc, %f1, %f2 ++ fmovsleu %xcc, %f1, %f2 ++ fmovscc %xcc, %f1, %f2 ++ fmovscs %xcc, %f1, %f2 ++ fmovspos %xcc, %f1, %f2 ++ fmovsneg %xcc, %f1, %f2 ++ fmovsvc %xcc, %f1, %f2 ++ fmovsvs %xcc, %f1, %f2 ++ ++ ! CHECK fmovsu %fcc0, %f1, %f2 ! encoding: [0x85,0xa9,0xc0,0x21] ++ ! CHECK fmovsg %fcc0, %f1, %f2 ! encoding: [0x85,0xa9,0x80,0x21] ++ ! CHECK fmovsug %fcc0, %f1, %f2 ! encoding: [0x85,0xa9,0x40,0x21] ++ ! CHECK fmovsl %fcc0, %f1, %f2 ! encoding: [0x85,0xa9,0x00,0x21] ++ ! CHECK fmovsul %fcc0, %f1, %f2 ! encoding: [0x85,0xa8,0xc0,0x21] ++ ! CHECK fmovslg %fcc0, %f1, %f2 ! encoding: [0x85,0xa8,0x80,0x21] ++ ! CHECK fmovsne %fcc0, %f1, %f2 ! encoding: [0x85,0xa8,0x40,0x21] ++ ! CHECK fmovse %fcc0, %f1, %f2 ! encoding: [0x85,0xaa,0x40,0x21] ++ ! CHECK fmovsue %fcc0, %f1, %f2 ! encoding: [0x85,0xaa,0x80,0x21] ++ ! CHECK fmovsge %fcc0, %f1, %f2 ! encoding: [0x85,0xaa,0xc0,0x21] ++ ! CHECK fmovsuge %fcc0, %f1, %f2 ! encoding: [0x85,0xab,0x00,0x21] ++ ! CHECK fmovsle %fcc0, %f1, %f2 ! encoding: [0x85,0xab,0x40,0x21] ++ ! CHECK fmovsule %fcc0, %f1, %f2 ! encoding: [0x85,0xab,0x80,0x21] ++ ! CHECK fmovso %fcc0, %f1, %f2 ! encoding: [0x85,0xab,0xc0,0x21] ++ fmovsu %fcc0, %f1, %f2 ++ fmovsg %fcc0, %f1, %f2 ++ fmovsug %fcc0, %f1, %f2 ++ fmovsl %fcc0, %f1, %f2 ++ fmovsul %fcc0, %f1, %f2 ++ fmovslg %fcc0, %f1, %f2 ++ fmovsne %fcc0, %f1, %f2 ++ fmovse %fcc0, %f1, %f2 ++ fmovsue %fcc0, %f1, %f2 ++ fmovsge %fcc0, %f1, %f2 ++ fmovsuge %fcc0, %f1, %f2 ++ fmovsle %fcc0, %f1, %f2 ++ fmovsule %fcc0, %f1, %f2 ++ fmovso %fcc0, %f1, %f2 ++ +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -333,32 +333,42 @@ class XBranchSP + let Predicates = [Is64Bit] in { + + let Uses = [ICC] in +-def BPXCC : XBranchSP<(ins brtarget:$imm22, CCOp:$cond), +- "b$cond %xcc, $imm22", +- [(SPbrxcc bb:$imm22, imm:$cond)]>; ++def BPXCC : XBranchSP<(ins brtarget:$imm19, CCOp:$cond), ++ "b$cond %xcc, $imm19", ++ [(SPbrxcc bb:$imm19, imm:$cond)]>; + + // Conditional moves on %xcc. + let Uses = [ICC], Constraints = "$f = $rd" in { +-def MOVXCCrr : Pseudo<(outs IntRegs:$rd), ++let cc = 0b110 in { ++def MOVXCCrr : F4_1<0b101100, (outs IntRegs:$rd), + (ins IntRegs:$rs2, IntRegs:$f, CCOp:$cond), + "mov$cond %xcc, $rs2, $rd", + [(set i32:$rd, + (SPselectxcc i32:$rs2, i32:$f, imm:$cond))]>; +-def MOVXCCri : Pseudo<(outs IntRegs:$rd), +- (ins i32imm:$i, IntRegs:$f, CCOp:$cond), +- "mov$cond %xcc, $i, $rd", ++def MOVXCCri : F4_2<0b101100, (outs IntRegs:$rd), ++ (ins i32imm:$simm11, IntRegs:$f, CCOp:$cond), ++ "mov$cond %xcc, $simm11, $rd", + [(set i32:$rd, +- (SPselectxcc simm11:$i, i32:$f, imm:$cond))]>; +-def FMOVS_XCC : Pseudo<(outs FPRegs:$rd), ++ (SPselectxcc simm11:$simm11, i32:$f, imm:$cond))]>; ++} // cc ++ ++let opf_cc = 0b110 in { ++def FMOVS_XCC : F4_3<0b110101, 0b000001, (outs FPRegs:$rd), + (ins FPRegs:$rs2, FPRegs:$f, CCOp:$cond), + "fmovs$cond %xcc, $rs2, $rd", + [(set f32:$rd, + (SPselectxcc f32:$rs2, f32:$f, imm:$cond))]>; +-def FMOVD_XCC : Pseudo<(outs DFPRegs:$rd), ++def FMOVD_XCC : F4_3<0b110101, 0b000010, (outs DFPRegs:$rd), + (ins DFPRegs:$rs2, DFPRegs:$f, CCOp:$cond), + "fmovd$cond %xcc, $rs2, $rd", + [(set f64:$rd, + (SPselectxcc f64:$rs2, f64:$f, imm:$cond))]>; ++def FMOVQ_XCC : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd), ++ (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond), ++ "fmovq$cond %xcc, $rs2, $rd", ++ [(set f128:$rd, ++ (SPselectxcc f128:$rs2, f128:$f, imm:$cond))]>; ++} // opf_cc + } // Uses, Constraints + + //===----------------------------------------------------------------------===// +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -928,8 +928,9 @@ let Predicates = [HasV9], Constraints = "$f = $rd" + def FMOVQ_ICC + : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd), + (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond), +- "fmovd$cond %icc, $rs2, $rd", +- [(set f128:$rd, (SPselecticc f128:$rs2, f128:$f, imm:$cond))]>; ++ "fmovq$cond %icc, $rs2, $rd", ++ [(set f128:$rd, (SPselecticc f128:$rs2, f128:$f, imm:$cond))]>, ++ Requires<[HasHardQuad]>; + } + + let Uses = [FCC], opf_cc = 0b000 in { +@@ -946,8 +947,9 @@ let Predicates = [HasV9], Constraints = "$f = $rd" + def FMOVQ_FCC + : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd), + (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond), +- "fmovd$cond %fcc0, $rs2, $rd", +- [(set f128:$rd, (SPselectfcc f128:$rs2, f128:$f, imm:$cond))]>; ++ "fmovq$cond %fcc0, $rs2, $rd", ++ [(set f128:$rd, (SPselectfcc f128:$rs2, f128:$f, imm:$cond))]>, ++ Requires<[HasHardQuad]>; + } + + } +@@ -1092,3 +1094,4 @@ def : Pat<(atomic_store ADDRri:$dst, i32:$val), (S + + + include "SparcInstr64Bit.td" ++include "SparcInstrAliases.td" +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -537,9 +537,29 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand + Parser.Lex(); // Eat the '%'. + unsigned RegNo; + if (matchRegisterName(Parser.getTok(), RegNo, false, false)) { ++ StringRef name = Parser.getTok().getString(); + Parser.Lex(); // Eat the identifier token. + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); +- Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E); ++ switch (RegNo) { ++ default: ++ Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E); ++ break; ++ case Sparc::Y: ++ Op = SparcOperand::CreateToken("%y", S); ++ break; ++ ++ case Sparc::ICC: ++ if (name == "xcc") ++ Op = SparcOperand::CreateToken("%xcc", S); ++ else ++ Op = SparcOperand::CreateToken("%icc", S); ++ break; ++ ++ case Sparc::FCC: ++ assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet"); ++ Op = SparcOperand::CreateToken("%fcc0", S); ++ break; ++ } + break; + } + if (matchSparcAsmModifiers(EVal, E)) { +Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +=================================================================== +--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp ++++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +@@ -83,6 +83,17 @@ void SparcInstPrinter::printCCOperand(const MCInst + raw_ostream &O) + { + int CC = (int)MI->getOperand(opNum).getImm(); ++ switch (MI->getOpcode()) { ++ default: break; ++ case SP::FBCOND: ++ case SP::MOVFCCrr: ++ case SP::MOVFCCri: ++ case SP::FMOVS_FCC: ++ case SP::FMOVD_FCC: ++ case SP::FMOVQ_FCC: // Make sure CC is a fp conditional flag. ++ CC = (CC < 16) ? (CC + 16) : CC; ++ break; ++ } + O << SPARCCondCodeToString((SPCC::CondCodes)CC); + } + +Index: lib/Target/Sparc/SparcInstrAliases.td +=================================================================== +--- lib/Target/Sparc/SparcInstrAliases.td ++++ lib/Target/Sparc/SparcInstrAliases.td +@@ -0,0 +1,119 @@ ++//===-- SparcInstrAliases.td - Instruction Aliases for Sparc Target -------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file contains instruction aliases for Sparc. ++//===----------------------------------------------------------------------===// ++ ++// Instruction aliases for conditional moves. ++ ++// mov rs2, rd ++multiclass cond_mov_alias { ++ ++ // mov (%icc|%xcc|%fcc0), rs2, rd ++ def : InstAlias; ++ ++ // mov (%icc|%xcc|%fcc0), simm11, rd ++ def : InstAlias; ++ ++ // fmovs (%icc|%xcc|%fcc0), $rs2, $rd ++ def : InstAlias; ++ ++ // fmovd (%icc|%xcc|%fcc0), $rs2, $rd ++ def : InstAlias; ++} ++ ++ ++// Instruction aliases for integer conditional branches and moves. ++multiclass int_cond_alias { ++ ++ // b $imm ++ def : InstAlias; ++ ++ // b %xcc, $imm ++ def : InstAlias, Requires<[Is64Bit]>; ++ ++ defm : cond_mov_alias, Requires<[HasV9]>; ++ ++ defm : cond_mov_alias, Requires<[Is64Bit]>; ++ ++ // fmovq (%icc|%xcc), $rs2, $rd ++ def : InstAlias, ++ Requires<[HasV9, HasHardQuad]>; ++ def : InstAlias, ++ Requires<[Is64Bit, HasHardQuad]>; ++ ++} ++ ++ ++// Instruction aliases for floating point conditional branches and moves. ++multiclass fp_cond_alias { ++ ++ // fb $imm ++ def : InstAlias; ++ ++ defm : cond_mov_alias, Requires<[HasV9]>; ++ ++ // fmovq %fcc0, $rs2, $rd ++ def : InstAlias, ++ Requires<[HasV9, HasHardQuad]>; ++} ++ ++defm : int_cond_alias<"a", 0b1000>; ++defm : int_cond_alias<"n", 0b0000>; ++defm : int_cond_alias<"ne", 0b1001>; ++defm : int_cond_alias<"e", 0b0001>; ++defm : int_cond_alias<"g", 0b1010>; ++defm : int_cond_alias<"le", 0b0010>; ++defm : int_cond_alias<"ge", 0b1011>; ++defm : int_cond_alias<"l", 0b0011>; ++defm : int_cond_alias<"gu", 0b1100>; ++defm : int_cond_alias<"leu", 0b0100>; ++defm : int_cond_alias<"cc", 0b1101>; ++defm : int_cond_alias<"cs", 0b0101>; ++defm : int_cond_alias<"pos", 0b1110>; ++defm : int_cond_alias<"neg", 0b0110>; ++defm : int_cond_alias<"vc", 0b1111>; ++defm : int_cond_alias<"vs", 0b0111>; ++ ++defm : fp_cond_alias<"u", 0b0111>; ++defm : fp_cond_alias<"g", 0b0110>; ++defm : fp_cond_alias<"ug", 0b0101>; ++defm : fp_cond_alias<"l", 0b0100>; ++defm : fp_cond_alias<"ul", 0b0011>; ++defm : fp_cond_alias<"lg", 0b0010>; ++defm : fp_cond_alias<"ne", 0b0001>; ++defm : fp_cond_alias<"e", 0b1001>; ++defm : fp_cond_alias<"ue", 0b1010>; ++defm : fp_cond_alias<"ge", 0b1011>; ++defm : fp_cond_alias<"uge", 0b1100>; ++defm : fp_cond_alias<"le", 0b1101>; ++defm : fp_cond_alias<"ule", 0b1110>; ++defm : fp_cond_alias<"o", 0b1111>; diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198739-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198739-sparc.diff new file mode 100644 index 000000000000..f7b884c5540e --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198739-sparc.diff @@ -0,0 +1,19 @@ +Pull in r198739 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Correct the mask for fixup_sparc_br19. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +@@ -31,7 +31,7 @@ static unsigned adjustFixupValue(unsigned Kind, ui + case Sparc::fixup_sparc_br22: + return (Value >> 2) & 0x3fffff; + case Sparc::fixup_sparc_br19: +- return (Value >> 2) & 0x1ffff; ++ return (Value >> 2) & 0x7ffff; + case Sparc::fixup_sparc_hi22: + return (Value >> 10) & 0x3fffff; + case Sparc::fixup_sparc_lo10: diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198740-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198740-sparc.diff new file mode 100644 index 000000000000..ff9bfd5948bb --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198740-sparc.diff @@ -0,0 +1,115 @@ +Pull in r198740 from upstream llvm trunk (by Venkatraman Govindaraju): + + [SparcV9] Rename operands in some sparc64 instructions so that TableGen can encode them correctly. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/MC/Sparc/sparc64-alu-instructions.s +=================================================================== +--- test/MC/Sparc/sparc64-alu-instructions.s ++++ test/MC/Sparc/sparc64-alu-instructions.s +@@ -0,0 +1,38 @@ ++! RUN: llvm-mc %s -triple=sparc64-unknown-linux-gnu -show-encoding | FileCheck %s ++ ++ ! CHECK: sllx %g1, %i2, %i0 ! encoding: [0xb1,0x28,0x50,0x1a] ++ sllx %g1, %i2, %i0 ++ ++ ! CHECK: sllx %g1, 63, %i0 ! encoding: [0xb1,0x28,0x70,0x3f] ++ sllx %g1, 63, %i0 ++ ++ ! CHECK: srlx %g1, %i2, %i0 ! encoding: [0xb1,0x30,0x50,0x1a] ++ srlx %g1, %i2, %i0 ++ ++ ! CHECK: srlx %g1, 63, %i0 ! encoding: [0xb1,0x30,0x70,0x3f] ++ srlx %g1, 63, %i0 ++ ++ ! CHECK: srax %g1, %i2, %i0 ! encoding: [0xb1,0x38,0x50,0x1a] ++ srax %g1, %i2, %i0 ++ ++ ! CHECK: srax %g1, 63, %i0 ! encoding: [0xb1,0x38,0x70,0x3f] ++ srax %g1, 63, %i0 ++ ++ ! CHECK: mulx %g1, %i2, %i0 ! encoding: [0xb0,0x48,0x40,0x1a] ++ mulx %g1, %i2, %i0 ++ ++ ! CHECK: mulx %g1, 63, %i0 ! encoding: [0xb0,0x48,0x60,0x3f] ++ mulx %g1, 63, %i0 ++ ++ ! CHECK: sdivx %g1, %i2, %i0 ! encoding: [0xb1,0x68,0x40,0x1a] ++ sdivx %g1, %i2, %i0 ++ ++ ! CHECK: sdivx %g1, 63, %i0 ! encoding: [0xb1,0x68,0x60,0x3f] ++ sdivx %g1, 63, %i0 ++ ++ ! CHECK: udivx %g1, %i2, %i0 ! encoding: [0xb0,0x68,0x40,0x1a] ++ udivx %g1, %i2, %i0 ++ ++ ! CHECK: udivx %g1, 63, %i0 ! encoding: [0xb0,0x68,0x60,0x3f] ++ udivx %g1, 63, %i0 ++ +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -193,9 +193,9 @@ def MULXrr : F3_1<2, 0b001001, + "mulx $rs1, $rs2, $rd", + [(set i64:$rd, (mul i64:$rs1, i64:$rs2))]>; + def MULXri : F3_2<2, 0b001001, +- (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$i), +- "mulx $rs1, $i, $rd", +- [(set i64:$rd, (mul i64:$rs1, (i64 simm13:$i)))]>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13), ++ "mulx $rs1, $simm13, $rd", ++ [(set i64:$rd, (mul i64:$rs1, (i64 simm13:$simm13)))]>; + + // Division can trap. + let hasSideEffects = 1 in { +@@ -204,9 +204,9 @@ def SDIVXrr : F3_1<2, 0b101101, + "sdivx $rs1, $rs2, $rd", + [(set i64:$rd, (sdiv i64:$rs1, i64:$rs2))]>; + def SDIVXri : F3_2<2, 0b101101, +- (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$i), +- "sdivx $rs1, $i, $rd", +- [(set i64:$rd, (sdiv i64:$rs1, (i64 simm13:$i)))]>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13), ++ "sdivx $rs1, $simm13, $rd", ++ [(set i64:$rd, (sdiv i64:$rs1, (i64 simm13:$simm13)))]>; + + def UDIVXrr : F3_1<2, 0b001101, + (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2), +@@ -213,9 +213,9 @@ def UDIVXrr : F3_1<2, 0b001101, + "udivx $rs1, $rs2, $rd", + [(set i64:$rd, (udiv i64:$rs1, i64:$rs2))]>; + def UDIVXri : F3_2<2, 0b001101, +- (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$i), +- "udivx $rs1, $i, $rd", +- [(set i64:$rd, (udiv i64:$rs1, (i64 simm13:$i)))]>; ++ (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13), ++ "udivx $rs1, $simm13, $rd", ++ [(set i64:$rd, (udiv i64:$rs1, (i64 simm13:$simm13)))]>; + } // hasSideEffects = 1 + + } // Predicates = [Is64Bit] +Index: lib/Target/Sparc/SparcInstrFormats.td +=================================================================== +--- lib/Target/Sparc/SparcInstrFormats.td ++++ lib/Target/Sparc/SparcInstrFormats.td +@@ -193,12 +193,12 @@ class F3_Si opVal, bits<6> op3val, bit xVa + // Define rr and ri shift instructions with patterns. + multiclass F3_S Op3Val, bit XVal, SDNode OpNode, + ValueType VT, RegisterClass RC> { +- def rr : F3_Sr<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs, IntRegs:$rs2), +- !strconcat(OpcStr, " $rs, $rs2, $rd"), +- [(set VT:$rd, (OpNode VT:$rs, i32:$rs2))]>; +- def ri : F3_Si<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs, i32imm:$shcnt), +- !strconcat(OpcStr, " $rs, $shcnt, $rd"), +- [(set VT:$rd, (OpNode VT:$rs, (i32 imm:$shcnt)))]>; ++ def rr : F3_Sr<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs1, IntRegs:$rs2), ++ !strconcat(OpcStr, " $rs1, $rs2, $rd"), ++ [(set VT:$rd, (OpNode VT:$rs1, i32:$rs2))]>; ++ def ri : F3_Si<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs1, i32imm:$shcnt), ++ !strconcat(OpcStr, " $rs1, $shcnt, $rd"), ++ [(set VT:$rd, (OpNode VT:$rs1, (i32 imm:$shcnt)))]>; + } + + class F4 op3, dag outs, dag ins, string asmstr, list pattern> diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198893-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198893-sparc.diff new file mode 100644 index 000000000000..a1434c0a05c7 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198893-sparc.diff @@ -0,0 +1,236 @@ +Pull in r198893 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Multiclass for loads/stores. No functionality change intended. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -235,14 +235,8 @@ def UDIVXri : F3_2<2, 0b001101, + let Predicates = [Is64Bit] in { + + // 64-bit loads. +-def LDXrr : F3_1<3, 0b001011, +- (outs I64Regs:$dst), (ins MEMrr:$addr), +- "ldx [$addr], $dst", +- [(set i64:$dst, (load ADDRrr:$addr))]>; +-def LDXri : F3_2<3, 0b001011, +- (outs I64Regs:$dst), (ins MEMri:$addr), +- "ldx [$addr], $dst", +- [(set i64:$dst, (load ADDRri:$addr))]>; ++defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>; ++ + let mayLoad = 1, isCodeGenOnly = 1, isAsmParserOnly = 1 in + def TLS_LDXrr : F3_1<3, 0b001011, + (outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym), +@@ -276,24 +270,10 @@ def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr + def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>; + + // Sign-extending load of i32 into i64 is a new SPARC v9 instruction. +-def LDSWrr : F3_1<3, 0b001000, +- (outs I64Regs:$dst), (ins MEMrr:$addr), +- "ldsw [$addr], $dst", +- [(set i64:$dst, (sextloadi32 ADDRrr:$addr))]>; +-def LDSWri : F3_2<3, 0b001000, +- (outs I64Regs:$dst), (ins MEMri:$addr), +- "ldsw [$addr], $dst", +- [(set i64:$dst, (sextloadi32 ADDRri:$addr))]>; ++defm LDSW : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>; + + // 64-bit stores. +-def STXrr : F3_1<3, 0b001110, +- (outs), (ins MEMrr:$addr, I64Regs:$rd), +- "stx $rd, [$addr]", +- [(store i64:$rd, ADDRrr:$addr)]>; +-def STXri : F3_2<3, 0b001110, +- (outs), (ins MEMri:$addr, I64Regs:$rd), +- "stx $rd, [$addr]", +- [(store i64:$rd, ADDRri:$addr)]>; ++defm STX : Store<"stx", 0b001110, store, I64Regs, i64>; + + // Truncating stores from i64 are identical to the i32 stores. + def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>; +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -250,6 +250,32 @@ multiclass F3_12np Op3Val> + !strconcat(OpcStr, " $rs1, $simm13, $rd"), []>; + } + ++// Load multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot. ++multiclass Load Op3Val, SDPatternOperator OpNode, ++ RegisterClass RC, ValueType Ty> { ++ def rr : F3_1<3, Op3Val, ++ (outs RC:$dst), (ins MEMrr:$addr), ++ !strconcat(OpcStr, " [$addr], $dst"), ++ [(set Ty:$dst, (OpNode ADDRrr:$addr))]>; ++ def ri : F3_2<3, Op3Val, ++ (outs RC:$dst), (ins MEMri:$addr), ++ !strconcat(OpcStr, " [$addr], $dst"), ++ [(set Ty:$dst, (OpNode ADDRri:$addr))]>; ++} ++ ++// Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot. ++multiclass Store Op3Val, SDPatternOperator OpNode, ++ RegisterClass RC, ValueType Ty> { ++ def rr : F3_1<3, Op3Val, ++ (outs), (ins MEMrr:$addr, RC:$rd), ++ !strconcat(OpcStr, " $rd, [$addr]"), ++ [(OpNode Ty:$rd, ADDRrr:$addr)]>; ++ def ri : F3_2<3, Op3Val, ++ (outs), (ins MEMri:$addr, RC:$rd), ++ !strconcat(OpcStr, " $rd, [$addr]"), ++ [(OpNode Ty:$rd, ADDRri:$addr)]>; ++} ++ + //===----------------------------------------------------------------------===// + // Instructions + //===----------------------------------------------------------------------===// +@@ -350,128 +376,28 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot = + } + + // Section B.1 - Load Integer Instructions, p. 90 +-def LDSBrr : F3_1<3, 0b001001, +- (outs IntRegs:$dst), (ins MEMrr:$addr), +- "ldsb [$addr], $dst", +- [(set i32:$dst, (sextloadi8 ADDRrr:$addr))]>; +-def LDSBri : F3_2<3, 0b001001, +- (outs IntRegs:$dst), (ins MEMri:$addr), +- "ldsb [$addr], $dst", +- [(set i32:$dst, (sextloadi8 ADDRri:$addr))]>; +-def LDSHrr : F3_1<3, 0b001010, +- (outs IntRegs:$dst), (ins MEMrr:$addr), +- "ldsh [$addr], $dst", +- [(set i32:$dst, (sextloadi16 ADDRrr:$addr))]>; +-def LDSHri : F3_2<3, 0b001010, +- (outs IntRegs:$dst), (ins MEMri:$addr), +- "ldsh [$addr], $dst", +- [(set i32:$dst, (sextloadi16 ADDRri:$addr))]>; +-def LDUBrr : F3_1<3, 0b000001, +- (outs IntRegs:$dst), (ins MEMrr:$addr), +- "ldub [$addr], $dst", +- [(set i32:$dst, (zextloadi8 ADDRrr:$addr))]>; +-def LDUBri : F3_2<3, 0b000001, +- (outs IntRegs:$dst), (ins MEMri:$addr), +- "ldub [$addr], $dst", +- [(set i32:$dst, (zextloadi8 ADDRri:$addr))]>; +-def LDUHrr : F3_1<3, 0b000010, +- (outs IntRegs:$dst), (ins MEMrr:$addr), +- "lduh [$addr], $dst", +- [(set i32:$dst, (zextloadi16 ADDRrr:$addr))]>; +-def LDUHri : F3_2<3, 0b000010, +- (outs IntRegs:$dst), (ins MEMri:$addr), +- "lduh [$addr], $dst", +- [(set i32:$dst, (zextloadi16 ADDRri:$addr))]>; +-def LDrr : F3_1<3, 0b000000, +- (outs IntRegs:$dst), (ins MEMrr:$addr), +- "ld [$addr], $dst", +- [(set i32:$dst, (load ADDRrr:$addr))]>; +-def LDri : F3_2<3, 0b000000, +- (outs IntRegs:$dst), (ins MEMri:$addr), +- "ld [$addr], $dst", +- [(set i32:$dst, (load ADDRri:$addr))]>; ++defm LDSB : Load<"ldsb", 0b001001, sextloadi8, IntRegs, i32>; ++defm LDSH : Load<"ldsh", 0b001010, sextloadi16, IntRegs, i32>; ++defm LDUB : Load<"ldub", 0b000001, zextloadi8, IntRegs, i32>; ++defm LDUH : Load<"lduh", 0b000010, zextloadi16, IntRegs, i32>; ++defm LD : Load<"ld", 0b000000, load, IntRegs, i32>; + + // Section B.2 - Load Floating-point Instructions, p. 92 +-def LDFrr : F3_1<3, 0b100000, +- (outs FPRegs:$dst), (ins MEMrr:$addr), +- "ld [$addr], $dst", +- [(set f32:$dst, (load ADDRrr:$addr))]>; +-def LDFri : F3_2<3, 0b100000, +- (outs FPRegs:$dst), (ins MEMri:$addr), +- "ld [$addr], $dst", +- [(set f32:$dst, (load ADDRri:$addr))]>; +-def LDDFrr : F3_1<3, 0b100011, +- (outs DFPRegs:$dst), (ins MEMrr:$addr), +- "ldd [$addr], $dst", +- [(set f64:$dst, (load ADDRrr:$addr))]>; +-def LDDFri : F3_2<3, 0b100011, +- (outs DFPRegs:$dst), (ins MEMri:$addr), +- "ldd [$addr], $dst", +- [(set f64:$dst, (load ADDRri:$addr))]>; +-def LDQFrr : F3_1<3, 0b100010, +- (outs QFPRegs:$dst), (ins MEMrr:$addr), +- "ldq [$addr], $dst", +- [(set f128:$dst, (load ADDRrr:$addr))]>, +- Requires<[HasV9, HasHardQuad]>; +-def LDQFri : F3_2<3, 0b100010, +- (outs QFPRegs:$dst), (ins MEMri:$addr), +- "ldq [$addr], $dst", +- [(set f128:$dst, (load ADDRri:$addr))]>, +- Requires<[HasV9, HasHardQuad]>; ++defm LDF : Load<"ld", 0b100000, load, FPRegs, f32>; ++defm LDDF : Load<"ldd", 0b100011, load, DFPRegs, f64>; ++defm LDQF : Load<"ldq", 0b100010, load, QFPRegs, f128>, ++ Requires<[HasV9, HasHardQuad]>; + + // Section B.4 - Store Integer Instructions, p. 95 +-def STBrr : F3_1<3, 0b000101, +- (outs), (ins MEMrr:$addr, IntRegs:$rd), +- "stb $rd, [$addr]", +- [(truncstorei8 i32:$rd, ADDRrr:$addr)]>; +-def STBri : F3_2<3, 0b000101, +- (outs), (ins MEMri:$addr, IntRegs:$rd), +- "stb $rd, [$addr]", +- [(truncstorei8 i32:$rd, ADDRri:$addr)]>; +-def STHrr : F3_1<3, 0b000110, +- (outs), (ins MEMrr:$addr, IntRegs:$rd), +- "sth $rd, [$addr]", +- [(truncstorei16 i32:$rd, ADDRrr:$addr)]>; +-def STHri : F3_2<3, 0b000110, +- (outs), (ins MEMri:$addr, IntRegs:$rd), +- "sth $rd, [$addr]", +- [(truncstorei16 i32:$rd, ADDRri:$addr)]>; +-def STrr : F3_1<3, 0b000100, +- (outs), (ins MEMrr:$addr, IntRegs:$rd), +- "st $rd, [$addr]", +- [(store i32:$rd, ADDRrr:$addr)]>; +-def STri : F3_2<3, 0b000100, +- (outs), (ins MEMri:$addr, IntRegs:$rd), +- "st $rd, [$addr]", +- [(store i32:$rd, ADDRri:$addr)]>; ++defm STB : Store<"stb", 0b000101, truncstorei8, IntRegs, i32>; ++defm STH : Store<"sth", 0b000110, truncstorei16, IntRegs, i32>; ++defm ST : Store<"st", 0b000100, store, IntRegs, i32>; + + // Section B.5 - Store Floating-point Instructions, p. 97 +-def STFrr : F3_1<3, 0b100100, +- (outs), (ins MEMrr:$addr, FPRegs:$rd), +- "st $rd, [$addr]", +- [(store f32:$rd, ADDRrr:$addr)]>; +-def STFri : F3_2<3, 0b100100, +- (outs), (ins MEMri:$addr, FPRegs:$rd), +- "st $rd, [$addr]", +- [(store f32:$rd, ADDRri:$addr)]>; +-def STDFrr : F3_1<3, 0b100111, +- (outs), (ins MEMrr:$addr, DFPRegs:$rd), +- "std $rd, [$addr]", +- [(store f64:$rd, ADDRrr:$addr)]>; +-def STDFri : F3_2<3, 0b100111, +- (outs), (ins MEMri:$addr, DFPRegs:$rd), +- "std $rd, [$addr]", +- [(store f64:$rd, ADDRri:$addr)]>; +-def STQFrr : F3_1<3, 0b100110, +- (outs), (ins MEMrr:$addr, QFPRegs:$rd), +- "stq $rd, [$addr]", +- [(store f128:$rd, ADDRrr:$addr)]>, +- Requires<[HasV9, HasHardQuad]>; +-def STQFri : F3_2<3, 0b100110, +- (outs), (ins MEMri:$addr, QFPRegs:$rd), +- "stq $rd, [$addr]", +- [(store f128:$rd, ADDRri:$addr)]>, +- Requires<[HasV9, HasHardQuad]>; ++defm STF : Store<"st", 0b100100, store, FPRegs, f32>; ++defm STDF : Store<"std", 0b100111, store, DFPRegs, f64>; ++defm STQF : Store<"stq", 0b100110, store, QFPRegs, f128>, ++ Requires<[HasV9, HasHardQuad]>; + + // Section B.9 - SETHI Instruction, p. 104 + def SETHIi: F2_1<0b100, diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198909-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198909-sparc.diff new file mode 100644 index 000000000000..e4fb0f350f1f --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198909-sparc.diff @@ -0,0 +1,229 @@ +Pull in r198909 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add support for parsing jmpl instruction and make indirect call and jmp instructions as aliases to jmpl. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -453,6 +453,7 @@ parseMEMOperand(SmallVectorImpl; + defm : fp_cond_alias<"le", 0b1101>; + defm : fp_cond_alias<"ule", 0b1110>; + defm : fp_cond_alias<"o", 0b1111>; ++ ++ ++// Instruction aliases for JMPL. ++ ++// jmp addr -> jmpl addr, %g0 ++def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr)>; ++def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr)>; ++ ++// call addr -> jmpl addr, %o7 ++def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr)>; ++def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr)>; +Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +=================================================================== +--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp ++++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +@@ -23,6 +23,7 @@ + using namespace llvm; + + #define GET_INSTRUCTION_NAME ++#define PRINT_ALIAS_INSTR + #include "SparcGenAsmWriter.inc" + + void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const +@@ -33,10 +34,34 @@ void SparcInstPrinter::printRegName(raw_ostream &O + void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O, + StringRef Annot) + { +- printInstruction(MI, O); ++ if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O)) ++ printInstruction(MI, O); + printAnnotation(O, Annot); + } + ++bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O) ++{ ++ switch (MI->getOpcode()) { ++ default: return false; ++ case SP::JMPLrr: ++ case SP::JMPLri: { ++ if (MI->getNumOperands() != 3) ++ return false; ++ if (!MI->getOperand(0).isReg()) ++ return false; ++ switch (MI->getOperand(0).getReg()) { ++ default: return false; ++ case SP::G0: // jmp $addr ++ O << "\tjmp "; printMemOperand(MI, 1, O); ++ return true; ++ case SP::O7: // call $addr ++ O << "\tcall "; printMemOperand(MI, 1, O); ++ return true; ++ } ++ } ++ } ++} ++ + void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, + raw_ostream &O) + { +Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.h +=================================================================== +--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h ++++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.h +@@ -29,9 +29,11 @@ class SparcInstPrinter : public MCInstPrinter { + + virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; + virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); ++ bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS); + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); ++ bool printAliasInstr(const MCInst *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); + + void printOperand(const MCInst *MI, int opNum, raw_ostream &OS); +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -362,10 +362,18 @@ let usesCustomInserter = 1, Uses = [FCC] in { + [(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>; + } + ++// JMPL Instruction. ++let isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { ++ def JMPLrr: F3_1<2, 0b111000, (outs IntRegs:$dst), (ins MEMrr:$addr), ++ "jmpl $addr, $dst", []>; ++ def JMPLri: F3_2<2, 0b111000, (outs IntRegs:$dst), (ins MEMri:$addr), ++ "jmpl $addr, $dst", []>; ++} + + // Section A.3 - Synthetic Instructions, p. 85 + // special cases of JMPL: +-let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { ++let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, ++ isCodeGenOnly = 1 in { + let rd = 0, rs1 = 15 in + def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val), + "jmp %o7+$val", [(retflag simm13:$val)]>; +@@ -519,9 +527,8 @@ class BranchSP p + } + + // Indirect branch instructions. +-let isTerminator = 1, isBarrier = 1, +- hasDelaySlot = 1, isBranch =1, +- isIndirectBranch = 1, rd = 0 in { ++let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1, ++ isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in { + def BINDrr : F3_1<2, 0b111000, + (outs), (ins MEMrr:$ptr), + "jmp $ptr", +@@ -564,15 +571,17 @@ let Uses = [O6], + let Inst{29-0} = disp; + } + +- // indirect calls +- def JMPLrr : F3_1<2, 0b111000, +- (outs), (ins MEMrr:$ptr, variable_ops), +- "call $ptr", +- [(call ADDRrr:$ptr)]> { let rd = 15; } +- def JMPLri : F3_2<2, 0b111000, +- (outs), (ins MEMri:$ptr, variable_ops), +- "call $ptr", +- [(call ADDRri:$ptr)]> { let rd = 15; } ++ // indirect calls: special cases of JMPL. ++ let isCodeGenOnly = 1, rd = 15 in { ++ def CALLrr : F3_1<2, 0b111000, ++ (outs), (ins MEMrr:$ptr, variable_ops), ++ "call $ptr", ++ [(call ADDRrr:$ptr)]>; ++ def CALLri : F3_2<2, 0b111000, ++ (outs), (ins MEMri:$ptr, variable_ops), ++ "call $ptr", ++ [(call ADDRri:$ptr)]>; ++ } + } + + // Section B.28 - Read State Register Instructions +Index: lib/Target/Sparc/DelaySlotFiller.cpp +=================================================================== +--- lib/Target/Sparc/DelaySlotFiller.cpp ++++ lib/Target/Sparc/DelaySlotFiller.cpp +@@ -278,19 +278,19 @@ void Filler::insertCallDefsUses(MachineBasicBlock: + switch(MI->getOpcode()) { + default: llvm_unreachable("Unknown opcode."); + case SP::CALL: break; +- case SP::JMPLrr: +- case SP::JMPLri: ++ case SP::CALLrr: ++ case SP::CALLri: + assert(MI->getNumOperands() >= 2); + const MachineOperand &Reg = MI->getOperand(0); +- assert(Reg.isReg() && "JMPL first operand is not a register."); +- assert(Reg.isUse() && "JMPL first operand is not a use."); ++ assert(Reg.isReg() && "CALL first operand is not a register."); ++ assert(Reg.isUse() && "CALL first operand is not a use."); + RegUses.insert(Reg.getReg()); + + const MachineOperand &RegOrImm = MI->getOperand(1); + if (RegOrImm.isImm()) + break; +- assert(RegOrImm.isReg() && "JMPLrr second operand is not a register."); +- assert(RegOrImm.isUse() && "JMPLrr second operand is not a use."); ++ assert(RegOrImm.isReg() && "CALLrr second operand is not a register."); ++ assert(RegOrImm.isUse() && "CALLrr second operand is not a use."); + RegUses.insert(RegOrImm.getReg()); + break; + } +@@ -353,8 +353,8 @@ bool Filler::needsUnimp(MachineBasicBlock::iterato + switch (I->getOpcode()) { + default: llvm_unreachable("Unknown call opcode."); + case SP::CALL: structSizeOpNum = 1; break; +- case SP::JMPLrr: +- case SP::JMPLri: structSizeOpNum = 2; break; ++ case SP::CALLrr: ++ case SP::CALLri: structSizeOpNum = 2; break; + case SP::TLS_CALL: return false; + } + +Index: test/MC/Sparc/sparc-ctrl-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-ctrl-instructions.s ++++ test/MC/Sparc/sparc-ctrl-instructions.s +@@ -31,6 +31,19 @@ + ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 + jmp %g1+%lo(sym) + ++ ! CHECK: jmpl %g1+%i2, %g2 ! encoding: [0x85,0xc0,0x40,0x1a] ++ jmpl %g1 + %i2, %g2 ++ ++ ! CHECK: jmpl %o1+8, %g2 ! encoding: [0x85,0xc2,0x60,0x08] ++ jmpl %o1 + 8, %g2 ++ ++ ! CHECK: jmpl %g1, %g2 ! encoding: [0x85,0xc0,0x60,0x00] ++ jmpl %g1, %g2 ++ ++ ! CHECK: jmpl %g1+%lo(sym), %g2 ! encoding: [0x85,0xc0,0b011000AA,A] ++ ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 ++ jmpl %g1+%lo(sym), %g2 ++ + ! CHECK: ba .BB0 ! encoding: [0x10,0b10AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22 + ba .BB0 diff --git a/contrib/llvm/patches/patch-r262261-llvm-r198910-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r198910-sparc.diff new file mode 100644 index 000000000000..94b320c202b8 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r198910-sparc.diff @@ -0,0 +1,463 @@ +Pull in r198910 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Emit retl/ret instead of jmp instruction. It improves the readability of the assembly generated. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/CodeGen/SPARC/ctpop.ll +=================================================================== +--- test/CodeGen/SPARC/ctpop.ll ++++ test/CodeGen/SPARC/ctpop.ll +@@ -9,12 +9,12 @@ declare i32 @llvm.ctpop.i32(i32) + + ; V9-LABEL: test + ; V9: srl %o0, 0, %o0 +-; V9-NEXT: jmp %o7+8 ++; V9-NEXT: retl + ; V9-NEXT: popc %o0, %o0 + + ; SPARC64-LABEL: test + ; SPARC64: srl %o0, 0, %o0 +-; SPARC64: jmp %o7+8 ++; SPARC64: retl + ; SPARC64: popc %o0, %o0 + + define i32 @test(i32 %X) { +Index: test/CodeGen/SPARC/2011-01-11-Call.ll +=================================================================== +--- test/CodeGen/SPARC/2011-01-11-Call.ll ++++ test/CodeGen/SPARC/2011-01-11-Call.ll +@@ -8,7 +8,7 @@ + ; V8-NEXT: nop + ; V8: call bar + ; V8-NEXT: nop +-; V8: jmp %i7+8 ++; V8: ret + ; V8-NEXT: restore + + ; V9-LABEL: test +@@ -17,7 +17,7 @@ + ; V9-NEXT: nop + ; V9: call bar + ; V9-NEXT: nop +-; V9: jmp %i7+8 ++; V9: ret + ; V9-NEXT: restore + + define void @test() nounwind { +@@ -36,7 +36,7 @@ declare void @bar(...) + ; V8: save %sp + ; V8: call foo + ; V8-NEXT: nop +-; V8: jmp %i7+8 ++; V8: ret + ; V8-NEXT: restore %g0, %o0, %o0 + + ; V9-LABEL: test_tail_call_with_return +@@ -43,7 +43,7 @@ declare void @bar(...) + ; V9: save %sp + ; V9: call foo + ; V9-NEXT: nop +-; V9: jmp %i7+8 ++; V9: ret + ; V9-NEXT: restore %g0, %o0, %o0 + + define i32 @test_tail_call_with_return() nounwind { +Index: test/CodeGen/SPARC/leafproc.ll +=================================================================== +--- test/CodeGen/SPARC/leafproc.ll ++++ test/CodeGen/SPARC/leafproc.ll +@@ -1,7 +1,7 @@ + ; RUN: llc -march=sparc -disable-sparc-leaf-proc=0 < %s | FileCheck %s + + ; CHECK-LABEL: func_nobody: +-; CHECK: jmp %o7+8 ++; CHECK: retl + ; CHECK-NEXT: nop + define void @func_nobody() { + entry: +@@ -10,7 +10,7 @@ entry: + + + ; CHECK-LABEL: return_int_const: +-; CHECK: jmp %o7+8 ++; CHECK: retl + ; CHECK-NEXT: or %g0, 1729, %o0 + define i32 @return_int_const() { + entry: +@@ -19,7 +19,7 @@ entry: + + ; CHECK-LABEL: return_double_const: + ; CHECK: sethi +-; CHECK: jmp %o7+8 ++; CHECK: retl + ; CHECK-NEXT: ldd {{.*}}, %f0 + + define double @return_double_const() { +@@ -29,7 +29,7 @@ entry: + + ; CHECK-LABEL: leaf_proc_with_args: + ; CHECK: add {{%o[0-1]}}, {{%o[0-1]}}, [[R:%[go][0-7]]] +-; CHECK: jmp %o7+8 ++; CHECK: retl + ; CHECK-NEXT: add [[R]], %o2, %o0 + + define i32 @leaf_proc_with_args(i32 %a, i32 %b, i32 %c) { +@@ -42,7 +42,7 @@ entry: + ; CHECK-LABEL: leaf_proc_with_args_in_stack: + ; CHECK-DAG: ld [%sp+92], {{%[go][0-7]}} + ; CHECK-DAG: ld [%sp+96], {{%[go][0-7]}} +-; CHECK: jmp %o7+8 ++; CHECK: retl + ; CHECK-NEXT: add {{.*}}, %o0 + define i32 @leaf_proc_with_args_in_stack(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) { + entry: +@@ -63,7 +63,7 @@ entry: + ; CHECK: or %g0, 2, [[R2:%[go][0-7]]] + ; CHECK: st [[R2]], [%sp+100] + ; CHECK: ld {{.+}}, %o0 +-; CHECK: jmp %o7+8 ++; CHECK: retl + ; CHECK-NEXT: add %sp, 104, %sp + + define i32 @leaf_proc_with_local_array(i32 %a, i32 %b, i32 %c) { +Index: test/CodeGen/SPARC/fp128.ll +=================================================================== +--- test/CodeGen/SPARC/fp128.ll ++++ test/CodeGen/SPARC/fp128.ll +@@ -45,7 +45,7 @@ entry: + ; HARD: std %f{{.+}}, [%[[S1:.+]]] + ; HARD-DAG: ldd [%[[S0]]], %f{{.+}} + ; HARD-DAG: ldd [%[[S1]]], %f{{.+}} +-; HARD: jmp ++; HARD: jmp %o7+12 + + ; SOFT-LABEL: f128_spill + ; SOFT: std %f{{.+}}, [%[[S0:.+]]] +@@ -52,7 +52,7 @@ entry: + ; SOFT: std %f{{.+}}, [%[[S1:.+]]] + ; SOFT-DAG: ldd [%[[S0]]], %f{{.+}} + ; SOFT-DAG: ldd [%[[S1]]], %f{{.+}} +-; SOFT: jmp ++; SOFT: jmp %o7+12 + + define void @f128_spill(fp128* noalias sret %scalar.result, fp128* byval %a) { + entry: +@@ -132,13 +132,13 @@ entry: + ; HARD: ldub + ; HARD: faddq + ; HARD: stb +-; HARD: jmp ++; HARD: ret + + ; SOFT-LABEL: fp128_unaligned + ; SOFT: ldub + ; SOFT: call _Q_add + ; SOFT: stb +-; SOFT: jmp ++; SOFT: ret + + define void @fp128_unaligned(fp128* %a, fp128* %b, fp128* %c) { + entry: +Index: test/CodeGen/SPARC/2011-01-11-FrameAddr.ll +=================================================================== +--- test/CodeGen/SPARC/2011-01-11-FrameAddr.ll ++++ test/CodeGen/SPARC/2011-01-11-FrameAddr.ll +@@ -9,18 +9,18 @@ define i8* @frameaddr() nounwind readnone { + entry: + ;V8-LABEL: frameaddr: + ;V8: save %sp, -96, %sp +-;V8: jmp %i7+8 ++;V8: ret + ;V8: restore %g0, %fp, %o0 + + ;V9-LABEL: frameaddr: + ;V9: save %sp, -96, %sp +-;V9: jmp %i7+8 ++;V9: ret + ;V9: restore %g0, %fp, %o0 + + ;SPARC64-LABEL: frameaddr + ;SPARC64: save %sp, -128, %sp + ;SPARC64: add %fp, 2047, %i0 +-;SPARC64: jmp %i7+8 ++;SPARC64: ret + ;SPARC64: restore %g0, %g0, %g0 + + %0 = tail call i8* @llvm.frameaddress(i32 0) +Index: test/CodeGen/SPARC/constpool.ll +=================================================================== +--- test/CodeGen/SPARC/constpool.ll ++++ test/CodeGen/SPARC/constpool.ll +@@ -12,7 +12,7 @@ entry: + + ; abs32: floatCP + ; abs32: sethi %hi(.LCPI0_0), %[[R:[gilo][0-7]]] +-; abs32: jmp %o7+8 ++; abs32: retl + ; abs32: ld [%[[R]]+%lo(.LCPI0_0)], %f + + +@@ -20,7 +20,7 @@ entry: + ; abs44: sethi %h44(.LCPI0_0), %[[R1:[gilo][0-7]]] + ; abs44: add %[[R1]], %m44(.LCPI0_0), %[[R2:[gilo][0-7]]] + ; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]] +-; abs44: jmp %o7+8 ++; abs44: retl + ; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f1 + + +@@ -30,7 +30,7 @@ entry: + ; abs64: sethi %hh(.LCPI0_0), %[[R3:[gilo][0-7]]] + ; abs64: add %[[R3]], %hm(.LCPI0_0), %[[R4:[gilo][0-7]]] + ; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]] +-; abs64: jmp %o7+8 ++; abs64: retl + ; abs64: ld [%[[R5]]+%[[R2]]], %f1 + + +@@ -40,7 +40,7 @@ entry: + ; v8pic32: add %[[R1]], %lo(.LCPI0_0), %[[Goffs:[gilo][0-7]]] + ; v8pic32: ld [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] + ; v8pic32: ld [%[[Gaddr]]], %f0 +-; v8pic32: jmp %i7+8 ++; v8pic32: ret + ; v8pic32: restore + + +@@ -51,7 +51,7 @@ entry: + ; v9pic32: add %[[R1]], %lo(.LCPI0_0), %[[Goffs:[gilo][0-7]]] + ; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] + ; v9pic32: ld [%[[Gaddr]]], %f1 +-; v9pic32: jmp %i7+8 ++; v9pic32: ret + ; v9pic32: restore + + +Index: test/CodeGen/SPARC/globals.ll +=================================================================== +--- test/CodeGen/SPARC/globals.ll ++++ test/CodeGen/SPARC/globals.ll +@@ -14,7 +14,7 @@ define zeroext i8 @loadG() { + + ; abs32: loadG + ; abs32: sethi %hi(G), %[[R:[gilo][0-7]]] +-; abs32: jmp %o7+8 ++; abs32: retl + ; abs32: ldub [%[[R]]+%lo(G)], %o0 + + +@@ -22,7 +22,7 @@ define zeroext i8 @loadG() { + ; abs44: sethi %h44(G), %[[R1:[gilo][0-7]]] + ; abs44: add %[[R1]], %m44(G), %[[R2:[gilo][0-7]]] + ; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]] +-; abs44: jmp %o7+8 ++; abs44: retl + ; abs44: ldub [%[[R3]]+%l44(G)], %o0 + + +@@ -32,7 +32,7 @@ define zeroext i8 @loadG() { + ; abs64: sethi %hh(G), %[[R3:[gilo][0-7]]] + ; abs64: add %[[R3]], %hm(G), %[[R4:[gilo][0-7]]] + ; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]] +-; abs64: jmp %o7+8 ++; abs64: retl + ; abs64: ldub [%[[R5]]+%[[R2]]], %o0 + + +@@ -42,7 +42,7 @@ define zeroext i8 @loadG() { + ; v8pic32: add %[[R1]], %lo(G), %[[Goffs:[gilo][0-7]]] + ; v8pic32: ld [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] + ; v8pic32: ldub [%[[Gaddr]]], %i0 +-; v8pic32: jmp %i7+8 ++; v8pic32: ret + ; v8pic32: restore + + +@@ -52,6 +52,6 @@ define zeroext i8 @loadG() { + ; v9pic32: add %[[R1]], %lo(G), %[[Goffs:[gilo][0-7]]] + ; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] + ; v9pic32: ldub [%[[Gaddr]]], %i0 +-; v9pic32: jmp %i7+8 ++; v9pic32: ret + ; v9pic32: restore + +Index: test/CodeGen/SPARC/rem.ll +=================================================================== +--- test/CodeGen/SPARC/rem.ll ++++ test/CodeGen/SPARC/rem.ll +@@ -3,7 +3,7 @@ + ; CHECK-LABEL: test1: + ; CHECK: sdivx %o0, %o1, %o2 + ; CHECK-NEXT: mulx %o2, %o1, %o1 +-; CHECK-NEXT: jmp %o7+8 ++; CHECK-NEXT: retl + ; CHECK-NEXT: sub %o0, %o1, %o0 + + define i64 @test1(i64 %X, i64 %Y) { +@@ -14,7 +14,7 @@ define i64 @test1(i64 %X, i64 %Y) { + ; CHECK-LABEL: test2: + ; CHECK: udivx %o0, %o1, %o2 + ; CHECK-NEXT: mulx %o2, %o1, %o1 +-; CHECK-NEXT: jmp %o7+8 ++; CHECK-NEXT: retl + ; CHECK-NEXT: sub %o0, %o1, %o0 + + define i64 @test2(i64 %X, i64 %Y) { +Index: test/CodeGen/SPARC/2011-01-19-DelaySlot.ll +=================================================================== +--- test/CodeGen/SPARC/2011-01-19-DelaySlot.ll ++++ test/CodeGen/SPARC/2011-01-19-DelaySlot.ll +@@ -7,7 +7,7 @@ entry: + ; CHECK: test + ; CHECK: call bar + ; CHECK-NOT: nop +-; CHECK: jmp ++; CHECK: ret + ; CHECK-NEXT: restore + %0 = tail call i32 @bar(i32 %a) nounwind + ret i32 %0 +@@ -18,7 +18,7 @@ entry: + ; CHECK: test_jmpl + ; CHECK: call + ; CHECK-NOT: nop +-; CHECK: jmp ++; CHECK: ret + ; CHECK-NEXT: restore + %0 = tail call i32 %f(i32 %a, i32 %b) nounwind + ret i32 %0 +@@ -47,7 +47,7 @@ bb: + + bb5: ; preds = %bb, %entry + %a_addr.1.lcssa = phi i32 [ %a, %entry ], [ %a_addr.0, %bb ] +-;CHECK: jmp ++;CHECK: retl + ;CHECK-NOT: restore + ret i32 %a_addr.1.lcssa + } +@@ -110,7 +110,7 @@ declare i32 @func(i32*) + define i32 @restore_add(i32 %a, i32 %b) { + entry: + ;CHECK-LABEL: restore_add: +-;CHECK: jmp %i7+8 ++;CHECK: ret + ;CHECK: restore %o0, %i1, %o0 + %0 = tail call i32 @bar(i32 %a) nounwind + %1 = add nsw i32 %0, %b +@@ -120,7 +120,7 @@ entry: + define i32 @restore_add_imm(i32 %a) { + entry: + ;CHECK-LABEL: restore_add_imm: +-;CHECK: jmp %i7+8 ++;CHECK: ret + ;CHECK: restore %o0, 20, %o0 + %0 = tail call i32 @bar(i32 %a) nounwind + %1 = add nsw i32 %0, 20 +@@ -130,7 +130,7 @@ entry: + define i32 @restore_or(i32 %a) { + entry: + ;CHECK-LABEL: restore_or: +-;CHECK: jmp %i7+8 ++;CHECK: ret + ;CHECK: restore %g0, %o0, %o0 + %0 = tail call i32 @bar(i32 %a) nounwind + ret i32 %0 +@@ -140,7 +140,7 @@ define i32 @restore_or_imm(i32 %a) { + entry: + ;CHECK-LABEL: restore_or_imm: + ;CHECK: or %o0, 20, %i0 +-;CHECK: jmp %i7+8 ++;CHECK: ret + ;CHECK: restore %g0, %g0, %g0 + %0 = tail call i32 @bar(i32 %a) nounwind + %1 = or i32 %0, 20 +Index: test/CodeGen/SPARC/64bit.ll +=================================================================== +--- test/CodeGen/SPARC/64bit.ll ++++ test/CodeGen/SPARC/64bit.ll +@@ -5,7 +5,7 @@ + ; CHECK: or %g0, %i1, %i0 + + ; OPT-LABEL: ret2: +-; OPT: jmp %o7+8 ++; OPT: retl + ; OPT: or %g0, %o1, %o0 + define i64 @ret2(i64 %a, i64 %b) { + ret i64 %b +@@ -15,7 +15,7 @@ define i64 @ret2(i64 %a, i64 %b) { + ; CHECK: sllx %i0, 7, %i0 + + ; OPT-LABEL: shl_imm: +-; OPT: jmp %o7+8 ++; OPT: retl + ; OPT: sllx %o0, 7, %o0 + define i64 @shl_imm(i64 %a) { + %x = shl i64 %a, 7 +@@ -26,7 +26,7 @@ define i64 @shl_imm(i64 %a) { + ; CHECK: srax %i0, %i1, %i0 + + ; OPT-LABEL: sra_reg: +-; OPT: jmp %o7+8 ++; OPT: retl + ; OPT: srax %o0, %o1, %o0 + define i64 @sra_reg(i64 %a, i64 %b) { + %x = ashr i64 %a, %b +@@ -42,7 +42,7 @@ define i64 @sra_reg(i64 %a, i64 %b) { + ; CHECK: or %g0, 0, %i0 + + ; OPT: ret_imm0 +-; OPT: jmp %o7+8 ++; OPT: retl + ; OPT: or %g0, 0, %o0 + define i64 @ret_imm0() { + ret i64 0 +@@ -52,7 +52,7 @@ define i64 @ret_imm0() { + ; CHECK: or %g0, -4096, %i0 + + ; OPT: ret_simm13 +-; OPT: jmp %o7+8 ++; OPT: retl + ; OPT: or %g0, -4096, %o0 + define i64 @ret_simm13() { + ret i64 -4096 +@@ -64,7 +64,7 @@ define i64 @ret_simm13() { + ; CHECK: restore + + ; OPT: ret_sethi +-; OPT: jmp %o7+8 ++; OPT: retl + ; OPT: sethi 4, %o0 + define i64 @ret_sethi() { + ret i64 4096 +@@ -76,7 +76,7 @@ define i64 @ret_sethi() { + + ; OPT: ret_sethi_or + ; OPT: sethi 4, [[R:%[go][0-7]]] +-; OPT: jmp %o7+8 ++; OPT: retl + ; OPT: or [[R]], 1, %o0 + + define i64 @ret_sethi_or() { +@@ -89,7 +89,7 @@ define i64 @ret_sethi_or() { + + ; OPT: ret_nimm33 + ; OPT: sethi 4, [[R:%[go][0-7]]] +-; OPT: jmp %o7+8 ++; OPT: retl + ; OPT: xor [[R]], -4, %o0 + + define i64 @ret_nimm33() { +Index: lib/Target/Sparc/SparcInstrAliases.td +=================================================================== +--- lib/Target/Sparc/SparcInstrAliases.td ++++ lib/Target/Sparc/SparcInstrAliases.td +@@ -128,3 +128,9 @@ def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$ad + // call addr -> jmpl addr, %o7 + def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr)>; + def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr)>; ++ ++// retl -> RETL 8 ++def : InstAlias<"retl", (RETL 8)>; ++ ++// ret -> RET 8 ++def : InstAlias<"ret", (RET 8)>; diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199014-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199014-sparc.diff new file mode 100644 index 000000000000..6db27a065c9e --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199014-sparc.diff @@ -0,0 +1,133 @@ +Pull in r199014 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Bundle instruction with delay slow and its filler. Now, we can use -verify-machineinstrs with SPARC backend. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/DelaySlotFiller.cpp +=================================================================== +--- lib/Target/Sparc/DelaySlotFiller.cpp ++++ lib/Target/Sparc/DelaySlotFiller.cpp +@@ -19,6 +19,7 @@ + #include "llvm/ADT/Statistic.h" + #include "llvm/CodeGen/MachineFunctionPass.h" + #include "llvm/CodeGen/MachineInstrBuilder.h" ++#include "llvm/CodeGen/MachineRegisterInfo.h" + #include "llvm/Support/CommandLine.h" + #include "llvm/Target/TargetInstrInfo.h" + #include "llvm/Target/TargetMachine.h" +@@ -55,6 +56,11 @@ namespace { + bool runOnMachineBasicBlock(MachineBasicBlock &MBB); + bool runOnMachineFunction(MachineFunction &F) { + bool Changed = false; ++ ++ // This pass invalidates liveness information when it reorders ++ // instructions to fill delay slot. ++ F.getRegInfo().invalidateLiveness(); ++ + for (MachineFunction::iterator FI = F.begin(), FE = F.end(); + FI != FE; ++FI) + Changed |= runOnMachineBasicBlock(*FI); +@@ -61,9 +67,6 @@ namespace { + return Changed; + } + +- bool isDelayFiller(MachineBasicBlock &MBB, +- MachineBasicBlock::iterator candidate); +- + void insertCallDefsUses(MachineBasicBlock::iterator MI, + SmallSet& RegDefs, + SmallSet& RegUses); +@@ -152,6 +155,10 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBl + assert (J != MBB.end() && "MI needs a delay instruction."); + BuildMI(MBB, ++J, MI->getDebugLoc(), + TII->get(SP::UNIMP)).addImm(structSize); ++ // Bundle the delay filler and unimp with the instruction. ++ MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), J); ++ } else { ++ MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), I); + } + } + return Changed; +@@ -209,7 +216,7 @@ Filler::findDelayInstr(MachineBasicBlock &MBB, + || I->isInlineAsm() + || I->isLabel() + || I->hasDelaySlot() +- || isDelayFiller(MBB, I)) ++ || I->isBundledWithSucc()) + break; + + if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) { +@@ -332,18 +339,6 @@ bool Filler::IsRegInSet(SmallSet& Re + return false; + } + +-// return true if the candidate is a delay filler. +-bool Filler::isDelayFiller(MachineBasicBlock &MBB, +- MachineBasicBlock::iterator candidate) +-{ +- if (candidate == MBB.begin()) +- return false; +- if (candidate->getOpcode() == SP::UNIMP) +- return true; +- --candidate; +- return candidate->hasDelaySlot(); +-} +- + bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize) + { + if (!I->isCall()) +@@ -484,10 +479,10 @@ bool Filler::tryCombineRestoreWithPrevInst(Machine + && MBBI->getOperand(1).getReg() == SP::G0 + && MBBI->getOperand(2).getReg() == SP::G0); + +- MachineBasicBlock::iterator PrevInst = MBBI; --PrevInst; ++ MachineBasicBlock::iterator PrevInst = llvm::prior(MBBI); + +- // It cannot combine with a delay filler. +- if (isDelayFiller(MBB, PrevInst)) ++ // It cannot be combined with a bundled instruction. ++ if (PrevInst->isBundledWithSucc()) + return false; + + const TargetInstrInfo *TII = TM.getInstrInfo(); +Index: lib/Target/Sparc/SparcAsmPrinter.cpp +=================================================================== +--- lib/Target/Sparc/SparcAsmPrinter.cpp ++++ lib/Target/Sparc/SparcAsmPrinter.cpp +@@ -184,7 +184,6 @@ static void LowerGETPCXAndEmitMCInsts(const Machin + + void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI) + { +- MCInst TmpInst; + + switch (MI->getOpcode()) { + default: break; +@@ -195,8 +194,13 @@ void SparcAsmPrinter::EmitInstruction(const Machin + LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext); + return; + } +- LowerSparcMachineInstrToMCInst(MI, TmpInst, *this); +- OutStreamer.EmitInstruction(TmpInst); ++ MachineBasicBlock::const_instr_iterator I = MI; ++ MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); ++ do { ++ MCInst TmpInst; ++ LowerSparcMachineInstrToMCInst(I, TmpInst, *this); ++ OutStreamer.EmitInstruction(TmpInst); ++ } while ((++I != E) && I->isInsideBundle()); // Delay slot check. + } + + void SparcAsmPrinter::EmitFunctionBodyStart() { +Index: test/CodeGen/SPARC/2011-01-19-DelaySlot.ll +=================================================================== +--- test/CodeGen/SPARC/2011-01-19-DelaySlot.ll ++++ test/CodeGen/SPARC/2011-01-19-DelaySlot.ll +@@ -1,5 +1,5 @@ +-;RUN: llc -march=sparc < %s | FileCheck %s +-;RUN: llc -march=sparc -O0 < %s | FileCheck %s -check-prefix=UNOPT ++;RUN: llc -march=sparc < %s -verify-machineinstrs | FileCheck %s ++;RUN: llc -march=sparc -O0 < %s -verify-machineinstrs | FileCheck %s -check-prefix=UNOPT + + + define i32 @test(i32 %a) nounwind { diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199024-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199024-sparc.diff new file mode 100644 index 000000000000..35bfc2bc40d6 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199024-sparc.diff @@ -0,0 +1,69 @@ +Pull in r199024 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add missing processor types: v7 and niagara + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/Sparc.td +=================================================================== +--- lib/Target/Sparc/Sparc.td ++++ lib/Target/Sparc/Sparc.td +@@ -56,6 +56,7 @@ class Proc Fea + : Processor; + + def : Proc<"generic", []>; ++def : Proc<"v7", []>; + def : Proc<"v8", []>; + def : Proc<"supersparc", []>; + def : Proc<"sparclite", []>; +@@ -67,7 +68,10 @@ def : Proc<"tsc701", []>; + def : Proc<"v9", [FeatureV9]>; + def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated]>; + def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>; +-def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>; ++def : Proc<"niagara", [FeatureV9, FeatureV8Deprecated]>; ++def : Proc<"niagara2", [FeatureV9, FeatureV8Deprecated]>; ++def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated]>; ++def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated]>; + + def SparcAsmWriter : AsmWriter { + string AsmWriterClassName = "InstPrinter"; +Index: lib/Target/Sparc/SparcSubtarget.cpp +=================================================================== +--- lib/Target/Sparc/SparcSubtarget.cpp ++++ lib/Target/Sparc/SparcSubtarget.cpp +@@ -35,13 +35,8 @@ SparcSubtarget::SparcSubtarget(const std::string & + + // Determine default and user specified characteristics + std::string CPUName = CPU; +- if (CPUName.empty()) { +- if (is64Bit) +- CPUName = "v9"; +- else +- CPUName = "v8"; +- } +- IsV9 = CPUName == "v9"; ++ if (CPUName.empty()) ++ CPUName = (is64Bit) ? "v9" : "v8"; + + // Parse features string. + ParseSubtargetFeatures(CPUName, FS); +Index: test/CodeGen/SPARC/ctpop.ll +=================================================================== +--- test/CodeGen/SPARC/ctpop.ll ++++ test/CodeGen/SPARC/ctpop.ll +@@ -1,6 +1,13 @@ + ; RUN: llc < %s -march=sparc -mattr=-v9 | FileCheck %s -check-prefix=V8 + ; RUN: llc < %s -march=sparc -mattr=+v9 | FileCheck %s -check-prefix=V9 +-; RUN: llc < %s -march=sparcv9 | FileCheck %s -check-prefix=SPARC64 ++; RUN: llc < %s -march=sparc -mcpu=v9 | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparc -mcpu=ultrasparc | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparc -mcpu=ultrasparc3 | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparc -mcpu=niagara | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparc -mcpu=niagara2 | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparc -mcpu=niagara3 | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparc -mcpu=niagara4 | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparcv9 | FileCheck %s -check-prefix=SPARC64 + + declare i32 @llvm.ctpop.i32(i32) + diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199028-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199028-sparc.diff new file mode 100644 index 000000000000..78bcc61d1479 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199028-sparc.diff @@ -0,0 +1,147 @@ +Pull in r199028 from upstream llvm trunk (by Jakob Stoklund Olesen): + + The SPARCv9 ABI returns a float in %f0. + + This is different from the argument passing convention which puts the + first float argument in %f1. + + With this patch, all returned floats are treated as if the 'inreg' flag + were set. This means multiple float return values get packed in %f0, + %f1, %f2, ... + + Note that when returning a struct in registers, clang will set the + 'inreg' flag on the return value, so that behavior is unchanged. This + also happens when returning a float _Complex. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/CodeGen/SPARC/64abi.ll +=================================================================== +--- test/CodeGen/SPARC/64abi.ll ++++ test/CodeGen/SPARC/64abi.ll +@@ -180,7 +180,7 @@ define void @call_inreg_fi(i32* %p, i32 %i1, float + } + + ; CHECK: inreg_ff +-; CHECK: fsubs %f0, %f1, %f1 ++; CHECK: fsubs %f0, %f1, %f0 + define float @inreg_ff(float inreg %a0, ; %f0 + float inreg %a1) { ; %f1 + %rv = fsub float %a0, %a1 +@@ -262,10 +262,10 @@ define void @call_ret_i64_pair(i64* %i0) { + ret void + } + +-; This is not a C struct, each member uses 8 bytes. ++; This is not a C struct, the i32 member uses 8 bytes, but the float only 4. + ; CHECK: ret_i32_float_pair + ; CHECK: ld [%i2], %i0 +-; CHECK: ld [%i3], %f3 ++; CHECK: ld [%i3], %f2 + define { i32, float } @ret_i32_float_pair(i32 %a0, i32 %a1, + i32* %p, float* %q) { + %r1 = load i32* %p +@@ -279,7 +279,7 @@ define { i32, float } @ret_i32_float_pair(i32 %a0, + ; CHECK: call_ret_i32_float_pair + ; CHECK: call ret_i32_float_pair + ; CHECK: st %o0, [%i0] +-; CHECK: st %f3, [%i1] ++; CHECK: st %f2, [%i1] + define void @call_ret_i32_float_pair(i32* %i0, float* %i1) { + %rv = call { i32, float } @ret_i32_float_pair(i32 undef, i32 undef, + i32* undef, float* undef) +Index: test/CodeGen/SPARC/constpool.ll +=================================================================== +--- test/CodeGen/SPARC/constpool.ll ++++ test/CodeGen/SPARC/constpool.ll +@@ -21,7 +21,7 @@ entry: + ; abs44: add %[[R1]], %m44(.LCPI0_0), %[[R2:[gilo][0-7]]] + ; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]] + ; abs44: retl +-; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f1 ++; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f0 + + + ; abs64: floatCP +@@ -31,7 +31,7 @@ entry: + ; abs64: add %[[R3]], %hm(.LCPI0_0), %[[R4:[gilo][0-7]]] + ; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]] + ; abs64: retl +-; abs64: ld [%[[R5]]+%[[R2]]], %f1 ++; abs64: ld [%[[R5]]+%[[R2]]], %f0 + + + ; v8pic32: floatCP +@@ -50,7 +50,7 @@ entry: + ; v9pic32: sethi %hi(.LCPI0_0), %[[R1:[gilo][0-7]]] + ; v9pic32: add %[[R1]], %lo(.LCPI0_0), %[[Goffs:[gilo][0-7]]] + ; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] +-; v9pic32: ld [%[[Gaddr]]], %f1 ++; v9pic32: ld [%[[Gaddr]]], %f0 + ; v9pic32: ret + ; v9pic32: restore + +Index: test/CodeGen/SPARC/64cond.ll +=================================================================== +--- test/CodeGen/SPARC/64cond.ll ++++ test/CodeGen/SPARC/64cond.ll +@@ -80,7 +80,7 @@ entry: + ; CHECK: selectf32_xcc + ; CHECK: cmp %i0, %i1 + ; CHECK: fmovsg %xcc, %f5, %f7 +-; CHECK: fmovs %f7, %f1 ++; CHECK: fmovs %f7, %f0 + define float @selectf32_xcc(i64 %x, i64 %y, float %a, float %b) { + entry: + %tobool = icmp sgt i64 %x, %y +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -254,7 +254,7 @@ SparcTargetLowering::LowerReturn_64(SDValue Chain, + DAG.getTarget(), RVLocs, *DAG.getContext()); + + // Analyze return values. +- CCInfo.AnalyzeReturn(Outs, CC_Sparc64); ++ CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64); + + SDValue Flag; + SmallVector RetOps(1, Chain); +@@ -1258,7 +1258,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering:: + if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && CLI.CS == 0) + CLI.Ins[0].Flags.setInReg(); + +- RVInfo.AnalyzeCallResult(CLI.Ins, CC_Sparc64); ++ RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { +Index: lib/Target/Sparc/SparcCallingConv.td +=================================================================== +--- lib/Target/Sparc/SparcCallingConv.td ++++ lib/Target/Sparc/SparcCallingConv.td +@@ -103,7 +103,7 @@ def RetCC_Sparc32 : CallingConv<[ + // Function return values are passed exactly like function arguments, except a + // struct up to 32 bytes in size can be returned in registers. + +-// Function arguments AND return values. ++// Function arguments AND most return values. + def CC_Sparc64 : CallingConv<[ + // The frontend uses the inreg flag to indicate i32 and float arguments from + // structs. These arguments are not promoted to 64 bits, but they can still +@@ -118,6 +118,15 @@ def CC_Sparc64 : CallingConv<[ + CCCustom<"CC_Sparc64_Full"> + ]>; + ++def RetCC_Sparc64 : CallingConv<[ ++ // A single f32 return value always goes in %f0. The ABI doesn't specify what ++ // happens to multiple f32 return values outside a struct. ++ CCIfType<[f32], CCCustom<"CC_Sparc64_Half">>, ++ ++ // Otherwise, return values are passed exactly like arguments. ++ CCDelegateTo ++]>; ++ + // Callee-saved registers are handled by the register window mechanism. + def CSR : CalleeSavedRegs<(add)> { + let OtherPreserved = (add (sequence "I%u", 0, 7), diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199031-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199031-sparc.diff new file mode 100644 index 000000000000..5eb954959f48 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199031-sparc.diff @@ -0,0 +1,42 @@ +Pull in r199031 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Replace (unsigned)-1 with ~OU as suggested by Reid Kleckner. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +=================================================================== +--- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp ++++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +@@ -104,14 +104,14 @@ static const unsigned DFPRegDecoderTable[] = { + SP::D14, SP::D30, SP::D15, SP::D31 }; + + static const unsigned QFPRegDecoderTable[] = { +- SP::Q0, SP::Q8, (unsigned)-1, (unsigned)-1, +- SP::Q1, SP::Q9, (unsigned)-1, (unsigned)-1, +- SP::Q2, SP::Q10, (unsigned)-1, (unsigned)-1, +- SP::Q3, SP::Q11, (unsigned)-1, (unsigned)-1, +- SP::Q4, SP::Q12, (unsigned)-1, (unsigned)-1, +- SP::Q5, SP::Q13, (unsigned)-1, (unsigned)-1, +- SP::Q6, SP::Q14, (unsigned)-1, (unsigned)-1, +- SP::Q7, SP::Q15, (unsigned)-1, (unsigned)-1 } ; ++ SP::Q0, SP::Q8, ~0U, ~0U, ++ SP::Q1, SP::Q9, ~0U, ~0U, ++ SP::Q2, SP::Q10, ~0U, ~0U, ++ SP::Q3, SP::Q11, ~0U, ~0U, ++ SP::Q4, SP::Q12, ~0U, ~0U, ++ SP::Q5, SP::Q13, ~0U, ~0U, ++ SP::Q6, SP::Q14, ~0U, ~0U, ++ SP::Q7, SP::Q15, ~0U, ~0U } ; + + static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, + unsigned RegNo, +@@ -168,7 +168,7 @@ static DecodeStatus DecodeQFPRegsRegisterClass(MCI + return MCDisassembler::Fail; + + unsigned Reg = QFPRegDecoderTable[RegNo]; +- if (Reg == (unsigned)-1) ++ if (Reg == ~0U) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::CreateReg(Reg)); + return MCDisassembler::Success; diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199033-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199033-sparc.diff new file mode 100644 index 000000000000..c4b343804a24 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199033-sparc.diff @@ -0,0 +1,944 @@ +Pull in r199033 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add support for parsing floating point instructions. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -601,91 +601,91 @@ let Defs = [Y], rd = 0 in { + } + // Convert Integer to Floating-point Instructions, p. 141 + def FITOS : F3_3u<2, 0b110100, 0b011000100, +- (outs FPRegs:$dst), (ins FPRegs:$src), +- "fitos $src, $dst", +- [(set FPRegs:$dst, (SPitof FPRegs:$src))]>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs2), ++ "fitos $rs2, $rd", ++ [(set FPRegs:$rd, (SPitof FPRegs:$rs2))]>; + def FITOD : F3_3u<2, 0b110100, 0b011001000, +- (outs DFPRegs:$dst), (ins FPRegs:$src), +- "fitod $src, $dst", +- [(set DFPRegs:$dst, (SPitof FPRegs:$src))]>; ++ (outs DFPRegs:$rd), (ins FPRegs:$rs2), ++ "fitod $rs2, $rd", ++ [(set DFPRegs:$rd, (SPitof FPRegs:$rs2))]>; + def FITOQ : F3_3u<2, 0b110100, 0b011001100, +- (outs QFPRegs:$dst), (ins FPRegs:$src), +- "fitoq $src, $dst", +- [(set QFPRegs:$dst, (SPitof FPRegs:$src))]>, ++ (outs QFPRegs:$rd), (ins FPRegs:$rs2), ++ "fitoq $rs2, $rd", ++ [(set QFPRegs:$rd, (SPitof FPRegs:$rs2))]>, + Requires<[HasHardQuad]>; + + // Convert Floating-point to Integer Instructions, p. 142 + def FSTOI : F3_3u<2, 0b110100, 0b011010001, +- (outs FPRegs:$dst), (ins FPRegs:$src), +- "fstoi $src, $dst", +- [(set FPRegs:$dst, (SPftoi FPRegs:$src))]>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs2), ++ "fstoi $rs2, $rd", ++ [(set FPRegs:$rd, (SPftoi FPRegs:$rs2))]>; + def FDTOI : F3_3u<2, 0b110100, 0b011010010, +- (outs FPRegs:$dst), (ins DFPRegs:$src), +- "fdtoi $src, $dst", +- [(set FPRegs:$dst, (SPftoi DFPRegs:$src))]>; ++ (outs FPRegs:$rd), (ins DFPRegs:$rs2), ++ "fdtoi $rs2, $rd", ++ [(set FPRegs:$rd, (SPftoi DFPRegs:$rs2))]>; + def FQTOI : F3_3u<2, 0b110100, 0b011010011, +- (outs FPRegs:$dst), (ins QFPRegs:$src), +- "fqtoi $src, $dst", +- [(set FPRegs:$dst, (SPftoi QFPRegs:$src))]>, ++ (outs FPRegs:$rd), (ins QFPRegs:$rs2), ++ "fqtoi $rs2, $rd", ++ [(set FPRegs:$rd, (SPftoi QFPRegs:$rs2))]>, + Requires<[HasHardQuad]>; + + // Convert between Floating-point Formats Instructions, p. 143 + def FSTOD : F3_3u<2, 0b110100, 0b011001001, +- (outs DFPRegs:$dst), (ins FPRegs:$src), +- "fstod $src, $dst", +- [(set f64:$dst, (fextend f32:$src))]>; ++ (outs DFPRegs:$rd), (ins FPRegs:$rs2), ++ "fstod $rs2, $rd", ++ [(set f64:$rd, (fextend f32:$rs2))]>; + def FSTOQ : F3_3u<2, 0b110100, 0b011001101, +- (outs QFPRegs:$dst), (ins FPRegs:$src), +- "fstoq $src, $dst", +- [(set f128:$dst, (fextend f32:$src))]>, ++ (outs QFPRegs:$rd), (ins FPRegs:$rs2), ++ "fstoq $rs2, $rd", ++ [(set f128:$rd, (fextend f32:$rs2))]>, + Requires<[HasHardQuad]>; + def FDTOS : F3_3u<2, 0b110100, 0b011000110, +- (outs FPRegs:$dst), (ins DFPRegs:$src), +- "fdtos $src, $dst", +- [(set f32:$dst, (fround f64:$src))]>; +-def FDTOQ : F3_3u<2, 0b110100, 0b01101110, +- (outs QFPRegs:$dst), (ins DFPRegs:$src), +- "fdtoq $src, $dst", +- [(set f128:$dst, (fextend f64:$src))]>, ++ (outs FPRegs:$rd), (ins DFPRegs:$rs2), ++ "fdtos $rs2, $rd", ++ [(set f32:$rd, (fround f64:$rs2))]>; ++def FDTOQ : F3_3u<2, 0b110100, 0b011001110, ++ (outs QFPRegs:$rd), (ins DFPRegs:$rs2), ++ "fdtoq $rs2, $rd", ++ [(set f128:$rd, (fextend f64:$rs2))]>, + Requires<[HasHardQuad]>; + def FQTOS : F3_3u<2, 0b110100, 0b011000111, +- (outs FPRegs:$dst), (ins QFPRegs:$src), +- "fqtos $src, $dst", +- [(set f32:$dst, (fround f128:$src))]>, ++ (outs FPRegs:$rd), (ins QFPRegs:$rs2), ++ "fqtos $rs2, $rd", ++ [(set f32:$rd, (fround f128:$rs2))]>, + Requires<[HasHardQuad]>; + def FQTOD : F3_3u<2, 0b110100, 0b011001011, +- (outs DFPRegs:$dst), (ins QFPRegs:$src), +- "fqtod $src, $dst", +- [(set f64:$dst, (fround f128:$src))]>, ++ (outs DFPRegs:$rd), (ins QFPRegs:$rs2), ++ "fqtod $rs2, $rd", ++ [(set f64:$rd, (fround f128:$rs2))]>, + Requires<[HasHardQuad]>; + + // Floating-point Move Instructions, p. 144 + def FMOVS : F3_3u<2, 0b110100, 0b000000001, +- (outs FPRegs:$dst), (ins FPRegs:$src), +- "fmovs $src, $dst", []>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs2), ++ "fmovs $rs2, $rd", []>; + def FNEGS : F3_3u<2, 0b110100, 0b000000101, +- (outs FPRegs:$dst), (ins FPRegs:$src), +- "fnegs $src, $dst", +- [(set f32:$dst, (fneg f32:$src))]>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs2), ++ "fnegs $rs2, $rd", ++ [(set f32:$rd, (fneg f32:$rs2))]>; + def FABSS : F3_3u<2, 0b110100, 0b000001001, +- (outs FPRegs:$dst), (ins FPRegs:$src), +- "fabss $src, $dst", +- [(set f32:$dst, (fabs f32:$src))]>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs2), ++ "fabss $rs2, $rd", ++ [(set f32:$rd, (fabs f32:$rs2))]>; + + + // Floating-point Square Root Instructions, p.145 + def FSQRTS : F3_3u<2, 0b110100, 0b000101001, +- (outs FPRegs:$dst), (ins FPRegs:$src), +- "fsqrts $src, $dst", +- [(set f32:$dst, (fsqrt f32:$src))]>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs2), ++ "fsqrts $rs2, $rd", ++ [(set f32:$rd, (fsqrt f32:$rs2))]>; + def FSQRTD : F3_3u<2, 0b110100, 0b000101010, +- (outs DFPRegs:$dst), (ins DFPRegs:$src), +- "fsqrtd $src, $dst", +- [(set f64:$dst, (fsqrt f64:$src))]>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs2), ++ "fsqrtd $rs2, $rd", ++ [(set f64:$rd, (fsqrt f64:$rs2))]>; + def FSQRTQ : F3_3u<2, 0b110100, 0b000101011, +- (outs QFPRegs:$dst), (ins QFPRegs:$src), +- "fsqrtq $src, $dst", +- [(set f128:$dst, (fsqrt f128:$src))]>, ++ (outs QFPRegs:$rd), (ins QFPRegs:$rs2), ++ "fsqrtq $rs2, $rd", ++ [(set f128:$rd, (fsqrt f128:$rs2))]>, + Requires<[HasHardQuad]>; + + +@@ -692,73 +692,73 @@ def FSQRTQ : F3_3u<2, 0b110100, 0b000101011, + + // Floating-point Add and Subtract Instructions, p. 146 + def FADDS : F3_3<2, 0b110100, 0b001000001, +- (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2), +- "fadds $src1, $src2, $dst", +- [(set f32:$dst, (fadd f32:$src1, f32:$src2))]>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), ++ "fadds $rs1, $rs2, $rd", ++ [(set f32:$rd, (fadd f32:$rs1, f32:$rs2))]>; + def FADDD : F3_3<2, 0b110100, 0b001000010, +- (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2), +- "faddd $src1, $src2, $dst", +- [(set f64:$dst, (fadd f64:$src1, f64:$src2))]>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), ++ "faddd $rs1, $rs2, $rd", ++ [(set f64:$rd, (fadd f64:$rs1, f64:$rs2))]>; + def FADDQ : F3_3<2, 0b110100, 0b001000011, +- (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2), +- "faddq $src1, $src2, $dst", +- [(set f128:$dst, (fadd f128:$src1, f128:$src2))]>, ++ (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), ++ "faddq $rs1, $rs2, $rd", ++ [(set f128:$rd, (fadd f128:$rs1, f128:$rs2))]>, + Requires<[HasHardQuad]>; + + def FSUBS : F3_3<2, 0b110100, 0b001000101, +- (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2), +- "fsubs $src1, $src2, $dst", +- [(set f32:$dst, (fsub f32:$src1, f32:$src2))]>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), ++ "fsubs $rs1, $rs2, $rd", ++ [(set f32:$rd, (fsub f32:$rs1, f32:$rs2))]>; + def FSUBD : F3_3<2, 0b110100, 0b001000110, +- (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2), +- "fsubd $src1, $src2, $dst", +- [(set f64:$dst, (fsub f64:$src1, f64:$src2))]>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), ++ "fsubd $rs1, $rs2, $rd", ++ [(set f64:$rd, (fsub f64:$rs1, f64:$rs2))]>; + def FSUBQ : F3_3<2, 0b110100, 0b001000111, +- (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2), +- "fsubq $src1, $src2, $dst", +- [(set f128:$dst, (fsub f128:$src1, f128:$src2))]>, ++ (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), ++ "fsubq $rs1, $rs2, $rd", ++ [(set f128:$rd, (fsub f128:$rs1, f128:$rs2))]>, + Requires<[HasHardQuad]>; + + + // Floating-point Multiply and Divide Instructions, p. 147 + def FMULS : F3_3<2, 0b110100, 0b001001001, +- (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2), +- "fmuls $src1, $src2, $dst", +- [(set f32:$dst, (fmul f32:$src1, f32:$src2))]>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), ++ "fmuls $rs1, $rs2, $rd", ++ [(set f32:$rd, (fmul f32:$rs1, f32:$rs2))]>; + def FMULD : F3_3<2, 0b110100, 0b001001010, +- (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2), +- "fmuld $src1, $src2, $dst", +- [(set f64:$dst, (fmul f64:$src1, f64:$src2))]>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), ++ "fmuld $rs1, $rs2, $rd", ++ [(set f64:$rd, (fmul f64:$rs1, f64:$rs2))]>; + def FMULQ : F3_3<2, 0b110100, 0b001001011, +- (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2), +- "fmulq $src1, $src2, $dst", +- [(set f128:$dst, (fmul f128:$src1, f128:$src2))]>, ++ (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), ++ "fmulq $rs1, $rs2, $rd", ++ [(set f128:$rd, (fmul f128:$rs1, f128:$rs2))]>, + Requires<[HasHardQuad]>; + + def FSMULD : F3_3<2, 0b110100, 0b001101001, +- (outs DFPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2), +- "fsmuld $src1, $src2, $dst", +- [(set f64:$dst, (fmul (fextend f32:$src1), +- (fextend f32:$src2)))]>; ++ (outs DFPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), ++ "fsmuld $rs1, $rs2, $rd", ++ [(set f64:$rd, (fmul (fextend f32:$rs1), ++ (fextend f32:$rs2)))]>; + def FDMULQ : F3_3<2, 0b110100, 0b001101110, +- (outs QFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2), +- "fdmulq $src1, $src2, $dst", +- [(set f128:$dst, (fmul (fextend f64:$src1), +- (fextend f64:$src2)))]>, ++ (outs QFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), ++ "fdmulq $rs1, $rs2, $rd", ++ [(set f128:$rd, (fmul (fextend f64:$rs1), ++ (fextend f64:$rs2)))]>, + Requires<[HasHardQuad]>; + + def FDIVS : F3_3<2, 0b110100, 0b001001101, +- (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2), +- "fdivs $src1, $src2, $dst", +- [(set f32:$dst, (fdiv f32:$src1, f32:$src2))]>; ++ (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), ++ "fdivs $rs1, $rs2, $rd", ++ [(set f32:$rd, (fdiv f32:$rs1, f32:$rs2))]>; + def FDIVD : F3_3<2, 0b110100, 0b001001110, +- (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2), +- "fdivd $src1, $src2, $dst", +- [(set f64:$dst, (fdiv f64:$src1, f64:$src2))]>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), ++ "fdivd $rs1, $rs2, $rd", ++ [(set f64:$rd, (fdiv f64:$rs1, f64:$rs2))]>; + def FDIVQ : F3_3<2, 0b110100, 0b001001111, +- (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2), +- "fdivq $src1, $src2, $dst", +- [(set f128:$dst, (fdiv f128:$src1, f128:$src2))]>, ++ (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), ++ "fdivq $rs1, $rs2, $rd", ++ [(set f128:$rd, (fdiv f128:$rs1, f128:$rs2))]>, + Requires<[HasHardQuad]>; + + // Floating-point Compare Instructions, p. 148 +@@ -770,17 +770,17 @@ def FDIVQ : F3_3<2, 0b110100, 0b001001111, + + let Defs = [FCC] in { + def FCMPS : F3_3c<2, 0b110101, 0b001010001, +- (outs), (ins FPRegs:$src1, FPRegs:$src2), +- "fcmps $src1, $src2", +- [(SPcmpfcc f32:$src1, f32:$src2)]>; ++ (outs), (ins FPRegs:$rs1, FPRegs:$rs2), ++ "fcmps $rs1, $rs2", ++ [(SPcmpfcc f32:$rs1, f32:$rs2)]>; + def FCMPD : F3_3c<2, 0b110101, 0b001010010, +- (outs), (ins DFPRegs:$src1, DFPRegs:$src2), +- "fcmpd $src1, $src2", +- [(SPcmpfcc f64:$src1, f64:$src2)]>; ++ (outs), (ins DFPRegs:$rs1, DFPRegs:$rs2), ++ "fcmpd $rs1, $rs2", ++ [(SPcmpfcc f64:$rs1, f64:$rs2)]>; + def FCMPQ : F3_3c<2, 0b110101, 0b001010011, +- (outs), (ins QFPRegs:$src1, QFPRegs:$src2), +- "fcmpq $src1, $src2", +- [(SPcmpfcc f128:$src1, f128:$src2)]>, ++ (outs), (ins QFPRegs:$rs1, QFPRegs:$rs2), ++ "fcmpq $rs1, $rs2", ++ [(SPcmpfcc f128:$rs1, f128:$rs2)]>, + Requires<[HasHardQuad]>; + } + +@@ -892,29 +892,29 @@ let Predicates = [HasV9], Constraints = "$f = $rd" + // Floating-Point Move Instructions, p. 164 of the V9 manual. + let Predicates = [HasV9] in { + def FMOVD : F3_3u<2, 0b110100, 0b000000010, +- (outs DFPRegs:$dst), (ins DFPRegs:$src), +- "fmovd $src, $dst", []>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs2), ++ "fmovd $rs2, $rd", []>; + def FMOVQ : F3_3u<2, 0b110100, 0b000000011, +- (outs QFPRegs:$dst), (ins QFPRegs:$src), +- "fmovq $src, $dst", []>, ++ (outs QFPRegs:$rd), (ins QFPRegs:$rs2), ++ "fmovq $rs2, $rd", []>, + Requires<[HasHardQuad]>; + def FNEGD : F3_3u<2, 0b110100, 0b000000110, +- (outs DFPRegs:$dst), (ins DFPRegs:$src), +- "fnegd $src, $dst", +- [(set f64:$dst, (fneg f64:$src))]>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs2), ++ "fnegd $rs2, $rd", ++ [(set f64:$rd, (fneg f64:$rs2))]>; + def FNEGQ : F3_3u<2, 0b110100, 0b000000111, +- (outs QFPRegs:$dst), (ins QFPRegs:$src), +- "fnegq $src, $dst", +- [(set f128:$dst, (fneg f128:$src))]>, ++ (outs QFPRegs:$rd), (ins QFPRegs:$rs2), ++ "fnegq $rs2, $rd", ++ [(set f128:$rd, (fneg f128:$rs2))]>, + Requires<[HasHardQuad]>; + def FABSD : F3_3u<2, 0b110100, 0b000001010, +- (outs DFPRegs:$dst), (ins DFPRegs:$src), +- "fabsd $src, $dst", +- [(set f64:$dst, (fabs f64:$src))]>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs2), ++ "fabsd $rs2, $rd", ++ [(set f64:$rd, (fabs f64:$rs2))]>; + def FABSQ : F3_3u<2, 0b110100, 0b000001011, +- (outs QFPRegs:$dst), (ins QFPRegs:$src), +- "fabsq $src, $dst", +- [(set f128:$dst, (fabs f128:$src))]>, ++ (outs QFPRegs:$rd), (ins QFPRegs:$rs2), ++ "fabsq $rs2, $rd", ++ [(set f128:$rd, (fabs f128:$rs2))]>, + Requires<[HasHardQuad]>; + } + +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -54,6 +54,8 @@ class SparcAsmParser : public MCTargetAsmParser { + SmallVectorImpl &Operands); + bool ParseDirective(AsmToken DirectiveID); + ++ virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op, ++ unsigned Kind); + + // Custom parse functions for Sparc specific operands. + OperandMatchResultTy +@@ -67,8 +69,9 @@ class SparcAsmParser : public MCTargetAsmParser { + parseSparcAsmOperand(SparcOperand *&Operand); + + // returns true if Tok is matched to a register and returns register in RegNo. +- bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP, +- bool isQFP); ++ bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, ++ unsigned &RegKind); ++ + bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc); + + public: +@@ -178,6 +181,16 @@ class SparcOperand : public MCParsedAsmOperand { + bool isMEMrr() const { return Kind == k_MemoryReg; } + bool isMEMri() const { return Kind == k_MemoryImm; } + ++ bool isFloatReg() const { ++ return (Kind == k_Register && Reg.Kind == rk_FloatReg); ++ } ++ ++ bool isFloatOrDoubleReg() const { ++ return (Kind == k_Register && (Reg.Kind == rk_FloatReg ++ || Reg.Kind == rk_DoubleReg)); ++ } ++ ++ + StringRef getToken() const { + assert(Kind == k_Token && "Invalid access!"); + return StringRef(Tok.Data, Tok.Length); +@@ -280,11 +293,11 @@ class SparcOperand : public MCParsedAsmOperand { + } + + static SparcOperand *CreateReg(unsigned RegNum, +- SparcOperand::RegisterKind Kind, ++ unsigned Kind, + SMLoc S, SMLoc E) { + SparcOperand *Op = new SparcOperand(k_Register); + Op->Reg.RegNum = RegNum; +- Op->Reg.Kind = Kind; ++ Op->Reg.Kind = (SparcOperand::RegisterKind)Kind; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; +@@ -298,6 +311,40 @@ class SparcOperand : public MCParsedAsmOperand { + return Op; + } + ++ static SparcOperand *MorphToDoubleReg(SparcOperand *Op) { ++ unsigned Reg = Op->getReg(); ++ assert(Op->Reg.Kind == rk_FloatReg); ++ unsigned regIdx = Reg - Sparc::F0; ++ if (regIdx % 2 || regIdx > 31) ++ return 0; ++ Op->Reg.RegNum = DoubleRegs[regIdx / 2]; ++ Op->Reg.Kind = rk_DoubleReg; ++ return Op; ++ } ++ ++ static SparcOperand *MorphToQuadReg(SparcOperand *Op) { ++ unsigned Reg = Op->getReg(); ++ unsigned regIdx = 0; ++ switch (Op->Reg.Kind) { ++ default: assert(0 && "Unexpected register kind!"); ++ case rk_FloatReg: ++ regIdx = Reg - Sparc::F0; ++ if (regIdx % 4 || regIdx > 31) ++ return 0; ++ Reg = QuadFPRegs[regIdx / 4]; ++ break; ++ case rk_DoubleReg: ++ regIdx = Reg - Sparc::D0; ++ if (regIdx % 2 || regIdx > 31) ++ return 0; ++ Reg = QuadFPRegs[regIdx / 2]; ++ break; ++ } ++ Op->Reg.RegNum = Reg; ++ Op->Reg.Kind = rk_QuadReg; ++ return Op; ++ } ++ + static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) { + unsigned offsetReg = Op->getReg(); + Op->Kind = k_MemoryReg; +@@ -383,7 +430,8 @@ ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SM + if (getLexer().getKind() != AsmToken::Percent) + return false; + Parser.Lex(); +- if (matchRegisterName(Tok, RegNo, false, false)) { ++ unsigned regKind = SparcOperand::rk_None; ++ if (matchRegisterName(Tok, RegNo, regKind)) { + Parser.Lex(); + return false; + } +@@ -537,13 +585,14 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand + case AsmToken::Percent: + Parser.Lex(); // Eat the '%'. + unsigned RegNo; +- if (matchRegisterName(Parser.getTok(), RegNo, false, false)) { ++ unsigned RegKind; ++ if (matchRegisterName(Parser.getTok(), RegNo, RegKind)) { + StringRef name = Parser.getTok().getString(); + Parser.Lex(); // Eat the identifier token. + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + switch (RegNo) { + default: +- Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E); ++ Op = SparcOperand::CreateReg(RegNo, RegKind, S, E); + break; + case Sparc::Y: + Op = SparcOperand::CreateToken("%y", S); +@@ -593,11 +642,11 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand + + bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, + unsigned &RegNo, +- bool isDFP, +- bool isQFP) ++ unsigned &RegKind) + { + int64_t intVal = 0; + RegNo = 0; ++ RegKind = SparcOperand::rk_None; + if (Tok.is(AsmToken::Identifier)) { + StringRef name = Tok.getString(); + +@@ -604,21 +653,25 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + // %fp + if (name.equals("fp")) { + RegNo = Sparc::I6; ++ RegKind = SparcOperand::rk_IntReg; + return true; + } + // %sp + if (name.equals("sp")) { + RegNo = Sparc::O6; ++ RegKind = SparcOperand::rk_IntReg; + return true; + } + + if (name.equals("y")) { + RegNo = Sparc::Y; ++ RegKind = SparcOperand::rk_Y; + return true; + } + + if (name.equals("icc")) { + RegNo = Sparc::ICC; ++ RegKind = SparcOperand::rk_CCReg; + return true; + } + +@@ -625,6 +678,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + if (name.equals("xcc")) { + // FIXME:: check 64bit. + RegNo = Sparc::ICC; ++ RegKind = SparcOperand::rk_CCReg; + return true; + } + +@@ -634,6 +688,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + && intVal < 4) { + // FIXME: check 64bit and handle %fcc1 - %fcc3 + RegNo = Sparc::FCC; ++ RegKind = SparcOperand::rk_CCReg; + return true; + } + +@@ -642,6 +697,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + && !name.substr(1).getAsInteger(10, intVal) + && intVal < 8) { + RegNo = IntRegs[intVal]; ++ RegKind = SparcOperand::rk_IntReg; + return true; + } + // %o0 - %o7 +@@ -649,6 +705,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + && !name.substr(1).getAsInteger(10, intVal) + && intVal < 8) { + RegNo = IntRegs[8 + intVal]; ++ RegKind = SparcOperand::rk_IntReg; + return true; + } + if (name.substr(0, 1).equals_lower("l") +@@ -655,6 +712,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + && !name.substr(1).getAsInteger(10, intVal) + && intVal < 8) { + RegNo = IntRegs[16 + intVal]; ++ RegKind = SparcOperand::rk_IntReg; + return true; + } + if (name.substr(0, 1).equals_lower("i") +@@ -661,18 +719,14 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + && !name.substr(1).getAsInteger(10, intVal) + && intVal < 8) { + RegNo = IntRegs[24 + intVal]; ++ RegKind = SparcOperand::rk_IntReg; + return true; + } + // %f0 - %f31 + if (name.substr(0, 1).equals_lower("f") + && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) { +- if (isDFP && (intVal%2 == 0)) { +- RegNo = DoubleRegs[intVal/2]; +- } else if (isQFP && (intVal%4 == 0)) { +- RegNo = QuadFPRegs[intVal/4]; +- } else { +- RegNo = FloatRegs[intVal]; +- } ++ RegNo = FloatRegs[intVal]; ++ RegKind = SparcOperand::rk_FloatReg; + return true; + } + // %f32 - %f62 +@@ -679,13 +733,9 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + if (name.substr(0, 1).equals_lower("f") + && !name.substr(1, 2).getAsInteger(10, intVal) + && intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) { +- if (isDFP) { +- RegNo = DoubleRegs[16 + intVal/2]; +- } else if (isQFP && (intVal % 4 == 0)) { +- RegNo = QuadFPRegs[8 + intVal/4]; +- } else { +- return false; +- } ++ // FIXME: Check V9 ++ RegNo = DoubleRegs[16 + intVal/2]; ++ RegKind = SparcOperand::rk_DoubleReg; + return true; + } + +@@ -693,6 +743,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + if (name.substr(0, 1).equals_lower("r") + && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) { + RegNo = IntRegs[intVal]; ++ RegKind = SparcOperand::rk_IntReg; + return true; + } + } +@@ -735,3 +786,26 @@ extern "C" void LLVMInitializeSparcAsmParser() { + #define GET_REGISTER_MATCHER + #define GET_MATCHER_IMPLEMENTATION + #include "SparcGenAsmMatcher.inc" ++ ++ ++ ++unsigned SparcAsmParser:: ++validateTargetOperandClass(MCParsedAsmOperand *GOp, ++ unsigned Kind) ++{ ++ SparcOperand *Op = (SparcOperand*)GOp; ++ if (Op->isFloatOrDoubleReg()) { ++ switch (Kind) { ++ default: break; ++ case MCK_DFPRegs: ++ if (!Op->isFloatReg() || SparcOperand::MorphToDoubleReg(Op)) ++ return MCTargetAsmParser::Match_Success; ++ break; ++ case MCK_QFPRegs: ++ if (SparcOperand::MorphToQuadReg(Op)) ++ return MCTargetAsmParser::Match_Success; ++ break; ++ } ++ } ++ return Match_InvalidOperand; ++} +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -358,31 +358,31 @@ def FMOVQ_XCC : F4_3<0b110101, 0b000011, (outs QFP + let Predicates = [Is64Bit] in { + + def FXTOS : F3_3u<2, 0b110100, 0b010000100, +- (outs FPRegs:$dst), (ins DFPRegs:$src), +- "fxtos $src, $dst", +- [(set FPRegs:$dst, (SPxtof DFPRegs:$src))]>; ++ (outs FPRegs:$rd), (ins DFPRegs:$rs2), ++ "fxtos $rs2, $rd", ++ [(set FPRegs:$rd, (SPxtof DFPRegs:$rs2))]>; + def FXTOD : F3_3u<2, 0b110100, 0b010001000, +- (outs DFPRegs:$dst), (ins DFPRegs:$src), +- "fxtod $src, $dst", +- [(set DFPRegs:$dst, (SPxtof DFPRegs:$src))]>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs2), ++ "fxtod $rs2, $rd", ++ [(set DFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>; + def FXTOQ : F3_3u<2, 0b110100, 0b010001100, +- (outs QFPRegs:$dst), (ins DFPRegs:$src), +- "fxtoq $src, $dst", +- [(set QFPRegs:$dst, (SPxtof DFPRegs:$src))]>, ++ (outs QFPRegs:$rd), (ins DFPRegs:$rs2), ++ "fxtoq $rs2, $rd", ++ [(set QFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>, + Requires<[HasHardQuad]>; + + def FSTOX : F3_3u<2, 0b110100, 0b010000001, +- (outs DFPRegs:$dst), (ins FPRegs:$src), +- "fstox $src, $dst", +- [(set DFPRegs:$dst, (SPftox FPRegs:$src))]>; ++ (outs DFPRegs:$rd), (ins FPRegs:$rs2), ++ "fstox $rs2, $rd", ++ [(set DFPRegs:$rd, (SPftox FPRegs:$rs2))]>; + def FDTOX : F3_3u<2, 0b110100, 0b010000010, +- (outs DFPRegs:$dst), (ins DFPRegs:$src), +- "fdtox $src, $dst", +- [(set DFPRegs:$dst, (SPftox DFPRegs:$src))]>; ++ (outs DFPRegs:$rd), (ins DFPRegs:$rs2), ++ "fdtox $rs2, $rd", ++ [(set DFPRegs:$rd, (SPftox DFPRegs:$rs2))]>; + def FQTOX : F3_3u<2, 0b110100, 0b010000011, +- (outs DFPRegs:$dst), (ins QFPRegs:$src), +- "fqtox $src, $dst", +- [(set DFPRegs:$dst, (SPftox QFPRegs:$src))]>, ++ (outs DFPRegs:$rd), (ins QFPRegs:$rs2), ++ "fqtox $rs2, $rd", ++ [(set DFPRegs:$rd, (SPftox QFPRegs:$rs2))]>, + Requires<[HasHardQuad]>; + + } // Predicates = [Is64Bit] +Index: test/MC/Disassembler/Sparc/sparc-fp.txt +=================================================================== +--- test/MC/Disassembler/Sparc/sparc-fp.txt ++++ test/MC/Disassembler/Sparc/sparc-fp.txt +@@ -0,0 +1,142 @@ ++# RUN: llvm-mc --disassemble %s -triple=sparc64-linux-gnu | FileCheck %s ++ ++ ++# CHECK: fitos %f0, %f4 ++0x89 0xa0 0x18 0x80 ++ ++# CHECK: fitod %f0, %f4 ++0x89 0xa0 0x19 0x00 ++ ++# CHECK: fitoq %f0, %f4 ++0x89 0xa0 0x19 0x80 ++ ++# CHECK: fstoi %f0, %f4 ++0x89 0xa0 0x1a 0x20 ++ ++# CHECK: fdtoi %f0, %f4 ++0x89 0xa0 0x1a 0x40 ++ ++# CHECK: fqtoi %f0, %f4 ++0x89 0xa0 0x1a 0x60 ++ ++# CHECK: fstod %f0, %f4 ++0x89 0xa0 0x19 0x20 ++# CHECK: fstoq %f0, %f4 ++0x89 0xa0 0x19 0xa0 ++ ++# CHECK: fdtos %f0, %f4 ++0x89 0xa0 0x18 0xc0 ++ ++# CHECK: fdtoq %f0, %f4 ++0x89 0xa0 0x19 0xc0 ++ ++# CHECK: fqtos %f0, %f4 ++0x89 0xa0 0x18 0xe0 ++ ++# CHECK: fqtod %f0, %f4 ++0x89 0xa0 0x19 0x60 ++ ++# CHECK: fmovs %f0, %f4 ++0x89 0xa0 0x00 0x20 ++ ++# CHECK: fmovd %f0, %f4 ++0x89 0xa0 0x00 0x40 ++ ++# CHECK: fmovq %f0, %f4 ++0x89 0xa0 0x00 0x60 ++ ++# CHECK: fnegs %f0, %f4 ++0x89 0xa0 0x00 0xa0 ++ ++# CHECK: fnegd %f0, %f4 ++0x89 0xa0 0x00 0xc0 ++ ++# CHECK: fnegq %f0, %f4 ++0x89 0xa0 0x00 0xe0 ++ ++# CHECK: fabss %f0, %f4 ++0x89 0xa0 0x01 0x20 ++ ++# CHECK: fabsd %f0, %f4 ++0x89 0xa0 0x01 0x40 ++ ++# CHECK: fabsq %f0, %f4 ++0x89 0xa0 0x01 0x60 ++ ++# CHECK: fsqrts %f0, %f4 ++0x89 0xa0 0x05 0x20 ++ ++# CHECK: fsqrtd %f0, %f4 ++0x89 0xa0 0x05 0x40 ++ ++# CHECK: fsqrtq %f0, %f4 ++0x89 0xa0 0x05 0x60 ++ ++# CHECK: fadds %f0, %f4, %f8 ++0x91 0xa0 0x08 0x24 ++ ++# CHECK: faddd %f0, %f4, %f8 ++0x91 0xa0 0x08 0x44 ++ ++# CHECK: faddq %f0, %f4, %f8 ++0x91 0xa0 0x08 0x64 ++ ++# CHECK: fsubs %f0, %f4, %f8 ++0x91 0xa0 0x08 0xa4 ++ ++# CHECK: fsubd %f0, %f4, %f8 ++0x91 0xa0 0x08 0xc4 ++ ++# CHECK: fsubq %f0, %f4, %f8 ++0x91 0xa0 0x08 0xe4 ++ ++# CHECK: fmuls %f0, %f4, %f8 ++0x91 0xa0 0x09 0x24 ++ ++# CHECK: fmuld %f0, %f4, %f8 ++0x91 0xa0 0x09 0x44 ++ ++# CHECK: fmulq %f0, %f4, %f8 ++0x91 0xa0 0x09 0x64 ++ ++# CHECK: fsmuld %f0, %f4, %f8 ++0x91 0xa0 0x0d 0x24 ++ ++# CHECK: fdmulq %f0, %f4, %f8 ++0x91 0xa0 0x0d 0xc4 ++ ++# CHECK: fdivs %f0, %f4, %f8 ++0x91 0xa0 0x09 0xa4 ++ ++# CHECK: fdivd %f0, %f4, %f8 ++0x91 0xa0 0x09 0xc4 ++ ++# CHECK: fdivq %f0, %f4, %f8 ++0x91 0xa0 0x09 0xe4 ++ ++# CHECK: fcmps %f0, %f4 ++0x81 0xa8 0x0a 0x24 ++ ++# CHECK: fcmpd %f0, %f4 ++0x81 0xa8 0x0a 0x44 ++ ++# CHECK: fcmpq %f0, %f4 ++0x81 0xa8 0x0a 0x64 ++ ++# CHECK: fxtos %f0, %f4 ++0x89 0xa0 0x10 0x80 ++ ++# CHECK: fxtod %f0, %f4 ++0x89 0xa0 0x11 0x00 ++ ++# CHECK: fxtoq %f0, %f4 ++0x89 0xa0 0x11 0x80 ++ ++# CHECK: fstox %f0, %f4 ++0x89 0xa0 0x10 0x20 ++ ++# CHECK: fdtox %f0, %f4 ++0x89 0xa0 0x10 0x40 ++ ++# CHECK: fqtox %f0, %f4 ++0x89 0xa0 0x10 0x60 +Index: test/MC/Sparc/sparc-fp-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-fp-instructions.s ++++ test/MC/Sparc/sparc-fp-instructions.s +@@ -0,0 +1,113 @@ ++! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s ++ ++ ! CHECK: fitos %f0, %f4 ! encoding: [0x89,0xa0,0x18,0x80] ++ ! CHECK: fitod %f0, %f4 ! encoding: [0x89,0xa0,0x19,0x00] ++ ! CHECK: fitoq %f0, %f4 ! encoding: [0x89,0xa0,0x19,0x80] ++ fitos %f0, %f4 ++ fitod %f0, %f4 ++ fitoq %f0, %f4 ++ ++ ! CHECK: fstoi %f0, %f4 ! encoding: [0x89,0xa0,0x1a,0x20] ++ ! CHECK: fdtoi %f0, %f4 ! encoding: [0x89,0xa0,0x1a,0x40] ++ ! CHECK: fqtoi %f0, %f4 ! encoding: [0x89,0xa0,0x1a,0x60] ++ fstoi %f0, %f4 ++ fdtoi %f0, %f4 ++ fqtoi %f0, %f4 ++ ++ ! CHECK: fstod %f0, %f4 ! encoding: [0x89,0xa0,0x19,0x20] ++ ! CHECK: fstoq %f0, %f4 ! encoding: [0x89,0xa0,0x19,0xa0] ++ fstod %f0, %f4 ++ fstoq %f0, %f4 ++ ++ ! CHECK: fdtos %f0, %f4 ! encoding: [0x89,0xa0,0x18,0xc0] ++ ! CHECK: fdtoq %f0, %f4 ! encoding: [0x89,0xa0,0x19,0xc0] ++ fdtos %f0, %f4 ++ fdtoq %f0, %f4 ++ ++ ! CHECK: fqtos %f0, %f4 ! encoding: [0x89,0xa0,0x18,0xe0] ++ ! CHECK: fqtod %f0, %f4 ! encoding: [0x89,0xa0,0x19,0x60] ++ fqtos %f0, %f4 ++ fqtod %f0, %f4 ++ ++ ! CHECK: fmovs %f0, %f4 ! encoding: [0x89,0xa0,0x00,0x20] ++ ! CHECK: fmovd %f0, %f4 ! encoding: [0x89,0xa0,0x00,0x40] ++ ! CHECK: fmovq %f0, %f4 ! encoding: [0x89,0xa0,0x00,0x60] ++ fmovs %f0, %f4 ++ fmovd %f0, %f4 ++ fmovq %f0, %f4 ++ ++ ! CHECK: fnegs %f0, %f4 ! encoding: [0x89,0xa0,0x00,0xa0] ++ ! CHECK: fnegd %f0, %f4 ! encoding: [0x89,0xa0,0x00,0xc0] ++ ! CHECK: fnegq %f0, %f4 ! encoding: [0x89,0xa0,0x00,0xe0] ++ fnegs %f0, %f4 ++ fnegd %f0, %f4 ++ fnegq %f0, %f4 ++ ++ ! CHECK: fabss %f0, %f4 ! encoding: [0x89,0xa0,0x01,0x20] ++ ! CHECK: fabsd %f0, %f4 ! encoding: [0x89,0xa0,0x01,0x40] ++ ! CHECK: fabsq %f0, %f4 ! encoding: [0x89,0xa0,0x01,0x60] ++ fabss %f0, %f4 ++ fabsd %f0, %f4 ++ fabsq %f0, %f4 ++ ++ ! CHECK: fsqrts %f0, %f4 ! encoding: [0x89,0xa0,0x05,0x20] ++ ! CHECK: fsqrtd %f0, %f4 ! encoding: [0x89,0xa0,0x05,0x40] ++ ! CHECK: fsqrtq %f0, %f4 ! encoding: [0x89,0xa0,0x05,0x60] ++ fsqrts %f0, %f4 ++ fsqrtd %f0, %f4 ++ fsqrtq %f0, %f4 ++ ++ ! CHECK: fadds %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0x24] ++ ! CHECK: faddd %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0x44] ++ ! CHECK: faddq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0x64] ++ fadds %f0, %f4, %f8 ++ faddd %f0, %f4, %f8 ++ faddq %f0, %f4, %f8 ++ ++ ! CHECK: fsubs %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0xa4] ++ ! CHECK: fsubd %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0xc4] ++ ! CHECK: fsubq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0xe4] ++ fsubs %f0, %f4, %f8 ++ fsubd %f0, %f4, %f8 ++ fsubq %f0, %f4, %f8 ++ ++ ! CHECK: fmuls %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0x24] ++ ! CHECK: fmuld %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0x44] ++ ! CHECK: fmulq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0x64] ++ fmuls %f0, %f4, %f8 ++ fmuld %f0, %f4, %f8 ++ fmulq %f0, %f4, %f8 ++ ++ ! CHECK: fsmuld %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x0d,0x24] ++ ! CHECK: fdmulq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x0d,0xc4] ++ fsmuld %f0, %f4, %f8 ++ fdmulq %f0, %f4, %f8 ++ ++ ! CHECK: fdivs %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0xa4] ++ ! CHECK: fdivd %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0xc4] ++ ! CHECK: fdivq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0xe4] ++ fdivs %f0, %f4, %f8 ++ fdivd %f0, %f4, %f8 ++ fdivq %f0, %f4, %f8 ++ ++ ! CHECK: fcmps %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x24] ++ ! CHECK: fcmpd %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x44] ++ ! CHECK: fcmpq %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x64] ++ fcmps %f0, %f4 ++ fcmpd %f0, %f4 ++ fcmpq %f0, %f4 ++ ++ ! CHECK: fxtos %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x80] ++ ! CHECK: fxtod %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x00] ++ ! CHECK: fxtoq %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x80] ++ fxtos %f0, %f4 ++ fxtod %f0, %f4 ++ fxtoq %f0, %f4 ++ ++ ! CHECK: fstox %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x20] ++ ! CHECK: fdtox %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x40] ++ ! CHECK: fqtox %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x60] ++ fstox %f0, %f4 ++ fdtox %f0, %f4 ++ fqtox %f0, %f4 ++ diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199061-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199061-sparc.diff new file mode 100644 index 000000000000..4a8e5b86a3ef --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199061-sparc.diff @@ -0,0 +1,126 @@ +Pull in r199061 from upstream llvm trunk (by Jakob Stoklund Olesen): + + Handle bundled terminators in isBlockOnlyReachableByFallthrough. + + Targets like SPARC and MIPS have delay slots and normally bundle the + delay slot instruction with the corresponding terminator. + + Teach isBlockOnlyReachableByFallthrough to find any MBB operands on + bundled terminators so SPARC doesn't need to specialize this function. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/CodeGen/SPARC/missinglabel.ll +=================================================================== +--- test/CodeGen/SPARC/missinglabel.ll ++++ test/CodeGen/SPARC/missinglabel.ll +@@ -0,0 +1,23 @@ ++; RUN: llc < %s -verify-machineinstrs | FileCheck %s ++target datalayout = "E-m:e-i64:64-n32:64-S128" ++target triple = "sparc64-unknown-linux-gnu" ++ ++define void @f() align 2 { ++entry: ++; CHECK: %xcc, .LBB0_1 ++ %cmp = icmp eq i64 undef, 0 ++ br i1 %cmp, label %targetblock, label %cond.false ++ ++cond.false: ++ unreachable ++ ++; CHECK: .LBB0_1: ! %targetblock ++targetblock: ++ br i1 undef, label %cond.false.i83, label %exit.i85 ++ ++cond.false.i83: ++ unreachable ++ ++exit.i85: ++ unreachable ++} +Index: lib/Target/Sparc/SparcAsmPrinter.cpp +=================================================================== +--- lib/Target/Sparc/SparcAsmPrinter.cpp ++++ lib/Target/Sparc/SparcAsmPrinter.cpp +@@ -65,10 +65,6 @@ namespace { + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); +- +- virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) +- const; +- + }; + } // end of anonymous namespace + +@@ -390,37 +386,6 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const + return false; + } + +-/// isBlockOnlyReachableByFallthough - Return true if the basic block has +-/// exactly one predecessor and the control transfer mechanism between +-/// the predecessor and this block is a fall-through. +-/// +-/// This overrides AsmPrinter's implementation to handle delay slots. +-bool SparcAsmPrinter:: +-isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { +- // If this is a landing pad, it isn't a fall through. If it has no preds, +- // then nothing falls through to it. +- if (MBB->isLandingPad() || MBB->pred_empty()) +- return false; +- +- // If there isn't exactly one predecessor, it can't be a fall through. +- MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; +- ++PI2; +- if (PI2 != MBB->pred_end()) +- return false; +- +- // The predecessor has to be immediately before this block. +- const MachineBasicBlock *Pred = *PI; +- +- if (!Pred->isLayoutSuccessor(MBB)) +- return false; +- +- // Check if the last terminator is an unconditional branch. +- MachineBasicBlock::const_iterator I = Pred->end(); +- while (I != Pred->begin() && !(--I)->isTerminator()) +- ; // Noop +- return I == Pred->end() || !I->isBarrier(); +-} +- + // Force static initialization. + extern "C" void LLVMInitializeSparcAsmPrinter() { + RegisterAsmPrinter X(TheSparcTarget); +Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp +=================================================================== +--- lib/CodeGen/AsmPrinter/AsmPrinter.cpp ++++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp +@@ -23,6 +23,7 @@ + #include "llvm/CodeGen/MachineConstantPool.h" + #include "llvm/CodeGen/MachineFrameInfo.h" + #include "llvm/CodeGen/MachineFunction.h" ++#include "llvm/CodeGen/MachineInstrBundle.h" + #include "llvm/CodeGen/MachineJumpTableInfo.h" + #include "llvm/CodeGen/MachineLoopInfo.h" + #include "llvm/CodeGen/MachineModuleInfo.h" +@@ -2221,14 +2222,13 @@ isBlockOnlyReachableByFallthrough(const MachineBas + if (!MI.isBranch() || MI.isIndirectBranch()) + return false; + +- // If we are the operands of one of the branches, this is not +- // a fall through. +- for (MachineInstr::mop_iterator OI = MI.operands_begin(), +- OE = MI.operands_end(); OI != OE; ++OI) { +- const MachineOperand& OP = *OI; +- if (OP.isJTI()) ++ // If we are the operands of one of the branches, this is not a fall ++ // through. Note that targets with delay slots will usually bundle ++ // terminators with the delay slot instruction. ++ for (ConstMIBundleOperands OP(&MI); OP.isValid(); ++OP) { ++ if (OP->isJTI()) + return false; +- if (OP.isMBB() && OP.getMBB() == MBB) ++ if (OP->isMBB() && OP->getMBB() == MBB) + return false; + } + } diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199186-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199186-sparc.diff new file mode 100644 index 000000000000..167aa6ab2dfc --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199186-sparc.diff @@ -0,0 +1,28 @@ +Pull in r199186 from upstream llvm trunk (by Jakob Stoklund Olesen): + + Switch the NEON register class from QPR to DPair. + + The already allocatable DPair superclass contains odd-even D register + pair in addition to the even-odd pairs in the QPR register class. There + is no reason to constrain the set of D register pairs that can be used + for NEON values. Any NEON instructions that require a Q register will + automatically constrain the register class to QPR. + + The allocation order for DPair begins with the QPR registers, so + register allocation is unlikely to change much. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/ARM/ARMISelLowering.cpp +=================================================================== +--- lib/Target/ARM/ARMISelLowering.cpp ++++ lib/Target/ARM/ARMISelLowering.cpp +@@ -156,7 +156,7 @@ void ARMTargetLowering::addDRTypeForNEON(MVT VT) { + } + + void ARMTargetLowering::addQRTypeForNEON(MVT VT) { +- addRegisterClass(VT, &ARM::QPRRegClass); ++ addRegisterClass(VT, &ARM::DPairRegClass); + addTypeForNEON(VT, MVT::v2f64, MVT::v4i32); + } + diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199187-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199187-sparc.diff new file mode 100644 index 000000000000..bfc1cfc6d584 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199187-sparc.diff @@ -0,0 +1,81 @@ +Pull in r199187 from upstream llvm trunk (by Jakob Stoklund Olesen): + + Always let value types influence register classes. + + When creating a virtual register for a def, the value type should be + used to pick the register class. If we only use the register class + constraint on the instruction, we might pick a too large register class. + + Some registers can store values of different sizes. For example, the x86 + xmm registers can hold f32, f64, and 128-bit vectors. The three + different value sizes are represented by register classes with identical + register sets: FR32, FR64, and VR128. These register classes have + different spill slot sizes, so it is important to use the right one. + + The register class constraint on an instruction doesn't necessarily care + about the size of the value its defining. The value type determines + that. + + This fixes a problem where InstrEmitter was picking 32-bit register + classes for 64-bit values on SPARC. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/CodeGen/SPARC/spillsize.ll +=================================================================== +--- test/CodeGen/SPARC/spillsize.ll ++++ test/CodeGen/SPARC/spillsize.ll +@@ -0,0 +1,25 @@ ++; RUN: llc < %s -verify-machineinstrs | FileCheck %s ++target datalayout = "E-m:e-i64:64-n32:64-S128" ++target triple = "sparcv9" ++ ++; CHECK-LABEL: spill4 ++; This function spills two values: %p and the materialized large constant. ++; Both must use 8-byte spill and fill instructions. ++; CHECK: stx %{{..}}, [%fp+ ++; CHECK: stx %{{..}}, [%fp+ ++; CHECK: ldx [%fp+ ++; CHECK: ldx [%fp+ ++define void @spill4(i64* nocapture %p) { ++entry: ++ %val0 = load i64* %p ++ %cmp0 = icmp ult i64 %val0, 385672958347594845 ++ %cm80 = zext i1 %cmp0 to i64 ++ store i64 %cm80, i64* %p, align 8 ++ tail call void asm sideeffect "", "~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{g2},~{g3},~{g4},~{g5},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o7}"() ++ %arrayidx1 = getelementptr inbounds i64* %p, i64 1 ++ %val = load i64* %arrayidx1 ++ %cmp = icmp ult i64 %val, 385672958347594845 ++ %cm8 = select i1 %cmp, i64 10, i64 20 ++ store i64 %cm8, i64* %arrayidx1, align 8 ++ ret void ++} +Index: lib/CodeGen/SelectionDAG/InstrEmitter.cpp +=================================================================== +--- lib/CodeGen/SelectionDAG/InstrEmitter.cpp ++++ lib/CodeGen/SelectionDAG/InstrEmitter.cpp +@@ -220,10 +220,19 @@ void InstrEmitter::CreateVirtualRegisters(SDNode * + unsigned VRBase = 0; + const TargetRegisterClass *RC = + TRI->getAllocatableClass(TII->getRegClass(II, i, TRI, *MF)); +- // If the register class is unknown for the given definition, then try to +- // infer one from the value type. +- if (!RC && i < NumResults) +- RC = TLI->getRegClassFor(Node->getSimpleValueType(i)); ++ // Always let the value type influence the used register class. The ++ // constraints on the instruction may be too lax to represent the value ++ // type correctly. For example, a 64-bit float (X86::FR64) can't live in ++ // the 32-bit float super-class (X86::FR32). ++ if (i < NumResults && TLI->isTypeLegal(Node->getSimpleValueType(i))) { ++ const TargetRegisterClass *VTRC = ++ TLI->getRegClassFor(Node->getSimpleValueType(i)); ++ if (RC) ++ VTRC = TRI->getCommonSubClass(RC, VTRC); ++ if (VTRC) ++ RC = VTRC; ++ } ++ + if (II.OpInfo[i].isOptionalDef()) { + // Optional def must be a physical register. + unsigned NumResults = CountResults(Node); diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199775-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199775-sparc.diff new file mode 100644 index 000000000000..489f4570d528 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199775-sparc.diff @@ -0,0 +1,200 @@ +Pull in r199775 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Do not add PC to _GLOBAL_OFFSET_TABLE_ address to access GOT in absolute code. + Fixes PR#18521 + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcAsmPrinter.cpp +=================================================================== +--- lib/Target/Sparc/SparcAsmPrinter.cpp ++++ lib/Target/Sparc/SparcAsmPrinter.cpp +@@ -65,18 +65,24 @@ namespace { + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); ++ ++ void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI); ++ + }; + } // end of anonymous namespace + +-static MCOperand createPCXCallOP(MCSymbol *Label, +- MCContext &OutContext) +-{ +- const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label, ++static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind, ++ MCSymbol *Sym, MCContext &OutContext) { ++ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym, + OutContext); +- const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None, +- MCSym, OutContext); ++ const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext); + return MCOperand::CreateExpr(expr); ++ + } ++static MCOperand createPCXCallOP(MCSymbol *Label, ++ MCContext &OutContext) { ++ return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext); ++} + + static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, + MCSymbol *GOTLabel, MCSymbol *StartLabel, +@@ -115,43 +121,101 @@ static void EmitSETHI(MCStreamer &OutStreamer, + OutStreamer.EmitInstruction(SETHIInst); + } + +-static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, +- MCOperand &Imm, MCOperand &RD) ++static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, ++ MCOperand &RS1, MCOperand &Src2, MCOperand &RD) + { +- MCInst ORInst; +- ORInst.setOpcode(SP::ORri); +- ORInst.addOperand(RD); +- ORInst.addOperand(RS1); +- ORInst.addOperand(Imm); +- OutStreamer.EmitInstruction(ORInst); ++ MCInst Inst; ++ Inst.setOpcode(Opcode); ++ Inst.addOperand(RD); ++ Inst.addOperand(RS1); ++ Inst.addOperand(Src2); ++ OutStreamer.EmitInstruction(Inst); + } + ++static void EmitOR(MCStreamer &OutStreamer, ++ MCOperand &RS1, MCOperand &Imm, MCOperand &RD) { ++ EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD); ++} ++ + static void EmitADD(MCStreamer &OutStreamer, +- MCOperand &RS1, MCOperand &RS2, MCOperand &RD) +-{ +- MCInst ADDInst; +- ADDInst.setOpcode(SP::ADDrr); +- ADDInst.addOperand(RD); +- ADDInst.addOperand(RS1); +- ADDInst.addOperand(RS2); +- OutStreamer.EmitInstruction(ADDInst); ++ MCOperand &RS1, MCOperand &RS2, MCOperand &RD) { ++ EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD); + } + +-static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, +- MCStreamer &OutStreamer, +- MCContext &OutContext) ++static void EmitSHL(MCStreamer &OutStreamer, ++ MCOperand &RS1, MCOperand &Imm, MCOperand &RD) { ++ EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD); ++} ++ ++ ++static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, ++ SparcMCExpr::VariantKind HiKind, ++ SparcMCExpr::VariantKind LoKind, ++ MCOperand &RD, ++ MCContext &OutContext) { ++ ++ MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext); ++ MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext); ++ EmitSETHI(OutStreamer, hi, RD); ++ EmitOR(OutStreamer, RD, lo, RD); ++} ++ ++void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI) + { +- const MachineOperand &MO = MI->getOperand(0); +- MCSymbol *StartLabel = OutContext.CreateTempSymbol(); +- MCSymbol *EndLabel = OutContext.CreateTempSymbol(); +- MCSymbol *SethiLabel = OutContext.CreateTempSymbol(); + MCSymbol *GOTLabel = + OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); + ++ const MachineOperand &MO = MI->getOperand(0); + assert(MO.getReg() != SP::O7 && + "%o7 is assigned as destination for getpcx!"); + + MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg()); ++ ++ ++ if (TM.getRelocationModel() != Reloc::PIC_) { ++ // Just load the address of GOT to MCRegOP. ++ switch(TM.getCodeModel()) { ++ default: ++ llvm_unreachable("Unsupported absolute code model"); ++ case CodeModel::Small: ++ EmitHiLo(OutStreamer, GOTLabel, ++ SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, ++ MCRegOP, OutContext); ++ break; ++ case CodeModel::Medium: { ++ EmitHiLo(OutStreamer, GOTLabel, ++ SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44, ++ MCRegOP, OutContext); ++ MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12, ++ OutContext)); ++ EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP); ++ MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44, ++ GOTLabel, OutContext); ++ EmitOR(OutStreamer, MCRegOP, lo, MCRegOP); ++ break; ++ } ++ case CodeModel::Large: { ++ EmitHiLo(OutStreamer, GOTLabel, ++ SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM, ++ MCRegOP, OutContext); ++ MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32, ++ OutContext)); ++ EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP); ++ // Use register %o7 to load the lower 32 bits. ++ MCOperand RegO7 = MCOperand::CreateReg(SP::O7); ++ EmitHiLo(OutStreamer, GOTLabel, ++ SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, ++ RegO7, OutContext); ++ EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP); ++ } ++ } ++ return; ++ } ++ ++ MCSymbol *StartLabel = OutContext.CreateTempSymbol(); ++ MCSymbol *EndLabel = OutContext.CreateTempSymbol(); ++ MCSymbol *SethiLabel = OutContext.CreateTempSymbol(); ++ + MCOperand RegO7 = MCOperand::CreateReg(SP::O7); + + // : +@@ -187,7 +251,7 @@ void SparcAsmPrinter::EmitInstruction(const Machin + // FIXME: Debug Value. + return; + case SP::GETPCX: +- LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext); ++ LowerGETPCXAndEmitMCInsts(MI); + return; + } + MachineBasicBlock::const_instr_iterator I = MI; +Index: test/CodeGen/SPARC/tls.ll +=================================================================== +--- test/CodeGen/SPARC/tls.ll ++++ test/CodeGen/SPARC/tls.ll +@@ -38,8 +38,7 @@ entry: + + + ; v8abs-LABEL: test_tls_extern +-; v8abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]] +-; v8abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]] ++; v8abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]] + ; v8abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]] + ; v8abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]] + ; v8abs: ld [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ld(extern_symbol) +@@ -47,8 +46,7 @@ entry: + ; v8abs: ld [%[[R4]]] + + ; v9abs-LABEL: test_tls_extern +-; v9abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]] +-; v9abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]] ++; v9abs: or {{%[goli][0-7]}}, %l44(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]] + ; v9abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]] + ; v9abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]] + ; v9abs: ldx [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ldx(extern_symbol) diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff new file mode 100644 index 000000000000..04174109328e --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199781-sparc.diff @@ -0,0 +1,142 @@ +Pull in r199781 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add support for inline assembly constraint 'I'. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/CodeGen/SPARC/inlineasm.ll +=================================================================== +--- test/CodeGen/SPARC/inlineasm.ll ++++ test/CodeGen/SPARC/inlineasm.ll +@@ -0,0 +1,35 @@ ++; RUN: llc -march=sparc <%s | FileCheck %s ++ ++; CHECK-LABEL: test_constraint_r ++; CHECK: add %o1, %o0, %o0 ++define i32 @test_constraint_r(i32 %a, i32 %b) { ++entry: ++ %0 = tail call i32 asm sideeffect "add $2, $1, $0", "=r,r,r"(i32 %a, i32 %b) ++ ret i32 %0 ++} ++ ++; CHECK-LABEL: test_constraint_I ++; CHECK: add %o0, 1023, %o0 ++define i32 @test_constraint_I(i32 %a) { ++entry: ++ %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 1023) ++ ret i32 %0 ++} ++ ++; CHECK-LABEL: test_constraint_I_neg ++; CHECK: add %o0, -4096, %o0 ++define i32 @test_constraint_I_neg(i32 %a) { ++entry: ++ %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 -4096) ++ ret i32 %0 ++} ++ ++; CHECK-LABEL: test_constraint_I_largeimm ++; CHECK: sethi 9, [[R0:%[gilo][0-7]]] ++; CHECK: or [[R0]], 784, [[R1:%[gilo][0-7]]] ++; CHECK: add %o0, [[R1]], %o0 ++define i32 @test_constraint_I_largeimm(i32 %a) { ++entry: ++ %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 10000) ++ ret i32 %0 ++} +Index: lib/Target/Sparc/SparcISelLowering.h +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.h ++++ lib/Target/Sparc/SparcISelLowering.h +@@ -73,6 +73,13 @@ namespace llvm { + virtual const char *getTargetNodeName(unsigned Opcode) const; + + ConstraintType getConstraintType(const std::string &Constraint) const; ++ ConstraintWeight ++ getSingleConstraintMatchWeight(AsmOperandInfo &info, ++ const char *constraint) const; ++ void LowerAsmOperandForConstraint(SDValue Op, ++ std::string &Constraint, ++ std::vector &Ops, ++ SelectionDAG &DAG) const; + std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const; + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -2918,6 +2918,8 @@ SparcTargetLowering::getConstraintType(const std:: + switch (Constraint[0]) { + default: break; + case 'r': return C_RegisterClass; ++ case 'I': // SIMM13 ++ return C_Other; + } + } + +@@ -2924,6 +2926,64 @@ SparcTargetLowering::getConstraintType(const std:: + return TargetLowering::getConstraintType(Constraint); + } + ++TargetLowering::ConstraintWeight SparcTargetLowering:: ++getSingleConstraintMatchWeight(AsmOperandInfo &info, ++ const char *constraint) const { ++ ConstraintWeight weight = CW_Invalid; ++ Value *CallOperandVal = info.CallOperandVal; ++ // If we don't have a value, we can't do a match, ++ // but allow it at the lowest weight. ++ if (CallOperandVal == NULL) ++ return CW_Default; ++ ++ // Look at the constraint type. ++ switch (*constraint) { ++ default: ++ weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); ++ break; ++ case 'I': // SIMM13 ++ if (ConstantInt *C = dyn_cast(info.CallOperandVal)) { ++ if (isInt<13>(C->getSExtValue())) ++ weight = CW_Constant; ++ } ++ break; ++ } ++ return weight; ++} ++ ++/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops ++/// vector. If it is invalid, don't add anything to Ops. ++void SparcTargetLowering:: ++LowerAsmOperandForConstraint(SDValue Op, ++ std::string &Constraint, ++ std::vector &Ops, ++ SelectionDAG &DAG) const { ++ SDValue Result(0, 0); ++ ++ // Only support length 1 constraints for now. ++ if (Constraint.length() > 1) ++ return; ++ ++ char ConstraintLetter = Constraint[0]; ++ switch (ConstraintLetter) { ++ default: break; ++ case 'I': ++ if (ConstantSDNode *C = dyn_cast(Op)) { ++ if (isInt<13>(C->getSExtValue())) { ++ Result = DAG.getTargetConstant(C->getSExtValue(), Op.getValueType()); ++ break; ++ } ++ return; ++ } ++ } ++ ++ if (Result.getNode()) { ++ Ops.push_back(Result); ++ return; ++ } ++ TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); ++} ++ + std::pair + SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, + MVT VT) const { diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199786-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199786-sparc.diff new file mode 100644 index 000000000000..844e4e4520ff --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199786-sparc.diff @@ -0,0 +1,55 @@ +Pull in r199786 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add support for inline assembly constraints which specify registers by their aliases. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -2992,6 +2992,26 @@ SparcTargetLowering::getRegForInlineAsmConstraint( + case 'r': + return std::make_pair(0U, &SP::IntRegsRegClass); + } ++ } else if (!Constraint.empty() && Constraint.size() <= 5 ++ && Constraint[0] == '{' && *(Constraint.end()-1) == '}') { ++ // constraint = '{r}' ++ // Remove the braces from around the name. ++ StringRef name(Constraint.data()+1, Constraint.size()-2); ++ // Handle register aliases: ++ // r0-r7 -> g0-g7 ++ // r8-r15 -> o0-o7 ++ // r16-r23 -> l0-l7 ++ // r24-r31 -> i0-i7 ++ uint64_t intVal = 0; ++ if (name.substr(0, 1).equals("r") ++ && !name.substr(1).getAsInteger(10, intVal) && intVal <= 31) { ++ const char regTypes[] = { 'g', 'o', 'l', 'i' }; ++ char regType = regTypes[intVal/8]; ++ char regIdx = '0' + (intVal % 8); ++ char tmp[] = { '{', regType, regIdx, '}', 0 }; ++ std::string newConstraint = std::string(tmp); ++ return TargetLowering::getRegForInlineAsmConstraint(newConstraint, VT); ++ } + } + + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); +Index: test/CodeGen/SPARC/inlineasm.ll +=================================================================== +--- test/CodeGen/SPARC/inlineasm.ll ++++ test/CodeGen/SPARC/inlineasm.ll +@@ -33,3 +33,13 @@ entry: + %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 10000) + ret i32 %0 + } ++ ++; CHECK-LABEL: test_constraint_reg ++; CHECK: ldda [%o1] 43, %g2 ++; CHECK: ldda [%o1] 43, %g3 ++define void @test_constraint_reg(i32 %s, i32* %ptr) { ++entry: ++ %0 = tail call i64 asm sideeffect "ldda [$1] $2, $0", "={r2},r,n"(i32* %ptr, i32 43) ++ %1 = tail call i64 asm sideeffect "ldda [$1] $2, $0", "={g3},r,n"(i32* %ptr, i32 43) ++ ret void ++} diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199940-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199940-sparc.diff new file mode 100644 index 000000000000..e171799df0a0 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199940-sparc.diff @@ -0,0 +1,21 @@ +Pull in r199940 from upstream llvm trunk (by Eric Christopher): + + Fix out of bounds access to the double regs array. Given the + code this looks correct, but could use review. The previous + was definitely not correct. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -734,7 +734,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo + && !name.substr(1, 2).getAsInteger(10, intVal) + && intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) { + // FIXME: Check V9 +- RegNo = DoubleRegs[16 + intVal/2]; ++ RegNo = DoubleRegs[intVal/2]; + RegKind = SparcOperand::rk_DoubleReg; + return true; + } diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199974-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199974-sparc.diff new file mode 100644 index 000000000000..095199534a0b --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199974-sparc.diff @@ -0,0 +1,54 @@ +Pull in r199974 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Correct quad register list in the asm parser. + Add test cases to check parsing of v9 double registers and their aliased quad registers. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/MC/Disassembler/Sparc/sparc-fp.txt +=================================================================== +--- test/MC/Disassembler/Sparc/sparc-fp.txt ++++ test/MC/Disassembler/Sparc/sparc-fp.txt +@@ -81,6 +81,12 @@ + # CHECK: faddq %f0, %f4, %f8 + 0x91 0xa0 0x08 0x64 + ++# CHECK: faddd %f32, %f34, %f62 ++0xbf 0xa0 0x48 0x43 ++ ++# CHECK: faddq %f32, %f36, %f60 ++0xbb 0xa0 0x48 0x65 ++ + # CHECK: fsubs %f0, %f4, %f8 + 0x91 0xa0 0x08 0xa4 + +Index: test/MC/Sparc/sparc-fp-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-fp-instructions.s ++++ test/MC/Sparc/sparc-fp-instructions.s +@@ -64,6 +64,12 @@ + faddd %f0, %f4, %f8 + faddq %f0, %f4, %f8 + ++ ! make sure we can handle V9 double registers and their aliased quad registers. ++ ! CHECK: faddd %f32, %f34, %f62 ! encoding: [0xbf,0xa0,0x48,0x43] ++ ! CHECK: faddq %f32, %f36, %f60 ! encoding: [0xbb,0xa0,0x48,0x65] ++ faddd %f32, %f34, %f62 ++ faddq %f32, %f36, %f60 ++ + ! CHECK: fsubs %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0xa4] + ! CHECK: fsubd %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0xc4] + ! CHECK: fsubq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0xe4] +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -117,7 +117,7 @@ class SparcAsmParser : public MCTargetAsmParser { + static unsigned QuadFPRegs[32] = { + Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3, + Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7, +- Sparc::Q8, Sparc::Q7, Sparc::Q8, Sparc::Q9, ++ Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11, + Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 }; + + diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199975-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199975-sparc.diff new file mode 100644 index 000000000000..b1dec41c684d --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199975-sparc.diff @@ -0,0 +1,344 @@ +Pull in r199975 from upstream llvm trunk (by Jakob Stoklund Olesen): + + Implement atomicrmw operations in 32 and 64 bits for SPARCv9. + + These all use the compare-and-swap CASA/CASXA instructions. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/CodeGen/SPARC/atomics.ll +=================================================================== +--- test/CodeGen/SPARC/atomics.ll ++++ test/CodeGen/SPARC/atomics.ll +@@ -1,4 +1,4 @@ +-; RUN: llc < %s -march=sparcv9 | FileCheck %s ++; RUN: llc < %s -march=sparcv9 -verify-machineinstrs | FileCheck %s + + ; CHECK-LABEL: test_atomic_i32 + ; CHECK: ld [%o0] +@@ -61,3 +61,84 @@ entry: + %b = atomicrmw xchg i32* %ptr, i32 42 monotonic + ret i32 %b + } ++ ++; CHECK-LABEL: test_load_add_32 ++; CHECK: membar ++; CHECK: add ++; CHECK: cas [%o0] ++; CHECK: membar ++define zeroext i32 @test_load_add_32(i32* %p, i32 zeroext %v) { ++entry: ++ %0 = atomicrmw add i32* %p, i32 %v seq_cst ++ ret i32 %0 ++} ++ ++; CHECK-LABEL: test_load_sub_64 ++; CHECK: membar ++; CHECK: sub ++; CHECK: casx [%o0] ++; CHECK: membar ++define zeroext i64 @test_load_sub_64(i64* %p, i64 zeroext %v) { ++entry: ++ %0 = atomicrmw sub i64* %p, i64 %v seq_cst ++ ret i64 %0 ++} ++ ++; CHECK-LABEL: test_load_xor_32 ++; CHECK: membar ++; CHECK: xor ++; CHECK: cas [%o0] ++; CHECK: membar ++define zeroext i32 @test_load_xor_32(i32* %p, i32 zeroext %v) { ++entry: ++ %0 = atomicrmw xor i32* %p, i32 %v seq_cst ++ ret i32 %0 ++} ++ ++; CHECK-LABEL: test_load_and_32 ++; CHECK: membar ++; CHECK: and ++; CHECK-NOT: xor ++; CHECK: cas [%o0] ++; CHECK: membar ++define zeroext i32 @test_load_and_32(i32* %p, i32 zeroext %v) { ++entry: ++ %0 = atomicrmw and i32* %p, i32 %v seq_cst ++ ret i32 %0 ++} ++ ++; CHECK-LABEL: test_load_nand_32 ++; CHECK: membar ++; CHECK: and ++; CHECK: xor ++; CHECK: cas [%o0] ++; CHECK: membar ++define zeroext i32 @test_load_nand_32(i32* %p, i32 zeroext %v) { ++entry: ++ %0 = atomicrmw nand i32* %p, i32 %v seq_cst ++ ret i32 %0 ++} ++ ++; CHECK-LABEL: test_load_max_64 ++; CHECK: membar ++; CHECK: cmp ++; CHECK: movg %xcc ++; CHECK: casx [%o0] ++; CHECK: membar ++define zeroext i64 @test_load_max_64(i64* %p, i64 zeroext %v) { ++entry: ++ %0 = atomicrmw max i64* %p, i64 %v seq_cst ++ ret i64 %0 ++} ++ ++; CHECK-LABEL: test_load_umin_32 ++; CHECK: membar ++; CHECK: cmp ++; CHECK: movleu %icc ++; CHECK: cas [%o0] ++; CHECK: membar ++define zeroext i32 @test_load_umin_32(i32* %p, i32 zeroext %v) { ++entry: ++ %0 = atomicrmw umin i32* %p, i32 %v seq_cst ++ ret i32 %0 ++} +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -438,6 +438,31 @@ def : Pat<(atomic_store ADDRri:$dst, i64:$val), (S + + } // Predicates = [Is64Bit] + ++let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1, ++ Defs = [ICC] in ++multiclass AtomicRMW { ++ ++ def _32 : Pseudo<(outs IntRegs:$rd), ++ (ins ptr_rc:$addr, IntRegs:$rs2), "", ++ [(set i32:$rd, (op32 iPTR:$addr, i32:$rs2))]>; ++ ++ let Predicates = [Is64Bit] in ++ def _64 : Pseudo<(outs I64Regs:$rd), ++ (ins ptr_rc:$addr, I64Regs:$rs2), "", ++ [(set i64:$rd, (op64 iPTR:$addr, i64:$rs2))]>; ++} ++ ++defm ATOMIC_LOAD_ADD : AtomicRMW; ++defm ATOMIC_LOAD_SUB : AtomicRMW; ++defm ATOMIC_LOAD_AND : AtomicRMW; ++defm ATOMIC_LOAD_OR : AtomicRMW; ++defm ATOMIC_LOAD_XOR : AtomicRMW; ++defm ATOMIC_LOAD_NAND : AtomicRMW; ++defm ATOMIC_LOAD_MIN : AtomicRMW; ++defm ATOMIC_LOAD_MAX : AtomicRMW; ++defm ATOMIC_LOAD_UMIN : AtomicRMW; ++defm ATOMIC_LOAD_UMAX : AtomicRMW; ++ + // Global addresses, constant pool entries + let Predicates = [Is64Bit] in { + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -2831,11 +2831,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons + MachineBasicBlock * + SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) const { +- const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); +- unsigned BROpcode; +- unsigned CC; +- DebugLoc dl = MI->getDebugLoc(); +- // Figure out the conditional branch opcode to use for this select_cc. + switch (MI->getOpcode()) { + default: llvm_unreachable("Unknown SELECT_CC!"); + case SP::SELECT_CC_Int_ICC: +@@ -2842,17 +2837,64 @@ SparcTargetLowering::EmitInstrWithCustomInserter(M + case SP::SELECT_CC_FP_ICC: + case SP::SELECT_CC_DFP_ICC: + case SP::SELECT_CC_QFP_ICC: +- BROpcode = SP::BCOND; +- break; ++ return expandSelectCC(MI, BB, SP::BCOND); + case SP::SELECT_CC_Int_FCC: + case SP::SELECT_CC_FP_FCC: + case SP::SELECT_CC_DFP_FCC: + case SP::SELECT_CC_QFP_FCC: +- BROpcode = SP::FBCOND; +- break; ++ return expandSelectCC(MI, BB, SP::FBCOND); ++ ++ case SP::ATOMIC_LOAD_ADD_32: ++ return expandAtomicRMW(MI, BB, SP::ADDrr); ++ case SP::ATOMIC_LOAD_ADD_64: ++ return expandAtomicRMW(MI, BB, SP::ADDXrr); ++ case SP::ATOMIC_LOAD_SUB_32: ++ return expandAtomicRMW(MI, BB, SP::SUBrr); ++ case SP::ATOMIC_LOAD_SUB_64: ++ return expandAtomicRMW(MI, BB, SP::SUBXrr); ++ case SP::ATOMIC_LOAD_AND_32: ++ return expandAtomicRMW(MI, BB, SP::ANDrr); ++ case SP::ATOMIC_LOAD_AND_64: ++ return expandAtomicRMW(MI, BB, SP::ANDXrr); ++ case SP::ATOMIC_LOAD_OR_32: ++ return expandAtomicRMW(MI, BB, SP::ORrr); ++ case SP::ATOMIC_LOAD_OR_64: ++ return expandAtomicRMW(MI, BB, SP::ORXrr); ++ case SP::ATOMIC_LOAD_XOR_32: ++ return expandAtomicRMW(MI, BB, SP::XORrr); ++ case SP::ATOMIC_LOAD_XOR_64: ++ return expandAtomicRMW(MI, BB, SP::XORXrr); ++ case SP::ATOMIC_LOAD_NAND_32: ++ return expandAtomicRMW(MI, BB, SP::ANDrr); ++ case SP::ATOMIC_LOAD_NAND_64: ++ return expandAtomicRMW(MI, BB, SP::ANDXrr); ++ ++ case SP::ATOMIC_LOAD_MAX_32: ++ return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_G); ++ case SP::ATOMIC_LOAD_MAX_64: ++ return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_G); ++ case SP::ATOMIC_LOAD_MIN_32: ++ return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LE); ++ case SP::ATOMIC_LOAD_MIN_64: ++ return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LE); ++ case SP::ATOMIC_LOAD_UMAX_32: ++ return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_GU); ++ case SP::ATOMIC_LOAD_UMAX_64: ++ return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_GU); ++ case SP::ATOMIC_LOAD_UMIN_32: ++ return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LEU); ++ case SP::ATOMIC_LOAD_UMIN_64: ++ return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LEU); + } ++} + +- CC = (SPCC::CondCodes)MI->getOperand(3).getImm(); ++MachineBasicBlock* ++SparcTargetLowering::expandSelectCC(MachineInstr *MI, ++ MachineBasicBlock *BB, ++ unsigned BROpcode) const { ++ const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); ++ DebugLoc dl = MI->getDebugLoc(); ++ unsigned CC = (SPCC::CondCodes)MI->getOperand(3).getImm(); + + // To "insert" a SELECT_CC instruction, we actually have to insert the diamond + // control-flow pattern. The incoming instruction knows the destination vreg +@@ -2906,6 +2948,100 @@ SparcTargetLowering::EmitInstrWithCustomInserter(M + return BB; + } + ++MachineBasicBlock* ++SparcTargetLowering::expandAtomicRMW(MachineInstr *MI, ++ MachineBasicBlock *MBB, ++ unsigned Opcode, ++ unsigned CondCode) const { ++ const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); ++ MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); ++ DebugLoc DL = MI->getDebugLoc(); ++ ++ // MI is an atomic read-modify-write instruction of the form: ++ // ++ // rd = atomicrmw addr, rs2 ++ // ++ // All three operands are registers. ++ unsigned DestReg = MI->getOperand(0).getReg(); ++ unsigned AddrReg = MI->getOperand(1).getReg(); ++ unsigned Rs2Reg = MI->getOperand(2).getReg(); ++ ++ // SelectionDAG has already inserted memory barriers before and after MI, so ++ // we simply have to implement the operatiuon in terms of compare-and-swap. ++ // ++ // %val0 = load %addr ++ // loop: ++ // %val = phi %val0, %dest ++ // %upd = op %val, %rs2 ++ // %dest = cas %addr, %upd, %val ++ // cmp %val, %dest ++ // bne loop ++ // done: ++ // ++ bool is64Bit = SP::I64RegsRegClass.hasSubClassEq(MRI.getRegClass(DestReg)); ++ const TargetRegisterClass *ValueRC = ++ is64Bit ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; ++ unsigned Val0Reg = MRI.createVirtualRegister(ValueRC); ++ ++ BuildMI(*MBB, MI, DL, TII.get(is64Bit ? SP::LDXri : SP::LDri), Val0Reg) ++ .addReg(AddrReg).addImm(0); ++ ++ // Split the basic block MBB before MI and insert the loop block in the hole. ++ MachineFunction::iterator MFI = MBB; ++ const BasicBlock *LLVM_BB = MBB->getBasicBlock(); ++ MachineFunction *MF = MBB->getParent(); ++ MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ MachineBasicBlock *DoneMBB = MF->CreateMachineBasicBlock(LLVM_BB); ++ ++MFI; ++ MF->insert(MFI, LoopMBB); ++ MF->insert(MFI, DoneMBB); ++ ++ // Move MI and following instructions to DoneMBB. ++ DoneMBB->splice(DoneMBB->begin(), MBB, MI, MBB->end()); ++ DoneMBB->transferSuccessorsAndUpdatePHIs(MBB); ++ ++ // Connect the CFG again. ++ MBB->addSuccessor(LoopMBB); ++ LoopMBB->addSuccessor(LoopMBB); ++ LoopMBB->addSuccessor(DoneMBB); ++ ++ // Build the loop block. ++ unsigned ValReg = MRI.createVirtualRegister(ValueRC); ++ unsigned UpdReg = MRI.createVirtualRegister(ValueRC); ++ ++ BuildMI(LoopMBB, DL, TII.get(SP::PHI), ValReg) ++ .addReg(Val0Reg).addMBB(MBB) ++ .addReg(DestReg).addMBB(LoopMBB); ++ ++ if (CondCode) { ++ // This is one of the min/max operations. We need a CMPrr followed by a ++ // MOVXCC/MOVICC. ++ BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(Rs2Reg); ++ BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) ++ .addReg(ValReg).addReg(Rs2Reg).addImm(CondCode); ++ } else { ++ BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) ++ .addReg(ValReg).addReg(Rs2Reg); ++ } ++ ++ if (MI->getOpcode() == SP::ATOMIC_LOAD_NAND_32 || ++ MI->getOpcode() == SP::ATOMIC_LOAD_NAND_64) { ++ unsigned TmpReg = UpdReg; ++ UpdReg = MRI.createVirtualRegister(ValueRC); ++ BuildMI(LoopMBB, DL, TII.get(SP::XORri), UpdReg).addReg(TmpReg).addImm(-1); ++ } ++ ++ BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::CASXrr : SP::CASrr), DestReg) ++ .addReg(AddrReg).addReg(UpdReg).addReg(ValReg) ++ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); ++ BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(DestReg); ++ BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::BPXCC : SP::BCOND)) ++ .addMBB(LoopMBB).addImm(SPCC::ICC_NE); ++ ++ MI->eraseFromParent(); ++ return DoneMBB; ++} ++ + //===----------------------------------------------------------------------===// + // Sparc Inline Assembly Support + //===----------------------------------------------------------------------===// +Index: lib/Target/Sparc/SparcISelLowering.h +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.h ++++ lib/Target/Sparc/SparcISelLowering.h +@@ -165,6 +165,13 @@ namespace llvm { + virtual void ReplaceNodeResults(SDNode *N, + SmallVectorImpl& Results, + SelectionDAG &DAG) const; ++ ++ MachineBasicBlock *expandSelectCC(MachineInstr *MI, MachineBasicBlock *BB, ++ unsigned BROpcode) const; ++ MachineBasicBlock *expandAtomicRMW(MachineInstr *MI, ++ MachineBasicBlock *BB, ++ unsigned Opcode, ++ unsigned CondCode = 0) const; + }; + } // end namespace llvm + diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199977-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199977-sparc.diff new file mode 100644 index 000000000000..166b5da6d577 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199977-sparc.diff @@ -0,0 +1,377 @@ +Pull in r199977 from upstream llvm trunk (by Venkatraman Govindaraju): + + [SparcV9] Add support for JIT in Sparc64. + With this change, all supported tests in test/ExecutionEngine pass in sparcv9. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcJITInfo.cpp +=================================================================== +--- lib/Target/Sparc/SparcJITInfo.cpp ++++ lib/Target/Sparc/SparcJITInfo.cpp +@@ -12,8 +12,9 @@ + //===----------------------------------------------------------------------===// + #define DEBUG_TYPE "jit" + #include "SparcJITInfo.h" ++#include "Sparc.h" + #include "SparcRelocations.h" +- ++#include "llvm/ADT/SmallVector.h" + #include "llvm/CodeGen/JITCodeEmitter.h" + #include "llvm/Support/Memory.h" + +@@ -35,18 +36,17 @@ extern "C" { + "SparcCompilationCallback:\n" + // Save current register window. + "\tsave %sp, -192, %sp\n" +- // stubaddr+4 is in %g1. ++ // stubaddr is in %g1. + "\tcall SparcCompilationCallbackC\n" +- "\t sub %g1, 4, %o0\n" ++ "\t mov %g1, %o0\n" + // restore original register window and + // copy %o0 to %g1 +- "\t restore %o0, 0, %g1\n" ++ "\trestore %o0, 0, %g1\n" + // call the new stub + "\tjmp %g1\n" + "\t nop\n" + "\t.size SparcCompilationCallback, .-SparcCompilationCallback" + ); +- + #else + void SparcCompilationCallback() { + llvm_unreachable( +@@ -55,33 +55,120 @@ extern "C" { + #endif + } + +-#define HI(Val) (((unsigned)(Val)) >> 10) +-#define LO(Val) (((unsigned)(Val)) & 0x3FF) + + #define SETHI_INST(imm, rd) (0x01000000 | ((rd) << 25) | ((imm) & 0x3FFFFF)) + #define JMP_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x38 << 19) \ + | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) + #define NOP_INST SETHI_INST(0, 0) ++#define OR_INST_I(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x02 << 19) \ ++ | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) ++#define OR_INST_R(rs1, rs2, rd) (0x80000000 | ((rd) << 25) | (0x02 << 19) \ ++ | ((rs1) << 14) | (0 << 13) | ((rs2) & 0x1F)) ++#define RDPC_INST(rd) (0x80000000 | ((rd) << 25) | (0x28 << 19) \ ++ | (5 << 14)) ++#define LDX_INST(rs1, imm, rd) (0xC0000000 | ((rd) << 25) | (0x0B << 19) \ ++ | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) ++#define SLLX_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x25 << 19) \ ++ | ((rs1) << 14) | (3 << 12) | ((imm) & 0x3F)) ++#define SUB_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x04 << 19) \ ++ | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) ++#define XOR_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x03 << 19) \ ++ | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF)) ++#define BA_INST(tgt) (0x10800000 | ((tgt) & 0x3FFFFF)) + ++// Emit instructions to jump to Addr and store the starting address of ++// the instructions emitted in the scratch register. ++static void emitInstrForIndirectJump(intptr_t Addr, ++ unsigned scratch, ++ SmallVectorImpl &Insts) { ++ ++ if (isInt<13>(Addr)) { ++ // Emit: jmpl %g0+Addr, ++ // nop ++ Insts.push_back(JMP_INST(0, LO10(Addr), scratch)); ++ Insts.push_back(NOP_INST); ++ return; ++ } ++ ++ if (isUInt<32>(Addr)) { ++ // Emit: sethi %hi(Addr), scratch ++ // jmpl scratch+%lo(Addr), scratch ++ // sub scratch, 4, scratch ++ Insts.push_back(SETHI_INST(HI22(Addr), scratch)); ++ Insts.push_back(JMP_INST(scratch, LO10(Addr), scratch)); ++ Insts.push_back(SUB_INST(scratch, 4, scratch)); ++ return; ++ } ++ ++ if (Addr < 0 && isInt<33>(Addr)) { ++ // Emit: sethi %hix(Addr), scratch) ++ // xor scratch, %lox(Addr), scratch ++ // jmpl scratch+0, scratch ++ // sub scratch, 8, scratch ++ Insts.push_back(SETHI_INST(HIX22(Addr), scratch)); ++ Insts.push_back(XOR_INST(scratch, LOX10(Addr), scratch)); ++ Insts.push_back(JMP_INST(scratch, 0, scratch)); ++ Insts.push_back(SUB_INST(scratch, 8, scratch)); ++ return; ++ } ++ ++ // Emit: rd %pc, scratch ++ // ldx [scratch+16], scratch ++ // jmpl scratch+0, scratch ++ // sub scratch, 8, scratch ++ // ++ Insts.push_back(RDPC_INST(scratch)); ++ Insts.push_back(LDX_INST(scratch, 16, scratch)); ++ Insts.push_back(JMP_INST(scratch, 0, scratch)); ++ Insts.push_back(SUB_INST(scratch, 8, scratch)); ++ Insts.push_back((uint32_t)(((int64_t)Addr) >> 32) & 0xffffffff); ++ Insts.push_back((uint32_t)(Addr & 0xffffffff)); ++ ++ // Instruction sequence without rdpc instruction ++ // 7 instruction and 2 scratch register ++ // Emit: sethi %hh(Addr), scratch ++ // or scratch, %hm(Addr), scratch ++ // sllx scratch, 32, scratch ++ // sethi %hi(Addr), scratch2 ++ // or scratch, scratch2, scratch ++ // jmpl scratch+%lo(Addr), scratch ++ // sub scratch, 20, scratch ++ // Insts.push_back(SETHI_INST(HH22(Addr), scratch)); ++ // Insts.push_back(OR_INST_I(scratch, HM10(Addr), scratch)); ++ // Insts.push_back(SLLX_INST(scratch, 32, scratch)); ++ // Insts.push_back(SETHI_INST(HI22(Addr), scratch2)); ++ // Insts.push_back(OR_INST_R(scratch, scratch2, scratch)); ++ // Insts.push_back(JMP_INST(scratch, LO10(Addr), scratch)); ++ // Insts.push_back(SUB_INST(scratch, 20, scratch)); ++} ++ + extern "C" void *SparcCompilationCallbackC(intptr_t StubAddr) { + // Get the address of the compiled code for this function. + intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr); + + // Rewrite the function stub so that we don't end up here every time we +- // execute the call. We're replacing the first three instructions of the +- // stub with code that jumps to the compiled function: +- // sethi %hi(NewVal), %g1 +- // jmp %g1+%lo(NewVal) +- // nop ++ // execute the call. We're replacing the stub instructions with code ++ // that jumps to the compiled function: + +- *(intptr_t *)(StubAddr) = SETHI_INST(HI(NewVal), 1); +- *(intptr_t *)(StubAddr + 4) = JMP_INST(1, LO(NewVal), 0); +- *(intptr_t *)(StubAddr + 8) = NOP_INST; ++ SmallVector Insts; ++ intptr_t diff = (NewVal - StubAddr) >> 2; ++ if (isInt<22>(diff)) { ++ // Use branch instruction to jump ++ Insts.push_back(BA_INST(diff)); ++ Insts.push_back(NOP_INST); ++ } else { ++ // Otherwise, use indirect jump to the compiled function ++ emitInstrForIndirectJump(NewVal, 1, Insts); ++ } + +- sys::Memory::InvalidateInstructionCache((void*) StubAddr, 12); ++ for (unsigned i = 0, e = Insts.size(); i != e; ++i) ++ *(uint32_t *)(StubAddr + i*4) = Insts[i]; ++ ++ sys::Memory::InvalidateInstructionCache((void*) StubAddr, Insts.size() * 4); + return (void*)StubAddr; + } + ++ + void SparcJITInfo::replaceMachineCodeForFunction(void *Old, void *New) { + assert(0 && "FIXME: Implement SparcJITInfo::replaceMachineCodeForFunction"); + } +@@ -88,10 +175,10 @@ void SparcJITInfo::replaceMachineCodeForFunction(v + + + TargetJITInfo::StubLayout SparcJITInfo::getStubLayout() { +- // The stub contains 3 4-byte instructions, aligned at 4 bytes. See +- // emitFunctionStub for details. +- +- StubLayout Result = { 3*4, 4 }; ++ // The stub contains maximum of 4 4-byte instructions and 8 bytes for address, ++ // aligned at 32 bytes. ++ // See emitFunctionStub and emitInstrForIndirectJump for details. ++ StubLayout Result = { 4*4 + 8, 32 }; + return Result; + } + +@@ -98,32 +185,41 @@ TargetJITInfo::StubLayout SparcJITInfo::getStubLay + void *SparcJITInfo::emitFunctionStub(const Function *F, void *Fn, + JITCodeEmitter &JCE) + { +- JCE.emitAlignment(4); ++ JCE.emitAlignment(32); + void *Addr = (void*) (JCE.getCurrentPCValue()); +- if (!sys::Memory::setRangeWritable(Addr, 12)) +- llvm_unreachable("ERROR: Unable to mark stub writable."); + ++ intptr_t CurrentAddr = (intptr_t)Addr; + intptr_t EmittedAddr; +- if (Fn != (void*)(intptr_t)SparcCompilationCallback) ++ SmallVector Insts; ++ if (Fn != (void*)(intptr_t)SparcCompilationCallback) { + EmittedAddr = (intptr_t)Fn; +- else ++ intptr_t diff = (EmittedAddr - CurrentAddr) >> 2; ++ if (isInt<22>(diff)) { ++ Insts.push_back(BA_INST(diff)); ++ Insts.push_back(NOP_INST); ++ } ++ } else { + EmittedAddr = (intptr_t)SparcCompilationCallback; ++ } + +- // sethi %hi(EmittedAddr), %g1 +- // jmp %g1+%lo(EmittedAddr), %g1 +- // nop ++ if (Insts.size() == 0) ++ emitInstrForIndirectJump(EmittedAddr, 1, Insts); + +- JCE.emitWordBE(SETHI_INST(HI(EmittedAddr), 1)); +- JCE.emitWordBE(JMP_INST(1, LO(EmittedAddr), 1)); +- JCE.emitWordBE(NOP_INST); + +- sys::Memory::InvalidateInstructionCache(Addr, 12); +- if (!sys::Memory::setRangeExecutable(Addr, 12)) ++ if (!sys::Memory::setRangeWritable(Addr, 4 * Insts.size())) ++ llvm_unreachable("ERROR: Unable to mark stub writable."); ++ ++ for (unsigned i = 0, e = Insts.size(); i != e; ++i) ++ JCE.emitWordBE(Insts[i]); ++ ++ sys::Memory::InvalidateInstructionCache(Addr, 4 * Insts.size()); ++ if (!sys::Memory::setRangeExecutable(Addr, 4 * Insts.size())) + llvm_unreachable("ERROR: Unable to mark stub executable."); + + return Addr; + } + ++ + TargetJITInfo::LazyResolverFn + SparcJITInfo::getLazyResolverFunction(JITCompilerFn F) { + JITCompilerFunction = F; +@@ -159,6 +255,27 @@ void SparcJITInfo::relocate(void *Function, Machin + case SP::reloc_sparc_pc19: + ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x7ffff; + break; ++ ++ case SP::reloc_sparc_h44: ++ ResultPtr = (ResultPtr >> 22) & 0x3fffff; ++ break; ++ ++ case SP::reloc_sparc_m44: ++ ResultPtr = (ResultPtr >> 12) & 0x3ff; ++ break; ++ ++ case SP::reloc_sparc_l44: ++ ResultPtr = (ResultPtr & 0xfff); ++ break; ++ ++ case SP::reloc_sparc_hh: ++ ResultPtr = (((int64_t)ResultPtr) >> 42) & 0x3fffff; ++ break; ++ ++ case SP::reloc_sparc_hm: ++ ResultPtr = (((int64_t)ResultPtr) >> 32) & 0x3ff; ++ break; ++ + } + *((unsigned*) RelocPos) |= (unsigned) ResultPtr; + } +Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +@@ -68,9 +68,13 @@ static MCCodeGenInfo *createSparcMCCodeGenInfo(Str + CodeGenOpt::Level OL) { + MCCodeGenInfo *X = new MCCodeGenInfo(); + +- // The default 32-bit code model is abs32/pic32. +- if (CM == CodeModel::Default) +- CM = RM == Reloc::PIC_ ? CodeModel::Medium : CodeModel::Small; ++ // The default 32-bit code model is abs32/pic32 and the default 32-bit ++ // code model for JIT is abs32. ++ switch (CM) { ++ default: break; ++ case CodeModel::Default: ++ case CodeModel::JITDefault: CM = CodeModel::Small; break; ++ } + + X->InitMCCodeGenInfo(RM, CM, OL); + return X; +@@ -81,9 +85,17 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(S + CodeGenOpt::Level OL) { + MCCodeGenInfo *X = new MCCodeGenInfo(); + +- // The default 64-bit code model is abs44/pic32. +- if (CM == CodeModel::Default) +- CM = CodeModel::Medium; ++ // The default 64-bit code model is abs44/pic32 and the default 64-bit ++ // code model for JIT is abs64. ++ switch (CM) { ++ default: break; ++ case CodeModel::Default: ++ CM = RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium; ++ break; ++ case CodeModel::JITDefault: ++ CM = CodeModel::Large; ++ break; ++ } + + X->InitMCCodeGenInfo(RM, CM, OL); + return X; +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -1810,7 +1810,6 @@ SDValue SparcTargetLowering::makeAddress(SDValue O + switch(getTargetMachine().getCodeModel()) { + default: + llvm_unreachable("Unsupported absolute code model"); +- case CodeModel::JITDefault: + case CodeModel::Small: + // abs32. + return makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG); +Index: lib/Target/Sparc/SparcCodeEmitter.cpp +=================================================================== +--- lib/Target/Sparc/SparcCodeEmitter.cpp ++++ lib/Target/Sparc/SparcCodeEmitter.cpp +@@ -207,11 +207,11 @@ unsigned SparcCodeEmitter::getRelocation(const Mac + case SPII::MO_NO_FLAG: break; + case SPII::MO_LO: return SP::reloc_sparc_lo; + case SPII::MO_HI: return SP::reloc_sparc_hi; +- case SPII::MO_H44: +- case SPII::MO_M44: +- case SPII::MO_L44: +- case SPII::MO_HH: +- case SPII::MO_HM: assert(0 && "FIXME: Implement Medium/Large code model."); ++ case SPII::MO_H44: return SP::reloc_sparc_h44; ++ case SPII::MO_M44: return SP::reloc_sparc_m44; ++ case SPII::MO_L44: return SP::reloc_sparc_l44; ++ case SPII::MO_HH: return SP::reloc_sparc_hh; ++ case SPII::MO_HM: return SP::reloc_sparc_hm; + } + + unsigned Opc = MI.getOpcode(); +Index: lib/Target/Sparc/SparcRelocations.h +=================================================================== +--- lib/Target/Sparc/SparcRelocations.h ++++ lib/Target/Sparc/SparcRelocations.h +@@ -33,7 +33,22 @@ namespace llvm { + reloc_sparc_pc22 = 4, + + // reloc_sparc_pc22 - pc rel. 19 bits for branch with icc/xcc +- reloc_sparc_pc19 = 5 ++ reloc_sparc_pc19 = 5, ++ ++ // reloc_sparc_h44 - 43-22 bits ++ reloc_sparc_h44 = 6, ++ ++ // reloc_sparc_m44 - 21-12 bits ++ reloc_sparc_m44 = 7, ++ ++ // reloc_sparc_l44 - lower 12 bits ++ reloc_sparc_l44 = 8, ++ ++ // reloc_sparc_hh - 63-42 bits ++ reloc_sparc_hh = 9, ++ ++ // reloc_sparc_hm - 41-32 bits ++ reloc_sparc_hm = 10 + }; + } + } diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200103-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200103-sparc.diff new file mode 100644 index 000000000000..a2fd7d207c5f --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200103-sparc.diff @@ -0,0 +1,49 @@ +Pull in r200103 from upstream llvm trunk (by Venkatraman Govindaraju): + + Missing ELF relocations for Sparc. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: include/llvm/Support/ELF.h +=================================================================== +--- include/llvm/Support/ELF.h ++++ include/llvm/Support/ELF.h +@@ -1143,7 +1143,37 @@ enum { + R_SPARC_L44 = 52, + R_SPARC_REGISTER = 53, + R_SPARC_UA64 = 54, +- R_SPARC_UA16 = 55 ++ R_SPARC_UA16 = 55, ++ R_SPARC_UA16 = 55, ++ R_SPARC_TLS_GD_HI22 = 56, ++ R_SPARC_TLS_GD_LO10 = 57, ++ R_SPARC_TLS_GD_ADD = 58, ++ R_SPARC_TLS_GD_CALL = 59, ++ R_SPARC_TLS_LDM_HI22 = 60, ++ R_SPARC_TLS_LDM_LO10 = 61, ++ R_SPARC_TLS_LDM_ADD = 62, ++ R_SPARC_TLS_LDM_CALL = 63, ++ R_SPARC_TLS_LDO_HIX22 = 64, ++ R_SPARC_TLS_LDO_LOX10 = 65, ++ R_SPARC_TLS_LDO_ADD = 66, ++ R_SPARC_TLS_IE_HI22 = 67, ++ R_SPARC_TLS_IE_LO10 = 68, ++ R_SPARC_TLS_IE_LD = 69, ++ R_SPARC_TLS_IE_LDX = 70, ++ R_SPARC_TLS_IE_ADD = 71, ++ R_SPARC_TLS_LE_HIX22 = 72, ++ R_SPARC_TLS_LE_LOX10 = 73, ++ R_SPARC_TLS_DTPMOD32 = 74, ++ R_SPARC_TLS_DTPMOD64 = 75, ++ R_SPARC_TLS_DTPOFF32 = 76, ++ R_SPARC_TLS_DTPOFF64 = 77, ++ R_SPARC_TLS_TPOFF32 = 78, ++ R_SPARC_TLS_TPOFF64 = 79, ++ R_SPARC_GOTDATA_HIX22 = 80, ++ R_SPARC_GOTDATA_LOX22 = 81, ++ R_SPARC_GOTDATA_OP_HIX22 = 82, ++ R_SPARC_GOTDATA_OP_LOX22 = 83, ++ R_SPARC_GOTDATA_OP = 84 + }; + + // Section header. diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200104-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200104-sparc.diff new file mode 100644 index 000000000000..c489ca10d40d --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200104-sparc.diff @@ -0,0 +1,18 @@ +Pull in r200104 from upstream llvm trunk (by Venkatraman Govindaraju): + + removing duplicate enum value + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: include/llvm/Support/ELF.h +=================================================================== +--- include/llvm/Support/ELF.h ++++ include/llvm/Support/ELF.h +@@ -1144,7 +1144,6 @@ enum { + R_SPARC_REGISTER = 53, + R_SPARC_UA64 = 54, + R_SPARC_UA16 = 55, +- R_SPARC_UA16 = 55, + R_SPARC_TLS_GD_HI22 = 56, + R_SPARC_TLS_GD_LO10 = 57, + R_SPARC_TLS_GD_ADD = 58, diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200112-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200112-sparc.diff new file mode 100644 index 000000000000..f499b590f89a --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200112-sparc.diff @@ -0,0 +1,169 @@ +Pull in r200112 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add support for sparc relocation types in ELF object file. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/MC/Sparc/sparc-relocations.s +=================================================================== +--- test/MC/Sparc/sparc-relocations.s ++++ test/MC/Sparc/sparc-relocations.s +@@ -1,5 +1,18 @@ + ! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s ++! RUN: llvm-mc %s -arch=sparcv9 -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-OBJ + ++ ! CHECK-OBJ: Format: ELF64-sparc ++ ! CHECK-OBJ: Relocations [ ++ ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 foo ++ ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_LO10 sym ++ ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HI22 sym ++ ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_H44 sym ++ ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_M44 sym ++ ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_L44 sym ++ ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HH22 sym ++ ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HM10 sym ++ ! CHECK-ELF: ] ++ + ! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A] + ! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30 + call foo +Index: include/llvm/Object/ELFObjectFile.h +=================================================================== +--- include/llvm/Object/ELFObjectFile.h ++++ include/llvm/Object/ELFObjectFile.h +@@ -922,6 +922,9 @@ StringRef ELFObjectFile::getFileFormatName() + return "ELF32-mips"; + case ELF::EM_PPC: + return "ELF32-ppc"; ++ case ELF::EM_SPARC: ++ case ELF::EM_SPARC32PLUS: ++ return "ELF32-sparc"; + default: + return "ELF32-unknown"; + } +@@ -937,6 +940,8 @@ StringRef ELFObjectFile::getFileFormatName() + return "ELF64-ppc64"; + case ELF::EM_S390: + return "ELF64-s390"; ++ case ELF::EM_SPARCV9: ++ return "ELF64-sparc"; + default: + return "ELF64-unknown"; + } +@@ -967,6 +972,13 @@ unsigned ELFObjectFile::getArch() const { + : Triple::ppc64; + case ELF::EM_S390: + return Triple::systemz; ++ ++ case ELF::EM_SPARC: ++ case ELF::EM_SPARC32PLUS: ++ return Triple::sparc; ++ case ELF::EM_SPARCV9: ++ return Triple::sparcv9; ++ + default: + return Triple::UnknownArch; + } +Index: lib/Object/ELF.cpp +=================================================================== +--- lib/Object/ELF.cpp ++++ lib/Object/ELF.cpp +@@ -702,6 +702,98 @@ StringRef getELFRelocationTypeName(uint32_t Machin + break; + } + break; ++ case ELF::EM_SPARC: ++ case ELF::EM_SPARC32PLUS: ++ case ELF::EM_SPARCV9: ++ switch (Type) { ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_NONE); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_8); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_16); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_32); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP8); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP16); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP32); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP30); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HI22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_13); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LO10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT13); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WPLT30); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_COPY); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GLOB_DAT); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_JMP_SLOT); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_RELATIVE); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA32); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PLT32); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HIPLT22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LOPLT10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT32); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_11); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_64); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_OLO10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HH22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HM10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LM22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_HH22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_HM10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_LM22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP16); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP19); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_7); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_5); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_6); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP64); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PLT64); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HIX22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LOX10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_H44); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_M44); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_L44); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_REGISTER); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA64); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA16); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_HI22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_LO10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_ADD); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_CALL); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_HI22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_LO10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_ADD); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_CALL); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_HIX22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_LOX10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_ADD); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_HI22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LO10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LD); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LDX); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_ADD); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LE_HIX22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LE_LOX10); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPMOD32); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPMOD64); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPOFF32); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPOFF64); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_TPOFF32); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_TPOFF64); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_HIX22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_LOX22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP_HIX22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP_LOX22); ++ LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP); ++ default: ++ break; ++ } ++ break; + default: + break; + } diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200130-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200130-sparc.diff new file mode 100644 index 000000000000..aad6ae905cc1 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200130-sparc.diff @@ -0,0 +1,45 @@ +Pull in r200130 from upstream llvm trunk (by Jakob Stoklund Olesen): + + Fix swapped CASA operands. + + Found by SingleSource/UnitTests/AtomicOps.c + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -2972,7 +2972,7 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr + // loop: + // %val = phi %val0, %dest + // %upd = op %val, %rs2 +- // %dest = cas %addr, %upd, %val ++ // %dest = cas %addr, %val, %upd + // cmp %val, %dest + // bne loop + // done: +@@ -3031,7 +3031,7 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr + } + + BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::CASXrr : SP::CASrr), DestReg) +- .addReg(AddrReg).addReg(UpdReg).addReg(ValReg) ++ .addReg(AddrReg).addReg(ValReg).addReg(UpdReg) + .setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); + BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(DestReg); + BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::BPXCC : SP::BCOND)) +Index: test/CodeGen/SPARC/atomics.ll +=================================================================== +--- test/CodeGen/SPARC/atomics.ll ++++ test/CodeGen/SPARC/atomics.ll +@@ -64,8 +64,8 @@ entry: + + ; CHECK-LABEL: test_load_add_32 + ; CHECK: membar +-; CHECK: add +-; CHECK: cas [%o0] ++; CHECK: add [[V:%[gilo][0-7]]], %o1, [[U:%[gilo][0-7]]] ++; CHECK: cas [%o0], [[V]], [[U]] + ; CHECK: membar + define zeroext i32 @test_load_add_32(i32* %p, i32 zeroext %v) { + entry: diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200131-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200131-sparc.diff new file mode 100644 index 000000000000..6b0ab16026f5 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200131-sparc.diff @@ -0,0 +1,117 @@ +Pull in r200131 from upstream llvm trunk (by Jakob Stoklund Olesen): + + Only generate the popc instruction for SPARC CPUs that implement it. + + The popc instruction is defined in the SPARCv9 instruction set + architecture, but it was emulated on CPUs older than Niagara 2. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -1461,7 +1461,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + setOperationAction(ISD::BR_CC, MVT::i64, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); + +- setOperationAction(ISD::CTPOP, MVT::i64, Legal); ++ if (Subtarget->usePopc()) ++ setOperationAction(ISD::CTPOP, MVT::i64, Legal); + setOperationAction(ISD::CTTZ , MVT::i64, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); + setOperationAction(ISD::CTLZ , MVT::i64, Expand); +@@ -1567,7 +1568,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + + setStackPointerRegisterToSaveRestore(SP::O6); + +- if (Subtarget->isV9()) ++ if (Subtarget->isV9() && Subtarget->usePopc()) + setOperationAction(ISD::CTPOP, MVT::i32, Legal); + + if (Subtarget->isV9() && Subtarget->hasHardQuad()) { +Index: lib/Target/Sparc/Sparc.td +=================================================================== +--- lib/Target/Sparc/Sparc.td ++++ lib/Target/Sparc/Sparc.td +@@ -34,6 +34,9 @@ def FeatureHardQuad + : SubtargetFeature<"hard-quad-float", "HasHardQuad", "true", + "Enable quad-word floating point instructions">; + ++def UsePopc : SubtargetFeature<"popc", "UsePopc", "true", ++ "Use the popc (population count) instruction">; ++ + //===----------------------------------------------------------------------===// + // Register File, Calling Conv, Instruction Descriptions + //===----------------------------------------------------------------------===// +@@ -69,9 +72,9 @@ def : Proc<"v9", [FeatureV9]>; + def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated]>; + def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>; + def : Proc<"niagara", [FeatureV9, FeatureV8Deprecated]>; +-def : Proc<"niagara2", [FeatureV9, FeatureV8Deprecated]>; +-def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated]>; +-def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated]>; ++def : Proc<"niagara2", [FeatureV9, FeatureV8Deprecated, UsePopc]>; ++def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated, UsePopc]>; ++def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated, UsePopc]>; + + def SparcAsmWriter : AsmWriter { + string AsmWriterClassName = "InstPrinter"; +Index: lib/Target/Sparc/SparcSubtarget.h +=================================================================== +--- lib/Target/Sparc/SparcSubtarget.h ++++ lib/Target/Sparc/SparcSubtarget.h +@@ -30,6 +30,7 @@ class SparcSubtarget : public SparcGenSubtargetInf + bool IsVIS; + bool Is64Bit; + bool HasHardQuad; ++ bool UsePopc; + + public: + SparcSubtarget(const std::string &TT, const std::string &CPU, +@@ -39,6 +40,7 @@ class SparcSubtarget : public SparcGenSubtargetInf + bool isVIS() const { return IsVIS; } + bool useDeprecatedV8Instructions() const { return V8DeprecatedInsts; } + bool hasHardQuad() const { return HasHardQuad; } ++ bool usePopc() const { return UsePopc; } + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. +Index: lib/Target/Sparc/SparcSubtarget.cpp +=================================================================== +--- lib/Target/Sparc/SparcSubtarget.cpp ++++ lib/Target/Sparc/SparcSubtarget.cpp +@@ -31,7 +31,8 @@ SparcSubtarget::SparcSubtarget(const std::string & + V8DeprecatedInsts(false), + IsVIS(false), + Is64Bit(is64Bit), +- HasHardQuad(false) { ++ HasHardQuad(false), ++ UsePopc(false) { + + // Determine default and user specified characteristics + std::string CPUName = CPU; +Index: test/CodeGen/SPARC/ctpop.ll +=================================================================== +--- test/CodeGen/SPARC/ctpop.ll ++++ test/CodeGen/SPARC/ctpop.ll +@@ -1,13 +1,13 @@ + ; RUN: llc < %s -march=sparc -mattr=-v9 | FileCheck %s -check-prefix=V8 +-; RUN: llc < %s -march=sparc -mattr=+v9 | FileCheck %s -check-prefix=V9 +-; RUN: llc < %s -march=sparc -mcpu=v9 | FileCheck %s -check-prefix=V9 +-; RUN: llc < %s -march=sparc -mcpu=ultrasparc | FileCheck %s -check-prefix=V9 +-; RUN: llc < %s -march=sparc -mcpu=ultrasparc3 | FileCheck %s -check-prefix=V9 +-; RUN: llc < %s -march=sparc -mcpu=niagara | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparc -mattr=+v9,+popc | FileCheck %s -check-prefix=V9 ++; RUN: llc < %s -march=sparc -mcpu=v9 | FileCheck %s -check-prefix=V8 ++; RUN: llc < %s -march=sparc -mcpu=ultrasparc | FileCheck %s -check-prefix=V8 ++; RUN: llc < %s -march=sparc -mcpu=ultrasparc3 | FileCheck %s -check-prefix=V8 ++; RUN: llc < %s -march=sparc -mcpu=niagara | FileCheck %s -check-prefix=V8 + ; RUN: llc < %s -march=sparc -mcpu=niagara2 | FileCheck %s -check-prefix=V9 + ; RUN: llc < %s -march=sparc -mcpu=niagara3 | FileCheck %s -check-prefix=V9 + ; RUN: llc < %s -march=sparc -mcpu=niagara4 | FileCheck %s -check-prefix=V9 +-; RUN: llc < %s -march=sparcv9 | FileCheck %s -check-prefix=SPARC64 ++; RUN: llc < %s -march=sparcv9 -mattr=+popc | FileCheck %s -check-prefix=SPARC64 + + declare i32 @llvm.ctpop.i32(i32) + diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200141-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200141-sparc.diff new file mode 100644 index 000000000000..d8016e8a4ca6 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200141-sparc.diff @@ -0,0 +1,67 @@ +Pull in r200141 from upstream llvm trunk (by Jakob Stoklund Olesen): + + Clean up the Legal/Expand logic for SPARC popc. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcSubtarget.cpp +=================================================================== +--- lib/Target/Sparc/SparcSubtarget.cpp ++++ lib/Target/Sparc/SparcSubtarget.cpp +@@ -41,6 +41,10 @@ SparcSubtarget::SparcSubtarget(const std::string & + + // Parse features string. + ParseSubtargetFeatures(CPUName, FS); ++ ++ // Popc is a v9-only instruction. ++ if (!IsV9) ++ UsePopc = false; + } + + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -1461,8 +1461,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + setOperationAction(ISD::BR_CC, MVT::i64, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); + +- if (Subtarget->usePopc()) +- setOperationAction(ISD::CTPOP, MVT::i64, Legal); ++ setOperationAction(ISD::CTPOP, MVT::i64, ++ Subtarget->usePopc() ? Legal : Expand); + setOperationAction(ISD::CTTZ , MVT::i64, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); + setOperationAction(ISD::CTLZ , MVT::i64, Expand); +@@ -1518,7 +1518,6 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + setOperationAction(ISD::FSINCOS, MVT::f32, Expand); + setOperationAction(ISD::FREM , MVT::f32, Expand); + setOperationAction(ISD::FMA , MVT::f32, Expand); +- setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTTZ , MVT::i32, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); + setOperationAction(ISD::CTLZ , MVT::i32, Expand); +@@ -1568,8 +1567,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + + setStackPointerRegisterToSaveRestore(SP::O6); + +- if (Subtarget->isV9() && Subtarget->usePopc()) +- setOperationAction(ISD::CTPOP, MVT::i32, Legal); ++ setOperationAction(ISD::CTPOP, MVT::i32, ++ Subtarget->usePopc() ? Legal : Expand); + + if (Subtarget->isV9() && Subtarget->hasHardQuad()) { + setOperationAction(ISD::LOAD, MVT::f128, Legal); +Index: test/CodeGen/SPARC/64bit.ll +=================================================================== +--- test/CodeGen/SPARC/64bit.ll ++++ test/CodeGen/SPARC/64bit.ll +@@ -1,5 +1,5 @@ +-; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s +-; RUN: llc < %s -march=sparcv9 | FileCheck %s -check-prefix=OPT ++; RUN: llc < %s -march=sparcv9 -mattr=+popc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s ++; RUN: llc < %s -march=sparcv9 -mattr=+popc | FileCheck %s -check-prefix=OPT + + ; CHECK-LABEL: ret2: + ; CHECK: or %g0, %i1, %i0 diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200282-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200282-sparc.diff new file mode 100644 index 000000000000..95f28684463a --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200282-sparc.diff @@ -0,0 +1,183 @@ +Pull in r200282 from upstream llvm trunk (by Jakob Stoklund Olesen): + + Fix the DWARF EH encodings for Sparc PIC code. + + Also emit the stubs that were generated for references to typeinfo + symbols. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcAsmPrinter.cpp +=================================================================== +--- lib/Target/Sparc/SparcAsmPrinter.cpp ++++ lib/Target/Sparc/SparcAsmPrinter.cpp +@@ -23,7 +23,9 @@ + #include "llvm/ADT/SmallString.h" + #include "llvm/CodeGen/AsmPrinter.h" + #include "llvm/CodeGen/MachineInstr.h" ++#include "llvm/CodeGen/MachineModuleInfoImpls.h" + #include "llvm/CodeGen/MachineRegisterInfo.h" ++#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" + #include "llvm/MC/MCAsmInfo.h" + #include "llvm/MC/MCContext.h" + #include "llvm/MC/MCInst.h" +@@ -54,6 +56,7 @@ namespace { + + virtual void EmitFunctionBodyStart(); + virtual void EmitInstruction(const MachineInstr *MI); ++ virtual void EmitEndOfAsmFile(Module &M); + + static const char *getRegisterName(unsigned RegNo) { + return SparcInstPrinter::getRegisterName(RegNo); +@@ -450,6 +453,23 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const + return false; + } + ++void SparcAsmPrinter::EmitEndOfAsmFile(Module &M) { ++ const TargetLoweringObjectFileELF &TLOFELF = ++ static_cast(getObjFileLowering()); ++ MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo(); ++ ++ // Generate stubs for global variables. ++ MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); ++ if (!Stubs.empty()) { ++ OutStreamer.SwitchSection(TLOFELF.getDataSection()); ++ unsigned PtrSize = TM.getDataLayout()->getPointerSize(0); ++ for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { ++ OutStreamer.EmitLabel(Stubs[i].first); ++ OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), PtrSize); ++ } ++ } ++} ++ + // Force static initialization. + extern "C" void LLVMInitializeSparcAsmPrinter() { + RegisterAsmPrinter X(TheSparcTarget); +Index: lib/MC/MCObjectFileInfo.cpp +=================================================================== +--- lib/MC/MCObjectFileInfo.cpp ++++ lib/MC/MCObjectFileInfo.cpp +@@ -310,6 +310,33 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Tri + FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; + TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_udata8; ++ } else if (T.getArch() == Triple::sparc) { ++ if (RelocM == Reloc::PIC_) { ++ LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; ++ PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | ++ dwarf::DW_EH_PE_sdata4; ++ FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; ++ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | ++ dwarf::DW_EH_PE_sdata4; ++ } else { ++ LSDAEncoding = dwarf::DW_EH_PE_absptr; ++ PersonalityEncoding = dwarf::DW_EH_PE_absptr; ++ FDEEncoding = dwarf::DW_EH_PE_udata4; ++ TTypeEncoding = dwarf::DW_EH_PE_absptr; ++ } ++ } else if (T.getArch() == Triple::sparcv9) { ++ LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; ++ if (RelocM == Reloc::PIC_) { ++ PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | ++ dwarf::DW_EH_PE_sdata4; ++ FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; ++ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | ++ dwarf::DW_EH_PE_sdata4; ++ } else { ++ PersonalityEncoding = dwarf::DW_EH_PE_absptr; ++ FDEEncoding = dwarf::DW_EH_PE_udata4; ++ TTypeEncoding = dwarf::DW_EH_PE_absptr; ++ } + } else if (T.getArch() == Triple::systemz) { + // All currently-defined code models guarantee that 4-byte PC-relative + // values will be in range. +Index: test/CodeGen/SPARC/exception.ll +=================================================================== +--- test/CodeGen/SPARC/exception.ll ++++ test/CodeGen/SPARC/exception.ll +@@ -1,4 +1,7 @@ +-; RUN: llc < %s -march=sparc | FileCheck %s ++; RUN: llc < %s -march=sparc -relocation-model=static | FileCheck -check-prefix=V8ABS %s ++; RUN: llc < %s -march=sparc -relocation-model=pic | FileCheck -check-prefix=V8PIC %s ++; RUN: llc < %s -march=sparcv9 -relocation-model=static | FileCheck -check-prefix=V9ABS %s ++; RUN: llc < %s -march=sparcv9 -relocation-model=pic | FileCheck -check-prefix=V9PIC %s + + + %struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo } +@@ -9,23 +12,64 @@ + @.cst = linker_private unnamed_addr constant [12 x i8] c"catched int\00", align 64 + @.cst1 = linker_private unnamed_addr constant [14 x i8] c"catched float\00", align 64 + +-; CHECK-LABEL: main: +-; CHECK: .cfi_startproc +-; CHECK: .cfi_def_cfa_register {{30|%fp}} +-; CHECK: .cfi_window_save +-; CHECK: .cfi_register 15, 31 ++; V8ABS-LABEL: main: ++; V8ABS: .cfi_startproc ++; V8ABS: .cfi_personality 0, __gxx_personality_v0 ++; V8ABS: .cfi_lsda 0, ++; V8ABS: .cfi_def_cfa_register {{30|%fp}} ++; V8ABS: .cfi_window_save ++; V8ABS: .cfi_register 15, 31 + +-; CHECK: call __cxa_throw +-; CHECK: call __cxa_throw ++; V8ABS: call __cxa_throw ++; V8ABS: call __cxa_throw + +-; CHECK: call __cxa_begin_catch +-; CHECK: call __cxa_end_catch ++; V8ABS: call __cxa_begin_catch ++; V8ABS: call __cxa_end_catch + +-; CHECK: call __cxa_begin_catch +-; CHECK: call __cxa_end_catch ++; V8ABS: call __cxa_begin_catch ++; V8ABS: call __cxa_end_catch + +-; CHECK: .cfi_endproc ++; V8ABS: .cfi_endproc + ++; V8PIC-LABEL: main: ++; V8PIC: .cfi_startproc ++; V8PIC: .cfi_personality 155, DW.ref.__gxx_personality_v0 ++; V8PIC: .cfi_lsda 27, ++; V8PIC: .cfi_def_cfa_register {{30|%fp}} ++; V8PIC: .cfi_window_save ++; V8PIC: .cfi_register 15, 31 ++; V8PIC: .section .gcc_except_table ++; V8PIC-NOT: .section ++; V8PIC: .word .L_ZTIi.DW.stub- ++; V8PIC: .data ++; V8PIC: .L_ZTIi.DW.stub: ++; V8PIC-NEXT: .word _ZTIi ++ ++; V9ABS-LABEL: main: ++; V9ABS: .cfi_startproc ++; V9ABS: .cfi_personality 0, __gxx_personality_v0 ++; V9ABS: .cfi_lsda 27, ++; V9ABS: .cfi_def_cfa_register {{30|%fp}} ++; V9ABS: .cfi_window_save ++; V9ABS: .cfi_register 15, 31 ++; V9ABS: .section .gcc_except_table ++; V9ABS-NOT: .section ++; V9ABS: .xword _ZTIi ++ ++; V9PIC-LABEL: main: ++; V9PIC: .cfi_startproc ++; V9PIC: .cfi_personality 155, DW.ref.__gxx_personality_v0 ++; V9PIC: .cfi_lsda 27, ++; V9PIC: .cfi_def_cfa_register {{30|%fp}} ++; V9PIC: .cfi_window_save ++; V9PIC: .cfi_register 15, 31 ++; V9PIC: .section .gcc_except_table ++; V9PIC-NOT: .section ++; V9PIC: .word .L_ZTIi.DW.stub- ++; V9PIC: .data ++; V9PIC: .L_ZTIi.DW.stub: ++; V9PIC-NEXT: .xword _ZTIi ++ + define i32 @main(i32 %argc, i8** nocapture readnone %argv) unnamed_addr #0 { + entry: + %0 = icmp eq i32 %argc, 2 diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200368-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200368-sparc.diff new file mode 100644 index 000000000000..f596b5f516d5 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200368-sparc.diff @@ -0,0 +1,88 @@ +Pull r200368 from upstream llvm trunk (by Venkatraman Govindaraju): + + [SparcV9] Use correct register class (I64RegClass) to hold the address of _GLOBAL_OFFSET_TABLE_ in sparcv9. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcInstrInfo.cpp +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.cpp ++++ lib/Target/Sparc/SparcInstrInfo.cpp +@@ -431,9 +431,10 @@ unsigned SparcInstrInfo::getGlobalBaseReg(MachineF + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + +- GlobalBaseReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); ++ const TargetRegisterClass *PtrRC = ++ Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; ++ GlobalBaseReg = RegInfo.createVirtualRegister(PtrRC); + +- + DebugLoc dl; + + BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg); +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -180,7 +180,7 @@ def tlscall : SDNode<"SPISD::TLS_CALL", SDT_ + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, + SDNPVariadic]>; + +-def getPCX : Operand { ++def getPCX : Operand { + let PrintMethod = "printGetPCX"; + } + +Index: test/CodeGen/SPARC/2009-08-28-PIC.ll +=================================================================== +--- test/CodeGen/SPARC/2009-08-28-PIC.ll ++++ test/CodeGen/SPARC/2009-08-28-PIC.ll +@@ -1,9 +1,45 @@ +-; RUN: llc -march=sparc --relocation-model=pic < %s | grep _GLOBAL_OFFSET_TABLE_ ++; RUN: llc -march=sparc --relocation-model=pic < %s | FileCheck %s --check-prefix=V8 ++; RUN: llc -march=sparcv9 --relocation-model=pic < %s | FileCheck %s --check-prefix=V9 ++; RUN: llc -march=sparc --relocation-model=pic < %s -O0 | FileCheck %s --check-prefix=V8UNOPT ++; RUN: llc -march=sparcv9 --relocation-model=pic < %s -O0 | FileCheck %s --check-prefix=V9UNOPT + ++ ++; V8-LABEL: func ++; V8: _GLOBAL_OFFSET_TABLE_ ++ ++; V9-LABEL: func ++; V9: _GLOBAL_OFFSET_TABLE_ ++ + @foo = global i32 0 ; [#uses=1] + +-define i32 @func() nounwind readonly { ++define i32 @func(i32 %a) nounwind readonly { + entry: + %0 = load i32* @foo, align 4 ; [#uses=1] + ret i32 %0 + } ++ ++; V8UNOPT-LABEL: test_spill ++; V8UNOPT: sethi %hi(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R:%[goli][0-7]]] ++; V8UNOPT: or [[R]], %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R]] ++; V8UNOPT: add [[R]], %o7, [[R]] ++; V8UNOPT: st [[R]], [%fp+{{.+}}] ++ ++; V9UNOPT-LABEL: test_spill ++; V9UNOPT: sethi %hi(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R:%[goli][0-7]]] ++; V9UNOPT: or [[R]], %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R]] ++; V9UNOPT: add [[R]], %o7, [[R]] ++; V9UNOPT: stx [[R]], [%fp+{{.+}}] ++ ++define i32 @test_spill(i32 %a, i32 %b) { ++entry: ++ %cmp = icmp eq i32 %b, 0 ++ br i1 %cmp, label %if.then, label %if.end ++ ++if.then: ++ %ret = load i32* @foo, align 4 ++ ret i32 %ret ++ ++if.end: ++ %add = add nsw i32 %b, %a ++ ret i32 %add ++} diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200373-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200373-sparc.diff new file mode 100644 index 000000000000..f9bed3572128 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200373-sparc.diff @@ -0,0 +1,296 @@ +Pull in r200373 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Use %r_disp32 for pc_rel entries in gcc_except_table and eh_frame. + + Otherwise, assembler (gas) fails to assemble them with error message "operation + combines symbols in different segments". This is because MC computes + pc_rel entries with subtract expression between labels from different sections. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcTargetObjectFile.h +=================================================================== +--- lib/Target/Sparc/SparcTargetObjectFile.h ++++ lib/Target/Sparc/SparcTargetObjectFile.h +@@ -0,0 +1,34 @@ ++//===-- SparcTargetObjectFile.h - Sparc Object Info -------------*- C++ -*-===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_TARGET_SPARC_TARGETOBJECTFILE_H ++#define LLVM_TARGET_SPARC_TARGETOBJECTFILE_H ++ ++#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" ++ ++namespace llvm { ++ ++class MCContext; ++class TargetMachine; ++ ++class SparcELFTargetObjectFile : public TargetLoweringObjectFileELF { ++public: ++ SparcELFTargetObjectFile() : ++ TargetLoweringObjectFileELF() ++ {} ++ ++ const MCExpr * ++ getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang, ++ MachineModuleInfo *MMI, unsigned Encoding, ++ MCStreamer &Streamer) const; ++}; ++ ++} // end namespace llvm ++ ++#endif +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -16,6 +16,7 @@ + #include "SparcMachineFunctionInfo.h" + #include "SparcRegisterInfo.h" + #include "SparcTargetMachine.h" ++#include "SparcTargetObjectFile.h" + #include "MCTargetDesc/SparcBaseInfo.h" + #include "llvm/CodeGen/CallingConvLower.h" + #include "llvm/CodeGen/MachineFrameInfo.h" +@@ -1361,7 +1362,7 @@ static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondC + } + + SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) +- : TargetLowering(TM, new TargetLoweringObjectFileELF()) { ++ : TargetLowering(TM, new SparcELFTargetObjectFile()) { + Subtarget = &TM.getSubtarget(); + + // Set up the register classes. +Index: lib/Target/Sparc/SparcTargetObjectFile.cpp +=================================================================== +--- lib/Target/Sparc/SparcTargetObjectFile.cpp ++++ lib/Target/Sparc/SparcTargetObjectFile.cpp +@@ -0,0 +1,48 @@ ++//===------- SparcTargetObjectFile.cpp - Sparc Object Info Impl -----------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "SparcTargetObjectFile.h" ++#include "MCTargetDesc/SparcMCExpr.h" ++#include "llvm/CodeGen/MachineModuleInfoImpls.h" ++#include "llvm/Support/Dwarf.h" ++#include "llvm/Target/Mangler.h" ++ ++using namespace llvm; ++ ++ ++const MCExpr *SparcELFTargetObjectFile:: ++getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang, ++ MachineModuleInfo *MMI, unsigned Encoding, ++ MCStreamer &Streamer) const { ++ ++ if (Encoding & dwarf::DW_EH_PE_pcrel) { ++ MachineModuleInfoELF &ELFMMI = MMI->getObjFileInfo(); ++ ++ //MCSymbol *SSym = getSymbolWithGlobalValueBase(*Mang, GV, ".DW.stub"); ++ SmallString<60> NameStr; ++ Mang->getNameWithPrefix(NameStr, GV, true); ++ NameStr.append(".DW.stub"); ++ MCSymbol *SSym = getContext().GetOrCreateSymbol(NameStr.str()); ++ ++ // Add information about the stub reference to ELFMMI so that the stub ++ // gets emitted by the asmprinter. ++ MachineModuleInfoImpl::StubValueTy &StubSym = ELFMMI.getGVStubEntry(SSym); ++ if (StubSym.getPointer() == 0) { ++ MCSymbol *Sym = getSymbol(*Mang, GV); ++ StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage()); ++ } ++ ++ MCContext &Ctx = getContext(); ++ return SparcMCExpr::Create(SparcMCExpr::VK_Sparc_R_DISP32, ++ MCSymbolRefExpr::Create(SSym, Ctx), Ctx); ++ } ++ ++ return TargetLoweringObjectFileELF:: ++ getTTypeGlobalReference(GV, Mang, MMI, Encoding, Streamer); ++} +Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp +@@ -12,7 +12,9 @@ + //===----------------------------------------------------------------------===// + + #include "SparcMCAsmInfo.h" ++#include "SparcMCExpr.h" + #include "llvm/ADT/Triple.h" ++#include "llvm/MC/MCStreamer.h" + + using namespace llvm; + +@@ -44,4 +46,15 @@ SparcELFMCAsmInfo::SparcELFMCAsmInfo(StringRef TT) + PrivateGlobalPrefix = ".L"; + } + ++const MCExpr* ++SparcELFMCAsmInfo::getExprForPersonalitySymbol(const MCSymbol *Sym, ++ unsigned Encoding, ++ MCStreamer &Streamer) const { ++ if (Encoding & dwarf::DW_EH_PE_pcrel) { ++ MCContext &Ctx = Streamer.getContext(); ++ return SparcMCExpr::Create(SparcMCExpr::VK_Sparc_R_DISP32, ++ MCSymbolRefExpr::Create(Sym, Ctx), Ctx); ++ } + ++ return MCAsmInfo::getExprForPersonalitySymbol(Sym, Encoding, Streamer); ++} +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +@@ -41,6 +41,7 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const + case VK_Sparc_L44: OS << "%l44("; break; + case VK_Sparc_HH: OS << "%hh("; break; + case VK_Sparc_HM: OS << "%hm("; break; ++ case VK_Sparc_R_DISP32: OS << "%r_disp32("; break; + case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break; + case VK_Sparc_TLS_GD_LO10: OS << "%tgd_lo10("; break; + case VK_Sparc_TLS_GD_ADD: OS << "%tgd_add("; break; +@@ -77,6 +78,7 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant + .Case("l44", VK_Sparc_L44) + .Case("hh", VK_Sparc_HH) + .Case("hm", VK_Sparc_HM) ++ .Case("r_disp32", VK_Sparc_R_DISP32) + .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22) + .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10) + .Case("tgd_add", VK_Sparc_TLS_GD_ADD) +@@ -101,6 +103,8 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant + bool + SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const { ++ if (!Layout) ++ return false; + return getSubExpr()->EvaluateAsRelocatable(Res, *Layout); + } + +Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h ++++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h +@@ -17,13 +17,16 @@ + #include "llvm/MC/MCAsmInfoELF.h" + + namespace llvm { +- class StringRef; ++class StringRef; + +- class SparcELFMCAsmInfo : public MCAsmInfoELF { +- virtual void anchor(); +- public: +- explicit SparcELFMCAsmInfo(StringRef TT); +- }; ++class SparcELFMCAsmInfo : public MCAsmInfoELF { ++ virtual void anchor(); ++public: ++ explicit SparcELFMCAsmInfo(StringRef TT); ++ virtual const MCExpr* getExprForPersonalitySymbol(const MCSymbol *Sym, ++ unsigned Encoding, ++ MCStreamer &Streamer) const; ++}; + + } // namespace llvm + +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +@@ -31,6 +31,7 @@ class SparcMCExpr : public MCTargetExpr { + VK_Sparc_L44, + VK_Sparc_HH, + VK_Sparc_HM, ++ VK_Sparc_R_DISP32, + VK_Sparc_TLS_GD_HI22, + VK_Sparc_TLS_GD_LO10, + VK_Sparc_TLS_GD_ADD, +Index: lib/Target/Sparc/CMakeLists.txt +=================================================================== +--- lib/Target/Sparc/CMakeLists.txt ++++ lib/Target/Sparc/CMakeLists.txt +@@ -27,6 +27,7 @@ add_llvm_target(SparcCodeGen + SparcJITInfo.cpp + SparcCodeEmitter.cpp + SparcMCInstLower.cpp ++ SparcTargetObjectFile.cpp + ) + + add_dependencies(LLVMSparcCodeGen SparcCommonTableGen intrinsics_gen) +Index: test/CodeGen/SPARC/exception.ll +=================================================================== +--- test/CodeGen/SPARC/exception.ll ++++ test/CodeGen/SPARC/exception.ll +@@ -1,7 +1,9 @@ + ; RUN: llc < %s -march=sparc -relocation-model=static | FileCheck -check-prefix=V8ABS %s + ; RUN: llc < %s -march=sparc -relocation-model=pic | FileCheck -check-prefix=V8PIC %s ++; RUN: llc < %s -march=sparc -relocation-model=pic -disable-cfi | FileCheck -check-prefix=V8PIC_NOCFI %s + ; RUN: llc < %s -march=sparcv9 -relocation-model=static | FileCheck -check-prefix=V9ABS %s + ; RUN: llc < %s -march=sparcv9 -relocation-model=pic | FileCheck -check-prefix=V9PIC %s ++; RUN: llc < %s -march=sparcv9 -relocation-model=pic -disable-cfi | FileCheck -check-prefix=V9PIC_NOCFI %s + + + %struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo } +@@ -40,11 +42,23 @@ + ; V8PIC: .cfi_register 15, 31 + ; V8PIC: .section .gcc_except_table + ; V8PIC-NOT: .section +-; V8PIC: .word .L_ZTIi.DW.stub- ++; V8PIC: .word %r_disp32(.L_ZTIi.DW.stub) + ; V8PIC: .data + ; V8PIC: .L_ZTIi.DW.stub: + ; V8PIC-NEXT: .word _ZTIi + ++; V8PIC_NOCFI-LABEL: main: ++; V8PIC_NOCFI: .section .gcc_except_table ++; V8PIC_NOCFI-NOT: .section ++; V8PIC_NOCFI: .word %r_disp32(.L_ZTIi.DW.stub) ++; V8PIC_NOCFI: .data ++; V8PIC_NOCFI: .L_ZTIi.DW.stub: ++; V8PIC_NOCFI-NEXT: .word _ZTIi ++; V8PIC_NOCFI: .section .eh_frame ++; V8PIC_NOCFI-NOT: .section ++; V8PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0) ++ ++ + ; V9ABS-LABEL: main: + ; V9ABS: .cfi_startproc + ; V9ABS: .cfi_personality 0, __gxx_personality_v0 +@@ -65,11 +79,22 @@ + ; V9PIC: .cfi_register 15, 31 + ; V9PIC: .section .gcc_except_table + ; V9PIC-NOT: .section +-; V9PIC: .word .L_ZTIi.DW.stub- ++; V9PIC: .word %r_disp32(.L_ZTIi.DW.stub) + ; V9PIC: .data + ; V9PIC: .L_ZTIi.DW.stub: + ; V9PIC-NEXT: .xword _ZTIi + ++; V9PIC_NOCFI-LABEL: main: ++; V9PIC_NOCFI: .section .gcc_except_table ++; V9PIC_NOCFI-NOT: .section ++; V9PIC_NOCFI: .word %r_disp32(.L_ZTIi.DW.stub) ++; V9PIC_NOCFI: .data ++; V9PIC_NOCFI: .L_ZTIi.DW.stub: ++; V9PIC_NOCFI-NEXT: .xword _ZTIi ++; V9PIC_NOCFI: .section .eh_frame ++; V9PIC_NOCFI-NOT: .section ++; V9PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0) ++ + define i32 @main(i32 %argc, i8** nocapture readnone %argv) unnamed_addr #0 { + entry: + %0 = icmp eq i32 %argc, 2 diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200376-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200376-sparc.diff new file mode 100644 index 000000000000..0053365f6ab0 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200376-sparc.diff @@ -0,0 +1,76 @@ +Pull in r200376 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Use %r_disp32 for pc_rel entries in FDE as well. + + This makes MCAsmInfo::getExprForFDESymbol() a virtual function and overrides it in SparcMCAsmInfo. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h ++++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h +@@ -26,6 +26,10 @@ class SparcELFMCAsmInfo : public MCAsmInfoELF { + virtual const MCExpr* getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; ++ virtual const MCExpr* getExprForFDESymbol(const MCSymbol *Sym, ++ unsigned Encoding, ++ MCStreamer &Streamer) const; ++ + }; + + } // namespace llvm +Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp +@@ -58,3 +58,15 @@ SparcELFMCAsmInfo::getExprForPersonalitySymbol(con + + return MCAsmInfo::getExprForPersonalitySymbol(Sym, Encoding, Streamer); + } ++ ++const MCExpr* ++SparcELFMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym, ++ unsigned Encoding, ++ MCStreamer &Streamer) const { ++ if (Encoding & dwarf::DW_EH_PE_pcrel) { ++ MCContext &Ctx = Streamer.getContext(); ++ return SparcMCExpr::Create(SparcMCExpr::VK_Sparc_R_DISP32, ++ MCSymbolRefExpr::Create(Sym, Ctx), Ctx); ++ } ++ return MCAsmInfo::getExprForFDESymbol(Sym, Encoding, Streamer); ++} +Index: test/CodeGen/SPARC/exception.ll +=================================================================== +--- test/CodeGen/SPARC/exception.ll ++++ test/CodeGen/SPARC/exception.ll +@@ -57,6 +57,7 @@ + ; V8PIC_NOCFI: .section .eh_frame + ; V8PIC_NOCFI-NOT: .section + ; V8PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0) ++; V8PIC_NOCFI: .word %r_disp32(.Ltmp{{.+}}) ! FDE initial location + + + ; V9ABS-LABEL: main: +@@ -94,6 +95,7 @@ + ; V9PIC_NOCFI: .section .eh_frame + ; V9PIC_NOCFI-NOT: .section + ; V9PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0) ++; V9PIC_NOCFI: .word %r_disp32(.Ltmp{{.+}}) ! FDE initial location + + define i32 @main(i32 %argc, i8** nocapture readnone %argv) unnamed_addr #0 { + entry: +Index: include/llvm/MC/MCAsmInfo.h +=================================================================== +--- include/llvm/MC/MCAsmInfo.h ++++ include/llvm/MC/MCAsmInfo.h +@@ -371,7 +371,7 @@ namespace llvm { + unsigned Encoding, + MCStreamer &Streamer) const; + +- const MCExpr * ++ virtual const MCExpr * + getExprForFDESymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200509-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200509-sparc.diff new file mode 100644 index 000000000000..9ada6aa93451 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200509-sparc.diff @@ -0,0 +1,73 @@ +Pull in r200509 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Save and restore float registers that may be used for parameter passing. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcJITInfo.cpp +=================================================================== +--- lib/Target/Sparc/SparcJITInfo.cpp ++++ lib/Target/Sparc/SparcJITInfo.cpp +@@ -28,6 +28,13 @@ extern "C" void SparcCompilationCallback(); + + extern "C" { + #if defined (__sparc__) ++ ++#if defined(__arch64__) ++#define FRAME_PTR(X) #X "+2047" ++#else ++#define FRAME_PTR(X) #X ++#endif ++ + asm( + ".text\n" + "\t.align 4\n" +@@ -34,11 +41,46 @@ extern "C" { + "\t.global SparcCompilationCallback\n" + "\t.type SparcCompilationCallback, #function\n" + "SparcCompilationCallback:\n" +- // Save current register window. +- "\tsave %sp, -192, %sp\n" ++ // Save current register window and create stack. ++ // 128 (save area) + 6*8 (for arguments) + 16*8 (for float regfile) = 304 ++ "\tsave %sp, -304, %sp\n" ++ // save float regfile to the stack. ++ "\tstd %f0, [" FRAME_PTR(%fp) "-0]\n" ++ "\tstd %f2, [" FRAME_PTR(%fp) "-8]\n" ++ "\tstd %f4, [" FRAME_PTR(%fp) "-16]\n" ++ "\tstd %f6, [" FRAME_PTR(%fp) "-24]\n" ++ "\tstd %f8, [" FRAME_PTR(%fp) "-32]\n" ++ "\tstd %f10, [" FRAME_PTR(%fp) "-40]\n" ++ "\tstd %f12, [" FRAME_PTR(%fp) "-48]\n" ++ "\tstd %f14, [" FRAME_PTR(%fp) "-56]\n" ++ "\tstd %f16, [" FRAME_PTR(%fp) "-64]\n" ++ "\tstd %f18, [" FRAME_PTR(%fp) "-72]\n" ++ "\tstd %f20, [" FRAME_PTR(%fp) "-80]\n" ++ "\tstd %f22, [" FRAME_PTR(%fp) "-88]\n" ++ "\tstd %f24, [" FRAME_PTR(%fp) "-96]\n" ++ "\tstd %f26, [" FRAME_PTR(%fp) "-104]\n" ++ "\tstd %f28, [" FRAME_PTR(%fp) "-112]\n" ++ "\tstd %f30, [" FRAME_PTR(%fp) "-120]\n" + // stubaddr is in %g1. + "\tcall SparcCompilationCallbackC\n" + "\t mov %g1, %o0\n" ++ // restore float regfile from the stack. ++ "\tldd [" FRAME_PTR(%fp) "-0], %f0\n" ++ "\tldd [" FRAME_PTR(%fp) "-8], %f2\n" ++ "\tldd [" FRAME_PTR(%fp) "-16], %f4\n" ++ "\tldd [" FRAME_PTR(%fp) "-24], %f6\n" ++ "\tldd [" FRAME_PTR(%fp) "-32], %f8\n" ++ "\tldd [" FRAME_PTR(%fp) "-40], %f10\n" ++ "\tldd [" FRAME_PTR(%fp) "-48], %f12\n" ++ "\tldd [" FRAME_PTR(%fp) "-56], %f14\n" ++ "\tldd [" FRAME_PTR(%fp) "-64], %f16\n" ++ "\tldd [" FRAME_PTR(%fp) "-72], %f18\n" ++ "\tldd [" FRAME_PTR(%fp) "-80], %f20\n" ++ "\tldd [" FRAME_PTR(%fp) "-88], %f22\n" ++ "\tldd [" FRAME_PTR(%fp) "-96], %f24\n" ++ "\tldd [" FRAME_PTR(%fp) "-104], %f26\n" ++ "\tldd [" FRAME_PTR(%fp) "-112], %f28\n" ++ "\tldd [" FRAME_PTR(%fp) "-120], %f30\n" + // restore original register window and + // copy %o0 to %g1 + "\trestore %o0, 0, %g1\n" diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200617-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200617-sparc.diff new file mode 100644 index 000000000000..831cd98eccd1 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200617-sparc.diff @@ -0,0 +1,97 @@ +Pull in r200617 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Set %o7 as the return address register instead of %i7 in MCRegisterInfo. Also, add CFI instructions to initialize the frame correctly. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +@@ -33,6 +33,25 @@ + + using namespace llvm; + ++ ++static MCAsmInfo *createSparcMCAsmInfo(const MCRegisterInfo &MRI, ++ StringRef TT) { ++ MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT); ++ unsigned Reg = MRI.getDwarfRegNum(SP::O6, true); ++ MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, Reg, 0); ++ MAI->addInitialFrameState(Inst); ++ return MAI; ++} ++ ++static MCAsmInfo *createSparcV9MCAsmInfo(const MCRegisterInfo &MRI, ++ StringRef TT) { ++ MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT); ++ unsigned Reg = MRI.getDwarfRegNum(SP::O6, true); ++ MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, Reg, 2047); ++ MAI->addInitialFrameState(Inst); ++ return MAI; ++} ++ + static MCInstrInfo *createSparcMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitSparcMCInstrInfo(X); +@@ -41,7 +60,7 @@ static MCInstrInfo *createSparcMCInstrInfo() { + + static MCRegisterInfo *createSparcMCRegisterInfo(StringRef TT) { + MCRegisterInfo *X = new MCRegisterInfo(); +- InitSparcMCRegisterInfo(X, SP::I7); ++ InitSparcMCRegisterInfo(X, SP::O7); + return X; + } + +@@ -132,8 +151,8 @@ static MCInstPrinter *createSparcMCInstPrinter(con + + extern "C" void LLVMInitializeSparcTargetMC() { + // Register the MC asm info. +- RegisterMCAsmInfo X(TheSparcTarget); +- RegisterMCAsmInfo Y(TheSparcV9Target); ++ RegisterMCAsmInfoFn X(TheSparcTarget, createSparcMCAsmInfo); ++ RegisterMCAsmInfoFn Y(TheSparcV9Target, createSparcV9MCAsmInfo); + + // Register the MC codegen info. + TargetRegistry::RegisterMCCodeGenInfo(TheSparcTarget, +Index: lib/Target/Sparc/SparcRegisterInfo.cpp +=================================================================== +--- lib/Target/Sparc/SparcRegisterInfo.cpp ++++ lib/Target/Sparc/SparcRegisterInfo.cpp +@@ -35,7 +35,7 @@ ReserveAppRegisters("sparc-reserve-app-registers", + cl::desc("Reserve application registers (%g2-%g4)")); + + SparcRegisterInfo::SparcRegisterInfo(SparcSubtarget &st) +- : SparcGenRegisterInfo(SP::I7), Subtarget(st) { ++ : SparcGenRegisterInfo(SP::O7), Subtarget(st) { + } + + const uint16_t* SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) +Index: test/CodeGen/SPARC/exception.ll +=================================================================== +--- test/CodeGen/SPARC/exception.ll ++++ test/CodeGen/SPARC/exception.ll +@@ -56,7 +56,11 @@ + ; V8PIC_NOCFI-NEXT: .word _ZTIi + ; V8PIC_NOCFI: .section .eh_frame + ; V8PIC_NOCFI-NOT: .section ++; V8PIC_NOCFI: .byte 15 ! CIE Return Address Column + ; V8PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0) ++; V8PIC_NOCFI: .byte 12 ! DW_CFA_def_cfa ++; V8PIC_NOCFI: .byte 14 ! Reg 14 ++; V8PIC_NOCFI-NEXT: .byte 0 ! Offset 0 + ; V8PIC_NOCFI: .word %r_disp32(.Ltmp{{.+}}) ! FDE initial location + + +@@ -94,7 +98,11 @@ + ; V9PIC_NOCFI-NEXT: .xword _ZTIi + ; V9PIC_NOCFI: .section .eh_frame + ; V9PIC_NOCFI-NOT: .section ++; V9PIC_NOCFI: .byte 15 ! CIE Return Address Column + ; V9PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0) ++; V9PIC_NOCFI: .byte 12 ! DW_CFA_def_cfa ++; V9PIC_NOCFI-NEXT: .byte 14 ! Reg 14 ++; V9PIC_NOCFI: .ascii "\377\017" ! Offset 2047 + ; V9PIC_NOCFI: .word %r_disp32(.Ltmp{{.+}}) ! FDE initial location + + define i32 @main(i32 %argc, i8** nocapture readnone %argv) unnamed_addr #0 { diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200960-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200960-sparc.diff new file mode 100644 index 000000000000..c430f882a2fd --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200960-sparc.diff @@ -0,0 +1,512 @@ +Pull in r200960 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Use SparcMCExpr::VariantKind itself as MachineOperand's target flags. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -13,11 +13,11 @@ + //===----------------------------------------------------------------------===// + + #include "SparcISelLowering.h" ++#include "MCTargetDesc/SparcMCExpr.h" + #include "SparcMachineFunctionInfo.h" + #include "SparcRegisterInfo.h" + #include "SparcTargetMachine.h" + #include "SparcTargetObjectFile.h" +-#include "MCTargetDesc/SparcBaseInfo.h" + #include "llvm/CodeGen/CallingConvLower.h" + #include "llvm/CodeGen/MachineFrameInfo.h" + #include "llvm/CodeGen/MachineFunction.h" +@@ -1796,7 +1796,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue O + // Handle PIC mode first. + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { + // This is the pic32 code model, the GOT is known to be smaller than 4GB. +- SDValue HiLo = makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG); ++ SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, ++ SparcMCExpr::VK_Sparc_LO, DAG); + SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT); + SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo); + // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this +@@ -1813,20 +1814,24 @@ SDValue SparcTargetLowering::makeAddress(SDValue O + llvm_unreachable("Unsupported absolute code model"); + case CodeModel::Small: + // abs32. +- return makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG); ++ return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, ++ SparcMCExpr::VK_Sparc_LO, DAG); + case CodeModel::Medium: { + // abs44. +- SDValue H44 = makeHiLoPair(Op, SPII::MO_H44, SPII::MO_M44, DAG); ++ SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44, ++ SparcMCExpr::VK_Sparc_M44, DAG); + H44 = DAG.getNode(ISD::SHL, DL, VT, H44, DAG.getConstant(12, MVT::i32)); +- SDValue L44 = withTargetFlags(Op, SPII::MO_L44, DAG); ++ SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG); + L44 = DAG.getNode(SPISD::Lo, DL, VT, L44); + return DAG.getNode(ISD::ADD, DL, VT, H44, L44); + } + case CodeModel::Large: { + // abs64. +- SDValue Hi = makeHiLoPair(Op, SPII::MO_HH, SPII::MO_HM, DAG); ++ SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH, ++ SparcMCExpr::VK_Sparc_HM, DAG); + Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, DAG.getConstant(32, MVT::i32)); +- SDValue Lo = makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG); ++ SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, ++ SparcMCExpr::VK_Sparc_LO, DAG); + return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo); + } + } +@@ -1858,14 +1863,18 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress + TLSModel::Model model = getTargetMachine().getTLSModel(GV); + + if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { +- unsigned HiTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_HI22 +- : SPII::MO_TLS_LDM_HI22); +- unsigned LoTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_LO10 +- : SPII::MO_TLS_LDM_LO10); +- unsigned addTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_ADD +- : SPII::MO_TLS_LDM_ADD); +- unsigned callTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_CALL +- : SPII::MO_TLS_LDM_CALL); ++ unsigned HiTF = ((model == TLSModel::GeneralDynamic) ++ ? SparcMCExpr::VK_Sparc_TLS_GD_HI22 ++ : SparcMCExpr::VK_Sparc_TLS_LDM_HI22); ++ unsigned LoTF = ((model == TLSModel::GeneralDynamic) ++ ? SparcMCExpr::VK_Sparc_TLS_GD_LO10 ++ : SparcMCExpr::VK_Sparc_TLS_LDM_LO10); ++ unsigned addTF = ((model == TLSModel::GeneralDynamic) ++ ? SparcMCExpr::VK_Sparc_TLS_GD_ADD ++ : SparcMCExpr::VK_Sparc_TLS_LDM_ADD); ++ unsigned callTF = ((model == TLSModel::GeneralDynamic) ++ ? SparcMCExpr::VK_Sparc_TLS_GD_CALL ++ : SparcMCExpr::VK_Sparc_TLS_LDM_CALL); + + SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG); + SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); +@@ -1903,17 +1912,17 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress + return Ret; + + SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, +- withTargetFlags(Op, SPII::MO_TLS_LDO_HIX22, DAG)); ++ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG)); + SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, +- withTargetFlags(Op, SPII::MO_TLS_LDO_LOX10, DAG)); ++ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG)); + HiLo = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); + return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo, +- withTargetFlags(Op, SPII::MO_TLS_LDO_ADD, DAG)); ++ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG)); + } + + if (model == TLSModel::InitialExec) { +- unsigned ldTF = ((PtrVT == MVT::i64)? SPII::MO_TLS_IE_LDX +- : SPII::MO_TLS_IE_LD); ++ unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX ++ : SparcMCExpr::VK_Sparc_TLS_IE_LD); + + SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); + +@@ -1923,7 +1932,8 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress + MFI->setHasCalls(true); + + SDValue TGA = makeHiLoPair(Op, +- SPII::MO_TLS_IE_HI22, SPII::MO_TLS_IE_LO10, DAG); ++ SparcMCExpr::VK_Sparc_TLS_IE_HI22, ++ SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG); + SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA); + SDValue Offset = DAG.getNode(SPISD::TLS_LD, + DL, PtrVT, Ptr, +@@ -1930,14 +1940,15 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress + withTargetFlags(Op, ldTF, DAG)); + return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, + DAG.getRegister(SP::G7, PtrVT), Offset, +- withTargetFlags(Op, SPII::MO_TLS_IE_ADD, DAG)); ++ withTargetFlags(Op, ++ SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG)); + } + + assert(model == TLSModel::LocalExec); + SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, +- withTargetFlags(Op, SPII::MO_TLS_LE_HIX22, DAG)); ++ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG)); + SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, +- withTargetFlags(Op, SPII::MO_TLS_LE_LOX10, DAG)); ++ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG)); + SDValue Offset = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); + + return DAG.getNode(ISD::ADD, DL, PtrVT, +Index: lib/Target/Sparc/SparcCodeEmitter.cpp +=================================================================== +--- lib/Target/Sparc/SparcCodeEmitter.cpp ++++ lib/Target/Sparc/SparcCodeEmitter.cpp +@@ -14,7 +14,7 @@ + + #define DEBUG_TYPE "jit" + #include "Sparc.h" +-#include "MCTargetDesc/SparcBaseInfo.h" ++#include "MCTargetDesc/SparcMCExpr.h" + #include "SparcRelocations.h" + #include "SparcTargetMachine.h" + #include "llvm/ADT/Statistic.h" +@@ -204,14 +204,14 @@ unsigned SparcCodeEmitter::getRelocation(const Mac + unsigned TF = MO.getTargetFlags(); + switch (TF) { + default: +- case SPII::MO_NO_FLAG: break; +- case SPII::MO_LO: return SP::reloc_sparc_lo; +- case SPII::MO_HI: return SP::reloc_sparc_hi; +- case SPII::MO_H44: return SP::reloc_sparc_h44; +- case SPII::MO_M44: return SP::reloc_sparc_m44; +- case SPII::MO_L44: return SP::reloc_sparc_l44; +- case SPII::MO_HH: return SP::reloc_sparc_hh; +- case SPII::MO_HM: return SP::reloc_sparc_hm; ++ case SparcMCExpr::VK_Sparc_None: break; ++ case SparcMCExpr::VK_Sparc_LO: return SP::reloc_sparc_lo; ++ case SparcMCExpr::VK_Sparc_HI: return SP::reloc_sparc_hi; ++ case SparcMCExpr::VK_Sparc_H44: return SP::reloc_sparc_h44; ++ case SparcMCExpr::VK_Sparc_M44: return SP::reloc_sparc_m44; ++ case SparcMCExpr::VK_Sparc_L44: return SP::reloc_sparc_l44; ++ case SparcMCExpr::VK_Sparc_HH: return SP::reloc_sparc_hh; ++ case SparcMCExpr::VK_Sparc_HM: return SP::reloc_sparc_hm; + } + + unsigned Opc = MI.getOpcode(); +Index: lib/Target/Sparc/SparcMCInstLower.cpp +=================================================================== +--- lib/Target/Sparc/SparcMCInstLower.cpp ++++ lib/Target/Sparc/SparcMCInstLower.cpp +@@ -13,7 +13,6 @@ + //===----------------------------------------------------------------------===// + + #include "Sparc.h" +-#include "MCTargetDesc/SparcBaseInfo.h" + #include "MCTargetDesc/SparcMCExpr.h" + #include "llvm/CodeGen/AsmPrinter.h" + #include "llvm/CodeGen/MachineFunction.h" +@@ -33,41 +32,10 @@ static MCOperand LowerSymbolOperand(const MachineI + const MachineOperand &MO, + AsmPrinter &AP) { + +- SparcMCExpr::VariantKind Kind; ++ SparcMCExpr::VariantKind Kind = ++ (SparcMCExpr::VariantKind)MO.getTargetFlags(); + const MCSymbol *Symbol = 0; + +- unsigned TF = MO.getTargetFlags(); +- +- switch(TF) { +- default: llvm_unreachable("Unknown target flags on operand"); +- case SPII::MO_NO_FLAG: Kind = SparcMCExpr::VK_Sparc_None; break; +- case SPII::MO_LO: Kind = SparcMCExpr::VK_Sparc_LO; break; +- case SPII::MO_HI: Kind = SparcMCExpr::VK_Sparc_HI; break; +- case SPII::MO_H44: Kind = SparcMCExpr::VK_Sparc_H44; break; +- case SPII::MO_M44: Kind = SparcMCExpr::VK_Sparc_M44; break; +- case SPII::MO_L44: Kind = SparcMCExpr::VK_Sparc_L44; break; +- case SPII::MO_HH: Kind = SparcMCExpr::VK_Sparc_HH; break; +- case SPII::MO_HM: Kind = SparcMCExpr::VK_Sparc_HM; break; +- case SPII::MO_TLS_GD_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_GD_HI22; break; +- case SPII::MO_TLS_GD_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_GD_LO10; break; +- case SPII::MO_TLS_GD_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_GD_ADD; break; +- case SPII::MO_TLS_GD_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_GD_CALL; break; +- case SPII::MO_TLS_LDM_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_HI22; break; +- case SPII::MO_TLS_LDM_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_LO10; break; +- case SPII::MO_TLS_LDM_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_ADD; break; +- case SPII::MO_TLS_LDM_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_CALL; break; +- case SPII::MO_TLS_LDO_HIX22:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_HIX22; break; +- case SPII::MO_TLS_LDO_LOX10:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_LOX10; break; +- case SPII::MO_TLS_LDO_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDO_ADD; break; +- case SPII::MO_TLS_IE_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_IE_HI22; break; +- case SPII::MO_TLS_IE_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LO10; break; +- case SPII::MO_TLS_IE_LD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LD; break; +- case SPII::MO_TLS_IE_LDX: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LDX; break; +- case SPII::MO_TLS_IE_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_ADD; break; +- case SPII::MO_TLS_LE_HIX22: Kind = SparcMCExpr::VK_Sparc_TLS_LE_HIX22; break; +- case SPII::MO_TLS_LE_LOX10: Kind = SparcMCExpr::VK_Sparc_TLS_LE_LOX10; break; +- } +- + switch(MO.getType()) { + default: llvm_unreachable("Unknown type in LowerSymbolOperand"); + case MachineOperand::MO_MachineBasicBlock: +Index: lib/Target/Sparc/SparcAsmPrinter.cpp +=================================================================== +--- lib/Target/Sparc/SparcAsmPrinter.cpp ++++ lib/Target/Sparc/SparcAsmPrinter.cpp +@@ -18,7 +18,6 @@ + #include "SparcTargetMachine.h" + #include "SparcTargetStreamer.h" + #include "InstPrinter/SparcInstPrinter.h" +-#include "MCTargetDesc/SparcBaseInfo.h" + #include "MCTargetDesc/SparcMCExpr.h" + #include "llvm/ADT/SmallString.h" + #include "llvm/CodeGen/AsmPrinter.h" +@@ -287,83 +286,60 @@ void SparcAsmPrinter::EmitFunctionBodyStart() { + void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand (opNum); +- unsigned TF = MO.getTargetFlags(); ++ SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags(); ++ + #ifndef NDEBUG + // Verify the target flags. + if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) { + if (MI->getOpcode() == SP::CALL) +- assert(TF == SPII::MO_NO_FLAG && ++ assert(TF == SparcMCExpr::VK_Sparc_None && + "Cannot handle target flags on call address"); + else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi) +- assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH +- || TF == SPII::MO_TLS_GD_HI22 +- || TF == SPII::MO_TLS_LDM_HI22 +- || TF == SPII::MO_TLS_LDO_HIX22 +- || TF == SPII::MO_TLS_IE_HI22 +- || TF == SPII::MO_TLS_LE_HIX22) && ++ assert((TF == SparcMCExpr::VK_Sparc_HI ++ || TF == SparcMCExpr::VK_Sparc_H44 ++ || TF == SparcMCExpr::VK_Sparc_HH ++ || TF == SparcMCExpr::VK_Sparc_TLS_GD_HI22 ++ || TF == SparcMCExpr::VK_Sparc_TLS_LDM_HI22 ++ || TF == SparcMCExpr::VK_Sparc_TLS_LDO_HIX22 ++ || TF == SparcMCExpr::VK_Sparc_TLS_IE_HI22 ++ || TF == SparcMCExpr::VK_Sparc_TLS_LE_HIX22) && + "Invalid target flags for address operand on sethi"); + else if (MI->getOpcode() == SP::TLS_CALL) +- assert((TF == SPII::MO_NO_FLAG +- || TF == SPII::MO_TLS_GD_CALL +- || TF == SPII::MO_TLS_LDM_CALL) && ++ assert((TF == SparcMCExpr::VK_Sparc_None ++ || TF == SparcMCExpr::VK_Sparc_TLS_GD_CALL ++ || TF == SparcMCExpr::VK_Sparc_TLS_LDM_CALL) && + "Cannot handle target flags on tls call address"); + else if (MI->getOpcode() == SP::TLS_ADDrr) +- assert((TF == SPII::MO_TLS_GD_ADD || TF == SPII::MO_TLS_LDM_ADD +- || TF == SPII::MO_TLS_LDO_ADD || TF == SPII::MO_TLS_IE_ADD) && ++ assert((TF == SparcMCExpr::VK_Sparc_TLS_GD_ADD ++ || TF == SparcMCExpr::VK_Sparc_TLS_LDM_ADD ++ || TF == SparcMCExpr::VK_Sparc_TLS_LDO_ADD ++ || TF == SparcMCExpr::VK_Sparc_TLS_IE_ADD) && + "Cannot handle target flags on add for TLS"); + else if (MI->getOpcode() == SP::TLS_LDrr) +- assert(TF == SPII::MO_TLS_IE_LD && ++ assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD && + "Cannot handle target flags on ld for TLS"); + else if (MI->getOpcode() == SP::TLS_LDXrr) +- assert(TF == SPII::MO_TLS_IE_LDX && ++ assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX && + "Cannot handle target flags on ldx for TLS"); + else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri) +- assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) && ++ assert((TF == SparcMCExpr::VK_Sparc_TLS_LDO_LOX10 ++ || TF == SparcMCExpr::VK_Sparc_TLS_LE_LOX10) && + "Cannot handle target flags on xor for TLS"); + else +- assert((TF == SPII::MO_LO || TF == SPII::MO_M44 || TF == SPII::MO_L44 +- || TF == SPII::MO_HM +- || TF == SPII::MO_TLS_GD_LO10 +- || TF == SPII::MO_TLS_LDM_LO10 +- || TF == SPII::MO_TLS_IE_LO10 ) && ++ assert((TF == SparcMCExpr::VK_Sparc_LO ++ || TF == SparcMCExpr::VK_Sparc_M44 ++ || TF == SparcMCExpr::VK_Sparc_L44 ++ || TF == SparcMCExpr::VK_Sparc_HM ++ || TF == SparcMCExpr::VK_Sparc_TLS_GD_LO10 ++ || TF == SparcMCExpr::VK_Sparc_TLS_LDM_LO10 ++ || TF == SparcMCExpr::VK_Sparc_TLS_IE_LO10 ) && + "Invalid target flags for small address operand"); + } + #endif + +- bool CloseParen = true; +- switch (TF) { +- default: +- llvm_unreachable("Unknown target flags on operand"); +- case SPII::MO_NO_FLAG: +- CloseParen = false; +- break; +- case SPII::MO_LO: O << "%lo("; break; +- case SPII::MO_HI: O << "%hi("; break; +- case SPII::MO_H44: O << "%h44("; break; +- case SPII::MO_M44: O << "%m44("; break; +- case SPII::MO_L44: O << "%l44("; break; +- case SPII::MO_HH: O << "%hh("; break; +- case SPII::MO_HM: O << "%hm("; break; +- case SPII::MO_TLS_GD_HI22: O << "%tgd_hi22("; break; +- case SPII::MO_TLS_GD_LO10: O << "%tgd_lo10("; break; +- case SPII::MO_TLS_GD_ADD: O << "%tgd_add("; break; +- case SPII::MO_TLS_GD_CALL: O << "%tgd_call("; break; +- case SPII::MO_TLS_LDM_HI22: O << "%tldm_hi22("; break; +- case SPII::MO_TLS_LDM_LO10: O << "%tldm_lo10("; break; +- case SPII::MO_TLS_LDM_ADD: O << "%tldm_add("; break; +- case SPII::MO_TLS_LDM_CALL: O << "%tldm_call("; break; +- case SPII::MO_TLS_LDO_HIX22: O << "%tldo_hix22("; break; +- case SPII::MO_TLS_LDO_LOX10: O << "%tldo_lox10("; break; +- case SPII::MO_TLS_LDO_ADD: O << "%tldo_add("; break; +- case SPII::MO_TLS_IE_HI22: O << "%tie_hi22("; break; +- case SPII::MO_TLS_IE_LO10: O << "%tie_lo10("; break; +- case SPII::MO_TLS_IE_LD: O << "%tie_ld("; break; +- case SPII::MO_TLS_IE_LDX: O << "%tie_ldx("; break; +- case SPII::MO_TLS_IE_ADD: O << "%tie_add("; break; +- case SPII::MO_TLS_LE_HIX22: O << "%tle_hix22("; break; +- case SPII::MO_TLS_LE_LOX10: O << "%tle_lox10("; break; +- } + ++ bool CloseParen = SparcMCExpr::printVariantKind(O, TF); ++ + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << "%" << StringRef(getRegisterName(MO.getReg())).lower(); +Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +=================================================================== +--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp ++++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +@@ -15,7 +15,6 @@ + #include "SparcInstPrinter.h" + + #include "Sparc.h" +-#include "MCTargetDesc/SparcBaseInfo.h" + #include "llvm/MC/MCExpr.h" + #include "llvm/MC/MCInst.h" + #include "llvm/MC/MCSymbol.h" +Index: lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h ++++ lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h +@@ -1,82 +0,0 @@ +-//===-- SparcBaseInfo.h - Top level definitions for Sparc ---- --*- C++ -*-===// +-// +-// The LLVM Compiler Infrastructure +-// +-// This file is distributed under the University of Illinois Open Source +-// License. See LICENSE.TXT for details. +-// +-//===----------------------------------------------------------------------===// +-// +-// This file contains small standalone helper functions and enum definitions +-// for the Sparc target useful for the compiler back-end and the MC libraries. +-// As such, it deliberately does not include references to LLVM core code gen +-// types, passes, etc.. +-// +-//===----------------------------------------------------------------------===// +- +-#ifndef SPARCBASEINFO_H +-#define SPARCBASEINFO_H +- +-namespace llvm { +- +-/// SPII - This namespace holds target specific flags for instruction info. +-namespace SPII { +- +-/// Target Operand Flags. Sparc specific TargetFlags for MachineOperands and +-/// SDNodes. +-enum TOF { +- MO_NO_FLAG, +- +- // Extract the low 10 bits of an address. +- // Assembler: %lo(addr) +- MO_LO, +- +- // Extract bits 31-10 of an address. Only for sethi. +- // Assembler: %hi(addr) or %lm(addr) +- MO_HI, +- +- // Extract bits 43-22 of an adress. Only for sethi. +- // Assembler: %h44(addr) +- MO_H44, +- +- // Extract bits 21-12 of an address. +- // Assembler: %m44(addr) +- MO_M44, +- +- // Extract bits 11-0 of an address. +- // Assembler: %l44(addr) +- MO_L44, +- +- // Extract bits 63-42 of an address. Only for sethi. +- // Assembler: %hh(addr) +- MO_HH, +- +- // Extract bits 41-32 of an address. +- // Assembler: %hm(addr) +- MO_HM, +- +- // TargetFlags for Thread Local Storage. +- MO_TLS_GD_HI22, +- MO_TLS_GD_LO10, +- MO_TLS_GD_ADD, +- MO_TLS_GD_CALL, +- MO_TLS_LDM_HI22, +- MO_TLS_LDM_LO10, +- MO_TLS_LDM_ADD, +- MO_TLS_LDM_CALL, +- MO_TLS_LDO_HIX22, +- MO_TLS_LDO_LOX10, +- MO_TLS_LDO_ADD, +- MO_TLS_IE_HI22, +- MO_TLS_IE_LO10, +- MO_TLS_IE_LD, +- MO_TLS_IE_LDX, +- MO_TLS_IE_ADD, +- MO_TLS_LE_HIX22, +- MO_TLS_LE_LOX10 +-}; +- +-} // end namespace SPII +-} // end namespace llvm +- +-#endif +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +@@ -29,8 +29,21 @@ SparcMCExpr::Create(VariantKind Kind, const MCExpr + } + + ++ + void SparcMCExpr::PrintImpl(raw_ostream &OS) const + { ++ ++ bool closeParen = printVariantKind(OS, Kind); ++ ++ const MCExpr *Expr = getSubExpr(); ++ Expr->print(OS); ++ ++ if (closeParen) ++ OS << ')'; ++} ++ ++bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) ++{ + bool closeParen = true; + switch (Kind) { + case VK_Sparc_None: closeParen = false; break; +@@ -61,11 +74,7 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const + case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; break; + case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; break; + } +- +- const MCExpr *Expr = getSubExpr(); +- Expr->print(OS); +- if (closeParen) +- OS << ')'; ++ return closeParen; + } + + SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name) +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +@@ -93,7 +93,7 @@ class SparcMCExpr : public MCTargetExpr { + static bool classof(const SparcMCExpr *) { return true; } + + static VariantKind parseVariantKind(StringRef name); +- ++ static bool printVariantKind(raw_ostream &OS, VariantKind Kind); + }; + + } // end namespace llvm. diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200961-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200961-sparc.diff new file mode 100644 index 000000000000..a08d173ed75c --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200961-sparc.diff @@ -0,0 +1,443 @@ +Pull in r200961 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Emit correct relocations for PIC code when integrated assembler is used. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/CodeGen/SPARC/obj-relocs.ll +=================================================================== +--- test/CodeGen/SPARC/obj-relocs.ll ++++ test/CodeGen/SPARC/obj-relocs.ll +@@ -0,0 +1,33 @@ ++; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=static | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-ABS ++; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=pic | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-PIC ++ ++;CHECK-ABS: Relocations [ ++;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_H44 AGlobalVar 0x0 ++;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_M44 AGlobalVar 0x0 ++;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_L44 AGlobalVar 0x0 ++;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 bar 0x0 ++;CHECK-ABS:] ++ ++; CHECK-PIC: Relocations [ ++; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4 ++; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8 ++; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0 ++; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0 ++; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0 ++; CHECK-PIC: ] ++ ++ ++@AGlobalVar = global i64 0, align 8 ++ ++; CHECK-ASM: sethi %h44(AGlobalVar), [[R:%[goli][0-7]]] ++; CHECK-ASM: add [[R]], %m44(AGlobalVar), [[R]] ++define i64 @foo(i64 %a) { ++entry: ++ %0 = load i64* @AGlobalVar, align 4 ++ %1 = add i64 %a, %0 ++ %2 = call i64 @bar(i64 %1) ++ ret i64 %2 ++} ++ ++ ++declare i64 @bar(i64) +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -895,10 +895,12 @@ SparcTargetLowering::LowerCall_32(TargetLowering:: + // If the callee is a GlobalAddress node (quite common, every direct call is) + // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. + // Likewise ExternalSymbol -> TargetExternalSymbol. ++ unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_) ++ ? SparcMCExpr::VK_Sparc_WPLT30 : 0); + if (GlobalAddressSDNode *G = dyn_cast(Callee)) +- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); ++ Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF); + else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) +- Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); ++ Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF); + + // Returns a chain & a flag for retval copy to use + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); +@@ -1209,10 +1211,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering:: + // Likewise ExternalSymbol -> TargetExternalSymbol. + SDValue Callee = CLI.Callee; + bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); ++ unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_) ++ ? SparcMCExpr::VK_Sparc_WPLT30 : 0); + if (GlobalAddressSDNode *G = dyn_cast(Callee)) +- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy()); ++ Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0, ++ TF); + else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) +- Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy()); ++ Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), TF); + + // Build the operands for the call instruction itself. + SmallVector Ops; +@@ -1796,8 +1801,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue O + // Handle PIC mode first. + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { + // This is the pic32 code model, the GOT is known to be smaller than 4GB. +- SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, +- SparcMCExpr::VK_Sparc_LO, DAG); ++ SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22, ++ SparcMCExpr::VK_Sparc_GOT10, DAG); + SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT); + SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo); + // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this +Index: lib/Target/Sparc/SparcAsmPrinter.cpp +=================================================================== +--- lib/Target/Sparc/SparcAsmPrinter.cpp ++++ lib/Target/Sparc/SparcAsmPrinter.cpp +@@ -232,12 +232,12 @@ void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(co + MCOperand Callee = createPCXCallOP(EndLabel, OutContext); + EmitCall(OutStreamer, Callee); + OutStreamer.EmitLabel(SethiLabel); +- MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_HI, ++ MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22, + GOTLabel, StartLabel, SethiLabel, + OutContext); + EmitSETHI(OutStreamer, hiImm, MCRegOP); + OutStreamer.EmitLabel(EndLabel); +- MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO, ++ MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10, + GOTLabel, StartLabel, EndLabel, + OutContext); + EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP); +Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +@@ -26,6 +26,7 @@ static unsigned adjustFixupValue(unsigned Kind, ui + case FK_Data_4: + case FK_Data_8: + return Value; ++ case Sparc::fixup_sparc_wplt30: + case Sparc::fixup_sparc_call30: + return (Value >> 2) & 0x3fffffff; + case Sparc::fixup_sparc_br22: +@@ -32,8 +33,12 @@ static unsigned adjustFixupValue(unsigned Kind, ui + return (Value >> 2) & 0x3fffff; + case Sparc::fixup_sparc_br19: + return (Value >> 2) & 0x7ffff; ++ case Sparc::fixup_sparc_pc22: ++ case Sparc::fixup_sparc_got22: + case Sparc::fixup_sparc_hi22: + return (Value >> 10) & 0x3fffff; ++ case Sparc::fixup_sparc_pc10: ++ case Sparc::fixup_sparc_got10: + case Sparc::fixup_sparc_lo10: + return Value & 0x3ff; + case Sparc::fixup_sparc_h44: +@@ -72,6 +77,11 @@ namespace { + { "fixup_sparc_l44", 20, 12, 0 }, + { "fixup_sparc_hh", 10, 22, 0 }, + { "fixup_sparc_hm", 22, 10, 0 }, ++ { "fixup_sparc_pc22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, ++ { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel }, ++ { "fixup_sparc_got22", 10, 22, 0 }, ++ { "fixup_sparc_got10", 22, 10, 0 }, ++ { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel } + }; + + if (Kind < FirstTargetFixupKind) +@@ -82,6 +92,20 @@ namespace { + return Infos[Kind - FirstTargetFixupKind]; + } + ++ void processFixupValue(const MCAssembler &Asm, ++ const MCAsmLayout &Layout, ++ const MCFixup &Fixup, ++ const MCFragment *DF, ++ MCValue & Target, ++ uint64_t &Value, ++ bool &IsResolved) { ++ switch ((Sparc::Fixups)Fixup.getKind()) { ++ default: break; ++ case Sparc::fixup_sparc_wplt30: IsResolved = false; break; ++ } ++ } ++ ++ + bool mayNeedRelaxation(const MCInst &Inst) const { + // FIXME. + return false; +Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h ++++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +@@ -48,6 +48,21 @@ namespace llvm { + /// fixup_sparc_hm - 10-bit fixup corresponding to %hm(foo) + fixup_sparc_hm, + ++ /// fixup_sparc_pc22 - 22-bit fixup corresponding to %pc22(foo) ++ fixup_sparc_pc22, ++ ++ /// fixup_sparc_pc10 - 10-bit fixup corresponding to %pc10(foo) ++ fixup_sparc_pc10, ++ ++ /// fixup_sparc_got22 - 22-bit fixup corresponding to %got22(foo) ++ fixup_sparc_got22, ++ ++ /// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo) ++ fixup_sparc_got10, ++ ++ /// fixup_sparc_wplt30 ++ fixup_sparc_wplt30, ++ + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind +Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +@@ -7,8 +7,9 @@ + // + //===----------------------------------------------------------------------===// + ++#include "MCTargetDesc/SparcFixupKinds.h" ++#include "MCTargetDesc/SparcMCExpr.h" + #include "MCTargetDesc/SparcMCTargetDesc.h" +-#include "MCTargetDesc/SparcFixupKinds.h" + #include "llvm/ADT/STLExtras.h" + #include "llvm/MC/MCELFObjectWriter.h" + #include "llvm/MC/MCExpr.h" +@@ -31,6 +32,11 @@ namespace { + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend) const; + ++ virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, ++ const MCValue &Target, ++ const MCFragment &F, ++ const MCFixup &Fixup, ++ bool IsPCRel) const; + }; + } + +@@ -40,6 +46,12 @@ unsigned SparcELFObjectWriter::GetRelocType(const + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) const { ++ ++ if (const SparcMCExpr *SExpr = dyn_cast(Fixup.getValue())) { ++ if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32) ++ return ELF::R_SPARC_DISP32; ++ } ++ + if (IsPCRel) { + switch((unsigned)Fixup.getKind()) { + default: +@@ -51,6 +63,9 @@ unsigned SparcELFObjectWriter::GetRelocType(const + case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30; + case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22; + case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19; ++ case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22; ++ case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10; ++ case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30; + } + } + +@@ -74,10 +89,30 @@ unsigned SparcELFObjectWriter::GetRelocType(const + case Sparc::fixup_sparc_l44: return ELF::R_SPARC_L44; + case Sparc::fixup_sparc_hh: return ELF::R_SPARC_HH22; + case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10; ++ case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22; ++ case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10; + } ++ + return ELF::R_SPARC_NONE; + } + ++const MCSymbol *SparcELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, ++ const MCValue &Target, ++ const MCFragment &F, ++ const MCFixup &Fixup, ++ bool IsPCRel) const { ++ ++ if (!Target.getSymA()) ++ return NULL; ++ switch((unsigned)Fixup.getKind()) { ++ default: break; ++ case Sparc::fixup_sparc_got22: ++ case Sparc::fixup_sparc_got10: ++ return &Target.getSymA()->getSymbol().AliasedSymbol(); ++ } ++ return NULL; ++} ++ + MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS, + bool Is64Bit, + uint8_t OSABI) { +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +@@ -17,6 +17,7 @@ + #include "llvm/MC/MCContext.h" + #include "llvm/MC/MCAssembler.h" + #include "llvm/MC/MCELF.h" ++#include "llvm/MC/MCSymbol.h" + #include "llvm/Object/ELF.h" + + +@@ -54,6 +55,13 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS + case VK_Sparc_L44: OS << "%l44("; break; + case VK_Sparc_HH: OS << "%hh("; break; + case VK_Sparc_HM: OS << "%hm("; break; ++ // FIXME: use %pc22/%pc10, if system assembler supports them. ++ case VK_Sparc_PC22: OS << "%hi("; break; ++ case VK_Sparc_PC10: OS << "%lo("; break; ++ // FIXME: use %got22/%got10, if system assembler supports them. ++ case VK_Sparc_GOT22: OS << "%hi("; break; ++ case VK_Sparc_GOT10: OS << "%lo("; break; ++ case VK_Sparc_WPLT30: closeParen = false; break; + case VK_Sparc_R_DISP32: OS << "%r_disp32("; break; + case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break; + case VK_Sparc_TLS_GD_LO10: OS << "%tgd_lo10("; break; +@@ -87,6 +95,10 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant + .Case("l44", VK_Sparc_L44) + .Case("hh", VK_Sparc_HH) + .Case("hm", VK_Sparc_HM) ++ .Case("pc22", VK_Sparc_PC22) ++ .Case("pc10", VK_Sparc_PC10) ++ .Case("got22", VK_Sparc_GOT22) ++ .Case("got10", VK_Sparc_GOT10) + .Case("r_disp32", VK_Sparc_R_DISP32) + .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22) + .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10) +@@ -109,9 +121,26 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant + .Default(VK_Sparc_None); + } + ++Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) { ++ switch (Kind) { ++ default: assert(0 && "Unhandled SparcMCExpr::VariantKind"); ++ case VK_Sparc_LO: return Sparc::fixup_sparc_lo10; ++ case VK_Sparc_HI: return Sparc::fixup_sparc_hi22; ++ case VK_Sparc_H44: return Sparc::fixup_sparc_h44; ++ case VK_Sparc_M44: return Sparc::fixup_sparc_m44; ++ case VK_Sparc_L44: return Sparc::fixup_sparc_l44; ++ case VK_Sparc_HH: return Sparc::fixup_sparc_hh; ++ case VK_Sparc_HM: return Sparc::fixup_sparc_hm; ++ case VK_Sparc_PC22: return Sparc::fixup_sparc_pc22; ++ case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10; ++ case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22; ++ case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10; ++ } ++} ++ + bool + SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, +- const MCAsmLayout *Layout) const { ++ const MCAsmLayout *Layout) const { + if (!Layout) + return false; + return getSubExpr()->EvaluateAsRelocatable(Res, *Layout); +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +@@ -15,6 +15,7 @@ + #ifndef LLVM_SPARCMCEXPR_H + #define LLVM_SPARCMCEXPR_H + ++#include "SparcFixupKinds.h" + #include "llvm/MC/MCExpr.h" + + namespace llvm { +@@ -31,6 +32,11 @@ class SparcMCExpr : public MCTargetExpr { + VK_Sparc_L44, + VK_Sparc_HH, + VK_Sparc_HM, ++ VK_Sparc_PC22, ++ VK_Sparc_PC10, ++ VK_Sparc_GOT22, ++ VK_Sparc_GOT10, ++ VK_Sparc_WPLT30, + VK_Sparc_R_DISP32, + VK_Sparc_TLS_GD_HI22, + VK_Sparc_TLS_GD_LO10, +@@ -75,6 +81,9 @@ class SparcMCExpr : public MCTargetExpr { + /// getSubExpr - Get the child of this expression. + const MCExpr *getSubExpr() const { return Expr; } + ++ /// getFixupKind - Get the fixup kind of this expression. ++ Sparc::Fixups getFixupKind() const { return getFixupKind(Kind); } ++ + /// @} + void PrintImpl(raw_ostream &OS) const; + bool EvaluateAsRelocatableImpl(MCValue &Res, +@@ -94,6 +103,7 @@ class SparcMCExpr : public MCTargetExpr { + + static VariantKind parseVariantKind(StringRef name); + static bool printVariantKind(raw_ostream &OS, VariantKind Kind); ++ static Sparc::Fixups getFixupKind(VariantKind Kind); + }; + + } // end namespace llvm. +Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +@@ -94,37 +94,8 @@ getMachineOpValue(const MCInst &MI, const MCOperan + assert(MO.isExpr()); + const MCExpr *Expr = MO.getExpr(); + if (const SparcMCExpr *SExpr = dyn_cast(Expr)) { +- switch(SExpr->getKind()) { +- default: assert(0 && "Unhandled sparc expression!"); break; +- case SparcMCExpr::VK_Sparc_LO: +- Fixups.push_back(MCFixup::Create(0, Expr, +- (MCFixupKind)Sparc::fixup_sparc_lo10)); +- break; +- case SparcMCExpr::VK_Sparc_HI: +- Fixups.push_back(MCFixup::Create(0, Expr, +- (MCFixupKind)Sparc::fixup_sparc_hi22)); +- break; +- case SparcMCExpr::VK_Sparc_H44: +- Fixups.push_back(MCFixup::Create(0, Expr, +- (MCFixupKind)Sparc::fixup_sparc_h44)); +- break; +- case SparcMCExpr::VK_Sparc_M44: +- Fixups.push_back(MCFixup::Create(0, Expr, +- (MCFixupKind)Sparc::fixup_sparc_m44)); +- break; +- case SparcMCExpr::VK_Sparc_L44: +- Fixups.push_back(MCFixup::Create(0, Expr, +- (MCFixupKind)Sparc::fixup_sparc_l44)); +- break; +- case SparcMCExpr::VK_Sparc_HH: +- Fixups.push_back(MCFixup::Create(0, Expr, +- (MCFixupKind)Sparc::fixup_sparc_hh)); +- break; +- case SparcMCExpr::VK_Sparc_HM: +- Fixups.push_back(MCFixup::Create(0, Expr, +- (MCFixupKind)Sparc::fixup_sparc_hm)); +- break; +- } ++ MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); ++ Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + return 0; + } + +@@ -143,8 +114,15 @@ getCallTargetOpValue(const MCInst &MI, unsigned Op + if (MO.isReg() || MO.isImm()) + return getMachineOpValue(MI, MO, Fixups); + +- Fixups.push_back(MCFixup::Create(0, MO.getExpr(), +- (MCFixupKind)Sparc::fixup_sparc_call30)); ++ MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30; ++ ++ if (const SparcMCExpr *SExpr = dyn_cast(MO.getExpr())) { ++ if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30) ++ fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30; ++ } ++ ++ Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind)); ++ + return 0; + } + diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200962-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200962-sparc.diff new file mode 100644 index 000000000000..2e668a31abc3 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200962-sparc.diff @@ -0,0 +1,378 @@ +Pull in r200962 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Emit relocations for Thread Local Storage (TLS) when integrated assembler is used. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +@@ -26,31 +26,65 @@ static unsigned adjustFixupValue(unsigned Kind, ui + case FK_Data_4: + case FK_Data_8: + return Value; ++ + case Sparc::fixup_sparc_wplt30: + case Sparc::fixup_sparc_call30: + return (Value >> 2) & 0x3fffffff; ++ + case Sparc::fixup_sparc_br22: + return (Value >> 2) & 0x3fffff; ++ + case Sparc::fixup_sparc_br19: + return (Value >> 2) & 0x7ffff; ++ + case Sparc::fixup_sparc_pc22: + case Sparc::fixup_sparc_got22: ++ case Sparc::fixup_sparc_tls_gd_hi22: ++ case Sparc::fixup_sparc_tls_ldm_hi22: ++ case Sparc::fixup_sparc_tls_ie_hi22: + case Sparc::fixup_sparc_hi22: + return (Value >> 10) & 0x3fffff; ++ + case Sparc::fixup_sparc_pc10: + case Sparc::fixup_sparc_got10: ++ case Sparc::fixup_sparc_tls_gd_lo10: ++ case Sparc::fixup_sparc_tls_ldm_lo10: ++ case Sparc::fixup_sparc_tls_ie_lo10: + case Sparc::fixup_sparc_lo10: + return Value & 0x3ff; ++ ++ case Sparc::fixup_sparc_tls_ldo_hix22: ++ case Sparc::fixup_sparc_tls_le_hix22: ++ return (~Value >> 10) & 0x3fffff; ++ ++ case Sparc::fixup_sparc_tls_ldo_lox10: ++ case Sparc::fixup_sparc_tls_le_lox10: ++ return (~(~Value & 0x3ff)) & 0x1fff; ++ + case Sparc::fixup_sparc_h44: + return (Value >> 22) & 0x3fffff; ++ + case Sparc::fixup_sparc_m44: + return (Value >> 12) & 0x3ff; ++ + case Sparc::fixup_sparc_l44: + return Value & 0xfff; ++ + case Sparc::fixup_sparc_hh: + return (Value >> 42) & 0x3fffff; ++ + case Sparc::fixup_sparc_hm: + return (Value >> 32) & 0x3ff; ++ ++ case Sparc::fixup_sparc_tls_gd_add: ++ case Sparc::fixup_sparc_tls_gd_call: ++ case Sparc::fixup_sparc_tls_ldm_add: ++ case Sparc::fixup_sparc_tls_ldm_call: ++ case Sparc::fixup_sparc_tls_ldo_add: ++ case Sparc::fixup_sparc_tls_ie_ld: ++ case Sparc::fixup_sparc_tls_ie_ldx: ++ case Sparc::fixup_sparc_tls_ie_add: ++ return 0; + } + } + +@@ -81,7 +115,25 @@ namespace { + { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_got22", 10, 22, 0 }, + { "fixup_sparc_got10", 22, 10, 0 }, +- { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel } ++ { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, ++ { "fixup_sparc_tls_gd_hi22", 10, 22, 0 }, ++ { "fixup_sparc_tls_gd_lo10", 22, 10, 0 }, ++ { "fixup_sparc_tls_gd_add", 0, 0, 0 }, ++ { "fixup_sparc_tls_gd_call", 0, 0, 0 }, ++ { "fixup_sparc_tls_ldm_hi22", 10, 22, 0 }, ++ { "fixup_sparc_tls_ldm_lo10", 22, 10, 0 }, ++ { "fixup_sparc_tls_ldm_add", 0, 0, 0 }, ++ { "fixup_sparc_tls_ldm_call", 0, 0, 0 }, ++ { "fixup_sparc_tls_ldo_hix22", 10, 22, 0 }, ++ { "fixup_sparc_tls_ldo_lox10", 22, 10, 0 }, ++ { "fixup_sparc_tls_ldo_add", 0, 0, 0 }, ++ { "fixup_sparc_tls_ie_hi22", 10, 22, 0 }, ++ { "fixup_sparc_tls_ie_lo10", 22, 10, 0 }, ++ { "fixup_sparc_tls_ie_ld", 0, 0, 0 }, ++ { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, ++ { "fixup_sparc_tls_ie_add", 0, 0, 0 }, ++ { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, ++ { "fixup_sparc_tls_le_lox10", 0, 0, 0 } + }; + + if (Kind < FirstTargetFixupKind) +@@ -101,11 +153,28 @@ namespace { + bool &IsResolved) { + switch ((Sparc::Fixups)Fixup.getKind()) { + default: break; +- case Sparc::fixup_sparc_wplt30: IsResolved = false; break; ++ case Sparc::fixup_sparc_wplt30: ++ case Sparc::fixup_sparc_tls_gd_hi22: ++ case Sparc::fixup_sparc_tls_gd_lo10: ++ case Sparc::fixup_sparc_tls_gd_add: ++ case Sparc::fixup_sparc_tls_gd_call: ++ case Sparc::fixup_sparc_tls_ldm_hi22: ++ case Sparc::fixup_sparc_tls_ldm_lo10: ++ case Sparc::fixup_sparc_tls_ldm_add: ++ case Sparc::fixup_sparc_tls_ldm_call: ++ case Sparc::fixup_sparc_tls_ldo_hix22: ++ case Sparc::fixup_sparc_tls_ldo_lox10: ++ case Sparc::fixup_sparc_tls_ldo_add: ++ case Sparc::fixup_sparc_tls_ie_hi22: ++ case Sparc::fixup_sparc_tls_ie_lo10: ++ case Sparc::fixup_sparc_tls_ie_ld: ++ case Sparc::fixup_sparc_tls_ie_ldx: ++ case Sparc::fixup_sparc_tls_ie_add: ++ case Sparc::fixup_sparc_tls_le_hix22: ++ case Sparc::fixup_sparc_tls_le_lox10: IsResolved = false; break; + } + } + +- + bool mayNeedRelaxation(const MCInst &Inst) const { + // FIXME. + return false; +Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h ++++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +@@ -63,6 +63,26 @@ namespace llvm { + /// fixup_sparc_wplt30 + fixup_sparc_wplt30, + ++ /// fixups for Thread Local Storage ++ fixup_sparc_tls_gd_hi22, ++ fixup_sparc_tls_gd_lo10, ++ fixup_sparc_tls_gd_add, ++ fixup_sparc_tls_gd_call, ++ fixup_sparc_tls_ldm_hi22, ++ fixup_sparc_tls_ldm_lo10, ++ fixup_sparc_tls_ldm_add, ++ fixup_sparc_tls_ldm_call, ++ fixup_sparc_tls_ldo_hix22, ++ fixup_sparc_tls_ldo_lox10, ++ fixup_sparc_tls_ldo_add, ++ fixup_sparc_tls_ie_hi22, ++ fixup_sparc_tls_ie_lo10, ++ fixup_sparc_tls_ie_ld, ++ fixup_sparc_tls_ie_ldx, ++ fixup_sparc_tls_ie_add, ++ fixup_sparc_tls_le_hix22, ++ fixup_sparc_tls_le_lox10, ++ + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind +Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +@@ -91,6 +91,24 @@ unsigned SparcELFObjectWriter::GetRelocType(const + case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10; + case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22; + case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10; ++ case Sparc::fixup_sparc_tls_gd_hi22: return ELF::R_SPARC_TLS_GD_HI22; ++ case Sparc::fixup_sparc_tls_gd_lo10: return ELF::R_SPARC_TLS_GD_LO10; ++ case Sparc::fixup_sparc_tls_gd_add: return ELF::R_SPARC_TLS_GD_ADD; ++ case Sparc::fixup_sparc_tls_gd_call: return ELF::R_SPARC_TLS_GD_CALL; ++ case Sparc::fixup_sparc_tls_ldm_hi22: return ELF::R_SPARC_TLS_LDM_HI22; ++ case Sparc::fixup_sparc_tls_ldm_lo10: return ELF::R_SPARC_TLS_LDM_LO10; ++ case Sparc::fixup_sparc_tls_ldm_add: return ELF::R_SPARC_TLS_LDM_ADD; ++ case Sparc::fixup_sparc_tls_ldm_call: return ELF::R_SPARC_TLS_LDM_CALL; ++ case Sparc::fixup_sparc_tls_ldo_hix22: return ELF::R_SPARC_TLS_LDO_HIX22; ++ case Sparc::fixup_sparc_tls_ldo_lox10: return ELF::R_SPARC_TLS_LDO_LOX10; ++ case Sparc::fixup_sparc_tls_ldo_add: return ELF::R_SPARC_TLS_LDO_ADD; ++ case Sparc::fixup_sparc_tls_ie_hi22: return ELF::R_SPARC_TLS_IE_HI22; ++ case Sparc::fixup_sparc_tls_ie_lo10: return ELF::R_SPARC_TLS_IE_LO10; ++ case Sparc::fixup_sparc_tls_ie_ld: return ELF::R_SPARC_TLS_IE_LD; ++ case Sparc::fixup_sparc_tls_ie_ldx: return ELF::R_SPARC_TLS_IE_LDX; ++ case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD; ++ case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22; ++ case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10; + } + + return ELF::R_SPARC_NONE; +Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +@@ -135,6 +135,25 @@ Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExp + case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10; + case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22; + case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10; ++ case VK_Sparc_WPLT30: return Sparc::fixup_sparc_wplt30; ++ case VK_Sparc_TLS_GD_HI22: return Sparc::fixup_sparc_tls_gd_hi22; ++ case VK_Sparc_TLS_GD_LO10: return Sparc::fixup_sparc_tls_gd_lo10; ++ case VK_Sparc_TLS_GD_ADD: return Sparc::fixup_sparc_tls_gd_add; ++ case VK_Sparc_TLS_GD_CALL: return Sparc::fixup_sparc_tls_gd_call; ++ case VK_Sparc_TLS_LDM_HI22: return Sparc::fixup_sparc_tls_ldm_hi22; ++ case VK_Sparc_TLS_LDM_LO10: return Sparc::fixup_sparc_tls_ldm_lo10; ++ case VK_Sparc_TLS_LDM_ADD: return Sparc::fixup_sparc_tls_ldm_add; ++ case VK_Sparc_TLS_LDM_CALL: return Sparc::fixup_sparc_tls_ldm_call; ++ case VK_Sparc_TLS_LDO_HIX22: return Sparc::fixup_sparc_tls_ldo_hix22; ++ case VK_Sparc_TLS_LDO_LOX10: return Sparc::fixup_sparc_tls_ldo_lox10; ++ case VK_Sparc_TLS_LDO_ADD: return Sparc::fixup_sparc_tls_ldo_add; ++ case VK_Sparc_TLS_IE_HI22: return Sparc::fixup_sparc_tls_ie_hi22; ++ case VK_Sparc_TLS_IE_LO10: return Sparc::fixup_sparc_tls_ie_lo10; ++ case VK_Sparc_TLS_IE_LD: return Sparc::fixup_sparc_tls_ie_ld; ++ case VK_Sparc_TLS_IE_LDX: return Sparc::fixup_sparc_tls_ie_ldx; ++ case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add; ++ case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22; ++ case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10; + } + } + +@@ -147,7 +166,33 @@ SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Re + } + + static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { +- assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!"); ++ switch (Expr->getKind()) { ++ case MCExpr::Target: ++ llvm_unreachable("Can't handle nested target expr!"); ++ break; ++ ++ case MCExpr::Constant: ++ break; ++ ++ case MCExpr::Binary: { ++ const MCBinaryExpr *BE = cast(Expr); ++ fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); ++ fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); ++ break; ++ } ++ ++ case MCExpr::SymbolRef: { ++ const MCSymbolRefExpr &SymRef = *cast(Expr); ++ MCSymbolData &SD = Asm.getOrCreateSymbolData(SymRef.getSymbol()); ++ MCELF::SetType(SD, ELF::STT_TLS); ++ break; ++ } ++ ++ case MCExpr::Unary: ++ fixELFSymbolsInTLSFixupsImpl(cast(Expr)->getSubExpr(), Asm); ++ break; ++ } ++ + } + + void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { +Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +=================================================================== +--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp ++++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +@@ -20,6 +20,7 @@ + #include "llvm/MC/MCExpr.h" + #include "llvm/MC/MCInst.h" + #include "llvm/MC/MCRegisterInfo.h" ++#include "llvm/MC/MCSymbol.h" + #include "llvm/ADT/Statistic.h" + #include "llvm/Support/raw_ostream.h" + +@@ -76,6 +77,21 @@ EncodeInstruction(const MCInst &MI, raw_ostream &O + OS << (char)(Bits >> 24); + Bits <<= 8; + } ++ unsigned tlsOpNo = 0; ++ switch (MI.getOpcode()) { ++ default: break; ++ case SP::TLS_CALL: tlsOpNo = 1; break; ++ case SP::TLS_ADDrr: ++ case SP::TLS_ADDXrr: ++ case SP::TLS_LDrr: ++ case SP::TLS_LDXrr: tlsOpNo = 3; break; ++ } ++ if (tlsOpNo != 0) { ++ const MCOperand &MO = MI.getOperand(tlsOpNo); ++ uint64_t op = getMachineOpValue(MI, MO, Fixups); ++ assert(op == 0 && "Unexpected operand value!"); ++ (void)op; // suppress warning. ++ } + + ++MCNumEmitted; // Keep track of the # of mi's emitted. + } +@@ -114,6 +130,21 @@ getCallTargetOpValue(const MCInst &MI, unsigned Op + if (MO.isReg() || MO.isImm()) + return getMachineOpValue(MI, MO, Fixups); + ++ if (MI.getOpcode() == SP::TLS_CALL) { ++ // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in ++ // EncodeInstruction. ++#ifndef NDEBUG ++ // Verify that the callee is actually __tls_get_addr. ++ const SparcMCExpr *SExpr = dyn_cast(MO.getExpr()); ++ assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef && ++ "Unexpected expression in TLS_CALL"); ++ const MCSymbolRefExpr *SymExpr = cast(SExpr->getSubExpr()); ++ assert(SymExpr->getSymbol().getName() == "__tls_get_addr" && ++ "Unexpected function for TLS_CALL"); ++#endif ++ return 0; ++ } ++ + MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30; + + if (const SparcMCExpr *SExpr = dyn_cast(MO.getExpr())) { +Index: test/CodeGen/SPARC/tls.ll +=================================================================== +--- test/CodeGen/SPARC/tls.ll ++++ test/CodeGen/SPARC/tls.ll +@@ -3,6 +3,10 @@ + ; RUN: llc <%s -march=sparc -relocation-model=pic | FileCheck %s --check-prefix=pic + ; RUN: llc <%s -march=sparcv9 -relocation-model=pic | FileCheck %s --check-prefix=pic + ++; RUN: llc <%s -march=sparc -relocation-model=static -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=v8abs-obj ++; RUN: llc <%s -march=sparcv9 -relocation-model=static -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=v9abs-obj ++; RUN: llc <%s -march=sparc -relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=pic-obj ++; RUN: llc <%s -march=sparcv9 -relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=pic-obj + + @local_symbol = internal thread_local global i32 0 + @extern_symbol = external thread_local global i32 +@@ -69,3 +73,47 @@ entry: + store i32 %1, i32* @extern_symbol, align 4 + ret i32 %1 + } ++ ++ ++; v8abs-obj: Relocations [ ++; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_HIX22 local_symbol 0x0 ++; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_LOX10 local_symbol 0x0 ++; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_HI22 _GLOBAL_OFFSET_TABLE_ 0x0 ++; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_LO10 _GLOBAL_OFFSET_TABLE_ 0x0 ++; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_HI22 extern_symbol 0x0 ++; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LO10 extern_symbol 0x0 ++; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LD extern_symbol 0x0 ++; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_ADD extern_symbol 0x0 ++; v8abs-obj: ] ++ ++; v9abs-obj: Relocations [ ++; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_HIX22 local_symbol 0x0 ++; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_LOX10 local_symbol 0x0 ++; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_H44 _GLOBAL_OFFSET_TABLE_ 0x0 ++; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_M44 _GLOBAL_OFFSET_TABLE_ 0x0 ++; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_L44 _GLOBAL_OFFSET_TABLE_ 0x0 ++; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_HI22 extern_symbol 0x0 ++; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LO10 extern_symbol 0x0 ++; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LDX extern_symbol 0x0 ++; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_ADD extern_symbol 0x0 ++; v9abs-obj: ] ++ ++; pic-obj: Relocations [ ++; pic-obj: Section (2) .rela.text { ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDO_HIX22 local_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDO_LOX10 local_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_HI22 local_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_LO10 local_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_ADD local_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_CALL local_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDO_ADD local_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_HI22 extern_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_LO10 extern_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_ADD extern_symbol 0x0 ++; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_CALL extern_symbol 0x0 ++; pic-obj: ] ++ diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200963-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200963-sparc.diff new file mode 100644 index 000000000000..f8a817ea0f17 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200963-sparc.diff @@ -0,0 +1,131 @@ +Pull in r200963 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Emit correct encoding for atomic instructions. Also, add support for parsing CAS instructions to test the CAS encoding. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/MC/Sparc/sparc-atomic-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-atomic-instructions.s ++++ test/MC/Sparc/sparc-atomic-instructions.s +@@ -0,0 +1,19 @@ ++! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s ++ ++ ! CHECK: membar 15 ! encoding: [0x81,0x43,0xe0,0x0f] ++ membar 15 ++ ++ ! CHECK: stbar ! encoding: [0x81,0x43,0xc0,0x00] ++ stbar ++ ++ ! CHECK: swap [%i0+%l6], %o2 ! encoding: [0xd4,0x7e,0x00,0x16] ++ swap [%i0+%l6], %o2 ++ ++ ! CHECK: swap [%i0+32], %o2 ! encoding: [0xd4,0x7e,0x20,0x20] ++ swap [%i0+32], %o2 ++ ++ ! CHECK: cas [%i0], %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16] ++ cas [%i0], %l6, %o2 ++ ++ ! CHECK: casx [%i0], %l6, %o2 ! encoding: [0xd5,0xf6,0x10,0x16] ++ casx [%i0], %l6, %o2 +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -935,19 +935,19 @@ let Predicates = [HasV9], hasSideEffects = 1, rd = + def MEMBARi : F3_2<2, 0b101000, (outs), (ins i32imm:$simm13), + "membar $simm13", []>; + +-let Constraints = "$val = $rd" in { ++let Constraints = "$val = $dst" in { + def SWAPrr : F3_1<3, 0b001111, +- (outs IntRegs:$rd), (ins IntRegs:$val, MEMrr:$addr), +- "swap [$addr], $rd", +- [(set i32:$rd, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>; ++ (outs IntRegs:$dst), (ins MEMrr:$addr, IntRegs:$val), ++ "swap [$addr], $dst", ++ [(set i32:$dst, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>; + def SWAPri : F3_2<3, 0b001111, +- (outs IntRegs:$rd), (ins IntRegs:$val, MEMri:$addr), +- "swap [$addr], $rd", +- [(set i32:$rd, (atomic_swap_32 ADDRri:$addr, i32:$val))]>; ++ (outs IntRegs:$dst), (ins MEMri:$addr, IntRegs:$val), ++ "swap [$addr], $dst", ++ [(set i32:$dst, (atomic_swap_32 ADDRri:$addr, i32:$val))]>; + } + + let Predicates = [HasV9], Constraints = "$swap = $rd" in +- def CASrr: F3_1<3, 0b111100, ++ def CASrr: F3_1_asi<3, 0b111100, 0b10000000, + (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, + IntRegs:$swap), + "cas [$rs1], $rs2, $rd", +Index: lib/Target/Sparc/SparcInstrFormats.td +=================================================================== +--- lib/Target/Sparc/SparcInstrFormats.td ++++ lib/Target/Sparc/SparcInstrFormats.td +@@ -100,9 +100,8 @@ class F3 opVal, bits<6> op3val, dag outs, dag ins, ++class F3_1_asi opVal, bits<6> op3val, bits<8> asi, dag outs, dag ins, + string asmstr, list pattern> : F3 { +- bits<8> asi = 0; // asi not currently used + bits<5> rs2; + + let op = opVal; +@@ -113,6 +112,10 @@ class F3 opVal, bits<6> op3val, dag outs, dag ins, string asmstr, ++ list pattern> : F3_1_asi; ++ + class F3_2 opVal, bits<6> op3val, dag outs, dag ins, + string asmstr, list pattern> : F3 { + bits<13> simm13; +Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +=================================================================== +--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp ++++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +@@ -546,7 +546,24 @@ parseOperand(SmallVectorImpl + Parser.getTok().getLoc())); + Parser.Lex(); // Eat the [ + +- ResTy = parseMEMOperand(Operands); ++ if (Mnemonic == "cas" || Mnemonic == "casx") { ++ SMLoc S = Parser.getTok().getLoc(); ++ if (getLexer().getKind() != AsmToken::Percent) ++ return MatchOperand_NoMatch; ++ Parser.Lex(); // eat % ++ ++ unsigned RegNo, RegKind; ++ if (!matchRegisterName(Parser.getTok(), RegNo, RegKind)) ++ return MatchOperand_NoMatch; ++ ++ Parser.Lex(); // Eat the identifier token. ++ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1); ++ Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E)); ++ ResTy = MatchOperand_Success; ++ } else { ++ ResTy = parseMEMOperand(Operands); ++ } ++ + if (ResTy != MatchOperand_Success) + return ResTy; + +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -415,7 +415,7 @@ def SETHIXi : F2_1<0b100, + + // ATOMICS. + let Predicates = [Is64Bit], Constraints = "$swap = $rd" in { +- def CASXrr: F3_1<3, 0b111110, ++ def CASXrr: F3_1_asi<3, 0b111110, 0b10000000, + (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2, + I64Regs:$swap), + "casx [$rs1], $rs2, $rd", diff --git a/contrib/llvm/patches/patch-r262261-llvm-r200965-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r200965-sparc.diff new file mode 100644 index 000000000000..2b0d41e5fea0 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r200965-sparc.diff @@ -0,0 +1,33 @@ +Pull in r200965 from upstream llvm trunk (by Venkatraman Govindaraju): + + [Sparc] Add support for parsing synthetic instruction 'mov'. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: lib/Target/Sparc/SparcInstrAliases.td +=================================================================== +--- lib/Target/Sparc/SparcInstrAliases.td ++++ lib/Target/Sparc/SparcInstrAliases.td +@@ -134,3 +134,9 @@ def : InstAlias<"retl", (RETL 8)>; + + // ret -> RET 8 + def : InstAlias<"ret", (RET 8)>; ++ ++// mov reg, rd -> or %g0, reg, rd ++def : InstAlias<"mov $rs2, $rd", (ORrr IntRegs:$rd, G0, IntRegs:$rs2)>; ++ ++// mov simm13, rd -> or %g0, simm13, rd ++def : InstAlias<"mov $simm13, $rd", (ORri IntRegs:$rd, G0, i32imm:$simm13)>; +Index: test/MC/Sparc/sparc-alu-instructions.s +=================================================================== +--- test/MC/Sparc/sparc-alu-instructions.s ++++ test/MC/Sparc/sparc-alu-instructions.s +@@ -70,3 +70,8 @@ + ! CHECK: subxcc %g1, %g2, %g3 ! encoding: [0x86,0xe0,0x40,0x02] + subxcc %g1, %g2, %g3 + ++ ! CHECK: or %g0, %g1, %g3 ! encoding: [0x86,0x10,0x00,0x01] ++ mov %g1, %g3 ++ ++ ! CHECK: or %g0, 255, %g3 ! encoding: [0x86,0x10,0x20,0xff] ++ mov 0xff, %g3 diff --git a/contrib/llvm/patches/patch-r262262-clang-r198311-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r198311-sparc.diff new file mode 100644 index 000000000000..751b976bc563 --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r198311-sparc.diff @@ -0,0 +1,31 @@ +Pull in r198311 from upstream clang trunk (by Roman Divacky): + + In the FreeBSD assembler driver, inform the sparc assembler that we're producing + PIC code. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -5785,6 +5785,19 @@ void freebsd::Assemble::ConstructJob(Compilation & + default: + CmdArgs.push_back("-matpcs"); + } ++ } else if (getToolChain().getArch() == llvm::Triple::sparc || ++ getToolChain().getArch() == llvm::Triple::sparcv9) { ++ Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, ++ options::OPT_fpic, options::OPT_fno_pic, ++ options::OPT_fPIE, options::OPT_fno_PIE, ++ options::OPT_fpie, options::OPT_fno_pie); ++ if (LastPICArg && ++ (LastPICArg->getOption().matches(options::OPT_fPIC) || ++ LastPICArg->getOption().matches(options::OPT_fpic) || ++ LastPICArg->getOption().matches(options::OPT_fPIE) || ++ LastPICArg->getOption().matches(options::OPT_fpie))) { ++ CmdArgs.push_back("-KPIC"); ++ } + } + + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, diff --git a/contrib/llvm/patches/patch-r262262-clang-r198312-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r198312-sparc.diff new file mode 100644 index 000000000000..8903d38eea67 --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r198312-sparc.diff @@ -0,0 +1,19 @@ +Pull in r198312 from upstream clang trunk (by Roman Divacky): + + Remove a tab that snuck in. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -5786,7 +5786,7 @@ void freebsd::Assemble::ConstructJob(Compilation & + CmdArgs.push_back("-matpcs"); + } + } else if (getToolChain().getArch() == llvm::Triple::sparc || +- getToolChain().getArch() == llvm::Triple::sparcv9) { ++ getToolChain().getArch() == llvm::Triple::sparcv9) { + Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, + options::OPT_fpic, options::OPT_fno_pic, + options::OPT_fPIE, options::OPT_fno_PIE, diff --git a/contrib/llvm/patches/patch-r262262-clang-r198911-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r198911-sparc.diff new file mode 100644 index 000000000000..d50b53f60db4 --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r198911-sparc.diff @@ -0,0 +1,46 @@ +Pull in r198911 from upstream clang trunk (by Jakob Stoklund Olesen): + + Pass -32/-64 to the assembler when building for sparc/sparc64. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/test/Driver/linux-as.c +=================================================================== +--- tools/clang/test/Driver/linux-as.c ++++ tools/clang/test/Driver/linux-as.c +@@ -60,6 +60,20 @@ + // RUN: | FileCheck -check-prefix=CHECK-PPC-NO-MCPU %s + // CHECK-PPC-NO-MCPU-NOT: as{{.*}} "-mcpu=invalid-cpu" + // ++// RUN: %clang -target sparc64-linux -mcpu=invalid-cpu -### \ ++// RUN: -no-integrated-as -c %s 2>&1 \ ++// RUN: | FileCheck -check-prefix=CHECK-SPARCV9 %s ++// CHECK-SPARCV9: as ++// CHECK-SPARCV9: -64 ++// CHECK-SPARCV9: -o ++// ++// RUN: %clang -target sparc-linux -mcpu=invalid-cpu -### \ ++// RUN: -no-integrated-as -c %s 2>&1 \ ++// RUN: | FileCheck -check-prefix=CHECK-SPARCV8 %s ++// CHECK-SPARCV8: as ++// CHECK-SPARCV8: -32 ++// CHECK-SPARCV8: -o ++// + // RUN: %clang -target s390x-linux -### -no-integrated-as -c %s 2>&1 \ + // RUN: | FileCheck -check-prefix=CHECK-Z-DEFAULT-ARCH %s + // CHECK-Z-DEFAULT-ARCH: as{{.*}} "-march=z10" +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -6226,6 +6226,10 @@ void gnutools::Assemble::ConstructJob(Compilation + CmdArgs.push_back("-a64"); + CmdArgs.push_back("-mppc64le"); + CmdArgs.push_back("-many"); ++ } else if (getToolChain().getArch() == llvm::Triple::sparc) { ++ CmdArgs.push_back("-32"); ++ } else if (getToolChain().getArch() == llvm::Triple::sparcv9) { ++ CmdArgs.push_back("-64"); + } else if (getToolChain().getArch() == llvm::Triple::arm) { + StringRef MArch = getToolChain().getArchName(); + if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") diff --git a/contrib/llvm/patches/patch-r262262-clang-r198912-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r198912-sparc.diff new file mode 100644 index 000000000000..9e3ce439a8a5 --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r198912-sparc.diff @@ -0,0 +1,44 @@ +Pull in r198912 from upstream clang trunk (by Jakob Stoklund Olesen): + + Give the linker the right ELF type for SPARC targets. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -6461,6 +6461,10 @@ void gnutools::Link::ConstructJob(Compilation &C, + CmdArgs.push_back("elf32ppclinux"); + else if (ToolChain.getArch() == llvm::Triple::ppc64) + CmdArgs.push_back("elf64ppc"); ++ else if (ToolChain.getArch() == llvm::Triple::sparc) ++ CmdArgs.push_back("elf32_sparc"); ++ else if (ToolChain.getArch() == llvm::Triple::sparcv9) ++ CmdArgs.push_back("elf64_sparc"); + else if (ToolChain.getArch() == llvm::Triple::mips) + CmdArgs.push_back("elf32btsmip"); + else if (ToolChain.getArch() == llvm::Triple::mipsel) +Index: tools/clang/test/Driver/linux-ld.c +=================================================================== +--- tools/clang/test/Driver/linux-ld.c ++++ tools/clang/test/Driver/linux-ld.c +@@ -384,6 +384,18 @@ + // CHECK-MIPS64EL-N32: "-dynamic-linker" "{{.*}}/lib32/ld.so.1" + // CHECK-MIPS64EL-N32-NOT: "--hash-style={{gnu|both}}" + // ++// RUN: %clang %s -### -o %t.o 2>&1 \ ++// RUN: --target=sparc-linux-gnu \ ++// RUN: | FileCheck --check-prefix=CHECK-SPARCV8 %s ++// CHECK-SPARCV8: "{{.*}}ld{{(.exe)?}}" ++// CHECK-SPARCV8: "-m" "elf32_sparc" ++// ++// RUN: %clang %s -### -o %t.o 2>&1 \ ++// RUN: --target=sparcv9-linux-gnu \ ++// RUN: | FileCheck --check-prefix=CHECK-SPARCV9 %s ++// CHECK-SPARCV9: "{{.*}}ld{{(.exe)?}}" ++// CHECK-SPARCV9: "-m" "elf64_sparc" ++// + // Thoroughly exercise the Debian multiarch environment. + // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ + // RUN: --target=i686-linux-gnu \ diff --git a/contrib/llvm/patches/patch-r262262-clang-r198918-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r198918-sparc.diff new file mode 100644 index 000000000000..a3c60261ae00 --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r198918-sparc.diff @@ -0,0 +1,59 @@ +Pull in r198918 from upstream clang trunk (by Jakob Stoklund Olesen): + + Locate GCC installations on SPARC systems. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/lib/Driver/ToolChains.cpp +=================================================================== +--- tools/clang/lib/Driver/ToolChains.cpp ++++ tools/clang/lib/Driver/ToolChains.cpp +@@ -1164,6 +1164,13 @@ void Generic_GCC::GCCInstallationDetector::print(r + "powerpc64le-suse-linux", + "ppc64le-redhat-linux" }; + ++ static const char *const SPARCv8LibDirs[] = { "/lib32", "/lib" }; ++ static const char *const SPARCv8Triples[] = { "sparc-linux-gnu", ++ "sparcv8-linux-gnu" }; ++ static const char *const SPARCv9LibDirs[] = { "/lib64", "/lib" }; ++ static const char *const SPARCv9Triples[] = { "sparc64-linux-gnu", ++ "sparcv9-linux-gnu" }; ++ + static const char *const SystemZLibDirs[] = { "/lib64", "/lib" }; + static const char *const SystemZTriples[] = { + "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", +@@ -1283,6 +1290,26 @@ void Generic_GCC::GCCInstallationDetector::print(r + TripleAliases.append(PPC64LETriples, + PPC64LETriples + llvm::array_lengthof(PPC64LETriples)); + break; ++ case llvm::Triple::sparc: ++ LibDirs.append(SPARCv8LibDirs, ++ SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs)); ++ TripleAliases.append(SPARCv8Triples, ++ SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples)); ++ BiarchLibDirs.append(SPARCv9LibDirs, ++ SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs)); ++ BiarchTripleAliases.append( ++ SPARCv9Triples, SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples)); ++ break; ++ case llvm::Triple::sparcv9: ++ LibDirs.append(SPARCv9LibDirs, ++ SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs)); ++ TripleAliases.append(SPARCv9Triples, ++ SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples)); ++ BiarchLibDirs.append(SPARCv8LibDirs, ++ SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs)); ++ BiarchTripleAliases.append( ++ SPARCv8Triples, SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples)); ++ break; + case llvm::Triple::systemz: + LibDirs.append(SystemZLibDirs, + SystemZLibDirs + llvm::array_lengthof(SystemZLibDirs)); +@@ -1379,6 +1406,7 @@ static bool findTargetBiarchSuffix(std::string &Su + Suffix = "/n32"; + else if (TargetArch == llvm::Triple::x86_64 || + TargetArch == llvm::Triple::ppc64 || ++ TargetArch == llvm::Triple::sparcv9 || + TargetArch == llvm::Triple::systemz || + TargetArch == llvm::Triple::mips64 || + TargetArch == llvm::Triple::mips64el) diff --git a/contrib/llvm/patches/patch-r262262-clang-r198923-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r198923-sparc.diff new file mode 100644 index 000000000000..912aa62545ad --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r198923-sparc.diff @@ -0,0 +1,49 @@ +Pull in r198923 from upstream clang trunk (by Jakob Stoklund Olesen): + + Use the right dynamic linker for SPARC Linux executables. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -6374,7 +6374,8 @@ static StringRef getLinuxDynamicLinker(const ArgLi + const toolchains::Linux &ToolChain) { + if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) + return "/system/bin/linker"; +- else if (ToolChain.getArch() == llvm::Triple::x86) ++ else if (ToolChain.getArch() == llvm::Triple::x86 || ++ ToolChain.getArch() == llvm::Triple::sparc) + return "/lib/ld-linux.so.2"; + else if (ToolChain.getArch() == llvm::Triple::aarch64) + return "/lib/ld-linux-aarch64.so.1"; +@@ -6399,6 +6400,8 @@ static StringRef getLinuxDynamicLinker(const ArgLi + ToolChain.getArch() == llvm::Triple::ppc64le || + ToolChain.getArch() == llvm::Triple::systemz) + return "/lib64/ld64.so.1"; ++ else if (ToolChain.getArch() == llvm::Triple::sparcv9) ++ return "/lib64/ld-linux.so.2"; + else + return "/lib64/ld-linux-x86-64.so.2"; + } +Index: tools/clang/test/Driver/linux-ld.c +=================================================================== +--- tools/clang/test/Driver/linux-ld.c ++++ tools/clang/test/Driver/linux-ld.c +@@ -389,6 +389,7 @@ + // RUN: | FileCheck --check-prefix=CHECK-SPARCV8 %s + // CHECK-SPARCV8: "{{.*}}ld{{(.exe)?}}" + // CHECK-SPARCV8: "-m" "elf32_sparc" ++// CHECK-SPARCV8: "-dynamic-linker" "/lib/ld-linux.so.2" + // + // RUN: %clang %s -### -o %t.o 2>&1 \ + // RUN: --target=sparcv9-linux-gnu \ +@@ -395,6 +396,7 @@ + // RUN: | FileCheck --check-prefix=CHECK-SPARCV9 %s + // CHECK-SPARCV9: "{{.*}}ld{{(.exe)?}}" + // CHECK-SPARCV9: "-m" "elf64_sparc" ++// CHECK-SPARCV9: "-dynamic-linker" "/lib64/ld-linux.so.2" + // + // Thoroughly exercise the Debian multiarch environment. + // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ diff --git a/contrib/llvm/patches/patch-r262262-clang-r199012-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r199012-sparc.diff new file mode 100644 index 000000000000..7bc4a78b361c --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r199012-sparc.diff @@ -0,0 +1,41 @@ +Pull in r199012 from upstream clang trunk (by Jakob Stoklund Olesen): + + Select the UltraSPARC instruction set when invoking the assembler. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -6228,8 +6228,10 @@ void gnutools::Assemble::ConstructJob(Compilation + CmdArgs.push_back("-many"); + } else if (getToolChain().getArch() == llvm::Triple::sparc) { + CmdArgs.push_back("-32"); ++ CmdArgs.push_back("-Av8plusa"); + } else if (getToolChain().getArch() == llvm::Triple::sparcv9) { + CmdArgs.push_back("-64"); ++ CmdArgs.push_back("-Av9a"); + } else if (getToolChain().getArch() == llvm::Triple::arm) { + StringRef MArch = getToolChain().getArchName(); + if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") +Index: tools/clang/test/Driver/linux-as.c +=================================================================== +--- tools/clang/test/Driver/linux-as.c ++++ tools/clang/test/Driver/linux-as.c +@@ -65,6 +65,7 @@ + // RUN: | FileCheck -check-prefix=CHECK-SPARCV9 %s + // CHECK-SPARCV9: as + // CHECK-SPARCV9: -64 ++// CHECK-SPARCV9: -Av9a + // CHECK-SPARCV9: -o + // + // RUN: %clang -target sparc-linux -mcpu=invalid-cpu -### \ +@@ -72,6 +73,7 @@ + // RUN: | FileCheck -check-prefix=CHECK-SPARCV8 %s + // CHECK-SPARCV8: as + // CHECK-SPARCV8: -32 ++// CHECK-SPARCV8: -Av8plusa + // CHECK-SPARCV8: -o + // + // RUN: %clang -target s390x-linux -### -no-integrated-as -c %s 2>&1 \ diff --git a/contrib/llvm/patches/patch-r262262-clang-r199034-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r199034-sparc.diff new file mode 100644 index 000000000000..8043e1f28186 --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r199034-sparc.diff @@ -0,0 +1,81 @@ +Pull in r199034 from upstream clang trunk (by Jakob Stoklund Olesen): + + MIPS and SPARC assemblers both take the -KPIC flag. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -6207,6 +6207,7 @@ void gnutools::Assemble::ConstructJob(Compilation + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; ++ bool NeedsKPIC = false; + + // Add --32/--64 to make sure we get the format we want. + // This is incomplete +@@ -6229,9 +6230,11 @@ void gnutools::Assemble::ConstructJob(Compilation + } else if (getToolChain().getArch() == llvm::Triple::sparc) { + CmdArgs.push_back("-32"); + CmdArgs.push_back("-Av8plusa"); ++ NeedsKPIC = true; + } else if (getToolChain().getArch() == llvm::Triple::sparcv9) { + CmdArgs.push_back("-64"); + CmdArgs.push_back("-Av9a"); ++ NeedsKPIC = true; + } else if (getToolChain().getArch() == llvm::Triple::arm) { + StringRef MArch = getToolChain().getArchName(); + if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") +@@ -6291,6 +6294,15 @@ void gnutools::Assemble::ConstructJob(Compilation + CmdArgs.push_back(Args.MakeArgString("-mmsa")); + } + ++ NeedsKPIC = true; ++ } else if (getToolChain().getArch() == llvm::Triple::systemz) { ++ // Always pass an -march option, since our default of z10 is later ++ // than the GNU assembler's default. ++ StringRef CPUName = getSystemZTargetCPU(Args); ++ CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName)); ++ } ++ ++ if (NeedsKPIC) { + Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, + options::OPT_fpic, options::OPT_fno_pic, + options::OPT_fPIE, options::OPT_fno_PIE, +@@ -6302,11 +6314,6 @@ void gnutools::Assemble::ConstructJob(Compilation + LastPICArg->getOption().matches(options::OPT_fpie))) { + CmdArgs.push_back("-KPIC"); + } +- } else if (getToolChain().getArch() == llvm::Triple::systemz) { +- // Always pass an -march option, since our default of z10 is later +- // than the GNU assembler's default. +- StringRef CPUName = getSystemZTargetCPU(Args); +- CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName)); + } + + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, +Index: tools/clang/test/Driver/linux-as.c +=================================================================== +--- tools/clang/test/Driver/linux-as.c ++++ tools/clang/test/Driver/linux-as.c +@@ -66,8 +66,18 @@ + // CHECK-SPARCV9: as + // CHECK-SPARCV9: -64 + // CHECK-SPARCV9: -Av9a ++// CHECK-SPARCV9-NOT: -KPIC + // CHECK-SPARCV9: -o + // ++// RUN: %clang -target sparc64-linux -mcpu=invalid-cpu -### \ ++// RUN: -no-integrated-as -fpic -c %s 2>&1 \ ++// RUN: | FileCheck -check-prefix=CHECK-SPARCV9PIC %s ++// CHECK-SPARCV9PIC: as ++// CHECK-SPARCV9PIC: -64 ++// CHECK-SPARCV9PIC: -Av9a ++// CHECK-SPARCV9PIC: -KPIC ++// CHECK-SPARCV9PIC: -o ++// + // RUN: %clang -target sparc-linux -mcpu=invalid-cpu -### \ + // RUN: -no-integrated-as -c %s 2>&1 \ + // RUN: | FileCheck -check-prefix=CHECK-SPARCV8 %s diff --git a/contrib/llvm/patches/patch-r262262-clang-r199037-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r199037-sparc.diff new file mode 100644 index 000000000000..beed0ed9162e --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r199037-sparc.diff @@ -0,0 +1,53 @@ +Pull in r199037 from upstream clang trunk (by Jakob Stokund Olesen): + + SPARC passes non-trivial C++ objects indirectly like everybody else. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/lib/CodeGen/TargetInfo.cpp +=================================================================== +--- tools/clang/lib/CodeGen/TargetInfo.cpp ++++ tools/clang/lib/CodeGen/TargetInfo.cpp +@@ -5349,6 +5349,11 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned + if (!isAggregateTypeForABI(Ty)) + return ABIArgInfo::getDirect(); + ++ // If a C++ object has either a non-trivial copy constructor or a non-trivial ++ // destructor, it is passed with an explicit indirect pointer / sret pointer. ++ if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) ++ return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory); ++ + // This is a small aggregate type that should be passed in registers. + // Build a coercion type from the LLVM struct type. + llvm::StructType *StrTy = dyn_cast(CGT.ConvertType(Ty)); +Index: tools/clang/test/CodeGenCXX/sparcv9-abi.cpp +=================================================================== +--- tools/clang/test/CodeGenCXX/sparcv9-abi.cpp ++++ tools/clang/test/CodeGenCXX/sparcv9-abi.cpp +@@ -0,0 +1,26 @@ ++// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s ++ ++struct pod { ++ int a, b; ++}; ++ ++void f0(); ++void f1(struct pod); ++ ++struct notpod { ++ int a, b; ++ ~notpod() { f0(); } ++}; ++ ++void f2(struct notpod); ++ ++// CHECK-LABEL: caller ++// CHECK: call void @_Z2f13pod(i64 ++// CHECK: call void @_Z2f26notpod(%struct.notpod* ++void caller() ++{ ++ pod p1; ++ notpod p2; ++ f1(p1); ++ f2(p2); ++} diff --git a/contrib/llvm/patches/patch-r262262-clang-r199188-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r199188-sparc.diff new file mode 100644 index 000000000000..77e5eafc277e --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r199188-sparc.diff @@ -0,0 +1,35 @@ +Pull in r199188 from upstream clang trunk (by Jakob Stoklund Olesen): + + Puny 24-byte structs are returned by value on SPARC. + + Pad these structs up so they are sret-returned even on that + architecture. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/test/CodeGen/sret.c +=================================================================== +--- tools/clang/test/CodeGen/sret.c ++++ tools/clang/test/CodeGen/sret.c +@@ -4,6 +4,8 @@ struct abc { + long a; + long b; + long c; ++ long d; ++ long e; + }; + + struct abc foo1(void); +Index: tools/clang/test/CodeGen/sret2.c +=================================================================== +--- tools/clang/test/CodeGen/sret2.c ++++ tools/clang/test/CodeGen/sret2.c +@@ -4,6 +4,8 @@ struct abc { + long a; + long b; + long c; ++ long d; ++ long e; + }; + + struct abc foo2(){} diff --git a/contrib/llvm/patches/patch-r262262-clang-r199399-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r199399-sparc.diff new file mode 100644 index 000000000000..106ab89236fe --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r199399-sparc.diff @@ -0,0 +1,37 @@ +Pull in r199399 from upstream clang trunk (by Jakob Stoklund Olesen): + + SPARCv9 implements long double as an IEEE quad. + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/test/CodeGen/sparcv9-abi.c +=================================================================== +--- tools/clang/test/CodeGen/sparcv9-abi.c ++++ tools/clang/test/CodeGen/sparcv9-abi.c +@@ -18,6 +18,9 @@ long long f_int_3(long long x) { return x; } + // CHECK-LABEL: define signext i8 @f_int_4(i8 signext %x) + char f_int_4(char x) { return x; } + ++// CHECK-LABEL: define fp128 @f_ld(fp128 %x) ++long double f_ld(long double x) { return x; } ++ + // Small structs are passed in registers. + struct small { + int *a, *b; +Index: tools/clang/lib/Basic/Targets.cpp +=================================================================== +--- tools/clang/lib/Basic/Targets.cpp ++++ tools/clang/lib/Basic/Targets.cpp +@@ -4529,6 +4529,12 @@ class SparcV9TargetInfo : public SparcTargetInfo { + UIntMaxType = UnsignedLong; + } + Int64Type = IntMaxType; ++ ++ // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit ++ // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned. ++ LongDoubleWidth = 128; ++ LongDoubleAlign = 128; ++ LongDoubleFormat = &llvm::APFloat::IEEEquad; + } + + virtual void getTargetDefines(const LangOptions &Opts, diff --git a/contrib/llvm/patches/patch-r262262-clang-r200452-sparc.diff b/contrib/llvm/patches/patch-r262262-clang-r200452-sparc.diff new file mode 100644 index 000000000000..e14306d86f14 --- /dev/null +++ b/contrib/llvm/patches/patch-r262262-clang-r200452-sparc.diff @@ -0,0 +1,20 @@ +Pull in r200452 from upstream clang trunk (by Jakob Stoklund Olesen): + + SPARCv9 supports atomic operations up to 64 bits. + + Patch by Roman Divacky! + +Introduced here: http://svn.freebsd.org/changeset/base/262262 + +Index: tools/clang/lib/Basic/Targets.cpp +=================================================================== +--- tools/clang/lib/Basic/Targets.cpp ++++ tools/clang/lib/Basic/Targets.cpp +@@ -4535,6 +4535,7 @@ class SparcV9TargetInfo : public SparcTargetInfo { + LongDoubleWidth = 128; + LongDoubleAlign = 128; + LongDoubleFormat = &llvm::APFloat::IEEEquad; ++ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; + } + + virtual void getTargetDefines(const LangOptions &Opts, diff --git a/contrib/llvm/patches/patch-r262264-llvm-r200453-sparc.diff b/contrib/llvm/patches/patch-r262264-llvm-r200453-sparc.diff new file mode 100644 index 000000000000..2c4470ccf34d --- /dev/null +++ b/contrib/llvm/patches/patch-r262264-llvm-r200453-sparc.diff @@ -0,0 +1,91 @@ +Pull in r200453 from upstream llvm trunk (by Jakob Stoklund Olesen): + + Implement SPARCv9 atomic_swap_64 with a pseudo. + + The SWAP instruction only exists in a 32-bit variant, but the 64-bit + atomic swap can be implemented in terms of CASX, like the other atomic + rmw primitives. + +Introduced here: http://svn.freebsd.org/changeset/base/262264 + +Index: lib/Target/Sparc/SparcInstr64Bit.td +=================================================================== +--- lib/Target/Sparc/SparcInstr64Bit.td ++++ lib/Target/Sparc/SparcInstr64Bit.td +@@ -463,6 +463,14 @@ defm ATOMIC_LOAD_MAX : AtomicRMW; + defm ATOMIC_LOAD_UMAX : AtomicRMW; + ++// There is no 64-bit variant of SWAP, so use a pseudo. ++let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1, ++ Defs = [ICC], Predicates = [Is64Bit] in ++def ATOMIC_SWAP_64 : Pseudo<(outs I64Regs:$rd), ++ (ins ptr_rc:$addr, I64Regs:$rs2), "", ++ [(set i64:$rd, ++ (atomic_swap_64 iPTR:$addr, i64:$rs2))]>; ++ + // Global addresses, constant pool entries + let Predicates = [Is64Bit] in { + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -1498,7 +1498,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + + if (Subtarget->is64Bit()) { + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal); +- setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Expand); ++ setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal); + setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom); + } +@@ -2885,6 +2885,9 @@ SparcTargetLowering::EmitInstrWithCustomInserter(M + case SP::ATOMIC_LOAD_NAND_64: + return expandAtomicRMW(MI, BB, SP::ANDXrr); + ++ case SP::ATOMIC_SWAP_64: ++ return expandAtomicRMW(MI, BB, 0); ++ + case SP::ATOMIC_LOAD_MAX_32: + return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_G); + case SP::ATOMIC_LOAD_MAX_64: +@@ -3023,7 +3026,8 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr + + // Build the loop block. + unsigned ValReg = MRI.createVirtualRegister(ValueRC); +- unsigned UpdReg = MRI.createVirtualRegister(ValueRC); ++ // Opcode == 0 means try to write Rs2Reg directly (ATOMIC_SWAP). ++ unsigned UpdReg = (Opcode ? MRI.createVirtualRegister(ValueRC) : Rs2Reg); + + BuildMI(LoopMBB, DL, TII.get(SP::PHI), ValReg) + .addReg(Val0Reg).addMBB(MBB) +@@ -3035,7 +3039,7 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr + BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(Rs2Reg); + BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) + .addReg(ValReg).addReg(Rs2Reg).addImm(CondCode); +- } else { ++ } else if (Opcode) { + BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) + .addReg(ValReg).addReg(Rs2Reg); + } +Index: test/CodeGen/SPARC/atomics.ll +=================================================================== +--- test/CodeGen/SPARC/atomics.ll ++++ test/CodeGen/SPARC/atomics.ll +@@ -62,6 +62,15 @@ entry: + ret i32 %b + } + ++; CHECK-LABEL: test_swap_i64 ++; CHECK: casx [%o1], ++ ++define i64 @test_swap_i64(i64 %a, i64* %ptr) { ++entry: ++ %b = atomicrmw xchg i64* %ptr, i64 42 monotonic ++ ret i64 %b ++} ++ + ; CHECK-LABEL: test_load_add_32 + ; CHECK: membar + ; CHECK: add [[V:%[gilo][0-7]]], %o1, [[U:%[gilo][0-7]]] diff --git a/contrib/llvm/patches/patch-r262265-llvm-r201718-sparc.diff b/contrib/llvm/patches/patch-r262265-llvm-r201718-sparc.diff new file mode 100644 index 000000000000..d9ca427a4f40 --- /dev/null +++ b/contrib/llvm/patches/patch-r262265-llvm-r201718-sparc.diff @@ -0,0 +1,40 @@ +Pull in r201718 from upstream llvm trunk (by Roman Divacky): + + Expand 64bit {SHL,SHR,SRA}_PARTS on sparcv9. + +Introduced here: http://svn.freebsd.org/changeset/base/262265 + +Index: test/CodeGen/SPARC/parts.ll +=================================================================== +--- test/CodeGen/SPARC/parts.ll ++++ test/CodeGen/SPARC/parts.ll +@@ -0,0 +1,14 @@ ++; RUN: llc < %s -march=sparcv9 | FileCheck %s ++ ++; CHECK-LABEL: test ++; CHECK: srl %i1, 0, %o2 ++; CHECK-NEXT: or %g0, %i2, %o0 ++; CHECK-NEXT: call __ashlti3 ++; CHECK-NEXT: or %g0, %i3, %o1 ++; CHECK-NEXT: or %g0, %o0, %i0 ++ ++define i128 @test(i128 %a, i128 %b) { ++entry: ++ %tmp = shl i128 %b, %a ++ ret i128 %tmp ++} +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -1554,6 +1554,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + + setOperationAction(ISD::UMULO, MVT::i64, Custom); + setOperationAction(ISD::SMULO, MVT::i64, Custom); ++ ++ setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand); ++ setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand); ++ setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand); + } + + // VASTART needs to be custom lowered to use the VarArgsFrameIndex. diff --git a/contrib/llvm/patches/patch-r262303-enable-ppc-integrated-as.diff b/contrib/llvm/patches/patch-r262303-enable-ppc-integrated-as.diff new file mode 100644 index 000000000000..3d2e107b974f --- /dev/null +++ b/contrib/llvm/patches/patch-r262303-enable-ppc-integrated-as.diff @@ -0,0 +1,25 @@ +Pull in r197521 from upstream clang trunk (by Roman Divacky): + + Use the integrated assembler by default on FreeBSD/ppc and ppc64. + +Introduced here: http://svn.freebsd.org/changeset/base/262303 + +Index: tools/clang/lib/Driver/ToolChains.h +=================================================================== +--- tools/clang/lib/Driver/ToolChains.h ++++ tools/clang/lib/Driver/ToolChains.h +@@ -512,8 +512,13 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Gen + virtual void + AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; ++ virtual bool IsIntegratedAssemblerDefault() const { ++ if (getTriple().getArch() == llvm::Triple::ppc || ++ getTriple().getArch() == llvm::Triple::ppc64) ++ return true; ++ return Generic_ELF::IsIntegratedAssemblerDefault(); ++ } + +- + virtual bool UseSjLjExceptions() const; + protected: + virtual Tool *buildAssembler() const; diff --git a/contrib/llvm/patches/patch-r262415-llvm-r201994-sparc.diff b/contrib/llvm/patches/patch-r262415-llvm-r201994-sparc.diff new file mode 100644 index 000000000000..4f9b9166c39d --- /dev/null +++ b/contrib/llvm/patches/patch-r262415-llvm-r201994-sparc.diff @@ -0,0 +1,49 @@ +Pull in r201994 from upstream llvm trunk (by Benjamin Kramer): + + SPARC: Implement TRAP lowering. Matches what GCC emits. + +Introduced here: http://svn.freebsd.org/changeset/base/262415 + +Index: lib/Target/Sparc/SparcInstrInfo.td +=================================================================== +--- lib/Target/Sparc/SparcInstrInfo.td ++++ lib/Target/Sparc/SparcInstrInfo.td +@@ -312,6 +312,9 @@ let hasSideEffects = 1, mayStore = 1 in { + [(flushw)]>; + } + ++let isBarrier = 1, isTerminator = 1, rd = 0b1000, rs1 = 0, simm13 = 5 in ++ def TA5 : F3_2<0b10, 0b111010, (outs), (ins), "ta 5", [(trap)]>; ++ + let rd = 0 in + def UNIMP : F2_1<0b000, (outs), (ins i32imm:$val), + "unimp $val", []>; +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -1565,6 +1565,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMac + // VAARG needs to be lowered to not do unaligned accesses for doubles. + setOperationAction(ISD::VAARG , MVT::Other, Custom); + ++ setOperationAction(ISD::TRAP , MVT::Other, Legal); ++ + // Use the default implementation. + setOperationAction(ISD::VACOPY , MVT::Other, Expand); + setOperationAction(ISD::VAEND , MVT::Other, Expand); +Index: test/CodeGen/SPARC/trap.ll +=================================================================== +--- test/CodeGen/SPARC/trap.ll ++++ test/CodeGen/SPARC/trap.ll +@@ -0,0 +1,11 @@ ++; RUN: llc -mtriple=sparc-linux-gnu < %s -show-mc-encoding | FileCheck %s ++ ++define void @test1() { ++ tail call void @llvm.trap() ++ unreachable ++ ++; CHECK-LABEL: test1: ++; CHECK: ta 5 ! encoding: [0x91,0xd0,0x20,0x05] ++} ++ ++declare void @llvm.trap() diff --git a/contrib/llvm/patches/patch-r262460-llvm-r202059-sparc.diff b/contrib/llvm/patches/patch-r262460-llvm-r202059-sparc.diff new file mode 100644 index 000000000000..e683e33ea327 --- /dev/null +++ b/contrib/llvm/patches/patch-r262460-llvm-r202059-sparc.diff @@ -0,0 +1,62 @@ +Pull in r202059 from upstream clang trunk (by Roman Divacky): + + Implement getDwarfEHStackPointer() and initDwarfEHRegSizeTable() for sparcv9. + +Introduced here: http://svn.freebsd.org/changeset/base/262460 + +Index: tools/clang/lib/CodeGen/TargetInfo.cpp +=================================================================== +--- tools/clang/lib/CodeGen/TargetInfo.cpp ++++ tools/clang/lib/CodeGen/TargetInfo.cpp +@@ -5435,10 +5435,51 @@ class SparcV9TargetCodeGenInfo : public TargetCode + public: + SparcV9TargetCodeGenInfo(CodeGenTypes &CGT) + : TargetCodeGenInfo(new SparcV9ABIInfo(CGT)) {} ++ ++ int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { ++ return 14; ++ } ++ ++ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, ++ llvm::Value *Address) const; + }; + } // end anonymous namespace + ++bool ++SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, ++ llvm::Value *Address) const { ++ // This is calculated from the LLVM and GCC tables and verified ++ // against gcc output. AFAIK all ABIs use the same encoding. + ++ CodeGen::CGBuilderTy &Builder = CGF.Builder; ++ ++ llvm::IntegerType *i8 = CGF.Int8Ty; ++ llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); ++ llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); ++ ++ // 0-31: the 8-byte general-purpose registers ++ AssignToArrayRange(Builder, Address, Eight8, 0, 31); ++ ++ // 32-63: f0-31, the 4-byte floating-point registers ++ AssignToArrayRange(Builder, Address, Four8, 32, 63); ++ ++ // Y = 64 ++ // PSR = 65 ++ // WIM = 66 ++ // TBR = 67 ++ // PC = 68 ++ // NPC = 69 ++ // FSR = 70 ++ // CSR = 71 ++ AssignToArrayRange(Builder, Address, Eight8, 64, 71); ++ ++ // 72-87: d0-15, the 8-byte floating-point registers ++ AssignToArrayRange(Builder, Address, Eight8, 72, 87); ++ ++ return false; ++} ++ ++ + //===----------------------------------------------------------------------===// + // Xcore ABI Implementation + //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/patches/patch-r262535-clang-r202177-sparc.diff b/contrib/llvm/patches/patch-r262535-clang-r202177-sparc.diff new file mode 100644 index 000000000000..00514eb10620 --- /dev/null +++ b/contrib/llvm/patches/patch-r262535-clang-r202177-sparc.diff @@ -0,0 +1,84 @@ +Pull in r202177 from upstream clang trunk (by Roman Divacky): + + Give sparcv9 the ability to set the target cpu. Change it from accepting + -march which doesnt exist on sparc gcc to -mcpu. While here adjust a + few tests to not write an unused temporary file. + +Introduced here: http://svn.freebsd.org/changeset/base/262535 + +Index: tools/clang/lib/Basic/Targets.cpp +=================================================================== +--- tools/clang/lib/Basic/Targets.cpp ++++ tools/clang/lib/Basic/Targets.cpp +@@ -4552,6 +4552,22 @@ class SparcV9TargetInfo : public SparcTargetInfo { + Builder.defineMacro("__sparcv9__"); + } + } ++ ++ virtual bool setCPU(const std::string &Name) { ++ bool CPUKnown = llvm::StringSwitch(Name) ++ .Case("v9", true) ++ .Case("ultrasparc", true) ++ .Case("ultrasparc3", true) ++ .Case("niagara", true) ++ .Case("niagara2", true) ++ .Case("niagara3", true) ++ .Case("niagara4", true) ++ .Default(false); ++ ++ // No need to store the CPU yet. There aren't any CPU-specific ++ // macros to define. ++ return CPUKnown; ++ } + }; + + } // end anonymous namespace. +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -1373,7 +1373,8 @@ static std::string getCPUName(const ArgList &Args, + } + + case llvm::Triple::sparc: +- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) ++ case llvm::Triple::sparcv9: ++ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) + return A->getValue(); + return ""; + +Index: tools/clang/test/Driver/freebsd.c +=================================================================== +--- tools/clang/test/Driver/freebsd.c ++++ tools/clang/test/Driver/freebsd.c +@@ -59,13 +59,13 @@ + // CHECK-MIPSEL: "{{[^" ]*}}ld{{[^" ]*}}" + // CHECK-MIPSEL: "-dynamic-linker" "{{.*}}/libexec/ld-elf.so.1" + // CHECK-MIPSEL-NOT: "--hash-style={{gnu|both}}" +-// RUN: %clang %s -### -o %t.o 2>&1 \ ++// RUN: %clang %s -### 2>&1 \ + // RUN: -target mips64-unknown-freebsd10.0 \ + // RUN: | FileCheck --check-prefix=CHECK-MIPS64 %s + // CHECK-MIPS64: "{{[^" ]*}}ld{{[^" ]*}}" + // CHECK-MIPS64: "-dynamic-linker" "{{.*}}/libexec/ld-elf.so.1" + // CHECK-MIPS64-NOT: "--hash-style={{gnu|both}}" +-// RUN: %clang %s -### -o %t.o 2>&1 \ ++// RUN: %clang %s -### 2>&1 \ + // RUN: -target mips64el-unknown-freebsd10.0 \ + // RUN: | FileCheck --check-prefix=CHECK-MIPS64EL %s + // CHECK-MIPS64EL: "{{[^" ]*}}ld{{[^" ]*}}" +@@ -97,12 +97,12 @@ + // CHECK-NORMAL: crt1.o + // CHECK-NORMAL: crtbegin.o + +-// RUN: %clang %s -### -o %t.o -target arm-unknown-freebsd10.0 2>&1 \ ++// RUN: %clang %s -### -target arm-unknown-freebsd10.0 2>&1 \ + // RUN: | FileCheck --check-prefix=CHECK-ARM %s + // CHECK-ARM: clang{{.*}}" "-cc1"{{.*}}" "-fsjlj-exceptions" + // CHECK-ARM: as{{.*}}" "-mfpu=softvfp"{{.*}}"-matpcs" + +-// RUN: %clang %s -### -o %t.o -target arm-gnueabi-freebsd10.0 2>&1 \ ++// RUN: %clang %s -### -target arm-gnueabi-freebsd10.0 2>&1 \ + // RUN: | FileCheck --check-prefix=CHECK-ARM-EABI %s + // CHECK-ARM-EABI-NOT: clang{{.*}}" "-cc1"{{.*}}" "-fsjlj-exceptions" + // CHECK-ARM-EABI: as{{.*}}" "-mfpu=softvfp" "-meabi=5" diff --git a/contrib/llvm/patches/patch-r262536-clang-r202179-sparc.diff b/contrib/llvm/patches/patch-r262536-clang-r202179-sparc.diff new file mode 100644 index 000000000000..5912dac935c0 --- /dev/null +++ b/contrib/llvm/patches/patch-r262536-clang-r202179-sparc.diff @@ -0,0 +1,22 @@ +Pull in r202179 from upstream clang trunk (by Roman Divacky): + + Pass the sparc architecture variant to the assembler. + +Introduced here: http://svn.freebsd.org/changeset/base/262536 + +Index: tools/clang/lib/Driver/Tools.cpp +=================================================================== +--- tools/clang/lib/Driver/Tools.cpp ++++ tools/clang/lib/Driver/Tools.cpp +@@ -5788,6 +5788,11 @@ void freebsd::Assemble::ConstructJob(Compilation & + } + } else if (getToolChain().getArch() == llvm::Triple::sparc || + getToolChain().getArch() == llvm::Triple::sparcv9) { ++ if (getToolChain().getArch() == llvm::Triple::sparc) ++ CmdArgs.push_back("-Av8plusa"); ++ else ++ CmdArgs.push_back("-Av9a"); ++ + Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, + options::OPT_fpic, options::OPT_fno_pic, + options::OPT_fPIE, options::OPT_fno_PIE, diff --git a/contrib/llvm/patches/patch-r262582-llvm-r202422-sparc.diff b/contrib/llvm/patches/patch-r262582-llvm-r202422-sparc.diff new file mode 100644 index 000000000000..589dd4772c9e --- /dev/null +++ b/contrib/llvm/patches/patch-r262582-llvm-r202422-sparc.diff @@ -0,0 +1,89 @@ +Pull in r202422 from upstream llvm trunk (by Roman Divacky): + + Lower FNEG just like FABS to fneg[ds] and fmov[ds], thus avoiding + expensive libcall. Also, Qp_neg is not implemented on at least + FreeBSD. This is also what gcc is doing. + +Introduced here: http://svn.freebsd.org/changeset/base/262582 + +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -2643,24 +2643,16 @@ static SDValue LowerF128Store(SDValue Op, Selectio + &OutChains[0], 2); + } + +-static SDValue LowerFNEG(SDValue Op, SelectionDAG &DAG, +- const SparcTargetLowering &TLI, +- bool is64Bit) { +- if (Op.getValueType() == MVT::f64) +- return LowerF64Op(Op, DAG, ISD::FNEG); +- if (Op.getValueType() == MVT::f128) +- return TLI.LowerF128Op(Op, DAG, ((is64Bit) ? "_Qp_neg" : "_Q_neg"), 1); +- return Op; +-} ++static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) { ++ assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) && "invalid"); + +-static SDValue LowerFABS(SDValue Op, SelectionDAG &DAG, bool isV9) { + if (Op.getValueType() == MVT::f64) +- return LowerF64Op(Op, DAG, ISD::FABS); ++ return LowerF64Op(Op, DAG, Op.getOpcode()); + if (Op.getValueType() != MVT::f128) + return Op; + +- // Lower fabs on f128 to fabs on f64 +- // fabs f128 => fabs f64:sub_even64, fmov f64:sub_odd64 ++ // Lower fabs/fneg on f128 to fabs/fneg on f64 ++ // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64 + + SDLoc dl(Op); + SDValue SrcReg128 = Op.getOperand(0); +@@ -2671,7 +2663,7 @@ static SDValue LowerF128Store(SDValue Op, Selectio + if (isV9) + Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64); + else +- Hi64 = LowerF64Op(Hi64, DAG, ISD::FABS); ++ Hi64 = LowerF64Op(Hi64, DAG, Op.getOpcode()); + + SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, + dl, MVT::f128), 0); +@@ -2792,7 +2784,6 @@ SDValue SparcTargetLowering:: + LowerOperation(SDValue Op, SelectionDAG &DAG) const { + + bool hasHardQuad = Subtarget->hasHardQuad(); +- bool is64Bit = Subtarget->is64Bit(); + bool isV9 = Subtarget->isV9(); + + switch (Op.getOpcode()) { +@@ -2835,8 +2826,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons + getLibcallName(RTLIB::DIV_F128), 2); + case ISD::FSQRT: return LowerF128Op(Op, DAG, + getLibcallName(RTLIB::SQRT_F128),1); +- case ISD::FNEG: return LowerFNEG(Op, DAG, *this, is64Bit); +- case ISD::FABS: return LowerFABS(Op, DAG, isV9); ++ case ISD::FABS: ++ case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9); + case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this); + case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this); + case ISD::ADDC: +Index: test/CodeGen/SPARC/fp128.ll +=================================================================== +--- test/CodeGen/SPARC/fp128.ll ++++ test/CodeGen/SPARC/fp128.ll +@@ -232,3 +232,14 @@ entry: + store i32 %3, i32* %4, align 8 + ret void + } ++ ++; SOFT-LABEL: f128_neg ++; SOFT: fnegs ++ ++define void @f128_neg(fp128* noalias sret %scalar.result, fp128* byval %a) { ++entry: ++ %0 = load fp128* %a, align 8 ++ %1 = fsub fp128 0xL00000000000000008000000000000000, %0 ++ store fp128 %1, fp128* %scalar.result, align 8 ++ ret void ++} diff --git a/contrib/llvm/patches/patch-r262611-llvm-r196874-fix-invalid-pwd-crash.diff b/contrib/llvm/patches/patch-r262611-llvm-r196874-fix-invalid-pwd-crash.diff new file mode 100644 index 000000000000..587693dd473d --- /dev/null +++ b/contrib/llvm/patches/patch-r262611-llvm-r196874-fix-invalid-pwd-crash.diff @@ -0,0 +1,76 @@ +Pull in r196874 from upstream llvm trunk (by Andrew Trick): + + Fix a crash that occurs when PWD is invalid. + + MCJIT needs to be able to run in hostile environments, even when PWD + is invalid. There's no need to crash MCJIT in this case. + + The obvious fix is to simply leave MCContext's CompilationDir empty + when PWD can't be determined. This way, MCJIT clients, + and other clients that link with LLVM don?\226?\128?\153t need a valid working directory. + + If we do want to guarantee valid CompilationDir, that should be done + only for clients of getCompilationDir(). This is as simple as checking + for an empty string. + + The only current use of getCompilationDir is EmitGenDwarfInfo, which + won?\226?\128?\153t conceivably run with an invalid working dir. However, in the + purely hypothetically and untestable case that this happens, the + AT_comp_dir will be omitted from the compilation_unit DIE. + +Introduced here: http://svn.freebsd.org/changeset/base/262611 + +Index: include/llvm/MC/MCContext.h +=================================================================== +--- include/llvm/MC/MCContext.h ++++ include/llvm/MC/MCContext.h +@@ -278,6 +278,7 @@ namespace llvm { + /// This can be overridden by clients which want to control the reported + /// compilation directory and have it be something other than the current + /// working directory. ++ /// Returns an empty string if the current directory cannot be determined. + StringRef getCompilationDir() const { return CompilationDir; } + + /// \brief Set the compilation directory for DW_AT_comp_dir +Index: lib/MC/MCContext.cpp +=================================================================== +--- lib/MC/MCContext.cpp ++++ lib/MC/MCContext.cpp +@@ -47,8 +47,8 @@ MCContext::MCContext(const MCAsmInfo *mai, const M + AllowTemporaryLabels(true), DwarfCompileUnitID(0), AutoReset(DoAutoReset) { + + error_code EC = llvm::sys::fs::current_path(CompilationDir); +- assert(!EC && "Could not determine the current directory"); +- (void)EC; ++ if (EC) ++ CompilationDir.clear(); + + MachOUniquingMap = 0; + ELFUniquingMap = 0; +Index: lib/MC/MCDwarf.cpp +=================================================================== +--- lib/MC/MCDwarf.cpp ++++ lib/MC/MCDwarf.cpp +@@ -467,7 +467,8 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { + EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); + EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); + EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); +- EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); ++ if (!context.getCompilationDir().empty()) ++ EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); + StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); + if (!DwarfDebugFlags.empty()) + EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string); +@@ -643,8 +644,10 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, + MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. + + // AT_comp_dir, the working directory the assembly was done in. +- MCOS->EmitBytes(context.getCompilationDir()); +- MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. ++ if (!context.getCompilationDir().empty()) { ++ MCOS->EmitBytes(context.getCompilationDir()); ++ MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. ++ } + + // AT_APPLE_flags, the command line arguments of the assembler tool. + StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); diff --git a/contrib/llvm/patches/patch-r262809-clang-r203007-destructor-calling-conv.diff b/contrib/llvm/patches/patch-r262809-clang-r203007-destructor-calling-conv.diff new file mode 100644 index 000000000000..5341b8bed845 --- /dev/null +++ b/contrib/llvm/patches/patch-r262809-clang-r203007-destructor-calling-conv.diff @@ -0,0 +1,61 @@ +Pull in r203007 from upstream clang trunk (by Rafael Espindola): + + Don't produce an alias between destructors with different calling conventions. + + Fixes pr19007. + +Introduced here: http://svn.freebsd.org/changeset/base/262809 + +Index: tools/clang/lib/CodeGen/CGCXX.cpp +=================================================================== +--- tools/clang/lib/CodeGen/CGCXX.cpp ++++ tools/clang/lib/CodeGen/CGCXX.cpp +@@ -92,7 +92,13 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(c + if (!ClassLayout.getBaseClassOffset(UniqueBase).isZero()) + return true; + ++ // Give up if the calling conventions don't match. We could update the call, ++ // but it is probably not worth it. + const CXXDestructorDecl *BaseD = UniqueBase->getDestructor(); ++ if (BaseD->getType()->getAs()->getCallConv() != ++ D->getType()->getAs()->getCallConv()) ++ return true; ++ + return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base), + GlobalDecl(BaseD, Dtor_Base), + false); +Index: tools/clang/test/CodeGenCXX/ctor-dtor-alias.cpp +=================================================================== +--- tools/clang/test/CodeGenCXX/ctor-dtor-alias.cpp ++++ tools/clang/test/CodeGenCXX/ctor-dtor-alias.cpp +@@ -1,5 +1,5 @@ +-// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s +-// RUN: %clang_cc1 %s -triple x86_64-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s ++// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s ++// RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s + + // RUN: %clang_cc1 -cc1 -triple x86_64--netbsd -emit-llvm \ + // RUN: -mconstructor-aliases -O2 %s -o - | FileCheck --check-prefix=CHECK-RAUW %s +@@ -133,6 +133,22 @@ namespace test8 { + zed foo; + } + ++namespace test9 { ++struct foo { ++ __attribute__((stdcall)) ~foo() { ++ } ++}; ++ ++struct bar : public foo {}; ++ ++void zed() { ++ // Test that we produce a call to bar's destructor. We used to call foo's, but ++ // it has a different calling conversion. ++ // CHECK-DAG: call void @_ZN5test93barD2Ev ++ bar ptr; ++} ++} ++ + // CHECK-RAUW: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}] + // r194296 replaced C::~C with B::~B without emitting the later. + diff --git a/contrib/llvm/patches/patch-r263048-clang-r203624-fix-CC-aliases.diff b/contrib/llvm/patches/patch-r263048-clang-r203624-fix-CC-aliases.diff new file mode 100644 index 000000000000..1aac8cb05818 --- /dev/null +++ b/contrib/llvm/patches/patch-r263048-clang-r203624-fix-CC-aliases.diff @@ -0,0 +1,24 @@ +Pull in r203624 from upstream clang trunk (by Hans Wennborg): + + Be case sensitive when determining driver mode based on argv[0] except on Windows + + This narrows the impact of r188833 after Dimitry pointed out that it's good to be + able to tell the difference between 'cc' and 'CC'. + +Introduced here: http://svn.freebsd.org/changeset/base/263048 + +Index: tools/clang/tools/driver/driver.cpp +=================================================================== +--- tools/clang/tools/driver/driver.cpp ++++ tools/clang/tools/driver/driver.cpp +@@ -229,8 +229,10 @@ static void ParseProgName(SmallVectorImpl&1 | FileCheck %s ++ ++; We don't currently support realigning the stack and adjusting the stack ++; pointer in inline asm. This can even happen in GNU asm. ++ ++; CHECK: Stack realignment in presence of dynamic stack adjustments is not supported with inline assembly ++ ++define i32 @foo() { ++entry: ++ %r = alloca i32, align 16 ++ store i32 -1, i32* %r, align 16 ++ call void asm sideeffect "push %esi\0A\09xor %esi, %esi\0A\09mov %esi, $0\0A\09pop %esi", "=*m,~{flags},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %r) ++ %0 = load i32* %r, align 16 ++ ret i32 %0 ++} +Index: test/CodeGen/X86/inline-asm-stack-realign.ll +=================================================================== +--- test/CodeGen/X86/inline-asm-stack-realign.ll ++++ test/CodeGen/X86/inline-asm-stack-realign.ll +@@ -0,0 +1,16 @@ ++; RUN: not llc -mtriple=i686-pc-win32 < %s 2>&1 | FileCheck %s ++ ++; We don't currently support realigning the stack and adjusting the stack ++; pointer in inline asm. This commonly happens in MS inline assembly using ++; push and pop. ++ ++; CHECK: Stack realignment in presence of dynamic stack adjustments is not supported with inline assembly ++ ++define i32 @foo() { ++entry: ++ %r = alloca i32, align 16 ++ store i32 -1, i32* %r, align 16 ++ call void asm sideeffect inteldialect "push esi\0A\09xor esi, esi\0A\09mov dword ptr $0, esi\0A\09pop esi", "=*m,~{flags},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %r) ++ %0 = load i32* %r, align 16 ++ ret i32 %0 ++} +Index: test/CodeGen/X86/ms-inline-asm.ll +=================================================================== +--- test/CodeGen/X86/ms-inline-asm.ll ++++ test/CodeGen/X86/ms-inline-asm.ll +@@ -5,7 +5,6 @@ entry: + %0 = tail call i32 asm sideeffect inteldialect "mov eax, $1\0A\09mov $0, eax", "=r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32 1) nounwind + ret i32 %0 + ; CHECK: t1 +-; CHECK: movl %esp, %ebp + ; CHECK: {{## InlineAsm Start|#APP}} + ; CHECK: .intel_syntax + ; CHECK: mov eax, ecx +@@ -19,7 +18,6 @@ entry: + call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind + ret void + ; CHECK: t2 +-; CHECK: movl %esp, %ebp + ; CHECK: {{## InlineAsm Start|#APP}} + ; CHECK: .intel_syntax + ; CHECK: mov eax, 1 +@@ -34,7 +32,6 @@ entry: + call void asm sideeffect inteldialect "mov eax, DWORD PTR [$0]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %V.addr) nounwind + ret void + ; CHECK: t3 +-; CHECK: movl %esp, %ebp + ; CHECK: {{## InlineAsm Start|#APP}} + ; CHECK: .intel_syntax + ; CHECK: mov eax, DWORD PTR {{[[esp]}} +@@ -56,7 +53,6 @@ entry: + %0 = load i32* %b1, align 4 + ret i32 %0 + ; CHECK: t18 +-; CHECK: movl %esp, %ebp + ; CHECK: {{## InlineAsm Start|#APP}} + ; CHECK: .intel_syntax + ; CHECK: lea ebx, foo +@@ -76,7 +72,6 @@ entry: + call void asm sideeffect inteldialect "call $0", "r,~{dirflag},~{fpsr},~{flags}"(void ()* @t19_helper) nounwind + ret void + ; CHECK-LABEL: t19: +-; CHECK: movl %esp, %ebp + ; CHECK: movl ${{_?}}t19_helper, %eax + ; CHECK: {{## InlineAsm Start|#APP}} + ; CHECK: .intel_syntax +@@ -95,7 +90,6 @@ entry: + %0 = load i32** %res, align 4 + ret i32* %0 + ; CHECK-LABEL: t30: +-; CHECK: movl %esp, %ebp + ; CHECK: {{## InlineAsm Start|#APP}} + ; CHECK: .intel_syntax + ; CHECK: lea edi, dword ptr [{{_?}}results] +@@ -103,8 +97,31 @@ entry: + ; CHECK: {{## InlineAsm End|#NO_APP}} + ; CHECK: {{## InlineAsm Start|#APP}} + ; CHECK: .intel_syntax +-; CHECK: mov dword ptr [esi], edi ++; CHECK: mov dword ptr [esp], edi + ; CHECK: .att_syntax + ; CHECK: {{## InlineAsm End|#NO_APP}} +-; CHECK: movl (%esi), %eax ++; CHECK: movl (%esp), %eax + } ++ ++; Stack realignment plus MS inline asm that does *not* adjust the stack is no ++; longer an error. ++ ++define i32 @t31() { ++entry: ++ %val = alloca i32, align 64 ++ store i32 -1, i32* %val, align 64 ++ call void asm sideeffect inteldialect "mov dword ptr $0, esp", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %val) #1 ++ %sp = load i32* %val, align 64 ++ ret i32 %sp ++; CHECK-LABEL: t31: ++; CHECK: pushl %ebp ++; CHECK: movl %esp, %ebp ++; CHECK: andl $-64, %esp ++; CHECK: {{## InlineAsm Start|#APP}} ++; CHECK: .intel_syntax ++; CHECK: mov dword ptr [esp], esp ++; CHECK: .att_syntax ++; CHECK: {{## InlineAsm End|#NO_APP}} ++; CHECK: movl (%esp), %eax ++; CHECK: ret ++} +Index: include/llvm/CodeGen/MachineFrameInfo.h +=================================================================== +--- include/llvm/CodeGen/MachineFrameInfo.h ++++ include/llvm/CodeGen/MachineFrameInfo.h +@@ -223,6 +223,10 @@ class MachineFrameInfo { + /// Whether the "realign-stack" option is on. + bool RealignOption; + ++ /// True if the function includes inline assembly that adjusts the stack ++ /// pointer. ++ bool HasInlineAsmWithSPAdjust; ++ + const TargetFrameLowering *getFrameLowering() const; + public: + explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt) +@@ -451,6 +455,10 @@ class MachineFrameInfo { + bool hasCalls() const { return HasCalls; } + void setHasCalls(bool V) { HasCalls = V; } + ++ /// Returns true if the function contains any stack-adjusting inline assembly. ++ bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; } ++ void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; } ++ + /// getMaxCallFrameSize - Return the maximum size of a call frame that must be + /// allocated for an outgoing function call. This is only available if + /// CallFrameSetup/Destroy pseudo instructions are used by the target, and +Index: include/llvm/CodeGen/MachineFunction.h +=================================================================== +--- include/llvm/CodeGen/MachineFunction.h ++++ include/llvm/CodeGen/MachineFunction.h +@@ -131,8 +131,8 @@ class MachineFunction { + /// about the control flow of such functions. + bool ExposesReturnsTwice; + +- /// True if the function includes MS-style inline assembly. +- bool HasMSInlineAsm; ++ /// True if the function includes any inline assembly. ++ bool HasInlineAsm; + + MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION; + void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; +@@ -218,15 +218,14 @@ class MachineFunction { + ExposesReturnsTwice = B; + } + +- /// Returns true if the function contains any MS-style inline assembly. +- bool hasMSInlineAsm() const { +- return HasMSInlineAsm; ++ /// Returns true if the function contains any inline assembly. ++ bool hasInlineAsm() const { ++ return HasInlineAsm; + } + +- /// Set a flag that indicates that the function contains MS-style inline +- /// assembly. +- void setHasMSInlineAsm(bool B) { +- HasMSInlineAsm = B; ++ /// Set a flag that indicates that the function contains inline assembly. ++ void setHasInlineAsm(bool B) { ++ HasInlineAsm = B; + } + + /// getInfo - Keep track of various per-function pieces of information for +Index: lib/Target/X86/X86FrameLowering.cpp +=================================================================== +--- lib/Target/X86/X86FrameLowering.cpp ++++ lib/Target/X86/X86FrameLowering.cpp +@@ -50,7 +50,7 @@ bool X86FrameLowering::hasFP(const MachineFunction + return (MF.getTarget().Options.DisableFramePointerElim(MF) || + RegInfo->needsStackRealignment(MF) || + MFI->hasVarSizedObjects() || +- MFI->isFrameAddressTaken() || MF.hasMSInlineAsm() || ++ MFI->isFrameAddressTaken() || MFI->hasInlineAsmWithSPAdjust() || + MF.getInfo()->getForceFramePointer() || + MMI.callsUnwindInit() || MMI.callsEHReturn()); + } +Index: lib/Target/X86/X86RegisterInfo.cpp +=================================================================== +--- lib/Target/X86/X86RegisterInfo.cpp ++++ lib/Target/X86/X86RegisterInfo.cpp +@@ -347,6 +347,12 @@ BitVector X86RegisterInfo::getReservedRegs(const M + "Stack realignment in presence of dynamic allocas is not supported with" + "this calling convention."); + ++ // FIXME: Do a proper analysis of the inline asm to see if it actually ++ // conflicts with the base register we chose. ++ if (MF.hasInlineAsm()) ++ report_fatal_error("Stack realignment in presence of dynamic stack " ++ "adjustments is not supported with inline assembly."); ++ + for (MCSubRegIterator I(getBaseRegister(), this, /*IncludeSelf=*/true); + I.isValid(); ++I) + Reserved.set(*I); +@@ -403,18 +409,15 @@ bool X86RegisterInfo::hasBasePointer(const Machine + if (!EnableBasePointer) + return false; + +- // When we need stack realignment and there are dynamic allocas, we can't +- // reference off of the stack pointer, so we reserve a base pointer. +- // +- // This is also true if the function contain MS-style inline assembly. We +- // do this because if any stack changes occur in the inline assembly, e.g., +- // "pusha", then any C local variable or C argument references in the +- // inline assembly will be wrong because the SP is not properly tracked. +- if ((needsStackRealignment(MF) && MFI->hasVarSizedObjects()) || +- MF.hasMSInlineAsm()) +- return true; +- +- return false; ++ // When we need stack realignment, we can't address the stack from the frame ++ // pointer. When we have dynamic allocas or stack-adjusting inline asm, we ++ // can't address variables from the stack pointer. MS inline asm can ++ // reference locals while also adjusting the stack pointer. When we can't ++ // use both the SP and the FP, we need a separate base pointer register. ++ bool CantUseFP = needsStackRealignment(MF); ++ bool CantUseSP = ++ MFI->hasVarSizedObjects() || MFI->hasInlineAsmWithSPAdjust(); ++ return CantUseFP && CantUseSP; + } + + bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const { +Index: lib/MC/MCParser/AsmParser.cpp +=================================================================== +--- lib/MC/MCParser/AsmParser.cpp ++++ lib/MC/MCParser/AsmParser.cpp +@@ -4192,6 +4192,11 @@ bool AsmParser::parseMSInlineAsm( + AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Start, SymName.size())); + } + } ++ ++ // Consider implicit defs to be clobbers. Think of cpuid and push. ++ const uint16_t *ImpDefs = Desc.getImplicitDefs(); ++ for (unsigned I = 0, E = Desc.getNumImplicitDefs(); I != E; ++I) ++ ClobberRegs.push_back(ImpDefs[I]); + } + + // Set the number of Outputs and Inputs. +Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +=================================================================== +--- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp ++++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +@@ -851,12 +851,20 @@ void RegsForValue::AddInlineAsmOperands(unsigned C + SDValue Res = DAG.getTargetConstant(Flag, MVT::i32); + Ops.push_back(Res); + ++ unsigned SP = TLI.getStackPointerRegisterToSaveRestore(); + for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) { + unsigned NumRegs = TLI.getNumRegisters(*DAG.getContext(), ValueVTs[Value]); + MVT RegisterVT = RegVTs[Value]; + for (unsigned i = 0; i != NumRegs; ++i) { + assert(Reg < Regs.size() && "Mismatch in # registers expected"); +- Ops.push_back(DAG.getRegister(Regs[Reg++], RegisterVT)); ++ unsigned TheReg = Regs[Reg++]; ++ Ops.push_back(DAG.getRegister(TheReg, RegisterVT)); ++ ++ // Notice if we clobbered the stack pointer. Yes, inline asm can do this. ++ if (TheReg == SP && Code == InlineAsm::Kind_Clobber) { ++ MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); ++ MFI->setHasInlineAsmWithSPAdjust(true); ++ } + } + } + } +Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +=================================================================== +--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp ++++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +@@ -428,7 +428,9 @@ bool SelectionDAGISel::runOnMachineFunction(Machin + + SDB->init(GFI, *AA, LibInfo); + +- MF->setHasMSInlineAsm(false); ++ MF->setHasInlineAsm(false); ++ MF->getFrameInfo()->setHasInlineAsmWithSPAdjust(false); ++ + SelectAllBasicBlocks(Fn); + + // If the first basic block in the function has live ins that need to be +@@ -511,7 +513,7 @@ bool SelectionDAGISel::runOnMachineFunction(Machin + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; + ++I) { + +- if (MFI->hasCalls() && MF->hasMSInlineAsm()) ++ if (MFI->hasCalls() && MF->hasInlineAsm()) + break; + + const MachineBasicBlock *MBB = I; +@@ -522,8 +524,8 @@ bool SelectionDAGISel::runOnMachineFunction(Machin + II->isStackAligningInlineAsm()) { + MFI->setHasCalls(true); + } +- if (II->isMSInlineAsm()) { +- MF->setHasMSInlineAsm(true); ++ if (II->isInlineAsm()) { ++ MF->setHasInlineAsm(true); + } + } + } diff --git a/contrib/llvm/patches/patch-r263312-llvm-r196940-update-inline-asm-test.diff b/contrib/llvm/patches/patch-r263312-llvm-r196940-update-inline-asm-test.diff new file mode 100644 index 000000000000..6ce56cbf4a5a --- /dev/null +++ b/contrib/llvm/patches/patch-r263312-llvm-r196940-update-inline-asm-test.diff @@ -0,0 +1,78 @@ +Pull in r196940 from upstream clang trunk (by Reid Kleckner): + + Update clang MS inline asm tests for r196939 + +Introduced here: http://svn.freebsd.org/changeset/base/263312 + +Index: tools/clang/test/CodeGen/ms-inline-asm.cpp +=================================================================== +--- tools/clang/test/CodeGen/ms-inline-asm.cpp ++++ tools/clang/test/CodeGen/ms-inline-asm.cpp +@@ -97,7 +97,7 @@ void test5() { + // CHECK: [[Y:%.*]] = alloca i32 + int x, y; + __asm push y +- // CHECK: call void asm sideeffect inteldialect "push dword ptr $0", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* [[Y]]) ++ // CHECK: call void asm sideeffect inteldialect "push dword ptr $0", "=*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* [[Y]]) + __asm call T5::create + // CHECK: call void asm sideeffect inteldialect "call $0", "r,~{dirflag},~{fpsr},~{flags}"(i32 (float)* @_ZN2T5IiE6createIfEEiT_) + __asm mov x, eax +Index: tools/clang/test/CodeGen/ms-inline-asm.c +=================================================================== +--- tools/clang/test/CodeGen/ms-inline-asm.c ++++ tools/clang/test/CodeGen/ms-inline-asm.c +@@ -77,7 +77,7 @@ void t9() { + pop ebx + } + // CHECK: t9 +-// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{dirflag},~{fpsr},~{flags}"() ++// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() + } + + unsigned t10(void) { +@@ -211,7 +211,7 @@ void t21() { + __asm pop ebx + } + // CHECK: t21 +-// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{dirflag},~{fpsr},~{flags}"() ++// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() + } + + extern void t22_helper(int x); +@@ -227,7 +227,7 @@ void t22() { + __asm pop ebx + } + // CHECK: t22 +-// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, esp", "~{ebx},~{dirflag},~{fpsr},~{flags}"() ++// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, esp", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void @t22_helper + // CHECK: call void asm sideeffect inteldialect "mov esp, ebx\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"() + } +@@ -268,13 +268,14 @@ void t26() { + __asm __emit 0a2h + __asm __EMIT 0a2h + __asm popad ++// FIXME: These all need to be merged into the same asm blob. + // CHECK: t26 +-// CHECK: call void asm sideeffect inteldialect "pushad", "~{dirflag},~{fpsr},~{flags}"() ++// CHECK: call void asm sideeffect inteldialect "pushad", "~{esp},~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect "mov eax, $$0", "~{eax},~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect ".byte 0fh", "~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect ".byte 0a2h", "~{dirflag},~{fpsr},~{flags}"() + // CHECK: call void asm sideeffect inteldialect ".byte 0a2h", "~{dirflag},~{fpsr},~{flags}"() +-// CHECK: call void asm sideeffect inteldialect "popad", "~{dirflag},~{fpsr},~{flags}"() ++// CHECK: call void asm sideeffect inteldialect "popad", "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"() + } + + void t27() { +@@ -323,8 +324,8 @@ void t31() { + __asm pushad + __asm popad + // CHECK: t31 +-// CHECK: call void asm sideeffect inteldialect "pushad", "~{dirflag},~{fpsr},~{flags}"() +-// CHECK: call void asm sideeffect inteldialect "popad", "~{dirflag},~{fpsr},~{flags}"() ++// CHECK: call void asm sideeffect inteldialect "pushad", "~{esp},~{dirflag},~{fpsr},~{flags}"() ++// CHECK: call void asm sideeffect inteldialect "popad", "~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"() + } + + void t32() { diff --git a/contrib/llvm/patches/patch-r263312-llvm-r196986-allow-realign-alloca.diff b/contrib/llvm/patches/patch-r263312-llvm-r196986-allow-realign-alloca.diff new file mode 100644 index 000000000000..2c0b75908583 --- /dev/null +++ b/contrib/llvm/patches/patch-r263312-llvm-r196986-allow-realign-alloca.diff @@ -0,0 +1,98 @@ +Pull in r196986 from upstream llvm trunk (by Reid Kleckner): + + Revert the backend fatal error from r196939 + + The combination of inline asm, stack realignment, and dynamic allocas + turns out to be too common to reject out of hand. + + ASan inserts empy inline asm fragments and uses aligned allocas. + Compiling any trivial function containing a dynamic alloca with ASan is + enough to trigger the check. + + XFAIL the test cases that would be miscompiled and add one that uses the + relevant functionality. + +Introduced here: http://svn.freebsd.org/changeset/base/263312 + +Index: lib/Target/X86/X86RegisterInfo.cpp +=================================================================== +--- lib/Target/X86/X86RegisterInfo.cpp ++++ lib/Target/X86/X86RegisterInfo.cpp +@@ -347,12 +347,6 @@ BitVector X86RegisterInfo::getReservedRegs(const M + "Stack realignment in presence of dynamic allocas is not supported with" + "this calling convention."); + +- // FIXME: Do a proper analysis of the inline asm to see if it actually +- // conflicts with the base register we chose. +- if (MF.hasInlineAsm()) +- report_fatal_error("Stack realignment in presence of dynamic stack " +- "adjustments is not supported with inline assembly."); +- + for (MCSubRegIterator I(getBaseRegister(), this, /*IncludeSelf=*/true); + I.isValid(); ++I) + Reserved.set(*I); +Index: test/CodeGen/X86/inline-asm-stack-realign3.ll +=================================================================== +--- test/CodeGen/X86/inline-asm-stack-realign3.ll ++++ test/CodeGen/X86/inline-asm-stack-realign3.ll +@@ -0,0 +1,29 @@ ++; RUN: llc -march=x86 < %s | FileCheck %s ++ ++declare void @bar(i32* %junk) ++ ++define i32 @foo(i1 %cond) { ++entry: ++ %r = alloca i32, align 128 ++ store i32 -1, i32* %r, align 128 ++ br i1 %cond, label %doit, label %skip ++ ++doit: ++ call void asm sideeffect "xor %ecx, %ecx\0A\09mov %ecx, $0", "=*m,~{ecx},~{flags}"(i32* %r) ++ %junk = alloca i32 ++ call void @bar(i32* %junk) ++ br label %skip ++ ++skip: ++ %0 = load i32* %r, align 128 ++ ret i32 %0 ++} ++ ++; CHECK-LABEL: foo: ++; CHECK: pushl %ebp ++; CHECK: andl $-128, %esp ++; CHECK: xor %ecx, %ecx ++; CHECK-NEXT: mov %ecx, (%esi) ++; CHECK: movl (%esi), %eax ++; CHECK: popl %ebp ++; CHECK: ret +Index: test/CodeGen/X86/inline-asm-stack-realign.ll +=================================================================== +--- test/CodeGen/X86/inline-asm-stack-realign.ll ++++ test/CodeGen/X86/inline-asm-stack-realign.ll +@@ -1,8 +1,8 @@ + ; RUN: not llc -mtriple=i686-pc-win32 < %s 2>&1 | FileCheck %s + +-; We don't currently support realigning the stack and adjusting the stack +-; pointer in inline asm. This commonly happens in MS inline assembly using +-; push and pop. ++; FIXME: This is miscompiled due to our unconditional use of ESI as the base ++; pointer. ++; XFAIL: + + ; CHECK: Stack realignment in presence of dynamic stack adjustments is not supported with inline assembly + +Index: test/CodeGen/X86/inline-asm-stack-realign2.ll +=================================================================== +--- test/CodeGen/X86/inline-asm-stack-realign2.ll ++++ test/CodeGen/X86/inline-asm-stack-realign2.ll +@@ -1,7 +1,8 @@ + ; RUN: not llc -mtriple=i686-pc-win32 < %s 2>&1 | FileCheck %s + +-; We don't currently support realigning the stack and adjusting the stack +-; pointer in inline asm. This can even happen in GNU asm. ++; FIXME: This is miscompiled due to our unconditional use of ESI as the base ++; pointer. ++; XFAIL: + + ; CHECK: Stack realignment in presence of dynamic stack adjustments is not supported with inline assembly + diff --git a/contrib/llvm/patches/patch-r263312-llvm-r202930-fix-alloca-esi-clobber.diff b/contrib/llvm/patches/patch-r263312-llvm-r202930-fix-alloca-esi-clobber.diff new file mode 100644 index 000000000000..b4017c967394 --- /dev/null +++ b/contrib/llvm/patches/patch-r263312-llvm-r202930-fix-alloca-esi-clobber.diff @@ -0,0 +1,263 @@ +Pull in r202930 from upstream llvm trunk (by Hans Wennborg): + + Check for dynamic allocas and inline asm that clobbers sp before building + selection dag (PR19012) + + In X86SelectionDagInfo::EmitTargetCodeForMemcpy we check with MachineFrameInfo + to make sure that ESI isn't used as a base pointer register before we choose to + emit rep movs (which clobbers esi). + + The problem is that MachineFrameInfo wouldn't know about dynamic allocas or + inline asm that clobbers the stack pointer until SelectionDAGBuilder has + encountered them. + + This patch fixes the problem by checking for such things when building the + FunctionLoweringInfo. + + Differential Revision: http://llvm-reviews.chandlerc.com/D2954 + +Introduced here: http://svn.freebsd.org/changeset/base/263312 + +Index: lib/CodeGen/MachineFunction.cpp +=================================================================== +--- lib/CodeGen/MachineFunction.cpp ++++ lib/CodeGen/MachineFunction.cpp +@@ -525,13 +525,14 @@ int MachineFrameInfo::CreateSpillStackObject(uint6 + /// variable sized object is created, whether or not the index returned is + /// actually used. + /// +-int MachineFrameInfo::CreateVariableSizedObject(unsigned Alignment) { ++int MachineFrameInfo::CreateVariableSizedObject(unsigned Alignment, ++ const AllocaInst *Alloca) { + HasVarSizedObjects = true; + Alignment = + clampStackAlignment(!getFrameLowering()->isStackRealignable() || + !RealignOption, + Alignment, getFrameLowering()->getStackAlignment()); +- Objects.push_back(StackObject(0, Alignment, 0, false, false, true, 0)); ++ Objects.push_back(StackObject(0, Alignment, 0, false, false, true, Alloca)); + ensureMaxAlignment(Alignment); + return (int)Objects.size()-NumFixedObjects-1; + } +Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +=================================================================== +--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp ++++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +@@ -419,7 +419,7 @@ bool SelectionDAGISel::runOnMachineFunction(Machin + SplitCriticalSideEffectEdges(const_cast(Fn), this); + + CurDAG->init(*MF, TTI, TLI); +- FuncInfo->set(Fn, *MF); ++ FuncInfo->set(Fn, *MF, CurDAG); + + if (UseMBPI && OptLevel != CodeGenOpt::None) + FuncInfo->BPI = &getAnalysis(); +@@ -429,7 +429,6 @@ bool SelectionDAGISel::runOnMachineFunction(Machin + SDB->init(GFI, *AA, LibInfo); + + MF->setHasInlineAsm(false); +- MF->getFrameInfo()->setHasInlineAsmWithSPAdjust(false); + + SelectAllBasicBlocks(Fn); + +Index: lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +=================================================================== +--- lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp ++++ lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +@@ -33,6 +33,7 @@ + #include "llvm/Support/ErrorHandling.h" + #include "llvm/Support/MathExtras.h" + #include "llvm/Target/TargetInstrInfo.h" ++#include "llvm/Target/TargetFrameLowering.h" + #include "llvm/Target/TargetLowering.h" + #include "llvm/Target/TargetOptions.h" + #include "llvm/Target/TargetRegisterInfo.h" +@@ -55,7 +56,8 @@ static bool isUsedOutsideOfDefiningBlock(const Ins + return false; + } + +-void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf) { ++void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, ++ SelectionDAG *DAG) { + const TargetLowering *TLI = TM.getTargetLowering(); + + Fn = &fn; +@@ -100,6 +102,43 @@ static bool isUsedOutsideOfDefiningBlock(const Ins + for (; BB != EB; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { ++ // Look for dynamic allocas. ++ if (const AllocaInst *AI = dyn_cast(I)) { ++ if (!AI->isStaticAlloca()) { ++ unsigned Align = std::max( ++ (unsigned)TLI->getDataLayout()->getPrefTypeAlignment( ++ AI->getAllocatedType()), ++ AI->getAlignment()); ++ unsigned StackAlign = TM.getFrameLowering()->getStackAlignment(); ++ if (Align <= StackAlign) ++ Align = 0; ++ // Inform the Frame Information that we have variable-sized objects. ++ MF->getFrameInfo()->CreateVariableSizedObject(Align ? Align : 1, AI); ++ } ++ } ++ ++ // Look for inline asm that clobbers the SP register. ++ if (isa(I) || isa(I)) { ++ ImmutableCallSite CS(I); ++ if (const InlineAsm *IA = dyn_cast(CS.getCalledValue())) { ++ unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); ++ std::vector Ops = ++ TLI->ParseConstraints(CS); ++ for (size_t I = 0, E = Ops.size(); I != E; ++I) { ++ TargetLowering::AsmOperandInfo &Op = Ops[I]; ++ if (Op.Type == InlineAsm::isClobber) { ++ // Clobbers don't have SDValue operands, hence SDValue(). ++ TLI->ComputeConstraintToUse(Op, SDValue(), DAG); ++ std::pair PhysReg = ++ TLI->getRegForInlineAsmConstraint(Op.ConstraintCode, ++ Op.ConstraintVT); ++ if (PhysReg.first == SP) ++ MF->getFrameInfo()->setHasInlineAsmWithSPAdjust(true); ++ } ++ } ++ } ++ } ++ + // Mark values used outside their block as exported, by allocating + // a virtual register for them. + if (isUsedOutsideOfDefiningBlock(I)) +Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +=================================================================== +--- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp ++++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +@@ -860,10 +860,10 @@ void RegsForValue::AddInlineAsmOperands(unsigned C + unsigned TheReg = Regs[Reg++]; + Ops.push_back(DAG.getRegister(TheReg, RegisterVT)); + +- // Notice if we clobbered the stack pointer. Yes, inline asm can do this. + if (TheReg == SP && Code == InlineAsm::Kind_Clobber) { +- MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); +- MFI->setHasInlineAsmWithSPAdjust(true); ++ // If we clobbered the stack pointer, MFI should know about it. ++ assert(DAG.getMachineFunction().getFrameInfo()-> ++ hasInlineAsmWithSPAdjust()); + } + } + } +@@ -3378,9 +3378,7 @@ void SelectionDAGBuilder::visitAlloca(const Alloca + setValue(&I, DSA); + DAG.setRoot(DSA.getValue(1)); + +- // Inform the Frame Information that we have just allocated a variable-sized +- // object. +- FuncInfo.MF->getFrameInfo()->CreateVariableSizedObject(Align ? Align : 1); ++ assert(FuncInfo.MF->getFrameInfo()->hasVarSizedObjects()); + } + + void SelectionDAGBuilder::visitLoad(const LoadInst &I) { +Index: test/CodeGen/X86/stack-align-memcpy.ll +=================================================================== +--- test/CodeGen/X86/stack-align-memcpy.ll ++++ test/CodeGen/X86/stack-align-memcpy.ll +@@ -2,6 +2,9 @@ + + %struct.foo = type { [88 x i8] } + ++declare void @bar(i8* nocapture, %struct.foo* align 4 byval) nounwind ++declare void @baz(i8*) nounwind ++ + ; PR15249 + ; We can't use rep;movsl here because it clobbers the base pointer in %esi. + define void @test1(%struct.foo* nocapture %x, i32 %y) nounwind { +@@ -15,4 +18,26 @@ define void @test1(%struct.foo* nocapture %x, i32 + ; CHECK-NOT: rep;movsl + } + +-declare void @bar(i8* nocapture, %struct.foo* align 4 byval) nounwind ++; PR19012 ++; Also don't clobber %esi if the dynamic alloca comes after the memcpy. ++define void @test2(%struct.foo* nocapture %x, i32 %y, i8* %z) nounwind { ++ call void @bar(i8* %z, %struct.foo* align 4 byval %x) ++ %dynalloc = alloca i8, i32 %y, align 1 ++ call void @baz(i8* %dynalloc) ++ ret void ++ ++; CHECK-LABEL: test2: ++; CHECK: movl %esp, %esi ++; CHECK-NOT: rep;movsl ++} ++ ++; Check that we do use rep movs if we make the alloca static. ++define void @test3(%struct.foo* nocapture %x, i32 %y, i8* %z) nounwind { ++ call void @bar(i8* %z, %struct.foo* align 4 byval %x) ++ %statalloc = alloca i8, i32 8, align 1 ++ call void @baz(i8* %statalloc) ++ ret void ++ ++; CHECK-LABEL: test3: ++; CHECK: rep;movsl ++} +Index: test/CodeGen/X86/inline-asm-sp-clobber-memcpy.ll +=================================================================== +--- test/CodeGen/X86/inline-asm-sp-clobber-memcpy.ll ++++ test/CodeGen/X86/inline-asm-sp-clobber-memcpy.ll +@@ -0,0 +1,17 @@ ++; RUN: llc < %s -force-align-stack -mtriple i386-apple-darwin -mcpu=i486 | FileCheck %s ++ ++%struct.foo = type { [88 x i8] } ++ ++declare void @bar(i8* nocapture, %struct.foo* align 4 byval) nounwind ++ ++; PR19012 ++; Don't clobber %esi if we have inline asm that clobbers %esp. ++define void @test1(%struct.foo* nocapture %x, i32 %y, i8* %z) nounwind { ++ call void @bar(i8* %z, %struct.foo* align 4 byval %x) ++ call void asm sideeffect inteldialect "xor esp, esp", "=*m,~{flags},~{esp},~{esp},~{dirflag},~{fpsr},~{flags}"(i8* %z) ++ ret void ++ ++; CHECK-LABEL: test1: ++; CHECK: movl %esp, %esi ++; CHECK-NOT: rep;movsl ++} +Index: include/llvm/CodeGen/FunctionLoweringInfo.h +=================================================================== +--- include/llvm/CodeGen/FunctionLoweringInfo.h ++++ include/llvm/CodeGen/FunctionLoweringInfo.h +@@ -41,6 +41,7 @@ class MachineBasicBlock; + class MachineFunction; + class MachineModuleInfo; + class MachineRegisterInfo; ++class SelectionDAG; + class TargetLowering; + class Value; + +@@ -125,7 +126,7 @@ class FunctionLoweringInfo { + /// set - Initialize this FunctionLoweringInfo with the given Function + /// and its associated MachineFunction. + /// +- void set(const Function &Fn, MachineFunction &MF); ++ void set(const Function &Fn, MachineFunction &MF, SelectionDAG *DAG); + + /// clear - Clear out all the function-specific state. This returns this + /// FunctionLoweringInfo to an empty state, ready to be used for a +Index: include/llvm/CodeGen/MachineFrameInfo.h +=================================================================== +--- include/llvm/CodeGen/MachineFrameInfo.h ++++ include/llvm/CodeGen/MachineFrameInfo.h +@@ -244,6 +244,7 @@ class MachineFrameInfo { + LocalFrameSize = 0; + LocalFrameMaxAlign = 0; + UseLocalStackAllocationBlock = false; ++ HasInlineAsmWithSPAdjust = false; + } + + /// hasStackObjects - Return true if there are any stack objects in this +@@ -529,7 +530,7 @@ class MachineFrameInfo { + /// variable sized object is created, whether or not the index returned is + /// actually used. + /// +- int CreateVariableSizedObject(unsigned Alignment); ++ int CreateVariableSizedObject(unsigned Alignment, const AllocaInst *Alloca); + + /// getCalleeSavedInfo - Returns a reference to call saved info vector for the + /// current function. diff --git a/contrib/llvm/patches/patch-r263313-llvm-r203311-fix-sse1-oom.diff b/contrib/llvm/patches/patch-r263313-llvm-r203311-fix-sse1-oom.diff new file mode 100644 index 000000000000..43efd12c87a0 --- /dev/null +++ b/contrib/llvm/patches/patch-r263313-llvm-r203311-fix-sse1-oom.diff @@ -0,0 +1,60 @@ +Pull in r203311 from upstream llvm trunk (by Arnold Schwaighofer): + + ISel: Make VSELECT selection terminate in cases where the condition type has to + be split and the result type widened. + + When the condition of a vselect has to be split it makes no sense widening the + vselect and thereby widening the condition. We end up in an endless loop of + widening (vselect result type) and splitting (condition mask type) doing this. + Instead, split both the condition and the vselect and widen the result. + + I ran this over the test suite with i686 and mattr=+sse and saw no regressions. + + Fixes PR18036. + +Introduced here: http://svn.freebsd.org/changeset/base/263313 + +Index: test/CodeGen/X86/sse1.ll +=================================================================== +--- test/CodeGen/X86/sse1.ll ++++ test/CodeGen/X86/sse1.ll +@@ -43,3 +43,17 @@ entry: + ; CHECK-NOT: shufps $16 + ; CHECK: ret + } ++ ++; We used to get stuck in type legalization for this example when lowering the ++; vselect. With SSE1 v4f32 is a legal type but v4i1 (or any vector integer type) ++; is not. We used to ping pong between splitting the vselect for the v4i ++; condition operand and widening the resulting vselect for the v4f32 result. ++; PR18036 ++ ++; CHECK-LABEL: vselect ++define <4 x float> @vselect(<4 x float>*%p, <4 x i32> %q) { ++entry: ++ %a1 = icmp eq <4 x i32> %q, zeroinitializer ++ %a14 = select <4 x i1> %a1, <4 x float> , <4 x float> zeroinitializer ++ ret <4 x float> %a14 ++} +Index: lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +=================================================================== +--- lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp ++++ lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +@@ -2180,6 +2180,17 @@ SDValue DAGTypeLegalizer::WidenVecRes_SELECT(SDNod + if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector) + Cond1 = GetWidenedVector(Cond1); + ++ // If we have to split the condition there is no point in widening the ++ // select. This would result in an cycle of widening the select -> ++ // widening the condition operand -> splitting the condition operand -> ++ // splitting the select -> widening the select. Instead split this select ++ // further and widen the resulting type. ++ if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) { ++ SDValue SplitSelect = SplitVecOp_VSELECT(N, 0); ++ SDValue Res = ModifyToType(SplitSelect, WidenVT); ++ return Res; ++ } ++ + if (Cond1.getValueType() != CondWidenVT) + Cond1 = ModifyToType(Cond1, CondWidenVT); + }