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