xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceClFlags.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceClFlags.cpp - Command line flags and parsing --------===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Defines commandline flags parsing of class Ice::ClFlags.
12*03ce13f7SAndroid Build Coastguard Worker ///
13*03ce13f7SAndroid Build Coastguard Worker /// This currently relies on llvm::cl to parse. In the future, the minimal build
14*03ce13f7SAndroid Build Coastguard Worker /// can have a simpler parser.
15*03ce13f7SAndroid Build Coastguard Worker ///
16*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "IceClFlags.h"
19*03ce13f7SAndroid Build Coastguard Worker 
20*03ce13f7SAndroid Build Coastguard Worker #include "IceClFlags.def"
21*03ce13f7SAndroid Build Coastguard Worker 
22*03ce13f7SAndroid Build Coastguard Worker #ifdef __clang__
23*03ce13f7SAndroid Build Coastguard Worker #pragma clang diagnostic push
24*03ce13f7SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wunused-parameter"
25*03ce13f7SAndroid Build Coastguard Worker #endif // __clang__
26*03ce13f7SAndroid Build Coastguard Worker 
27*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
28*03ce13f7SAndroid Build Coastguard Worker 
29*03ce13f7SAndroid Build Coastguard Worker #ifdef __clang__
30*03ce13f7SAndroid Build Coastguard Worker #pragma clang diagnostic pop
31*03ce13f7SAndroid Build Coastguard Worker #endif // __clang__
32*03ce13f7SAndroid Build Coastguard Worker 
33*03ce13f7SAndroid Build Coastguard Worker #include <utility>
34*03ce13f7SAndroid Build Coastguard Worker 
35*03ce13f7SAndroid Build Coastguard Worker namespace {
36*03ce13f7SAndroid Build Coastguard Worker // cl is used to alias the llvm::cl types and functions that we need.
37*03ce13f7SAndroid Build Coastguard Worker namespace cl {
38*03ce13f7SAndroid Build Coastguard Worker 
39*03ce13f7SAndroid Build Coastguard Worker using alias = llvm::cl::alias;
40*03ce13f7SAndroid Build Coastguard Worker 
41*03ce13f7SAndroid Build Coastguard Worker using aliasopt = llvm::cl::aliasopt;
42*03ce13f7SAndroid Build Coastguard Worker 
43*03ce13f7SAndroid Build Coastguard Worker using llvm::cl::CommaSeparated;
44*03ce13f7SAndroid Build Coastguard Worker 
45*03ce13f7SAndroid Build Coastguard Worker using desc = llvm::cl::desc;
46*03ce13f7SAndroid Build Coastguard Worker 
47*03ce13f7SAndroid Build Coastguard Worker template <typename T> using initializer = llvm::cl::initializer<T>;
48*03ce13f7SAndroid Build Coastguard Worker 
init(const T & Val)49*03ce13f7SAndroid Build Coastguard Worker template <typename T> initializer<T> init(const T &Val) {
50*03ce13f7SAndroid Build Coastguard Worker   return initializer<T>(Val);
51*03ce13f7SAndroid Build Coastguard Worker }
52*03ce13f7SAndroid Build Coastguard Worker 
53*03ce13f7SAndroid Build Coastguard Worker template <typename T> using list = llvm::cl::list<T>;
54*03ce13f7SAndroid Build Coastguard Worker 
55*03ce13f7SAndroid Build Coastguard Worker using llvm::cl::NotHidden;
56*03ce13f7SAndroid Build Coastguard Worker 
57*03ce13f7SAndroid Build Coastguard Worker template <typename T> using opt = llvm::cl::opt<T>;
58*03ce13f7SAndroid Build Coastguard Worker 
59*03ce13f7SAndroid Build Coastguard Worker using llvm::cl::ParseCommandLineOptions;
60*03ce13f7SAndroid Build Coastguard Worker 
61*03ce13f7SAndroid Build Coastguard Worker using llvm::cl::Positional;
62*03ce13f7SAndroid Build Coastguard Worker 
63*03ce13f7SAndroid Build Coastguard Worker // LLVM commit 3ffe113e11168abcd809ec5ac539538ade5db0cb changed the internals of
64*03ce13f7SAndroid Build Coastguard Worker // llvm::cl that need to be mirrored here.  That commit removed the clEnumValEnd
65*03ce13f7SAndroid Build Coastguard Worker // macro, so we can use that to determine which version of LLVM we're compiling
66*03ce13f7SAndroid Build Coastguard Worker // against.
67*03ce13f7SAndroid Build Coastguard Worker #if defined(clEnumValEnd)
68*03ce13f7SAndroid Build Coastguard Worker 
69*03ce13f7SAndroid Build Coastguard Worker #define CLENUMVALEND , clEnumValEnd
70*03ce13f7SAndroid Build Coastguard Worker 
71*03ce13f7SAndroid Build Coastguard Worker template <typename T> using ValuesClass = llvm::cl::ValuesClass<T>;
72*03ce13f7SAndroid Build Coastguard Worker 
73*03ce13f7SAndroid Build Coastguard Worker template <typename T, typename... A>
values(const char * Arg,T Val,const char * Desc,A &&...Args)74*03ce13f7SAndroid Build Coastguard Worker ValuesClass<T> values(const char *Arg, T Val, const char *Desc, A &&... Args) {
75*03ce13f7SAndroid Build Coastguard Worker   return llvm::cl::values(Arg, Val, Desc, std::forward<A>(Args)..., nullptr);
76*03ce13f7SAndroid Build Coastguard Worker }
77*03ce13f7SAndroid Build Coastguard Worker 
78*03ce13f7SAndroid Build Coastguard Worker #else // !defined(clEnumValEnd)
79*03ce13f7SAndroid Build Coastguard Worker 
80*03ce13f7SAndroid Build Coastguard Worker #define CLENUMVALEND
81*03ce13f7SAndroid Build Coastguard Worker 
82*03ce13f7SAndroid Build Coastguard Worker using llvm::cl::OptionEnumValue;
83*03ce13f7SAndroid Build Coastguard Worker 
values(A &&...Args)84*03ce13f7SAndroid Build Coastguard Worker template <typename... A> llvm::cl::ValuesClass values(A &&... Args) {
85*03ce13f7SAndroid Build Coastguard Worker   return llvm::cl::values(std::forward<A>(Args)...);
86*03ce13f7SAndroid Build Coastguard Worker }
87*03ce13f7SAndroid Build Coastguard Worker 
88*03ce13f7SAndroid Build Coastguard Worker #endif // !defined(clEnumValEnd)
89*03ce13f7SAndroid Build Coastguard Worker 
90*03ce13f7SAndroid Build Coastguard Worker using llvm::cl::value_desc;
91*03ce13f7SAndroid Build Coastguard Worker } // end of namespace cl
92*03ce13f7SAndroid Build Coastguard Worker 
93*03ce13f7SAndroid Build Coastguard Worker // cl_type_traits is used to convert between a tuple of <T, cl_detail::*flag> to
94*03ce13f7SAndroid Build Coastguard Worker // the appropriate (llvm::)cl object.
95*03ce13f7SAndroid Build Coastguard Worker template <typename B, typename CL> struct cl_type_traits {};
96*03ce13f7SAndroid Build Coastguard Worker 
97*03ce13f7SAndroid Build Coastguard Worker template <typename T>
98*03ce13f7SAndroid Build Coastguard Worker struct cl_type_traits<T, ::Ice::cl_detail::dev_list_flag> {
99*03ce13f7SAndroid Build Coastguard Worker   using cl_type = cl::list<T>;
100*03ce13f7SAndroid Build Coastguard Worker };
101*03ce13f7SAndroid Build Coastguard Worker 
102*03ce13f7SAndroid Build Coastguard Worker template <typename T> struct cl_type_traits<T, ::Ice::cl_detail::dev_opt_flag> {
103*03ce13f7SAndroid Build Coastguard Worker   using cl_type = cl::opt<T>;
104*03ce13f7SAndroid Build Coastguard Worker };
105*03ce13f7SAndroid Build Coastguard Worker 
106*03ce13f7SAndroid Build Coastguard Worker template <typename T>
107*03ce13f7SAndroid Build Coastguard Worker struct cl_type_traits<T, ::Ice::cl_detail::release_opt_flag> {
108*03ce13f7SAndroid Build Coastguard Worker   using cl_type = cl::opt<T>;
109*03ce13f7SAndroid Build Coastguard Worker };
110*03ce13f7SAndroid Build Coastguard Worker 
111*03ce13f7SAndroid Build Coastguard Worker #define X(Name, Type, ClType, ...)                                             \
112*03ce13f7SAndroid Build Coastguard Worker   cl_type_traits<Type, Ice::cl_detail::ClType>::cl_type Name##Obj(__VA_ARGS__);
113*03ce13f7SAndroid Build Coastguard Worker COMMAND_LINE_FLAGS
114*03ce13f7SAndroid Build Coastguard Worker #undef X
115*03ce13f7SAndroid Build Coastguard Worker 
116*03ce13f7SAndroid Build Coastguard Worker // Add declarations that do not need to add members to ClFlags below.
117*03ce13f7SAndroid Build Coastguard Worker cl::alias AllowExternDefinedSymbolsA(
118*03ce13f7SAndroid Build Coastguard Worker     "allow-extern", cl::desc("Alias for --allow-externally-defined-symbols"),
119*03ce13f7SAndroid Build Coastguard Worker     cl::NotHidden, cl::aliasopt(AllowExternDefinedSymbolsObj));
120*03ce13f7SAndroid Build Coastguard Worker 
121*03ce13f7SAndroid Build Coastguard Worker std::string AppNameObj;
122*03ce13f7SAndroid Build Coastguard Worker 
123*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
124*03ce13f7SAndroid Build Coastguard Worker 
125*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
126*03ce13f7SAndroid Build Coastguard Worker 
127*03ce13f7SAndroid Build Coastguard Worker ClFlags ClFlags::Flags;
128*03ce13f7SAndroid Build Coastguard Worker 
parseFlags(int argc,const char * const * argv)129*03ce13f7SAndroid Build Coastguard Worker void ClFlags::parseFlags(int argc, const char *const *argv) {
130*03ce13f7SAndroid Build Coastguard Worker   cl::ParseCommandLineOptions(argc, argv);
131*03ce13f7SAndroid Build Coastguard Worker   AppNameObj = argv[0];
132*03ce13f7SAndroid Build Coastguard Worker }
133*03ce13f7SAndroid Build Coastguard Worker 
134*03ce13f7SAndroid Build Coastguard Worker namespace {
135*03ce13f7SAndroid Build Coastguard Worker // flagInitOrStorageTypeDefault is some template voodoo for peeling off the
136*03ce13f7SAndroid Build Coastguard Worker // llvm::cl modifiers from a flag's declaration, until its initial value is
137*03ce13f7SAndroid Build Coastguard Worker // found. If none is found, then the default value for the storage type is
138*03ce13f7SAndroid Build Coastguard Worker // returned.
flagInitOrStorageTypeDefault()139*03ce13f7SAndroid Build Coastguard Worker template <typename Ty> Ty flagInitOrStorageTypeDefault() { return Ty(); }
140*03ce13f7SAndroid Build Coastguard Worker 
141*03ce13f7SAndroid Build Coastguard Worker template <typename Ty, typename T, typename... A>
flagInitOrStorageTypeDefault(cl::initializer<T> && Value,A &&...)142*03ce13f7SAndroid Build Coastguard Worker Ty flagInitOrStorageTypeDefault(cl::initializer<T> &&Value, A &&...) {
143*03ce13f7SAndroid Build Coastguard Worker   return Value.Init;
144*03ce13f7SAndroid Build Coastguard Worker }
145*03ce13f7SAndroid Build Coastguard Worker 
146*03ce13f7SAndroid Build Coastguard Worker // is_cl_initializer is used to prevent an ambiguous call between the previous
147*03ce13f7SAndroid Build Coastguard Worker // version of flagInitOrStorageTypeDefault, and the next, which is flagged by
148*03ce13f7SAndroid Build Coastguard Worker // g++.
149*03ce13f7SAndroid Build Coastguard Worker template <typename T> struct is_cl_initializer {
150*03ce13f7SAndroid Build Coastguard Worker   static constexpr bool value = false;
151*03ce13f7SAndroid Build Coastguard Worker };
152*03ce13f7SAndroid Build Coastguard Worker 
153*03ce13f7SAndroid Build Coastguard Worker template <typename T> struct is_cl_initializer<cl::initializer<T>> {
154*03ce13f7SAndroid Build Coastguard Worker   static constexpr bool value = true;
155*03ce13f7SAndroid Build Coastguard Worker };
156*03ce13f7SAndroid Build Coastguard Worker 
157*03ce13f7SAndroid Build Coastguard Worker template <typename Ty, typename T, typename... A>
158*03ce13f7SAndroid Build Coastguard Worker typename std::enable_if<!is_cl_initializer<T>::value, Ty>::type
flagInitOrStorageTypeDefault(T &&,A &&...Other)159*03ce13f7SAndroid Build Coastguard Worker flagInitOrStorageTypeDefault(T &&, A &&... Other) {
160*03ce13f7SAndroid Build Coastguard Worker   return flagInitOrStorageTypeDefault<Ty>(std::forward<A>(Other)...);
161*03ce13f7SAndroid Build Coastguard Worker }
162*03ce13f7SAndroid Build Coastguard Worker 
163*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
164*03ce13f7SAndroid Build Coastguard Worker 
resetClFlags()165*03ce13f7SAndroid Build Coastguard Worker void ClFlags::resetClFlags() {
166*03ce13f7SAndroid Build Coastguard Worker #define X(Name, Type, ClType, ...)                                             \
167*03ce13f7SAndroid Build Coastguard Worker   Name = flagInitOrStorageTypeDefault<                                         \
168*03ce13f7SAndroid Build Coastguard Worker       detail::cl_type_traits<Type, cl_detail::ClType>::storage_type>(          \
169*03ce13f7SAndroid Build Coastguard Worker       __VA_ARGS__);
170*03ce13f7SAndroid Build Coastguard Worker   COMMAND_LINE_FLAGS
171*03ce13f7SAndroid Build Coastguard Worker #undef X
172*03ce13f7SAndroid Build Coastguard Worker }
173*03ce13f7SAndroid Build Coastguard Worker 
174*03ce13f7SAndroid Build Coastguard Worker namespace {
175*03ce13f7SAndroid Build Coastguard Worker 
176*03ce13f7SAndroid Build Coastguard Worker // toSetterParam is template magic that is needed to convert between (llvm::)cl
177*03ce13f7SAndroid Build Coastguard Worker // objects and the arguments to ClFlags' setters. ToSetterParam is a traits
178*03ce13f7SAndroid Build Coastguard Worker // object that we need in order for the multiple specializations to
179*03ce13f7SAndroid Build Coastguard Worker // toSetterParam to agree on their return type.
180*03ce13f7SAndroid Build Coastguard Worker template <typename T> struct ToSetterParam { using ReturnType = const T &; };
181*03ce13f7SAndroid Build Coastguard Worker 
182*03ce13f7SAndroid Build Coastguard Worker template <> struct ToSetterParam<cl::list<Ice::VerboseItem>> {
183*03ce13f7SAndroid Build Coastguard Worker   using ReturnType = Ice::VerboseMask;
184*03ce13f7SAndroid Build Coastguard Worker };
185*03ce13f7SAndroid Build Coastguard Worker 
186*03ce13f7SAndroid Build Coastguard Worker template <> struct ToSetterParam<cl::list<std::string>> {
187*03ce13f7SAndroid Build Coastguard Worker   using ReturnType = std::vector<std::string>;
188*03ce13f7SAndroid Build Coastguard Worker };
189*03ce13f7SAndroid Build Coastguard Worker 
190*03ce13f7SAndroid Build Coastguard Worker template <typename T>
toSetterParam(const T & Param)191*03ce13f7SAndroid Build Coastguard Worker typename ToSetterParam<T>::ReturnType toSetterParam(const T &Param) {
192*03ce13f7SAndroid Build Coastguard Worker   return Param;
193*03ce13f7SAndroid Build Coastguard Worker }
194*03ce13f7SAndroid Build Coastguard Worker 
195*03ce13f7SAndroid Build Coastguard Worker template <>
196*03ce13f7SAndroid Build Coastguard Worker ToSetterParam<cl::list<Ice::VerboseItem>>::ReturnType
toSetterParam(const cl::list<Ice::VerboseItem> & Param)197*03ce13f7SAndroid Build Coastguard Worker toSetterParam(const cl::list<Ice::VerboseItem> &Param) {
198*03ce13f7SAndroid Build Coastguard Worker   Ice::VerboseMask VMask = Ice::IceV_None;
199*03ce13f7SAndroid Build Coastguard Worker   // Don't generate verbose messages if routines to dump messages are not
200*03ce13f7SAndroid Build Coastguard Worker   // available.
201*03ce13f7SAndroid Build Coastguard Worker   if (BuildDefs::dump()) {
202*03ce13f7SAndroid Build Coastguard Worker     for (unsigned i = 0; i != Param.size(); ++i)
203*03ce13f7SAndroid Build Coastguard Worker       VMask |= Param[i];
204*03ce13f7SAndroid Build Coastguard Worker   }
205*03ce13f7SAndroid Build Coastguard Worker   return VMask;
206*03ce13f7SAndroid Build Coastguard Worker }
207*03ce13f7SAndroid Build Coastguard Worker 
208*03ce13f7SAndroid Build Coastguard Worker template <>
209*03ce13f7SAndroid Build Coastguard Worker ToSetterParam<cl::list<std::string>>::ReturnType
toSetterParam(const cl::list<std::string> & Param)210*03ce13f7SAndroid Build Coastguard Worker toSetterParam(const cl::list<std::string> &Param) {
211*03ce13f7SAndroid Build Coastguard Worker   return *&Param;
212*03ce13f7SAndroid Build Coastguard Worker }
213*03ce13f7SAndroid Build Coastguard Worker 
214*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
215*03ce13f7SAndroid Build Coastguard Worker 
getParsedClFlags(ClFlags & OutFlags)216*03ce13f7SAndroid Build Coastguard Worker void ClFlags::getParsedClFlags(ClFlags &OutFlags) {
217*03ce13f7SAndroid Build Coastguard Worker #define X(Name, Type, ClType, ...) OutFlags.set##Name(toSetterParam(Name##Obj));
218*03ce13f7SAndroid Build Coastguard Worker   COMMAND_LINE_FLAGS
219*03ce13f7SAndroid Build Coastguard Worker #undef X
220*03ce13f7SAndroid Build Coastguard Worker 
221*03ce13f7SAndroid Build Coastguard Worker   // If any value needs a non-trivial parsed value, set it below.
222*03ce13f7SAndroid Build Coastguard Worker   OutFlags.setAllowExternDefinedSymbols(AllowExternDefinedSymbolsObj ||
223*03ce13f7SAndroid Build Coastguard Worker                                         DisableInternalObj);
224*03ce13f7SAndroid Build Coastguard Worker   OutFlags.setDisableHybridAssembly(DisableHybridAssemblyObj ||
225*03ce13f7SAndroid Build Coastguard Worker                                     (OutFileTypeObj != Ice::FT_Iasm));
226*03ce13f7SAndroid Build Coastguard Worker   OutFlags.ForceO2.init(OutFlags.getForceO2String());
227*03ce13f7SAndroid Build Coastguard Worker   OutFlags.SplitInsts.init(OutFlags.getSplitInstString());
228*03ce13f7SAndroid Build Coastguard Worker   OutFlags.TestStatus.init(OutFlags.getTestStatusString());
229*03ce13f7SAndroid Build Coastguard Worker   OutFlags.TimingFocus.init(OutFlags.getTimingFocusOnString());
230*03ce13f7SAndroid Build Coastguard Worker   OutFlags.TranslateOnly.init(OutFlags.getTranslateOnlyString());
231*03ce13f7SAndroid Build Coastguard Worker   OutFlags.VerboseFocus.init(OutFlags.getVerboseFocusOnString());
232*03ce13f7SAndroid Build Coastguard Worker }
233*03ce13f7SAndroid Build Coastguard Worker 
234*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
235