Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/Driver/ToolChains/WebAssembly.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- WebAssembly.cpp - WebAssembly ToolChain Implementation -*- C++ -*-===//
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 "WebAssembly.h"
10
#include "CommonArgs.h"
11
#include "clang/Config/config.h"
12
#include "clang/Driver/Compilation.h"
13
#include "clang/Driver/Driver.h"
14
#include "clang/Driver/DriverDiagnostic.h"
15
#include "clang/Driver/Options.h"
16
#include "llvm/Support/FileSystem.h"
17
#include "llvm/Support/Path.h"
18
#include "llvm/Option/ArgList.h"
19
20
using namespace clang::driver;
21
using namespace clang::driver::tools;
22
using namespace clang::driver::toolchains;
23
using namespace clang;
24
using namespace llvm::opt;
25
26
/// Following the conventions in https://wiki.debian.org/Multiarch/Tuples,
27
/// we remove the vendor field to form the multiarch triple.
28
static std::string getMultiarchTriple(const Driver &D,
29
                                      const llvm::Triple &TargetTriple,
30
17
                                      StringRef SysRoot) {
31
17
    return (TargetTriple.getArchName() + "-" +
32
17
            TargetTriple.getOSAndEnvironmentName()).str();
33
17
}
34
35
19
std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
36
19
  const ToolChain &ToolChain = getToolChain();
37
19
  if (const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
38
1
    StringRef UseLinker = A->getValue();
39
1
    if (!UseLinker.empty()) {
40
1
      if (llvm::sys::path::is_absolute(UseLinker) &&
41
1
          
llvm::sys::fs::can_execute(UseLinker)0
)
42
0
        return UseLinker;
43
1
44
1
      // Accept 'lld', and 'ld' as aliases for the default linker
45
1
      if (UseLinker != "lld" && UseLinker != "ld")
46
1
        ToolChain.getDriver().Diag(diag::err_drv_invalid_linker_name)
47
1
            << A->getAsString(Args);
48
1
    }
49
1
  }
50
19
51
19
  return ToolChain.GetProgramPath(ToolChain.getDefaultLinker());
52
19
}
53
54
void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
55
                                const InputInfo &Output,
56
                                const InputInfoList &Inputs,
57
                                const ArgList &Args,
58
19
                                const char *LinkingOutput) const {
59
19
60
19
  const ToolChain &ToolChain = getToolChain();
61
19
  const char *Linker = Args.MakeArgString(getLinkerPath(Args));
62
19
  ArgStringList CmdArgs;
63
19
64
19
  if (Args.hasArg(options::OPT_s))
65
0
    CmdArgs.push_back("--strip-all");
66
19
67
19
  Args.AddAllArgs(CmdArgs, options::OPT_L);
68
19
  Args.AddAllArgs(CmdArgs, options::OPT_u);
69
19
  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
70
19
71
19
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
72
19
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
73
19
74
19
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
75
19
76
19
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
77
19
    if (ToolChain.ShouldLinkCXXStdlib(Args))
78
7
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
79
19
80
19
    if (Args.hasArg(options::OPT_pthread)) {
81
4
      CmdArgs.push_back("-lpthread");
82
4
      CmdArgs.push_back("--shared-memory");
83
4
    }
84
19
85
19
    CmdArgs.push_back("-lc");
86
19
    AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
87
19
  }
88
19
89
19
  CmdArgs.push_back("-o");
90
19
  CmdArgs.push_back(Output.getFilename());
91
19
92
19
  C.addCommand(llvm::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs));
93
19
}
94
95
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
96
                         const llvm::opt::ArgList &Args)
97
53
    : ToolChain(D, Triple, Args) {
98
53
99
53
  assert(Triple.isArch32Bit() != Triple.isArch64Bit());
100
53
101
53
  getProgramPaths().push_back(getDriver().getInstalledDir());
102
53
103
53
  if (getTriple().getOS() == llvm::Triple::UnknownOS) {
104
46
    // Theoretically an "unknown" OS should mean no standard libraries, however
105
46
    // it could also mean that a custom set of libraries is in use, so just add
106
46
    // /lib to the search path. Disable multiarch in this case, to discourage
107
46
    // paths containing "unknown" from acquiring meanings.
108
46
    getFilePaths().push_back(getDriver().SysRoot + "/lib");
109
46
  } else {
110
7
    const std::string MultiarchTriple =
111
7
        getMultiarchTriple(getDriver(), Triple, getDriver().SysRoot);
112
7
    getFilePaths().push_back(getDriver().SysRoot + "/lib/" + MultiarchTriple);
113
7
  }
114
53
}
115
116
53
bool WebAssembly::IsMathErrnoDefault() const { return false; }
117
118
53
bool WebAssembly::IsObjCNonFragileABIDefault() const { return true; }
119
120
0
bool WebAssembly::UseObjCMixedDispatch() const { return true; }
121
122
53
bool WebAssembly::isPICDefault() const { return false; }
123
124
53
bool WebAssembly::isPIEDefault() const { return false; }
125
126
53
bool WebAssembly::isPICDefaultForced() const { return false; }
127
128
226
bool WebAssembly::IsIntegratedAssemblerDefault() const { return true; }
129
130
0
bool WebAssembly::hasBlocksRuntime() const { return false; }
131
132
// TODO: Support profiling.
133
106
bool WebAssembly::SupportsProfiling() const { return false; }
134
135
19
bool WebAssembly::HasNativeLLVMSupport() const { return true; }
136
137
void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
138
                                        ArgStringList &CC1Args,
139
53
                                        Action::OffloadKind) const {
140
53
  if (DriverArgs.hasFlag(clang::driver::options::OPT_fuse_init_array,
141
53
                         options::OPT_fno_use_init_array, true))
142
53
    CC1Args.push_back("-fuse-init-array");
143
53
144
53
  // '-pthread' implies atomics, bulk-memory, and mutable-globals
145
53
  if (DriverArgs.hasFlag(options::OPT_pthread, options::OPT_no_pthread,
146
53
                         false)) {
147
8
    if (DriverArgs.hasFlag(options::OPT_mno_atomics, options::OPT_matomics,
148
8
                           false))
149
1
      getDriver().Diag(diag::err_drv_argument_not_allowed_with)
150
1
          << "-pthread"
151
1
          << "-mno-atomics";
152
8
    if (DriverArgs.hasFlag(options::OPT_mno_bulk_memory,
153
8
                           options::OPT_mbulk_memory, false))
154
1
      getDriver().Diag(diag::err_drv_argument_not_allowed_with)
155
1
          << "-pthread"
156
1
          << "-mno-bulk-memory";
157
8
    if (DriverArgs.hasFlag(options::OPT_mno_mutable_globals,
158
8
                           options::OPT_mmutable_globals, false))
159
1
      getDriver().Diag(diag::err_drv_argument_not_allowed_with)
160
1
          << "-pthread"
161
1
          << "-mno-mutable-globals";
162
8
    CC1Args.push_back("-target-feature");
163
8
    CC1Args.push_back("+atomics");
164
8
    CC1Args.push_back("-target-feature");
165
8
    CC1Args.push_back("+bulk-memory");
166
8
    CC1Args.push_back("-target-feature");
167
8
    CC1Args.push_back("+mutable-globals");
168
8
  }
169
53
}
170
171
38
ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const {
172
38
  return ToolChain::RLT_CompilerRT;
173
38
}
174
175
ToolChain::CXXStdlibType
176
7
WebAssembly::GetCXXStdlibType(const ArgList &Args) const {
177
7
  if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
178
5
    StringRef Value = A->getValue();
179
5
    if (Value != "libc++")
180
5
      getDriver().Diag(diag::err_drv_invalid_stdlib_name)
181
5
          << A->getAsString(Args);
182
5
  }
183
7
  return ToolChain::CST_Libcxx;
184
7
}
185
186
void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
187
53
                                            ArgStringList &CC1Args) const {
188
53
  if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
189
0
    return;
190
53
191
53
  const Driver &D = getDriver();
192
53
193
53
  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
194
53
    SmallString<128> P(D.ResourceDir);
195
53
    llvm::sys::path::append(P, "include");
196
53
    addSystemInclude(DriverArgs, CC1Args, P);
197
53
  }
198
53
199
53
  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
200
0
    return;
201
53
202
53
  // Check for configure-time C include directories.
203
53
  StringRef CIncludeDirs(C_INCLUDE_DIRS);
204
53
  if (CIncludeDirs != "") {
205
0
    SmallVector<StringRef, 5> dirs;
206
0
    CIncludeDirs.split(dirs, ":");
207
0
    for (StringRef dir : dirs) {
208
0
      StringRef Prefix =
209
0
          llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
210
0
      addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
211
0
    }
212
0
    return;
213
0
  }
214
53
215
53
  if (getTriple().getOS() != llvm::Triple::UnknownOS) {
216
7
    const std::string MultiarchTriple =
217
7
        getMultiarchTriple(D, getTriple(), D.SysRoot);
218
7
    addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include/" + MultiarchTriple);
219
7
  }
220
53
  addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include");
221
53
}
222
223
void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
224
13
                                               ArgStringList &CC1Args) const {
225
13
  if (!DriverArgs.hasArg(options::OPT_nostdlibinc) &&
226
13
      !DriverArgs.hasArg(options::OPT_nostdincxx)) {
227
13
    if (getTriple().getOS() != llvm::Triple::UnknownOS) {
228
3
      const std::string MultiarchTriple =
229
3
          getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
230
3
      addSystemInclude(DriverArgs, CC1Args,
231
3
                       getDriver().SysRoot + "/include/" + MultiarchTriple +
232
3
                           "/c++/v1");
233
3
    }
234
13
    addSystemInclude(DriverArgs, CC1Args,
235
13
                     getDriver().SysRoot + "/include/c++/v1");
236
13
  }
237
13
}
238
239
void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
240
7
                                      llvm::opt::ArgStringList &CmdArgs) const {
241
7
242
7
  switch (GetCXXStdlibType(Args)) {
243
7
  case ToolChain::CST_Libcxx:
244
7
    CmdArgs.push_back("-lc++");
245
7
    CmdArgs.push_back("-lc++abi");
246
7
    break;
247
7
  case ToolChain::CST_Libstdcxx:
248
0
    llvm_unreachable("invalid stdlib name");
249
7
  }
250
7
}
251
252
53
SanitizerMask WebAssembly::getSupportedSanitizers() const {
253
53
  SanitizerMask Res = ToolChain::getSupportedSanitizers();
254
53
  if (getTriple().isOSEmscripten()) {
255
1
    Res |= SanitizerKind::Vptr | SanitizerKind::Leak | SanitizerKind::Address;
256
1
  }
257
53
  return Res;
258
53
}
259
260
19
Tool *WebAssembly::buildLinker() const {
261
19
  return new tools::wasm::Linker(*this);
262
19
}