This is a re-apply of r319294. adds -fseh-exceptions and -fdwarf-exceptions flags clang will check if the user has specified an exception model flag, in the absense of specifying the exception model clang will then check the driver default and append the model flag for that target to cc1 -fno-exceptions has a higher priority then specifying the model move __SEH__ macro definitions out of Targets into InitPreprocessor behind the -fseh-exceptions flag move __ARM_DWARF_EH__ macrodefinitions out of verious targets and into InitPreprocessor behind the -fdwarf-exceptions flag and arm|thumb check remove unused USESEHExceptions from the MinGW Driver fold USESjLjExceptions into a new GetExceptionModel function that gives the toolchain classes more flexibility with eh models Reviewers: rnk, mstorsjo Differential Revision: https://reviews.llvm.org/D39673 llvm-svn: 319297
483 lines
16 KiB
C++
483 lines
16 KiB
C++
//===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MinGW.h"
|
|
#include "InputInfo.h"
|
|
#include "CommonArgs.h"
|
|
#include "clang/Driver/Compilation.h"
|
|
#include "clang/Driver/Driver.h"
|
|
#include "clang/Driver/DriverDiagnostic.h"
|
|
#include "clang/Driver/Options.h"
|
|
#include "llvm/Option/ArgList.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include <system_error>
|
|
|
|
using namespace clang::diag;
|
|
using namespace clang::driver;
|
|
using namespace clang;
|
|
using namespace llvm::opt;
|
|
|
|
/// MinGW Tools
|
|
void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
|
|
const InputInfo &Output,
|
|
const InputInfoList &Inputs,
|
|
const ArgList &Args,
|
|
const char *LinkingOutput) const {
|
|
claimNoWarnArgs(Args);
|
|
ArgStringList CmdArgs;
|
|
|
|
if (getToolChain().getArch() == llvm::Triple::x86) {
|
|
CmdArgs.push_back("--32");
|
|
} else if (getToolChain().getArch() == llvm::Triple::x86_64) {
|
|
CmdArgs.push_back("--64");
|
|
}
|
|
|
|
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
|
|
|
|
CmdArgs.push_back("-o");
|
|
CmdArgs.push_back(Output.getFilename());
|
|
|
|
for (const auto &II : Inputs)
|
|
CmdArgs.push_back(II.getFilename());
|
|
|
|
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
|
|
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
|
|
|
|
if (Args.hasArg(options::OPT_gsplit_dwarf))
|
|
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
|
|
SplitDebugName(Args, Inputs[0]));
|
|
}
|
|
|
|
void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
|
|
ArgStringList &CmdArgs) const {
|
|
if (Args.hasArg(options::OPT_mthreads))
|
|
CmdArgs.push_back("-lmingwthrd");
|
|
CmdArgs.push_back("-lmingw32");
|
|
|
|
// Make use of compiler-rt if --rtlib option is used
|
|
ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args);
|
|
if (RLT == ToolChain::RLT_Libgcc) {
|
|
bool Static = Args.hasArg(options::OPT_static_libgcc) ||
|
|
Args.hasArg(options::OPT_static);
|
|
bool Shared = Args.hasArg(options::OPT_shared);
|
|
bool CXX = getToolChain().getDriver().CCCIsCXX();
|
|
|
|
if (Static || (!CXX && !Shared)) {
|
|
CmdArgs.push_back("-lgcc");
|
|
CmdArgs.push_back("-lgcc_eh");
|
|
} else {
|
|
CmdArgs.push_back("-lgcc_s");
|
|
CmdArgs.push_back("-lgcc");
|
|
}
|
|
} else {
|
|
AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args);
|
|
}
|
|
|
|
CmdArgs.push_back("-lmoldname");
|
|
CmdArgs.push_back("-lmingwex");
|
|
for (auto Lib : Args.getAllArgValues(options::OPT_l))
|
|
if (StringRef(Lib).startswith("msvcr") || Lib == "ucrtbase")
|
|
return;
|
|
CmdArgs.push_back("-lmsvcrt");
|
|
}
|
|
|
|
void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|
const InputInfo &Output,
|
|
const InputInfoList &Inputs,
|
|
const ArgList &Args,
|
|
const char *LinkingOutput) const {
|
|
const ToolChain &TC = getToolChain();
|
|
const Driver &D = TC.getDriver();
|
|
// const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
|
|
|
|
ArgStringList CmdArgs;
|
|
|
|
// Silence warning for "clang -g foo.o -o foo"
|
|
Args.ClaimAllArgs(options::OPT_g_Group);
|
|
// and "clang -emit-llvm foo.o -o foo"
|
|
Args.ClaimAllArgs(options::OPT_emit_llvm);
|
|
// and for "clang -w foo.o -o foo". Other warning options are already
|
|
// handled somewhere else.
|
|
Args.ClaimAllArgs(options::OPT_w);
|
|
|
|
if (!D.SysRoot.empty())
|
|
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
|
|
|
|
if (Args.hasArg(options::OPT_s))
|
|
CmdArgs.push_back("-s");
|
|
|
|
CmdArgs.push_back("-m");
|
|
switch (TC.getArch()) {
|
|
case llvm::Triple::x86:
|
|
CmdArgs.push_back("i386pe");
|
|
break;
|
|
case llvm::Triple::x86_64:
|
|
CmdArgs.push_back("i386pep");
|
|
break;
|
|
case llvm::Triple::arm:
|
|
case llvm::Triple::thumb:
|
|
// FIXME: this is incorrect for WinCE
|
|
CmdArgs.push_back("thumb2pe");
|
|
break;
|
|
case llvm::Triple::aarch64:
|
|
CmdArgs.push_back("arm64pe");
|
|
break;
|
|
default:
|
|
llvm_unreachable("Unsupported target architecture.");
|
|
}
|
|
|
|
if (Args.hasArg(options::OPT_mwindows)) {
|
|
CmdArgs.push_back("--subsystem");
|
|
CmdArgs.push_back("windows");
|
|
} else if (Args.hasArg(options::OPT_mconsole)) {
|
|
CmdArgs.push_back("--subsystem");
|
|
CmdArgs.push_back("console");
|
|
}
|
|
|
|
if (Args.hasArg(options::OPT_static))
|
|
CmdArgs.push_back("-Bstatic");
|
|
else {
|
|
if (Args.hasArg(options::OPT_mdll))
|
|
CmdArgs.push_back("--dll");
|
|
else if (Args.hasArg(options::OPT_shared))
|
|
CmdArgs.push_back("--shared");
|
|
CmdArgs.push_back("-Bdynamic");
|
|
if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) {
|
|
CmdArgs.push_back("-e");
|
|
if (TC.getArch() == llvm::Triple::x86)
|
|
CmdArgs.push_back("_DllMainCRTStartup@12");
|
|
else
|
|
CmdArgs.push_back("DllMainCRTStartup");
|
|
CmdArgs.push_back("--enable-auto-image-base");
|
|
}
|
|
}
|
|
|
|
CmdArgs.push_back("-o");
|
|
CmdArgs.push_back(Output.getFilename());
|
|
|
|
Args.AddAllArgs(CmdArgs, options::OPT_e);
|
|
// FIXME: add -N, -n flags
|
|
Args.AddLastArg(CmdArgs, options::OPT_r);
|
|
Args.AddLastArg(CmdArgs, options::OPT_s);
|
|
Args.AddLastArg(CmdArgs, options::OPT_t);
|
|
Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
|
|
Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);
|
|
|
|
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
|
|
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
|
|
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o")));
|
|
} else {
|
|
if (Args.hasArg(options::OPT_municode))
|
|
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o")));
|
|
else
|
|
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o")));
|
|
}
|
|
if (Args.hasArg(options::OPT_pg))
|
|
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o")));
|
|
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
|
|
}
|
|
|
|
Args.AddAllArgs(CmdArgs, options::OPT_L);
|
|
TC.AddFilePathLibArgs(Args, CmdArgs);
|
|
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
|
|
|
|
// TODO: Add ASan stuff here
|
|
|
|
// TODO: Add profile stuff here
|
|
|
|
if (TC.ShouldLinkCXXStdlib(Args)) {
|
|
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
|
|
!Args.hasArg(options::OPT_static);
|
|
if (OnlyLibstdcxxStatic)
|
|
CmdArgs.push_back("-Bstatic");
|
|
TC.AddCXXStdlibLibArgs(Args, CmdArgs);
|
|
if (OnlyLibstdcxxStatic)
|
|
CmdArgs.push_back("-Bdynamic");
|
|
}
|
|
|
|
if (!Args.hasArg(options::OPT_nostdlib)) {
|
|
if (!Args.hasArg(options::OPT_nodefaultlibs)) {
|
|
if (Args.hasArg(options::OPT_static))
|
|
CmdArgs.push_back("--start-group");
|
|
|
|
if (Args.hasArg(options::OPT_fstack_protector) ||
|
|
Args.hasArg(options::OPT_fstack_protector_strong) ||
|
|
Args.hasArg(options::OPT_fstack_protector_all)) {
|
|
CmdArgs.push_back("-lssp_nonshared");
|
|
CmdArgs.push_back("-lssp");
|
|
}
|
|
if (Args.hasArg(options::OPT_fopenmp))
|
|
CmdArgs.push_back("-lgomp");
|
|
|
|
AddLibGCC(Args, CmdArgs);
|
|
|
|
if (Args.hasArg(options::OPT_pg))
|
|
CmdArgs.push_back("-lgmon");
|
|
|
|
if (Args.hasArg(options::OPT_pthread))
|
|
CmdArgs.push_back("-lpthread");
|
|
|
|
// add system libraries
|
|
if (Args.hasArg(options::OPT_mwindows)) {
|
|
CmdArgs.push_back("-lgdi32");
|
|
CmdArgs.push_back("-lcomdlg32");
|
|
}
|
|
CmdArgs.push_back("-ladvapi32");
|
|
CmdArgs.push_back("-lshell32");
|
|
CmdArgs.push_back("-luser32");
|
|
CmdArgs.push_back("-lkernel32");
|
|
|
|
if (Args.hasArg(options::OPT_static))
|
|
CmdArgs.push_back("--end-group");
|
|
else
|
|
AddLibGCC(Args, CmdArgs);
|
|
}
|
|
|
|
if (!Args.hasArg(options::OPT_nostartfiles)) {
|
|
// Add crtfastmath.o if available and fast math is enabled.
|
|
TC.AddFastMathRuntimeIfAvailable(Args, CmdArgs);
|
|
|
|
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
|
|
}
|
|
}
|
|
const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
|
|
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
|
|
}
|
|
|
|
// Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
|
|
static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
|
|
std::string &Ver) {
|
|
auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
|
|
std::error_code EC;
|
|
for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE;
|
|
LI = LI.increment(EC)) {
|
|
StringRef VersionText = llvm::sys::path::filename(LI->path());
|
|
auto CandidateVersion =
|
|
toolchains::Generic_GCC::GCCVersion::Parse(VersionText);
|
|
if (CandidateVersion.Major == -1)
|
|
continue;
|
|
if (CandidateVersion <= Version)
|
|
continue;
|
|
Ver = VersionText;
|
|
GccLibDir = LI->path();
|
|
}
|
|
return Ver.size();
|
|
}
|
|
|
|
void toolchains::MinGW::findGccLibDir() {
|
|
llvm::SmallVector<llvm::SmallString<32>, 2> Archs;
|
|
Archs.emplace_back(getTriple().getArchName());
|
|
Archs[0] += "-w64-mingw32";
|
|
Archs.emplace_back("mingw32");
|
|
Arch = Archs[0].str();
|
|
// lib: Arch Linux, Ubuntu, Windows
|
|
// lib64: openSUSE Linux
|
|
for (StringRef CandidateLib : {"lib", "lib64"}) {
|
|
for (StringRef CandidateArch : Archs) {
|
|
llvm::SmallString<1024> LibDir(Base);
|
|
llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateArch);
|
|
if (findGccVersion(LibDir, GccLibDir, Ver)) {
|
|
Arch = CandidateArch;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() {
|
|
llvm::SmallVector<llvm::SmallString<32>, 2> Gccs;
|
|
Gccs.emplace_back(getTriple().getArchName());
|
|
Gccs[0] += "-w64-mingw32-gcc";
|
|
Gccs.emplace_back("mingw32-gcc");
|
|
// Please do not add "gcc" here
|
|
for (StringRef CandidateGcc : Gccs)
|
|
if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc))
|
|
return GPPName;
|
|
return make_error_code(std::errc::no_such_file_or_directory);
|
|
}
|
|
|
|
toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
|
|
const ArgList &Args)
|
|
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
|
|
getProgramPaths().push_back(getDriver().getInstalledDir());
|
|
|
|
if (getDriver().SysRoot.size())
|
|
Base = getDriver().SysRoot;
|
|
else if (llvm::ErrorOr<std::string> GPPName = findGcc())
|
|
Base = llvm::sys::path::parent_path(
|
|
llvm::sys::path::parent_path(GPPName.get()));
|
|
else
|
|
Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
|
|
|
|
Base += llvm::sys::path::get_separator();
|
|
findGccLibDir();
|
|
// GccLibDir must precede Base/lib so that the
|
|
// correct crtbegin.o ,cetend.o would be found.
|
|
getFilePaths().push_back(GccLibDir);
|
|
getFilePaths().push_back(
|
|
(Base + Arch + llvm::sys::path::get_separator() + "lib").str());
|
|
getFilePaths().push_back(Base + "lib");
|
|
// openSUSE
|
|
getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib");
|
|
}
|
|
|
|
bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
|
|
|
|
Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const {
|
|
switch (AC) {
|
|
case Action::PreprocessJobClass:
|
|
if (!Preprocessor)
|
|
Preprocessor.reset(new tools::gcc::Preprocessor(*this));
|
|
return Preprocessor.get();
|
|
case Action::CompileJobClass:
|
|
if (!Compiler)
|
|
Compiler.reset(new tools::gcc::Compiler(*this));
|
|
return Compiler.get();
|
|
default:
|
|
return ToolChain::getTool(AC);
|
|
}
|
|
}
|
|
|
|
Tool *toolchains::MinGW::buildAssembler() const {
|
|
return new tools::MinGW::Assembler(*this);
|
|
}
|
|
|
|
Tool *toolchains::MinGW::buildLinker() const {
|
|
return new tools::MinGW::Linker(*this);
|
|
}
|
|
|
|
bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const {
|
|
return getArch() == llvm::Triple::x86_64;
|
|
}
|
|
|
|
bool toolchains::MinGW::isPICDefault() const {
|
|
return getArch() == llvm::Triple::x86_64;
|
|
}
|
|
|
|
bool toolchains::MinGW::isPIEDefault() const { return false; }
|
|
|
|
bool toolchains::MinGW::isPICDefaultForced() const {
|
|
return getArch() == llvm::Triple::x86_64;
|
|
}
|
|
|
|
llvm::ExceptionHandling
|
|
toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
|
|
if (getArch() == llvm::Triple::x86_64)
|
|
return llvm::ExceptionHandling::WinEH;
|
|
return llvm::ExceptionHandling::DwarfCFI;
|
|
}
|
|
|
|
void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
|
|
ArgStringList &CC1Args) const {
|
|
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
|
|
}
|
|
|
|
void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const {
|
|
CudaInstallation.print(OS);
|
|
}
|
|
|
|
// Include directories for various hosts:
|
|
|
|
// Windows, mingw.org
|
|
// c:\mingw\lib\gcc\mingw32\4.8.1\include\c++
|
|
// c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32
|
|
// c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward
|
|
// c:\mingw\include
|
|
// c:\mingw\mingw32\include
|
|
|
|
// Windows, mingw-w64 mingw-builds
|
|
// c:\mingw32\i686-w64-mingw32\include
|
|
// c:\mingw32\i686-w64-mingw32\include\c++
|
|
// c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32
|
|
// c:\mingw32\i686-w64-mingw32\include\c++\backward
|
|
|
|
// Windows, mingw-w64 msys2
|
|
// c:\msys64\mingw32\include
|
|
// c:\msys64\mingw32\i686-w64-mingw32\include
|
|
// c:\msys64\mingw32\include\c++\4.9.2
|
|
// c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32
|
|
// c:\msys64\mingw32\include\c++\4.9.2\backward
|
|
|
|
// openSUSE
|
|
// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++
|
|
// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32
|
|
// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward
|
|
// /usr/x86_64-w64-mingw32/sys-root/mingw/include
|
|
|
|
// Arch Linux
|
|
// /usr/i686-w64-mingw32/include/c++/5.1.0
|
|
// /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32
|
|
// /usr/i686-w64-mingw32/include/c++/5.1.0/backward
|
|
// /usr/i686-w64-mingw32/include
|
|
|
|
// Ubuntu
|
|
// /usr/include/c++/4.8
|
|
// /usr/include/c++/4.8/x86_64-w64-mingw32
|
|
// /usr/include/c++/4.8/backward
|
|
// /usr/x86_64-w64-mingw32/include
|
|
|
|
void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
|
|
ArgStringList &CC1Args) const {
|
|
if (DriverArgs.hasArg(options::OPT_nostdinc))
|
|
return;
|
|
|
|
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
|
|
SmallString<1024> P(getDriver().ResourceDir);
|
|
llvm::sys::path::append(P, "include");
|
|
addSystemInclude(DriverArgs, CC1Args, P.str());
|
|
}
|
|
|
|
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
|
|
return;
|
|
|
|
if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) {
|
|
// openSUSE
|
|
addSystemInclude(DriverArgs, CC1Args,
|
|
Base + Arch + "/sys-root/mingw/include");
|
|
}
|
|
|
|
addSystemInclude(DriverArgs, CC1Args,
|
|
Base + Arch + llvm::sys::path::get_separator() + "include");
|
|
addSystemInclude(DriverArgs, CC1Args, Base + "include");
|
|
}
|
|
|
|
void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
|
|
const ArgList &DriverArgs, ArgStringList &CC1Args) const {
|
|
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
|
|
DriverArgs.hasArg(options::OPT_nostdincxx))
|
|
return;
|
|
|
|
switch (GetCXXStdlibType(DriverArgs)) {
|
|
case ToolChain::CST_Libcxx:
|
|
addSystemInclude(DriverArgs, CC1Args,
|
|
Base + "include" + llvm::sys::path::get_separator() +
|
|
"c++" + llvm::sys::path::get_separator() + "v1");
|
|
break;
|
|
|
|
case ToolChain::CST_Libstdcxx:
|
|
llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases;
|
|
CppIncludeBases.emplace_back(Base);
|
|
llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++");
|
|
CppIncludeBases.emplace_back(Base);
|
|
llvm::sys::path::append(CppIncludeBases[1], Arch, "include", "c++", Ver);
|
|
CppIncludeBases.emplace_back(Base);
|
|
llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver);
|
|
CppIncludeBases.emplace_back(GccLibDir);
|
|
llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
|
|
for (auto &CppIncludeBase : CppIncludeBases) {
|
|
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
|
|
CppIncludeBase += llvm::sys::path::get_separator();
|
|
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch);
|
|
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
|
|
}
|
|
break;
|
|
}
|
|
}
|