Index: CMakeLists.txt =================================================================== --- CMakeLists.txt (revision 311547) +++ CMakeLists.txt (working copy) @@ -182,11 +182,12 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") set (LIBXML2_FOUND 0) -find_package(LibXml2 2.5.3 QUIET) -if (LIBXML2_FOUND) - set(CLANG_HAVE_LIBXML 1) -endif() - +# RICH: This finds the host library. +#find_package(LibXml2 2.5.3 QUIET) +#if (LIBXML2_FOUND) +# set(CLANG_HAVE_LIBXML 1) +#endif() + find_package(Z3 4.5) include(CheckIncludeFile) Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td (revision 311547) +++ include/clang/Basic/DiagnosticDriverKinds.td (working copy) @@ -108,6 +108,13 @@ def err_drv_malformed_sanitizer_blacklist : Error< "malformed sanitizer blacklist: '%0'">; +def err_drv_malformed_compilation_info : Error< + "malformed compilation info file: '%0'">; +def err_drv_invalid_based_on : Error< + "can't find compilation info for based_on value: '%0'">; +def err_drv_compilation_info_nesting : Error< + "too many based_on nesting levels (%0) for compilation info: '%1'">; + def err_target_unsupported_arch : Error<"the target architecture '%0' is not supported by the target '%1'">; def err_cpu_unsupported_isa Index: include/clang/Driver/Driver.h =================================================================== --- include/clang/Driver/Driver.h (revision 311547) +++ include/clang/Driver/Driver.h (working copy) @@ -17,6 +17,7 @@ #include "clang/Driver/ToolChain.h" #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" +#include "clang/Driver/ToolInfo.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -119,6 +120,9 @@ // FIXME: Privatize once interface is stable. public: + /// Tool Information. + std::unique_ptr Info; + /// The name the driver was invoked as. std::string Name; @@ -179,6 +183,9 @@ /// Whether the driver should follow cl.exe like behavior. bool IsCLMode() const { return Mode == CLMode; } + /// Whether the driver is ELLCC. + unsigned CCCIsELLCC : 1; + /// Only print tool bindings, don't build any jobs. unsigned CCCPrintBindings : 1; @@ -302,6 +309,7 @@ InstalledDir = Value; } + void setResourceDir(); bool isSaveTempsEnabled() const { return SaveTemps != SaveTempsNone; } bool isSaveTempsObj() const { return SaveTemps == SaveTempsObj; } Index: include/clang/Driver/ToolChain.h =================================================================== --- include/clang/Driver/ToolChain.h (revision 311547) +++ include/clang/Driver/ToolChain.h (working copy) @@ -58,7 +58,7 @@ enum RuntimeLibType { RLT_CompilerRT, - RLT_Libgcc + RLT_Libgcc, }; enum RTTIMode { @@ -199,7 +199,7 @@ /// e.g., argv[0]) /// \return A pair of (`target`, `mode-flag`), where one or both may be empty. static std::pair - getTargetAndModeFromProgramName(StringRef ProgName); + getTargetAndModeFromProgramName(StringRef ProgName, bool& isELLCC); // Tool access. Index: include/clang/Tooling/Tooling.h =================================================================== --- include/clang/Tooling/Tooling.h (revision 311547) +++ include/clang/Tooling/Tooling.h (working copy) @@ -451,7 +451,7 @@ /// infrastructure expects that CommandLine[0] is a tool path relative to which /// the builtin headers can be found. void addTargetAndModeForProgramName(std::vector &CommandLine, - StringRef InvokedAs); + StringRef InvokedAs, bool& isELLCC); /// \brief Creates a \c CompilerInvocation. clang::CompilerInvocation *newInvocation( Index: lib/Basic/Targets/ARM.cpp =================================================================== --- lib/Basic/Targets/ARM.cpp (revision 311547) +++ lib/Basic/Targets/ARM.cpp (working copy) @@ -99,6 +99,10 @@ else SizeType = UnsignedLong; + // size_t is unsigned int on ELLCC. + if (T.getVendor() == llvm::Triple::ELLCC) + SizeType = UnsignedInt; + // Revert to using SignedInt on apcs-gnu to comply with existing behaviour. WCharType = SignedInt; Index: lib/Basic/Targets/PPC.h =================================================================== --- lib/Basic/Targets/PPC.h (revision 311547) +++ lib/Basic/Targets/PPC.h (working copy) @@ -277,6 +277,12 @@ LongDoubleFormat = &llvm::APFloat::IEEEdouble(); } + if (getTriple().getVendor() == llvm::Triple::ELLCC) { + LongDoubleWidth = LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + WCharType = SignedLong; + } + // PPC32 supports atomics up to 4 bytes. MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; } @@ -305,6 +311,11 @@ ABI = "elfv1"; } + if (getTriple().getVendor() == llvm::Triple::ELLCC) { + LongDoubleWidth = LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } + switch (getTriple().getOS()) { case llvm::Triple::FreeBSD: LongDoubleWidth = LongDoubleAlign = 64; Index: lib/Basic/Version.cpp =================================================================== --- lib/Basic/Version.cpp (revision 311547) +++ lib/Basic/Version.cpp (working copy) @@ -22,6 +22,12 @@ # include "SVNVersion.inc" #endif +#if defined(__has_include) +#if __has_include("ELLCCVersion.h") +# include "ELLCCVersion.h" +#endif +#endif + namespace clang { std::string getClangRepositoryPath() { @@ -122,16 +128,26 @@ std::string getClangToolFullVersion(StringRef ToolName) { std::string buf; llvm::raw_string_ostream OS(buf); +#if defined(ELLCC_REVISION) + if (ToolName == "clang") { + OS << "ecc version " << ELLCC_REVISION << " (http://ellcc.org) based on "; + } +#else #ifdef CLANG_VENDOR OS << CLANG_VENDOR; #endif +#endif OS << ToolName << " version " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion(); +#if defined(ELLCC_REVISION) + // The ELLCC backend version is the same as the clang version above. +#else // If vendor supplied, include the base LLVM version as well. #ifdef CLANG_VENDOR OS << " (based on " << BACKEND_PACKAGE_STRING << ")"; #endif +#endif return OS.str(); } Index: lib/Driver/CMakeLists.txt =================================================================== --- lib/Driver/CMakeLists.txt (revision 311547) +++ lib/Driver/CMakeLists.txt (working copy) @@ -21,6 +21,7 @@ SanitizerArgs.cpp Tool.cpp ToolChain.cpp + ToolInfo.cpp ToolChains/Arch/AArch64.cpp ToolChains/Arch/ARM.cpp ToolChains/Arch/Mips.cpp @@ -40,6 +41,7 @@ ToolChains/Cuda.cpp ToolChains/Darwin.cpp ToolChains/DragonFly.cpp + ToolChains/ELLCC.cpp ToolChains/FreeBSD.cpp ToolChains/Fuchsia.cpp ToolChains/Gnu.cpp Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp (revision 311547) +++ lib/Driver/Driver.cpp (working copy) @@ -19,6 +19,7 @@ #include "ToolChains/Cuda.h" #include "ToolChains/Darwin.h" #include "ToolChains/DragonFly.h" +#include "ToolChains/ELLCC.h" #include "ToolChains/FreeBSD.h" #include "ToolChains/Fuchsia.h" #include "ToolChains/Gnu.h" @@ -88,8 +89,9 @@ Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None), ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), - DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr), + DriverTitle("ecc clang LLVM compiler"), CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr), + CCCIsELLCC(false), CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), DefaultTargetTriple(DefaultTargetTriple), CCCGenericGCCName(""), CheckInputsExist(true), CCCUsePCH(true), @@ -103,6 +105,11 @@ Dir = llvm::sys::path::parent_path(ClangExecutable); InstalledDir = Dir; // Provide a sensible default installed dir. + // Set the resource directory. + setResourceDir(); +} + +void Driver::setResourceDir() { // Compute the path to the resource directory. StringRef ClangResourceDir(CLANG_RESOURCE_DIR); SmallString<128> P(Dir); @@ -109,10 +116,14 @@ if (ClangResourceDir != "") { llvm::sys::path::append(P, ClangResourceDir); } else { - StringRef ClangLibdirSuffix(CLANG_LIBDIR_SUFFIX); P = llvm::sys::path::parent_path(Dir); - llvm::sys::path::append(P, Twine("lib") + ClangLibdirSuffix, "clang", - CLANG_VERSION_STRING); + if (CCCIsELLCC) { + llvm::sys::path::append(P, "libecc"); + } else { + StringRef ClangLibdirSuffix(CLANG_LIBDIR_SUFFIX); + llvm::sys::path::append(P, Twine("lib") + ClangLibdirSuffix, "clang", + CLANG_VERSION_STRING); + } } ResourceDir = P.str(); } @@ -119,7 +130,9 @@ void Driver::ParseDriverMode(StringRef ProgramName, ArrayRef Args) { - auto Default = ToolChain::getTargetAndModeFromProgramName(ProgramName); + bool isELLCC; + auto Default = ToolChain::getTargetAndModeFromProgramName(ProgramName, + isELLCC); StringRef DefaultMode(Default.second); setDriverModeFromOption(DefaultMode); @@ -717,6 +730,18 @@ const ToolChain &TC = getToolChain( *UArgs, computeTargetTriple(*this, DefaultTargetTriple, *UArgs)); + llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple)); + if (Target.getVendor() == llvm::Triple::ELLCC && Info == NULL) { + // Need to get compilation info. + std::string target = (Target.getArchName() + "-ellcc-" + + Target.getOSName()).str(); + toolinfo::ToolInfo::CheckForAndReadInfo(target.c_str(), *this); + if (Info) { + // Expand the compiler information + Info->compiler.Expand(*this); + } + } + // The compilation takes ownership of Args. Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs, ContainsError); @@ -3796,6 +3821,10 @@ const llvm::Triple &Target) const { auto &TC = ToolChains[Target.str()]; + + if (Target.getVendor() == llvm::Triple::ELLCC) + TC = llvm::make_unique(*this, Target, Args); + if (!TC) { switch (Target.getOS()) { case llvm::Triple::Haiku: Index: lib/Driver/ToolChain.cpp =================================================================== --- lib/Driver/ToolChain.cpp (revision 311547) +++ lib/Driver/ToolChain.cpp (working copy) @@ -111,6 +111,7 @@ struct DriverSuffix { const char *Suffix; const char *ModeFlag; + bool IsELLCC; }; const DriverSuffix *FindDriverSuffix(StringRef ProgName) { @@ -118,18 +119,20 @@ // program name in order. If there is a match, the frontend type is updated as // necessary by applying the ModeFlag. static const DriverSuffix DriverSuffixes[] = { - {"clang", nullptr}, - {"clang++", "--driver-mode=g++"}, - {"clang-c++", "--driver-mode=g++"}, - {"clang-cc", nullptr}, - {"clang-cpp", "--driver-mode=cpp"}, - {"clang-g++", "--driver-mode=g++"}, - {"clang-gcc", nullptr}, - {"clang-cl", "--driver-mode=cl"}, - {"cc", nullptr}, - {"cpp", "--driver-mode=cpp"}, - {"cl", "--driver-mode=cl"}, - {"++", "--driver-mode=g++"}, + {"clang", nullptr, false}, + {"clang++", "--driver-mode=g++", false}, + {"clang-c++", "--driver-mode=g++", false}, + {"clang-cc", nullptr, false}, + {"clang-cpp", "--driver-mode=cpp", false}, + {"clang-g++", "--driver-mode=g++", false}, + {"clang-gcc", nullptr, false}, + {"clang-cl", "--driver-mode=cl", false}, + { "ecc", nullptr, true }, + { "ecc++", "--driver-mode=g++", true }, + {"cc", nullptr, false}, + {"cpp", "--driver-mode=cpp", false}, + {"cl", "--driver-mode=cl", false}, + {"++", "--driver-mode=g++", false}, }; for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) @@ -149,7 +152,7 @@ return ProgName; } -const DriverSuffix *parseDriverSuffix(StringRef ProgName) { +const DriverSuffix *parseDriverSuffix(StringRef ProgName, bool& isELLCC) { // Try to infer frontend type and default target from the program name by // comparing it against DriverSuffixes in order. @@ -172,14 +175,18 @@ ProgName = ProgName.slice(0, ProgName.rfind('-')); DS = FindDriverSuffix(ProgName); } + + if (DS) { + isELLCC = DS->IsELLCC; + } return DS; } } // anonymous namespace std::pair -ToolChain::getTargetAndModeFromProgramName(StringRef PN) { +ToolChain::getTargetAndModeFromProgramName(StringRef PN, bool& isELLCC) { std::string ProgName = normalizeProgramName(PN); - const DriverSuffix *DS = parseDriverSuffix(ProgName); + const DriverSuffix *DS = parseDriverSuffix(ProgName, isELLCC); if (!DS) return std::make_pair("", ""); std::string ModeFlag = DS->ModeFlag == nullptr ? "" : DS->ModeFlag; @@ -194,7 +201,7 @@ Prefix = Prefix.slice(0, LastComponent); std::string IgnoredError; std::string Target; - if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { + if (isELLCC || llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { Target = Prefix; } return std::make_pair(Target, ModeFlag); Index: lib/Frontend/InitHeaderSearch.cpp =================================================================== --- lib/Frontend/InitHeaderSearch.cpp (revision 311547) +++ lib/Frontend/InitHeaderSearch.cpp (working copy) @@ -438,6 +438,12 @@ // driver which has the information necessary to do target-specific // selections of default include paths. Each target which moves there will be // exempted from this logic here until we can delete the entire pile of code. + + // ELLCC's include paths are supplied by the driver. + if (triple.getVendor() == llvm::Triple::ELLCC) { + return; + } + switch (triple.getOS()) { default: break; // Everything else continues to use this routine's logic. Index: lib/Frontend/InitPreprocessor.cpp =================================================================== --- lib/Frontend/InitPreprocessor.cpp (revision 311547) +++ lib/Frontend/InitPreprocessor.cpp (working copy) @@ -961,6 +961,10 @@ if (LangOpts.FastRelaxedMath) Builder.defineMacro("__FAST_RELAXED_MATH__"); + // ELLCC is a cross development environment. + if (TI.getTriple().getVendor() == llvm::Triple::ELLCC) + Builder.defineMacro("__ELLCC__"); + if (FEOpts.ProgramAction == frontend::RewriteObjC || LangOpts.getGC() != LangOptions::NonGC) { Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))"); Index: lib/Tooling/Tooling.cpp =================================================================== --- lib/Tooling/Tooling.cpp (revision 311547) +++ lib/Tooling/Tooling.cpp (working copy) @@ -175,7 +175,7 @@ } void addTargetAndModeForProgramName(std::vector &CommandLine, - StringRef InvokedAs) { + StringRef InvokedAs, bool& isELLCC) { if (!CommandLine.empty() && !InvokedAs.empty()) { bool AlreadyHasTarget = false; bool AlreadyHasMode = false; @@ -189,7 +189,8 @@ TokenRef.startswith("--driver-mode=")); } auto TargetMode = - clang::driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs); + clang::driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs, + isELLCC); if (!AlreadyHasMode && !TargetMode.second.empty()) { CommandLine.insert(++CommandLine.begin(), TargetMode.second); } Index: tools/c-arcmt-test/CMakeLists.txt =================================================================== --- tools/c-arcmt-test/CMakeLists.txt (revision 311547) +++ tools/c-arcmt-test/CMakeLists.txt (working copy) @@ -4,7 +4,7 @@ if (LLVM_BUILD_STATIC) target_link_libraries(c-arcmt-test - libclang_static + libclang ) else() target_link_libraries(c-arcmt-test Index: tools/c-index-test/CMakeLists.txt =================================================================== --- tools/c-index-test/CMakeLists.txt (revision 311547) +++ tools/c-index-test/CMakeLists.txt (working copy) @@ -16,7 +16,7 @@ if (LLVM_BUILD_STATIC) target_link_libraries(c-index-test - libclang_static + libclang clangCodeGen clangIndex ) Index: tools/driver/driver.cpp =================================================================== --- tools/driver/driver.cpp (revision 311547) +++ tools/driver/driver.cpp (working copy) @@ -17,6 +17,7 @@ #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" +#include "clang/Driver/ToolInfo.h" #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ChainedDiagnosticConsumer.h" #include "clang/Frontend/CompilerInvocation.h" @@ -208,7 +209,8 @@ static void insertTargetAndModeArgs(StringRef Target, StringRef Mode, SmallVectorImpl &ArgVector, - std::set &SavedStrings) { + std::set &SavedStrings, + Driver& TheDriver) { if (!Mode.empty()) { // Add the mode flag to the arguments. auto it = ArgVector.begin(); @@ -217,6 +219,13 @@ ArgVector.insert(it, GetStableCStr(SavedStrings, Mode)); } +#if defined(ELLCC_ARG0) + // Building and running ecc. Set the default target. + if (TheDriver.CCCIsELLCC && Target.empty()) { + Target = ELLCC_ARG0; + } +#endif + if (!Target.empty()) { auto it = ArgVector.begin(); if (it != ArgVector.end()) @@ -224,6 +233,42 @@ const char *arr[] = {"-target", GetStableCStr(SavedStrings, Target)}; ArgVector.insert(it, std::begin(arr), std::end(arr)); } + + // Check for and process the last -target option which specifies a config + // file. + auto it = ArgVector.begin(); + auto ie = ArgVector.end(); + auto target = ie; + for ( ; it != ie; ++it) { + // Skip end-of-line response file markers + if (*it == nullptr) + continue; + + if (strcmp(*it, "-target") == 0) { + // Remember the last one. + target = it; + } + } + + if (target == ie || target + 1 == ie) { + // No -target or no argument to -target. + return; + } + + auto ib = target; + ++target; + if (clang::toolinfo::ToolInfo::CheckForAndReadInfo(*target, TheDriver)) { + // Remove the -target and its argument. + ArgVector.erase(ib, ++target); + // Process the compiler options immediately. + TheDriver.Info->compiler.Expand(TheDriver); + for (size_t i = 0; i < TheDriver.Info->compiler.options.size(); ++i) { + const char *opt = GetStableCStr(SavedStrings, + TheDriver.Info->compiler.options[i]); + ArgVector.insert(ib, GetStableCStr(SavedStrings, opt)); + ++ib; + } + } } static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver, @@ -331,8 +376,9 @@ llvm::InitializeAllTargets(); std::string ProgName = argv[0]; + bool isELLCC; std::pair TargetAndMode = - ToolChain::getTargetAndModeFromProgramName(ProgName); + ToolChain::getTargetAndModeFromProgramName(ProgName, isELLCC); llvm::BumpPtrAllocator A; llvm::StringSaver Saver(A); @@ -454,9 +500,14 @@ Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags); SetInstallDir(argv, TheDriver, CanonicalPrefixes); + TheDriver.CCCIsELLCC = isELLCC; + if (isELLCC) { + // Set the ResourceDir correctly for ELLCC. + TheDriver.setResourceDir(); + } insertTargetAndModeArgs(TargetAndMode.first, TargetAndMode.second, argv, - SavedStrings); + SavedStrings, TheDriver); SetBackdoorDriverOutputsFromEnvVars(TheDriver); Index: unittests/Tooling/ToolingTest.cpp =================================================================== --- unittests/Tooling/ToolingTest.cpp (revision 311547) +++ unittests/Tooling/ToolingTest.cpp (working copy) @@ -426,9 +426,10 @@ ASSERT_FALSE(Target.empty()); std::vector Args = {"clang", "-foo"}; - addTargetAndModeForProgramName(Args, ""); + bool isELLCC; + addTargetAndModeForProgramName(Args, "", isELLCC); EXPECT_EQ((std::vector{"clang", "-foo"}), Args); - addTargetAndModeForProgramName(Args, Target + "-g++"); + addTargetAndModeForProgramName(Args, Target + "-g++", isELLCC); EXPECT_EQ((std::vector{"clang", "-target", Target, "--driver-mode=g++", "-foo"}), Args); @@ -442,7 +443,8 @@ llvm::sys::path::append(ToolPath, "foo", "bar", Target + "-g++"); std::vector Args = {"clang", "-foo"}; - addTargetAndModeForProgramName(Args, ToolPath); + bool isELLCC; + addTargetAndModeForProgramName(Args, ToolPath, isELLCC); EXPECT_EQ((std::vector{"clang", "-target", Target, "--driver-mode=g++", "-foo"}), Args); @@ -453,13 +455,14 @@ ASSERT_FALSE(Target.empty()); std::vector Args = {"clang", "-foo", "-target", "something"}; - addTargetAndModeForProgramName(Args, Target + "-g++"); + bool isELLCC; + addTargetAndModeForProgramName(Args, Target + "-g++", isELLCC); EXPECT_EQ((std::vector{"clang", "--driver-mode=g++", "-foo", "-target", "something"}), Args); std::vector ArgsAlt = {"clang", "-foo", "-target=something"}; - addTargetAndModeForProgramName(ArgsAlt, Target + "-g++"); + addTargetAndModeForProgramName(ArgsAlt, Target + "-g++", isELLCC); EXPECT_EQ((std::vector{"clang", "--driver-mode=g++", "-foo", "-target=something"}), ArgsAlt); @@ -470,13 +473,14 @@ ASSERT_FALSE(Target.empty()); std::vector Args = {"clang", "-foo", "--driver-mode=abc"}; - addTargetAndModeForProgramName(Args, Target + "-g++"); + bool isELLCC; + addTargetAndModeForProgramName(Args, Target + "-g++", isELLCC); EXPECT_EQ((std::vector{"clang", "-target", Target, "-foo", "--driver-mode=abc"}), Args); std::vector ArgsAlt = {"clang", "-foo", "--driver-mode", "abc"}; - addTargetAndModeForProgramName(ArgsAlt, Target + "-g++"); + addTargetAndModeForProgramName(ArgsAlt, Target + "-g++", isELLCC); EXPECT_EQ((std::vector{"clang", "-target", Target, "-foo", "--driver-mode", "abc"}), ArgsAlt);