Home | History | Annotate | Line # | Download | only in ToolChains
CrossWindows.cpp revision 1.1
      1 //===-- CrossWindows.cpp - Cross Windows Tool Chain -----------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "CrossWindows.h"
     10 #include "CommonArgs.h"
     11 #include "clang/Driver/Compilation.h"
     12 #include "clang/Driver/Driver.h"
     13 #include "clang/Driver/Options.h"
     14 #include "clang/Driver/SanitizerArgs.h"
     15 #include "llvm/Option/ArgList.h"
     16 #include "llvm/Support/Path.h"
     17 
     18 using namespace clang::driver;
     19 using namespace clang::driver::toolchains;
     20 
     21 using llvm::opt::ArgList;
     22 using llvm::opt::ArgStringList;
     23 
     24 void tools::CrossWindows::Assembler::ConstructJob(
     25     Compilation &C, const JobAction &JA, const InputInfo &Output,
     26     const InputInfoList &Inputs, const ArgList &Args,
     27     const char *LinkingOutput) const {
     28   claimNoWarnArgs(Args);
     29   const auto &TC =
     30       static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
     31   ArgStringList CmdArgs;
     32   const char *Exec;
     33 
     34   switch (TC.getArch()) {
     35   default:
     36     llvm_unreachable("unsupported architecture");
     37   case llvm::Triple::arm:
     38   case llvm::Triple::thumb:
     39   case llvm::Triple::aarch64:
     40     break;
     41   case llvm::Triple::x86:
     42     CmdArgs.push_back("--32");
     43     break;
     44   case llvm::Triple::x86_64:
     45     CmdArgs.push_back("--64");
     46     break;
     47   }
     48 
     49   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
     50 
     51   CmdArgs.push_back("-o");
     52   CmdArgs.push_back(Output.getFilename());
     53 
     54   for (const auto &Input : Inputs)
     55     CmdArgs.push_back(Input.getFilename());
     56 
     57   const std::string Assembler = TC.GetProgramPath("as");
     58   Exec = Args.MakeArgString(Assembler);
     59 
     60   C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
     61 }
     62 
     63 void tools::CrossWindows::Linker::ConstructJob(
     64     Compilation &C, const JobAction &JA, const InputInfo &Output,
     65     const InputInfoList &Inputs, const ArgList &Args,
     66     const char *LinkingOutput) const {
     67   const auto &TC =
     68       static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
     69   const llvm::Triple &T = TC.getTriple();
     70   const Driver &D = TC.getDriver();
     71   SmallString<128> EntryPoint;
     72   ArgStringList CmdArgs;
     73   const char *Exec;
     74 
     75   // Silence warning for "clang -g foo.o -o foo"
     76   Args.ClaimAllArgs(options::OPT_g_Group);
     77   // and "clang -emit-llvm foo.o -o foo"
     78   Args.ClaimAllArgs(options::OPT_emit_llvm);
     79   // and for "clang -w foo.o -o foo"
     80   Args.ClaimAllArgs(options::OPT_w);
     81   // Other warning options are already handled somewhere else.
     82 
     83   if (!D.SysRoot.empty())
     84     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
     85 
     86   if (Args.hasArg(options::OPT_pie))
     87     CmdArgs.push_back("-pie");
     88   if (Args.hasArg(options::OPT_rdynamic))
     89     CmdArgs.push_back("-export-dynamic");
     90   if (Args.hasArg(options::OPT_s))
     91     CmdArgs.push_back("--strip-all");
     92 
     93   CmdArgs.push_back("-m");
     94   switch (TC.getArch()) {
     95   default:
     96     llvm_unreachable("unsupported architecture");
     97   case llvm::Triple::arm:
     98   case llvm::Triple::thumb:
     99     // FIXME: this is incorrect for WinCE
    100     CmdArgs.push_back("thumb2pe");
    101     break;
    102   case llvm::Triple::aarch64:
    103     CmdArgs.push_back("arm64pe");
    104     break;
    105   case llvm::Triple::x86:
    106     CmdArgs.push_back("i386pe");
    107     EntryPoint.append("_");
    108     break;
    109   case llvm::Triple::x86_64:
    110     CmdArgs.push_back("i386pep");
    111     break;
    112   }
    113 
    114   if (Args.hasArg(options::OPT_shared)) {
    115     switch (T.getArch()) {
    116     default:
    117       llvm_unreachable("unsupported architecture");
    118     case llvm::Triple::aarch64:
    119     case llvm::Triple::arm:
    120     case llvm::Triple::thumb:
    121     case llvm::Triple::x86_64:
    122       EntryPoint.append("_DllMainCRTStartup");
    123       break;
    124     case llvm::Triple::x86:
    125       EntryPoint.append("_DllMainCRTStartup@12");
    126       break;
    127     }
    128 
    129     CmdArgs.push_back("-shared");
    130     CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
    131                                                        : "-Bdynamic");
    132 
    133     CmdArgs.push_back("--enable-auto-image-base");
    134 
    135     CmdArgs.push_back("--entry");
    136     CmdArgs.push_back(Args.MakeArgString(EntryPoint));
    137   } else {
    138     EntryPoint.append("mainCRTStartup");
    139 
    140     CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
    141                                                        : "-Bdynamic");
    142 
    143     if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    144       CmdArgs.push_back("--entry");
    145       CmdArgs.push_back(Args.MakeArgString(EntryPoint));
    146     }
    147 
    148     // FIXME: handle subsystem
    149   }
    150 
    151   // NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
    152   CmdArgs.push_back("--allow-multiple-definition");
    153 
    154   CmdArgs.push_back("-o");
    155   CmdArgs.push_back(Output.getFilename());
    156 
    157   if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_rdynamic)) {
    158     SmallString<261> ImpLib(Output.getFilename());
    159     llvm::sys::path::replace_extension(ImpLib, ".lib");
    160 
    161     CmdArgs.push_back("--out-implib");
    162     CmdArgs.push_back(Args.MakeArgString(ImpLib));
    163   }
    164 
    165   Args.AddAllArgs(CmdArgs, options::OPT_L);
    166   TC.AddFilePathLibArgs(Args, CmdArgs);
    167   AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
    168 
    169   if (TC.ShouldLinkCXXStdlib(Args)) {
    170     bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) &&
    171                      !Args.hasArg(options::OPT_static);
    172     if (StaticCXX)
    173       CmdArgs.push_back("-Bstatic");
    174     TC.AddCXXStdlibLibArgs(Args, CmdArgs);
    175     if (StaticCXX)
    176       CmdArgs.push_back("-Bdynamic");
    177   }
    178 
    179   if (!Args.hasArg(options::OPT_nostdlib)) {
    180     if (!Args.hasArg(options::OPT_nodefaultlibs)) {
    181       // TODO handle /MT[d] /MD[d]
    182       CmdArgs.push_back("-lmsvcrt");
    183       AddRunTimeLibs(TC, D, CmdArgs, Args);
    184     }
    185   }
    186 
    187   if (TC.getSanitizerArgs().needsAsanRt()) {
    188     // TODO handle /MT[d] /MD[d]
    189     if (Args.hasArg(options::OPT_shared)) {
    190       CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
    191     } else {
    192       for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
    193         CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
    194       // Make sure the dynamic runtime thunk is not optimized out at link time
    195       // to ensure proper SEH handling.
    196       CmdArgs.push_back(Args.MakeArgString("--undefined"));
    197       CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
    198                                                ? "___asan_seh_interceptor"
    199                                                : "__asan_seh_interceptor"));
    200     }
    201   }
    202 
    203   Exec = Args.MakeArgString(TC.GetLinkerPath());
    204 
    205   C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
    206 }
    207 
    208 CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D,
    209                                              const llvm::Triple &T,
    210                                              const llvm::opt::ArgList &Args)
    211     : Generic_GCC(D, T, Args) {}
    212 
    213 bool CrossWindowsToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
    214   // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does
    215   // not know how to emit them.
    216   return getArch() == llvm::Triple::x86_64;
    217 }
    218 
    219 bool CrossWindowsToolChain::isPICDefault() const {
    220   return getArch() == llvm::Triple::x86_64;
    221 }
    222 
    223 bool CrossWindowsToolChain::isPIEDefault() const {
    224   return getArch() == llvm::Triple::x86_64;
    225 }
    226 
    227 bool CrossWindowsToolChain::isPICDefaultForced() const {
    228   return getArch() == llvm::Triple::x86_64;
    229 }
    230 
    231 void CrossWindowsToolChain::
    232 AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
    233                           llvm::opt::ArgStringList &CC1Args) const {
    234   const Driver &D = getDriver();
    235   const std::string &SysRoot = D.SysRoot;
    236 
    237   auto AddSystemAfterIncludes = [&]() {
    238     for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after))
    239       addSystemInclude(DriverArgs, CC1Args, P);
    240   };
    241 
    242   if (DriverArgs.hasArg(options::OPT_nostdinc)) {
    243     AddSystemAfterIncludes();
    244     return;
    245   }
    246 
    247   addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
    248   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
    249     SmallString<128> ResourceDir(D.ResourceDir);
    250     llvm::sys::path::append(ResourceDir, "include");
    251     addSystemInclude(DriverArgs, CC1Args, ResourceDir);
    252   }
    253   AddSystemAfterIncludes();
    254   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
    255 }
    256 
    257 void CrossWindowsToolChain::
    258 AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
    259                              llvm::opt::ArgStringList &CC1Args) const {
    260   const std::string &SysRoot = getDriver().SysRoot;
    261 
    262   if (DriverArgs.hasArg(options::OPT_nostdinc) ||
    263       DriverArgs.hasArg(options::OPT_nostdincxx))
    264     return;
    265 
    266   if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
    267     addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1");
    268 }
    269 
    270 void CrossWindowsToolChain::
    271 AddCXXStdlibLibArgs(const llvm::opt::ArgList &DriverArgs,
    272                     llvm::opt::ArgStringList &CC1Args) const {
    273   if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
    274     CC1Args.push_back("-lc++");
    275 }
    276 
    277 clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
    278   SanitizerMask Res = ToolChain::getSupportedSanitizers();
    279   Res |= SanitizerKind::Address;
    280   Res |= SanitizerKind::PointerCompare;
    281   Res |= SanitizerKind::PointerSubtract;
    282   return Res;
    283 }
    284 
    285 Tool *CrossWindowsToolChain::buildLinker() const {
    286   return new tools::CrossWindows::Linker(*this);
    287 }
    288 
    289 Tool *CrossWindowsToolChain::buildAssembler() const {
    290   return new tools::CrossWindows::Assembler(*this);
    291 }
    292