xref: /openbsd-src/gnu/llvm/clang/lib/Driver/ToolChains/Arch/PPC.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
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