/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- PPC.cpp - PPC 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 "PPC.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/TargetParser/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 | 545 | static std::string getPPCGenericTargetCPU(const llvm::Triple &T) { |
24 | | // LLVM may default to generating code for the native CPU, |
25 | | // but, like gcc, we default to a more generic option for |
26 | | // each architecture. (except on AIX) |
27 | 545 | if (T.isOSAIX()) |
28 | 246 | return "pwr7"; |
29 | 299 | else if (T.getArch() == llvm::Triple::ppc64le) |
30 | 76 | return "ppc64le"; |
31 | 223 | else if (T.getArch() == llvm::Triple::ppc64) |
32 | 155 | return "ppc64"; |
33 | 68 | else |
34 | 68 | return "ppc"; |
35 | 545 | } |
36 | | |
37 | 255 | static std::string normalizeCPUName(StringRef CPUName, const llvm::Triple &T) { |
38 | | // Clang/LLVM does not actually support code generation |
39 | | // for the 405 CPU. However, there are uses of this CPU ID |
40 | | // in projects that previously used GCC and rely on Clang |
41 | | // accepting it. Clang has always ignored it and passed the |
42 | | // generic CPU ID to the back end. |
43 | 255 | if (CPUName == "generic" || CPUName == "405"253 ) |
44 | 3 | return getPPCGenericTargetCPU(T); |
45 | | |
46 | 252 | if (CPUName == "native") { |
47 | 1 | std::string CPU = std::string(llvm::sys::getHostCPUName()); |
48 | 1 | if (!CPU.empty() && CPU != "generic") |
49 | 1 | return CPU; |
50 | 0 | else |
51 | 0 | return getPPCGenericTargetCPU(T); |
52 | 1 | } |
53 | | |
54 | 251 | return llvm::StringSwitch<const char *>(CPUName) |
55 | 251 | .Case("common", "generic") |
56 | 251 | .Case("440fp", "440") |
57 | 251 | .Case("630", "pwr3") |
58 | 251 | .Case("G3", "g3") |
59 | 251 | .Case("G4", "g4") |
60 | 251 | .Case("G4+", "g4+") |
61 | 251 | .Case("8548", "e500") |
62 | 251 | .Case("G5", "g5") |
63 | 251 | .Case("power3", "pwr3") |
64 | 251 | .Case("power4", "pwr4") |
65 | 251 | .Case("power5", "pwr5") |
66 | 251 | .Case("power5x", "pwr5x") |
67 | 251 | .Case("power6", "pwr6") |
68 | 251 | .Case("power6x", "pwr6x") |
69 | 251 | .Case("power7", "pwr7") |
70 | 251 | .Case("power8", "pwr8") |
71 | 251 | .Case("power9", "pwr9") |
72 | 251 | .Case("power10", "pwr10") |
73 | 251 | .Case("future", "future") |
74 | 251 | .Case("powerpc", "ppc") |
75 | 251 | .Case("powerpc64", "ppc64") |
76 | 251 | .Case("powerpc64le", "ppc64le") |
77 | 251 | .Default(CPUName.data()); |
78 | 252 | } |
79 | | |
80 | | /// Get the (LLVM) name of the PowerPC cpu we are tuning for. |
81 | 2 | std::string ppc::getPPCTuneCPU(const ArgList &Args, const llvm::Triple &T) { |
82 | 2 | if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) |
83 | 2 | return normalizeCPUName(A->getValue(), T); |
84 | 0 | return getPPCGenericTargetCPU(T); |
85 | 2 | } |
86 | | |
87 | | /// Get the (LLVM) name of the PowerPC cpu we are targeting. |
88 | | std::string ppc::getPPCTargetCPU(const Driver &D, const ArgList &Args, |
89 | 795 | const llvm::Triple &T) { |
90 | 795 | if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) |
91 | 253 | return normalizeCPUName(A->getValue(), T); |
92 | 542 | return getPPCGenericTargetCPU(T); |
93 | 795 | } |
94 | | |
95 | 12 | const char *ppc::getPPCAsmModeForCPU(StringRef Name) { |
96 | 12 | return llvm::StringSwitch<const char *>(Name) |
97 | 12 | .Case("pwr7", "-mpower7") |
98 | 12 | .Case("power7", "-mpower7") |
99 | 12 | .Case("pwr8", "-mpower8") |
100 | 12 | .Case("power8", "-mpower8") |
101 | 12 | .Case("ppc64le", "-mpower8") |
102 | 12 | .Case("pwr9", "-mpower9") |
103 | 12 | .Case("power9", "-mpower9") |
104 | 12 | .Case("pwr10", "-mpower10") |
105 | 12 | .Case("power10", "-mpower10") |
106 | 12 | .Default("-many"); |
107 | 12 | } |
108 | | |
109 | | void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, |
110 | | const ArgList &Args, |
111 | 597 | std::vector<StringRef> &Features) { |
112 | 597 | if (Triple.getSubArch() == llvm::Triple::PPCSubArch_spe) |
113 | 3 | Features.push_back("+spe"); |
114 | | |
115 | 597 | handleTargetFeaturesGroup(D, Triple, Args, Features, |
116 | 597 | options::OPT_m_ppc_Features_Group); |
117 | | |
118 | 597 | ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args); |
119 | 597 | if (FloatABI == ppc::FloatABI::Soft) |
120 | 9 | Features.push_back("-hard-float"); |
121 | | |
122 | 597 | ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Triple, Args); |
123 | 597 | if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt) |
124 | 18 | Features.push_back("+secure-plt"); |
125 | 597 | } |
126 | | |
127 | | ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple, |
128 | 597 | const ArgList &Args) { |
129 | 597 | if (Args.getLastArg(options::OPT_msecure_plt)) |
130 | 1 | return ppc::ReadGOTPtrMode::SecurePlt; |
131 | 596 | if (Triple.isPPC32SecurePlt()) |
132 | 17 | return ppc::ReadGOTPtrMode::SecurePlt; |
133 | 579 | else |
134 | 579 | return ppc::ReadGOTPtrMode::Bss; |
135 | 596 | } |
136 | | |
137 | 1.19k | ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) { |
138 | 1.19k | ppc::FloatABI ABI = ppc::FloatABI::Invalid; |
139 | 1.19k | if (Arg *A = |
140 | 1.19k | Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, |
141 | 1.19k | options::OPT_mfloat_abi_EQ)) { |
142 | 26 | if (A->getOption().matches(options::OPT_msoft_float)) |
143 | 12 | ABI = ppc::FloatABI::Soft; |
144 | 14 | else if (A->getOption().matches(options::OPT_mhard_float)) |
145 | 4 | ABI = ppc::FloatABI::Hard; |
146 | 10 | else { |
147 | 10 | ABI = llvm::StringSwitch<ppc::FloatABI>(A->getValue()) |
148 | 10 | .Case("soft", ppc::FloatABI::Soft) |
149 | 10 | .Case("hard", ppc::FloatABI::Hard) |
150 | 10 | .Default(ppc::FloatABI::Invalid); |
151 | 10 | if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()2 ) { |
152 | 2 | D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
153 | 2 | ABI = ppc::FloatABI::Hard; |
154 | 2 | } |
155 | 10 | } |
156 | 26 | } |
157 | | |
158 | | // If unspecified, choose the default based on the platform. |
159 | 1.19k | if (ABI == ppc::FloatABI::Invalid) { |
160 | 1.16k | ABI = ppc::FloatABI::Hard; |
161 | 1.16k | } |
162 | | |
163 | 1.19k | return ABI; |
164 | 1.19k | } |
165 | | |
166 | 94 | bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) { |
167 | 94 | Arg *A = Args.getLastArg(options::OPT_mabi_EQ); |
168 | 94 | return A && (A->getValue() == StringRef(Value))21 ; |
169 | 94 | } |