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