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