xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp (revision 9c77fb6aaa366cbabc80ee1b834bcfe4df135491)
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 "clang/Driver/CommonArgs.h"
11 #include "clang/Driver/Driver.h"
12 #include "clang/Driver/Options.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/Option/ArgList.h"
15 #include "llvm/TargetParser/Host.h"
16 
17 using namespace clang::driver;
18 using namespace clang::driver::tools;
19 using namespace clang;
20 using namespace llvm::opt;
21 
22 const char *ppc::getPPCAsmModeForCPU(StringRef Name) {
23   return llvm::StringSwitch<const char *>(Name)
24       .Case("pwr7", "-mpower7")
25       .Case("power7", "-mpower7")
26       .Case("pwr8", "-mpower8")
27       .Case("power8", "-mpower8")
28       .Case("ppc64le", "-mpower8")
29       .Case("pwr9", "-mpower9")
30       .Case("power9", "-mpower9")
31       .Case("pwr10", "-mpower10")
32       .Case("power10", "-mpower10")
33       .Case("pwr11", "-mpower11")
34       .Case("power11", "-mpower11")
35       .Default("-many");
36 }
37 
38 void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
39                                const ArgList &Args,
40                                std::vector<StringRef> &Features) {
41   if (Triple.getSubArch() == llvm::Triple::PPCSubArch_spe)
42     Features.push_back("+spe");
43 
44   handleTargetFeaturesGroup(D, Triple, Args, Features,
45                             options::OPT_m_ppc_Features_Group);
46 
47   ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
48   if (FloatABI == ppc::FloatABI::Soft)
49     Features.push_back("-hard-float");
50 
51   ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Triple, Args);
52   if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt)
53     Features.push_back("+secure-plt");
54 
55   bool UseSeparateSections = isUseSeparateSections(Triple);
56   bool HasDefaultDataSections = Triple.isOSBinFormatXCOFF();
57   if (Args.hasArg(options::OPT_maix_small_local_exec_tls) ||
58       Args.hasArg(options::OPT_maix_small_local_dynamic_tls)) {
59     if (!Triple.isOSAIX() || !Triple.isArch64Bit())
60       D.Diag(diag::err_opt_not_valid_on_target)
61           << "-maix-small-local-[exec|dynamic]-tls";
62 
63     // The -maix-small-local-[exec|dynamic]-tls option should only be used with
64     // -fdata-sections, as having data sections turned off with this option
65     // is not ideal for performance. Moreover, the
66     // small-local-[exec|dynamic]-tls region is a limited resource, and should
67     // not be used for variables that may be replaced.
68     if (!Args.hasFlag(options::OPT_fdata_sections,
69                       options::OPT_fno_data_sections,
70                       UseSeparateSections || HasDefaultDataSections))
71       D.Diag(diag::err_drv_argument_only_allowed_with)
72           << "-maix-small-local-[exec|dynamic]-tls" << "-fdata-sections";
73   }
74 
75   if (Args.hasArg(options::OPT_maix_shared_lib_tls_model_opt) &&
76       !(Triple.isOSAIX() && Triple.isArch64Bit()))
77     D.Diag(diag::err_opt_not_valid_on_target)
78         << "-maix-shared-lib-tls-model-opt";
79 }
80 
81 ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
82                                               const ArgList &Args) {
83   if (Args.getLastArg(options::OPT_msecure_plt))
84     return ppc::ReadGOTPtrMode::SecurePlt;
85   if (Triple.isPPC32SecurePlt())
86     return ppc::ReadGOTPtrMode::SecurePlt;
87   else
88     return ppc::ReadGOTPtrMode::Bss;
89 }
90 
91 ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
92   ppc::FloatABI ABI = ppc::FloatABI::Invalid;
93   if (Arg *A =
94           Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
95                           options::OPT_mfloat_abi_EQ)) {
96     if (A->getOption().matches(options::OPT_msoft_float))
97       ABI = ppc::FloatABI::Soft;
98     else if (A->getOption().matches(options::OPT_mhard_float))
99       ABI = ppc::FloatABI::Hard;
100     else {
101       ABI = llvm::StringSwitch<ppc::FloatABI>(A->getValue())
102                 .Case("soft", ppc::FloatABI::Soft)
103                 .Case("hard", ppc::FloatABI::Hard)
104                 .Default(ppc::FloatABI::Invalid);
105       if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
106         D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
107         ABI = ppc::FloatABI::Hard;
108       }
109     }
110   }
111 
112   // If unspecified, choose the default based on the platform.
113   if (ABI == ppc::FloatABI::Invalid) {
114     ABI = ppc::FloatABI::Hard;
115   }
116 
117   return ABI;
118 }
119 
120 bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) {
121   Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
122   return A && (A->getValue() == StringRef(Value));
123 }
124