diff --git a/.gitignore b/.gitignore index fc842489a0..aed34187bc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ # See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html # # This file is intentionally different from the output of `git svn show-ignore`, -# as most of those are useless. +# as most of those are useless. #==============================================================================# #==============================================================================# @@ -35,3 +35,5 @@ docs/_build docs/analyzer/_build # debug info testsuite test/debuginfo-tests + +build \ No newline at end of file diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 9ace002b62..214bbe52d0 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -482,7 +482,8 @@ class ToolChain { /// AddFortranStdlibLibArgs - Add the system specific linker arguments to use /// for the given Fortran runtime library type. virtual void AddFortranStdlibLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const; + llvm::opt::ArgStringList &CmdArgs, + bool AddMLinker=false) const; /// \brief Return sanitizers which are available in this toolchain. virtual SanitizerMask getSupportedSanitizers() const; diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 283a8823d0..f4c93438dd 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -216,8 +216,13 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, Arg *PhaseArg = nullptr; phases::ID FinalPhase; + /* + Note: when passed '-E' and in fortran mode, we do not use the builtin + preprocessor. + */ // -{E,EP,P,M,MM} only run the preprocessor. - if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) || + if (CCCIsCPP() || (!IsFortranMode() && + (PhaseArg = DAL.getLastArg(options::OPT_E))) || (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) || (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) || (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) { @@ -2764,7 +2769,8 @@ Action *Driver::ConstructPhaseAction(Compilation &C, const ArgList &Args, return C.MakeAction(Input, OutputTy); } case phases::FortranFrontend: { - if (Args.hasArg(options::OPT_fsyntax_only)) + if (Args.hasArg(options::OPT_fsyntax_only) || + Args.hasArg(options::OPT_E)) return C.MakeAction(Input, types::TY_Nothing); return C.MakeAction(Input, diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index cd32ba7c75..522ffbca90 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -687,7 +687,8 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args, } void ToolChain::AddFortranStdlibLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { + ArgStringList &CmdArgs, + bool AddMLinker) const { bool staticFlangLibs = false; bool useOpenMP = false; diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index fe22b76556..969656b364 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -67,7 +67,7 @@ bool tools::needFortranLibs(const Driver &D, const ArgList &Args) { } /// \brief Determine if Fortran "main" object is needed -static bool needFortranMain(const Driver &D, const ArgList &Args) { +bool tools::needFortranMain(const Driver &D, const ArgList &Args) { return (needFortranLibs(D, Args) && (!Args.hasArg(options::OPT_Mnomain) || !Args.hasArg(options::OPT_no_fortran_main))); diff --git a/lib/Driver/ToolChains/CommonArgs.h b/lib/Driver/ToolChains/CommonArgs.h index 70ac75b2de..8bfdf162b9 100644 --- a/lib/Driver/ToolChains/CommonArgs.h +++ b/lib/Driver/ToolChains/CommonArgs.h @@ -22,6 +22,8 @@ namespace tools { bool needFortranLibs(const Driver &D, const llvm::opt::ArgList &Args); +bool needFortranMain(const Driver &D, const llvm::opt::ArgList &Args); + void addPathIfExists(const Driver &D, const Twine &Path, ToolChain::path_list &Paths); diff --git a/lib/Driver/ToolChains/Flang.cpp b/lib/Driver/ToolChains/Flang.cpp index 98572e0317..f05e49ce03 100644 --- a/lib/Driver/ToolChains/Flang.cpp +++ b/lib/Driver/ToolChains/Flang.cpp @@ -57,7 +57,8 @@ void FlangFrontend::ConstructJob(Compilation &C, const JobAction &JA, // Check file type sanity assert(types::isFortran(InputType) && "Can only accept Fortran"); - if (Args.hasArg(options::OPT_fsyntax_only)) { + if (Args.hasArg(options::OPT_fsyntax_only) || + Args.hasArg(options::OPT_E)) { // For -fsyntax-only produce temp files only Stem = C.getDriver().GetTemporaryPath("", ""); } else { @@ -577,20 +578,37 @@ void FlangFrontend::ConstructJob(Compilation &C, const JobAction &JA, // Add system include arguments. getToolChain().AddFlangSystemIncludeArgs(Args, UpperCmdArgs); + + bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment(); + if (!IsWindowsMSVC) { UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("unix"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__unix"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__unix__"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("linux"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__linux"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__linux__"); - UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__NO_MATH_INLINES"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__LP64__"); - UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__x86_64"); - UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__x86_64__"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__LONG_MAX__=9223372036854775807L"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__SIZE_TYPE__=unsigned long int"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__PTRDIFF_TYPE__=long int"); + } else { + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__LONG_MAX__=2147483647L"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__SIZE_TYPE__=unsigned long long int"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__PTRDIFF_TYPE__=long long int"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("_WIN32"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("WIN32"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("_WIN64"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("WIN64"); + VersionTuple MSVT = + getToolChain().computeMSVCVersion(&getToolChain().getDriver(), Args); + auto msc_ver = MSVT.getMajor() * 100 + MSVT.getMinor().getValueOr(0); + UpperCmdArgs.push_back("-def"); + UpperCmdArgs.push_back(Args.MakeArgString(std::string("_MSC_VER=")+std::to_string(msc_ver))); + } + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__NO_MATH_INLINES"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__x86_64"); + UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__x86_64__"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__THROW="); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__extension__="); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__amd_64__amd64__"); @@ -598,12 +616,21 @@ void FlangFrontend::ConstructJob(Compilation &C, const JobAction &JA, UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__k8__"); UpperCmdArgs.push_back("-def"); UpperCmdArgs.push_back("__PGLLVM__"); + /* + When the -E option is given, run flang1 in preprocessor only mode + */ + if (Args.hasArg(options::OPT_E)) { + UpperCmdArgs.push_back("-es"); + } + // Enable preprocessor - if (Args.hasArg(options::OPT_Mpreprocess) || + if (Args.hasArg(options::OPT_E) || + Args.hasArg(options::OPT_Mpreprocess) || Args.hasArg(options::OPT_cpp) || types::getPreprocessedType(InputType) != types::TY_INVALID) { UpperCmdArgs.push_back("-preprocess"); - for (auto Arg : Args.filtered(options::OPT_Mpreprocess, options::OPT_cpp)) { + for (auto Arg : Args.filtered(options::OPT_E, options::OPT_Mpreprocess, + options::OPT_cpp)) { Arg->claim(); } } @@ -681,6 +708,10 @@ void FlangFrontend::ConstructJob(Compilation &C, const JobAction &JA, UpperCmdArgs.push_back(Arg->getValue(0)); } + // Add env variables + addDirectoryList(Args, UpperCmdArgs, "-idir", "C_INCLUDE_PATH"); + addDirectoryList(Args, UpperCmdArgs, "-idir", "CPATH"); + // "Define" preprocessor flags for (auto Arg : Args.filtered(options::OPT_D)) { Arg->claim(); @@ -743,13 +774,20 @@ void FlangFrontend::ConstructJob(Compilation &C, const JobAction &JA, UpperCmdArgs.push_back("-modindex"); UpperCmdArgs.push_back(ModuleIndexFile); - UpperCmdArgs.push_back("-output"); - UpperCmdArgs.push_back(ILMFile); - + if (Args.hasArg(options::OPT_E)) { + if (Arg *A = Args.getLastArg(options::OPT_o)) { + UpperCmdArgs.push_back("-output"); + UpperCmdArgs.push_back(Args.MakeArgString(A->getValue())); + } + } else { + UpperCmdArgs.push_back("-output"); + UpperCmdArgs.push_back(ILMFile); + } C.addCommand(llvm::make_unique(JA, *this, UpperExec, UpperCmdArgs, Inputs)); - // For -fsyntax-only that is it - if (Args.hasArg(options::OPT_fsyntax_only)) return; + // For -fsyntax-only or -E that is it + if (Args.hasArg(options::OPT_fsyntax_only) || + Args.hasArg(options::OPT_E)) return; /***** Lower part of Fortran frontend *****/ @@ -851,6 +889,25 @@ void FlangFrontend::ConstructJob(Compilation &C, const JobAction &JA, LowerCmdArgs.push_back(STBFile); LowerCmdArgs.push_back("-asm"); LowerCmdArgs.push_back(Args.MakeArgString(OutFile)); + + const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); + const std::string &TripleStr = Triple.getTriple(); + LowerCmdArgs.push_back("-target"); + LowerCmdArgs.push_back(Args.MakeArgString(TripleStr)); + + if (IsWindowsMSVC && !Args.hasArg(options::OPT_noFlangLibs)) { + getToolChain().AddFortranStdlibLibArgs(Args, LowerCmdArgs, true); + if (needFortranMain(getToolChain().getDriver(), Args)) { + LowerCmdArgs.push_back("-linker"); + LowerCmdArgs.push_back("/subsystem:console"); + LowerCmdArgs.push_back("-linker"); + LowerCmdArgs.push_back("/defaultlib:flangmain"); + } + } + + for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) { + Arg->claim(); + } C.addCommand(llvm::make_unique(JA, *this, LowerExec, LowerCmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp index 7978a6941c..0e5c08b67c 100644 --- a/lib/Driver/ToolChains/MSVC.cpp +++ b/lib/Driver/ToolChains/MSVC.cpp @@ -325,9 +325,13 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back( Args.MakeArgString(std::string("-out:") + Output.getFilename())); - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) && - !C.getDriver().IsCLMode()) - CmdArgs.push_back("-defaultlib:libcmt"); + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + if (C.getDriver().IsFortranMode()) { + CmdArgs.push_back("-defaultlib:msvcrt"); + } else if (!C.getDriver().IsCLMode() && !C.getDriver().IsFortranMode()) { + CmdArgs.push_back("-defaultlib:libcmt"); + } + } if (!llvm::sys::Process::GetEnv("LIB")) { // If the VC environment hasn't been configured (perhaps because the user @@ -372,6 +376,16 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName)); } + // Add Fortran runtime libraries + if (needFortranLibs(TC.getDriver(), Args)) { + TC.AddFortranStdlibLibArgs(Args, CmdArgs); + } else { + // Claim "no Flang libraries" arguments if any + for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) { + Arg->claim(); + } + } + if (TC.getSanitizerArgs().needsAsanRt()) { CmdArgs.push_back(Args.MakeArgString("-debug")); CmdArgs.push_back(Args.MakeArgString("-incremental:no")); @@ -1255,6 +1269,79 @@ void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, // FIXME: There should probably be logic here to find libc++ on Windows. } +void MSVCToolChain::addLinkerHelper(const ArgList &Args, + ArgStringList &CmdArgs, + bool IsLinker, + StringRef Arg) const { + if (IsLinker) { + CmdArgs.push_back("-linker"); + CmdArgs.push_back(Args.MakeArgString(Arg)); + } else { + CmdArgs.push_back(Args.MakeArgString(Arg)); + } +} + +void MSVCToolChain::AddFortranStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs, + bool AddMLinker) const { + bool staticFlangLibs = false; + bool useOpenMP = false; + + const auto &D = getDriver(); + + if (Args.hasArg(options::OPT_staticFlangLibs)) { + for (auto *A: Args.filtered(options::OPT_staticFlangLibs)) { + A->claim(); + staticFlangLibs = true; + } + } + + Arg *A = Args.getLastArg(options::OPT_mp, options::OPT_nomp, + options::OPT_fopenmp, options::OPT_fno_openmp); + if (A && + (A->getOption().matches(options::OPT_mp) || + A->getOption().matches(options::OPT_fopenmp))) { + useOpenMP = true; + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + if (getDriver().IsFortranMode()) { + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:msvcrt"); + } else if (!getDriver().IsCLMode() && !getDriver().IsFortranMode()) { + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:libcmt"); + } + } + + if (!AddMLinker) { + CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + + D.Dir + "/../lib")); + } + + if (needFortranMain(D, Args)) { + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:flangmain"); + addLinkerHelper(Args, CmdArgs, AddMLinker, "/subsystem:console"); + } + + if (staticFlangLibs) { + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:libflang"); + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:libflangrti"); + if (!useOpenMP) { + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:libompstub"); + } else { + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:libomp"); + } + } + else { + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:flang"); + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:flangrti"); + if (!useOpenMP) { + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:ompstub"); + } else { + addLinkerHelper(Args, CmdArgs, AddMLinker, "/defaultlib:omp"); + } + } +} + VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, const ArgList &Args) const { bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment(); diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h index 854f88a36f..ce887af204 100644 --- a/lib/Driver/ToolChains/MSVC.h +++ b/lib/Driver/ToolChains/MSVC.h @@ -106,6 +106,10 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain { const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + void AddFortranStdlibLibArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + bool AddMLinker=false) const override; + void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; @@ -134,6 +138,11 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain { Tool *buildLinker() const override; Tool *buildAssembler() const override; private: + void addLinkerHelper(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, + bool IsLinker, + StringRef Arg) const; + std::string VCToolChainPath; ToolsetLayout VSLayout = ToolsetLayout::OlderVS; CudaInstallationDetector CudaInstallation;