clang  5.0.0
CrossWindows.cpp
Go to the documentation of this file.
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"
13 #include "clang/Driver/Driver.h"
14 #include "clang/Driver/Options.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 
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 
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 
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 ArgList &Args) 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 
224  return getArch() == llvm::Triple::x86_64;
225 }
226 
228  return getArch() == llvm::Triple::x86_64;
229 }
230 
232  return getArch() == llvm::Triple::x86_64;
233 }
234 
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  auto AddSystemAfterIncludes = [&]() {
242  for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after))
243  addSystemInclude(DriverArgs, CC1Args, P);
244  };
245 
246  if (DriverArgs.hasArg(options::OPT_nostdinc)) {
247  AddSystemAfterIncludes();
248  return;
249  }
250 
251  addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
252  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
253  SmallString<128> ResourceDir(D.ResourceDir);
254  llvm::sys::path::append(ResourceDir, "include");
255  addSystemInclude(DriverArgs, CC1Args, ResourceDir);
256  }
257  AddSystemAfterIncludes();
258  addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
259 }
260 
262 AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
263  llvm::opt::ArgStringList &CC1Args) const {
264  const llvm::Triple &Triple = getTriple();
265  const std::string &SysRoot = getDriver().SysRoot;
266 
267  if (DriverArgs.hasArg(options::OPT_nostdinc) ||
268  DriverArgs.hasArg(options::OPT_nostdincxx))
269  return;
270 
271  switch (GetCXXStdlibType(DriverArgs)) {
273  addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1");
274  break;
275 
277  addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++");
278  addSystemInclude(DriverArgs, CC1Args,
279  SysRoot + "/usr/include/c++/" + Triple.str());
280  addSystemInclude(DriverArgs, CC1Args,
281  SysRoot + "/usr/include/c++/backwards");
282  }
283 }
284 
286 AddCXXStdlibLibArgs(const llvm::opt::ArgList &DriverArgs,
287  llvm::opt::ArgStringList &CC1Args) const {
288  switch (GetCXXStdlibType(DriverArgs)) {
290  CC1Args.push_back("-lc++");
291  break;
293  CC1Args.push_back("-lstdc++");
294  CC1Args.push_back("-lmingw32");
295  CC1Args.push_back("-lmingwex");
296  CC1Args.push_back("-lgcc");
297  CC1Args.push_back("-lmoldname");
298  CC1Args.push_back("-lmingw32");
299  break;
300  }
301 }
302 
305  Res |= SanitizerKind::Address;
306  return Res;
307 }
308 
310  return new tools::CrossWindows::Linker(*this);
311 }
312 
314  return new tools::CrossWindows::Assembler(*this);
315 }
const llvm::Triple & getTriple() const
Definition: ToolChain.h:144
static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory with extern "C" semantics to CC1 arguments...
Definition: ToolChain.cpp:613
Generic_GCC - A tool chain using the 'gcc' command to perform all subcommands; this relies on gcc tra...
Definition: Gnu.h:140
virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const
Definition: ToolChain.cpp:579
StringRef P
bool isPICDefault() const override
Test whether this toolchain defaults to PIC.
void AddRunTimeLibs(const ToolChain &TC, const Driver &D, llvm::opt::ArgStringList &CmdArgs, const llvm::opt::ArgList &Args)
llvm::Triple::ArchType getArch() const
Definition: ToolChain.h:153
void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set the include paths to use for...
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:702
bool CCCIsCXX() const
Whether the driver should follow g++ like behavior.
Definition: Driver.h:174
InputInfo - Wrapper for information about an input source.
Definition: InputInfo.h:23
path_list & getFilePaths()
Definition: ToolChain.h:172
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:65
const Driver & getDriver() const
Definition: ToolChain.h:142
CrossWindowsToolChain(const Driver &D, const llvm::Triple &T, const llvm::opt::ArgList &Args)
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
void addCommand(std::unique_ptr< Command > C)
Definition: Compilation.h:189
bool isPIEDefault() const override
Test whether this toolchain defaults to PIE.
void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
Add the clang cc1 arguments for system include paths.
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs...
const char * getFilename() const
Definition: InputInfo.h:84
bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override
IsUnwindTablesDefault - Does this tool chain use -funwind-tables by default.
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory to CC1 arguments.
Definition: ToolChain.cpp:598
uint64_t SanitizerMask
Definition: Sanitizers.h:24
void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const JobAction &JA)
std::string SysRoot
sysroot, if present
Definition: Driver.h:146
Tool - Information on a specific compilation tool.
Definition: Tool.h:34
void claimNoWarnArgs(const llvm::opt::ArgList &Args)
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:34
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs...
const StringRef Input
bool isPICDefaultForced() const override
Tests whether this toolchain forces its default for PIC, PIE or non-PIC.
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override
AddCXXStdlibLibArgs - Add the system specific linker arguments to use for the given C++ standard libr...
std::string ResourceDir
The path to the compiler resource directory.
Definition: Driver.h:136