Coverage Report

Created: 2020-09-19 12:23

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- X86.cpp - X86 Helpers for Tools ------------------------*- 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 "X86.h"
10
#include "ToolChains/CommonArgs.h"
11
#include "clang/Driver/Driver.h"
12
#include "clang/Driver/DriverDiagnostic.h"
13
#include "clang/Driver/Options.h"
14
#include "llvm/ADT/StringSwitch.h"
15
#include "llvm/Option/ArgList.h"
16
#include "llvm/Support/Host.h"
17
18
using namespace clang::driver;
19
using namespace clang::driver::tools;
20
using namespace clang;
21
using namespace llvm::opt;
22
23
std::string x86::getX86TargetCPU(const ArgList &Args,
24
38.0k
                                 const llvm::Triple &Triple) {
25
38.0k
  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
26
412
    StringRef CPU = A->getValue();
27
412
    if (CPU != "native")
28
412
      return std::string(CPU);
29
0
30
    // FIXME: Reject attempts to use -march=native unless the target matches
31
    // the host.
32
    //
33
    // FIXME: We should also incorporate the detected target features for use
34
    // with -native.
35
0
    CPU = llvm::sys::getHostCPUName();
36
0
    if (!CPU.empty() && CPU != "generic")
37
0
      return std::string(CPU);
38
37.6k
  }
39
37.6k
40
37.6k
  if (const Arg *A = Args.getLastArgNoClaim(options::OPT__SLASH_arch)) {
41
    // Mapping built by looking at lib/Basic's X86TargetInfo::initFeatureMap().
42
30
    StringRef Arch = A->getValue();
43
30
    StringRef CPU;
44
30
    if (Triple.getArch() == llvm::Triple::x86) {  // 32-bit-only /arch: flags.
45
18
      CPU = llvm::StringSwitch<StringRef>(Arch)
46
18
                .Case("IA32", "i386")
47
18
                .Case("SSE", "pentium3")
48
18
                .Case("SSE2", "pentium4")
49
18
                .Default("");
50
18
    }
51
30
    if (CPU.empty()) {  // 32-bit and 64-bit /arch: flags.
52
23
      CPU = llvm::StringSwitch<StringRef>(Arch)
53
23
                .Case("AVX", "sandybridge")
54
23
                .Case("AVX2", "haswell")
55
23
                .Case("AVX512F", "knl")
56
23
                .Case("AVX512", "skylake-avx512")
57
23
                .Default("");
58
23
    }
59
30
    if (!CPU.empty()) {
60
16
      A->claim();
61
16
      return std::string(CPU);
62
16
    }
63
37.6k
  }
64
37.6k
65
  // Select the default CPU if none was given (or detection failed).
66
37.6k
67
37.6k
  if (!Triple.isX86())
68
0
    return ""; // This routine is only handling x86 targets.
69
37.6k
70
37.6k
  bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
71
37.6k
72
  // FIXME: Need target hooks.
73
37.6k
  if (Triple.isOSDarwin()) {
74
17.9k
    if (Triple.getArchName() == "x86_64h")
75
5
      return "core-avx2";
76
    // macosx10.12 drops support for all pre-Penryn Macs.
77
    // Simulators can still run on 10.11 though, like Xcode.
78
17.9k
    if (Triple.isMacOSX() && 
!Triple.isOSVersionLT(10, 12)17.8k
)
79
17.6k
      return "penryn";
80
    // The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah.
81
323
    return Is64Bit ? 
"core2"260
:
"yonah"63
;
82
323
  }
83
19.6k
84
  // Set up default CPU name for PS4 compilers.
85
19.6k
  if (Triple.isPS4CPU())
86
131
    return "btver2";
87
19.5k
88
  // On Android use targets compatible with gcc
89
19.5k
  if (Triple.isAndroid())
90
37
    return Is64Bit ? 
"x86-64"15
:
"i686"22
;
91
19.5k
92
  // Everything else goes to x86-64 in 64-bit mode.
93
19.5k
  if (Is64Bit)
94
10.1k
    return "x86-64";
95
9.37k
96
9.37k
  switch (Triple.getOS()) {
97
10
  case llvm::Triple::NetBSD:
98
10
    return "i486";
99
39
  case llvm::Triple::Haiku:
100
39
  case llvm::Triple::OpenBSD:
101
39
    return "i586";
102
14
  case llvm::Triple::FreeBSD:
103
14
    return "i686";
104
9.31k
  default:
105
    // Fallback to p4.
106
9.31k
    return "pentium4";
107
9.37k
  }
108
9.37k
}
109
110
void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
111
                               const ArgList &Args,
112
37.9k
                               std::vector<StringRef> &Features) {
113
  // If -march=native, autodetect the feature list.
114
37.9k
  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
115
412
    if (StringRef(A->getValue()) == "native") {
116
0
      llvm::StringMap<bool> HostFeatures;
117
0
      if (llvm::sys::getHostCPUFeatures(HostFeatures))
118
0
        for (auto &F : HostFeatures)
119
0
          Features.push_back(
120
0
              Args.MakeArgString((F.second ? "+" : "-") + F.first()));
121
0
    }
122
412
  }
123
37.9k
124
37.9k
  if (Triple.getArchName() == "x86_64h") {
125
    // x86_64h implies quite a few of the more modern subtarget features
126
    // for Haswell class CPUs, but not all of them. Opt-out of a few.
127
6
    Features.push_back("-rdrnd");
128
6
    Features.push_back("-aes");
129
6
    Features.push_back("-pclmul");
130
6
    Features.push_back("-rtm");
131
6
    Features.push_back("-fsgsbase");
132
6
  }
133
37.9k
134
37.9k
  const llvm::Triple::ArchType ArchType = Triple.getArch();
135
  // Add features to be compatible with gcc for Android.
136
37.9k
  if (Triple.isAndroid()) {
137
37
    if (ArchType == llvm::Triple::x86_64) {
138
15
      Features.push_back("+sse4.2");
139
15
      Features.push_back("+popcnt");
140
15
      Features.push_back("+cx16");
141
15
    } else
142
22
      Features.push_back("+ssse3");
143
37
  }
144
37.9k
145
  // Translate the high level `-mretpoline` flag to the specific target feature
146
  // flags. We also detect if the user asked for retpoline external thunks but
147
  // failed to ask for retpolines themselves (through any of the different
148
  // flags). This is a bit hacky but keeps existing usages working. We should
149
  // consider deprecating this and instead warn if the user requests external
150
  // retpoline thunks and *doesn't* request some form of retpolines.
151
37.9k
  auto SpectreOpt = clang::driver::options::ID::OPT_INVALID;
152
37.9k
  if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline,
153
37.9k
                         options::OPT_mspeculative_load_hardening,
154
18
                         options::OPT_mno_speculative_load_hardening)) {
155
18
    if (Args.hasFlag(options::OPT_mretpoline, options::OPT_mno_retpoline,
156
7
                     false)) {
157
7
      Features.push_back("+retpoline-indirect-calls");
158
7
      Features.push_back("+retpoline-indirect-branches");
159
7
      SpectreOpt = options::OPT_mretpoline;
160
11
    } else if (Args.hasFlag(options::OPT_mspeculative_load_hardening,
161
11
                            options::OPT_mno_speculative_load_hardening,
162
5
                            false)) {
163
      // On x86, speculative load hardening relies on at least using retpolines
164
      // for indirect calls.
165
5
      Features.push_back("+retpoline-indirect-calls");
166
5
      SpectreOpt = options::OPT_mspeculative_load_hardening;
167
5
    }
168
37.9k
  } else if (Args.hasFlag(options::OPT_mretpoline_external_thunk,
169
3
                          options::OPT_mno_retpoline_external_thunk, false)) {
170
    // FIXME: Add a warning about failing to specify `-mretpoline` and
171
    // eventually switch to an error here.
172
3
    Features.push_back("+retpoline-indirect-calls");
173
3
    Features.push_back("+retpoline-indirect-branches");
174
3
    SpectreOpt = options::OPT_mretpoline_external_thunk;
175
3
  }
176
37.9k
177
37.9k
  auto LVIOpt = clang::driver::options::ID::OPT_INVALID;
178
37.9k
  if (Args.hasFlag(options::OPT_mlvi_hardening, options::OPT_mno_lvi_hardening,
179
5
                   false)) {
180
5
    Features.push_back("+lvi-load-hardening");
181
5
    Features.push_back("+lvi-cfi"); // load hardening implies CFI protection
182
5
    LVIOpt = options::OPT_mlvi_hardening;
183
37.9k
  } else if (Args.hasFlag(options::OPT_mlvi_cfi, options::OPT_mno_lvi_cfi,
184
4
                          false)) {
185
4
    Features.push_back("+lvi-cfi");
186
4
    LVIOpt = options::OPT_mlvi_cfi;
187
4
  }
188
37.9k
189
37.9k
  if (Args.hasFlag(options::OPT_m_seses, options::OPT_mno_seses, false)) {
190
6
    if (LVIOpt == options::OPT_mlvi_hardening)
191
1
      D.Diag(diag::err_drv_argument_not_allowed_with)
192
1
          << D.getOpts().getOptionName(options::OPT_mlvi_hardening)
193
1
          << D.getOpts().getOptionName(options::OPT_m_seses);
194
6
195
6
    if (SpectreOpt != clang::driver::options::ID::OPT_INVALID)
196
3
      D.Diag(diag::err_drv_argument_not_allowed_with)
197
3
          << D.getOpts().getOptionName(SpectreOpt)
198
3
          << D.getOpts().getOptionName(options::OPT_m_seses);
199
6
200
6
    Features.push_back("+seses");
201
6
    if (!Args.hasArg(options::OPT_mno_lvi_cfi)) {
202
5
      Features.push_back("+lvi-cfi");
203
5
      LVIOpt = options::OPT_mlvi_cfi;
204
5
    }
205
6
  }
206
37.9k
207
37.9k
  if (SpectreOpt != clang::driver::options::ID::OPT_INVALID &&
208
15
      LVIOpt != clang::driver::options::ID::OPT_INVALID) {
209
9
    D.Diag(diag::err_drv_argument_not_allowed_with)
210
9
        << D.getOpts().getOptionName(SpectreOpt)
211
9
        << D.getOpts().getOptionName(LVIOpt);
212
9
  }
213
37.9k
214
  // Now add any that the user explicitly requested on the command line,
215
  // which may override the defaults.
216
37.9k
  handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);
217
37.9k
}