Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- LoongArch.cpp - LoongArch 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 "LoongArch.h"
10
#include "ToolChains/CommonArgs.h"
11
#include "clang/Basic/DiagnosticDriver.h"
12
#include "clang/Driver/Driver.h"
13
#include "clang/Driver/DriverDiagnostic.h"
14
#include "clang/Driver/Options.h"
15
#include "llvm/TargetParser/Host.h"
16
#include "llvm/TargetParser/LoongArchTargetParser.h"
17
18
using namespace clang::driver;
19
using namespace clang::driver::tools;
20
using namespace clang;
21
using namespace llvm::opt;
22
23
StringRef loongarch::getLoongArchABI(const Driver &D, const ArgList &Args,
24
167
                                     const llvm::Triple &Triple) {
25
167
  assert((Triple.getArch() == llvm::Triple::loongarch32 ||
26
167
          Triple.getArch() == llvm::Triple::loongarch64) &&
27
167
         "Unexpected triple");
28
167
  bool IsLA32 = Triple.getArch() == llvm::Triple::loongarch32;
29
30
  // Record -mabi value for later use.
31
167
  const Arg *MABIArg = Args.getLastArg(options::OPT_mabi_EQ);
32
167
  StringRef MABIValue;
33
167
  if (MABIArg) {
34
48
    MABIValue = MABIArg->getValue();
35
48
  }
36
37
  // Parse -mfpu value for later use.
38
167
  const Arg *MFPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
39
167
  int FPU = -1;
40
167
  if (MFPUArg) {
41
30
    StringRef V = MFPUArg->getValue();
42
30
    if (V == "64")
43
11
      FPU = 64;
44
19
    else if (V == "32")
45
7
      FPU = 32;
46
12
    else if (V == "0" || 
V == "none"6
)
47
11
      FPU = 0;
48
1
    else
49
1
      D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << V;
50
30
  }
51
52
  // Check -m*-float firstly since they have highest priority.
53
167
  if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
54
167
                                     options::OPT_msingle_float,
55
167
                                     options::OPT_msoft_float)) {
56
19
    StringRef ImpliedABI;
57
19
    int ImpliedFPU = -1;
58
19
    if (A->getOption().matches(options::OPT_mdouble_float)) {
59
7
      ImpliedABI = IsLA32 ? 
"ilp32d"1
:
"lp64d"6
;
60
7
      ImpliedFPU = 64;
61
7
    }
62
19
    if (A->getOption().matches(options::OPT_msingle_float)) {
63
6
      ImpliedABI = IsLA32 ? 
"ilp32f"1
:
"lp64f"5
;
64
6
      ImpliedFPU = 32;
65
6
    }
66
19
    if (A->getOption().matches(options::OPT_msoft_float)) {
67
6
      ImpliedABI = IsLA32 ? 
"ilp32s"1
:
"lp64s"5
;
68
6
      ImpliedFPU = 0;
69
6
    }
70
71
    // Check `-mabi=` and `-mfpu=` settings and report if they conflict with
72
    // the higher-priority settings implied by -m*-float.
73
    //
74
    // ImpliedABI and ImpliedFPU are guaranteed to have valid values because
75
    // one of the match arms must match if execution can arrive here at all.
76
19
    if (!MABIValue.empty() && 
ImpliedABI != MABIValue7
)
77
4
      D.Diag(diag::warn_drv_loongarch_conflicting_implied_val)
78
4
          << MABIArg->getAsString(Args) << A->getAsString(Args) << ImpliedABI;
79
80
19
    if (FPU != -1 && 
ImpliedFPU != FPU7
)
81
4
      D.Diag(diag::warn_drv_loongarch_conflicting_implied_val)
82
4
          << MFPUArg->getAsString(Args) << A->getAsString(Args) << ImpliedFPU;
83
84
19
    return ImpliedABI;
85
19
  }
86
87
  // If `-mabi=` is specified, use it.
88
148
  if (!MABIValue.empty())
89
41
    return MABIValue;
90
91
  // Select abi based on -mfpu=xx.
92
107
  switch (FPU) {
93
2
  case 64:
94
2
    return IsLA32 ? 
"ilp32d"0
: "lp64d";
95
2
  case 32:
96
2
    return IsLA32 ? 
"ilp32f"0
: "lp64f";
97
4
  case 0:
98
4
    return IsLA32 ? 
"ilp32s"0
: "lp64s";
99
107
  }
100
101
  // Choose a default based on the triple.
102
  // Honor the explicit ABI modifier suffix in triple's environment part if
103
  // present, falling back to {ILP32,LP64}D otherwise.
104
99
  switch (Triple.getEnvironment()) {
105
4
  case llvm::Triple::GNUSF:
106
4
    return IsLA32 ? 
"ilp32s"1
:
"lp64s"3
;
107
4
  case llvm::Triple::GNUF32:
108
4
    return IsLA32 ? 
"ilp32f"1
:
"lp64f"3
;
109
7
  case llvm::Triple::GNUF64:
110
    // This was originally permitted (and indeed the canonical way) to
111
    // represent the {ILP32,LP64}D ABIs, but in Feb 2023 Loongson decided to
112
    // drop the explicit suffix in favor of unmarked `-gnu` for the
113
    // "general-purpose" ABIs, among other non-technical reasons.
114
    //
115
    // The spec change did not mention whether existing usages of "gnuf64"
116
    // shall remain valid or not, so we are going to continue recognizing it
117
    // for some time, until it is clear that everyone else has migrated away
118
    // from it.
119
7
    [[fallthrough]];
120
22
  case llvm::Triple::GNU:
121
91
  default:
122
91
    return IsLA32 ? 
"ilp32d"13
:
"lp64d"78
;
123
99
  }
124
99
}
125
126
void loongarch::getLoongArchTargetFeatures(const Driver &D,
127
                                           const llvm::Triple &Triple,
128
                                           const ArgList &Args,
129
153
                                           std::vector<StringRef> &Features) {
130
153
  std::string ArchName;
131
153
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
132
10
    ArchName = A->getValue();
133
153
  ArchName = postProcessTargetCPUString(ArchName, Triple);
134
153
  llvm::LoongArch::getArchFeatures(ArchName, Features);
135
136
  // Select floating-point features determined by -mdouble-float,
137
  // -msingle-float, -msoft-float and -mfpu.
138
  // Note: -m*-float wins any other options.
139
153
  if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
140
153
                                     options::OPT_msingle_float,
141
153
                                     options::OPT_msoft_float)) {
142
19
    if (A->getOption().matches(options::OPT_mdouble_float)) {
143
7
      Features.push_back("+f");
144
7
      Features.push_back("+d");
145
12
    } else if (A->getOption().matches(options::OPT_msingle_float)) {
146
6
      Features.push_back("+f");
147
6
      Features.push_back("-d");
148
6
    } else /*Soft-float*/ {
149
6
      Features.push_back("-f");
150
6
      Features.push_back("-d");
151
6
    }
152
134
  } else if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
153
23
    StringRef FPU = A->getValue();
154
23
    if (FPU == "64") {
155
8
      Features.push_back("+f");
156
8
      Features.push_back("+d");
157
15
    } else if (FPU == "32") {
158
6
      Features.push_back("+f");
159
6
      Features.push_back("-d");
160
9
    } else if (FPU == "0" || 
FPU == "none"5
) {
161
8
      Features.push_back("-f");
162
8
      Features.push_back("-d");
163
8
    } else {
164
1
      D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;
165
1
    }
166
23
  }
167
168
  // Select the `ual` feature determined by -m[no-]unaligned-access
169
  // or the alias -m[no-]strict-align.
170
153
  AddTargetFeature(Args, Features, options::OPT_munaligned_access,
171
153
                   options::OPT_mno_unaligned_access, "ual");
172
173
  // Accept but warn about these TargetSpecific options.
174
153
  if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))
175
44
    A->ignoreTargetSpecific();
176
153
  if (Arg *A = Args.getLastArgNoClaim(options::OPT_mfpu_EQ))
177
30
    A->ignoreTargetSpecific();
178
153
}
179
180
std::string loongarch::postProcessTargetCPUString(const std::string &CPU,
181
320
                                                  const llvm::Triple &Triple) {
182
320
  std::string CPUString = CPU;
183
320
  if (CPUString == "native") {
184
0
    CPUString = llvm::sys::getHostCPUName();
185
0
    if (CPUString == "generic")
186
0
      CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64());
187
0
  }
188
320
  if (CPUString.empty())
189
286
    CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64());
190
320
  return CPUString;
191
320
}
192
193
std::string loongarch::getLoongArchTargetCPU(const llvm::opt::ArgList &Args,
194
153
                                             const llvm::Triple &Triple) {
195
153
  std::string CPU;
196
  // If we have -march, use that.
197
153
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
198
10
    CPU = A->getValue();
199
153
  return postProcessTargetCPUString(CPU, Triple);
200
153
}