41
41
using namespace mlir ;
42
42
using llvm::Error;
43
43
44
- static llvm::cl::opt<std::string> inputFilename (llvm::cl::Positional,
45
- llvm::cl::desc (" <input file>" ),
46
- llvm::cl::init(" -" ));
47
- static llvm::cl::opt<std::string>
48
- mainFuncName (" e" , llvm::cl::desc(" The function to be called" ),
49
- llvm::cl::value_desc(" <function name>" ),
50
- llvm::cl::init(" main" ));
51
- static llvm::cl::opt<std::string> mainFuncType (
52
- " entry-point-result" ,
53
- llvm::cl::desc (" Textual description of the function type to be called" ),
54
- llvm::cl::value_desc(" f32 | void" ), llvm::cl::init(" f32" ));
55
-
56
- static llvm::cl::OptionCategory optFlags (" opt-like flags" );
57
-
58
- // CLI list of pass information
59
- static llvm::cl::list<const llvm::PassInfo *, bool , llvm::PassNameParser>
60
- llvmPasses (llvm::cl::desc(" LLVM optimizing passes to run" ),
61
- llvm::cl::cat(optFlags));
62
-
63
- // CLI variables for -On options.
64
- static llvm::cl::opt<bool >
65
- optO0 (" O0" , llvm::cl::desc(" Run opt passes and codegen at O0" ),
66
- llvm::cl::cat(optFlags));
67
- static llvm::cl::opt<bool >
68
- optO1 (" O1" , llvm::cl::desc(" Run opt passes and codegen at O1" ),
69
- llvm::cl::cat(optFlags));
70
- static llvm::cl::opt<bool >
71
- optO2 (" O2" , llvm::cl::desc(" Run opt passes and codegen at O2" ),
72
- llvm::cl::cat(optFlags));
73
- static llvm::cl::opt<bool >
74
- optO3 (" O3" , llvm::cl::desc(" Run opt passes and codegen at O3" ),
75
- llvm::cl::cat(optFlags));
76
-
77
- static llvm::cl::OptionCategory clOptionsCategory (" linking options" );
78
- static llvm::cl::list<std::string>
79
- clSharedLibs (" shared-libs" , llvm::cl::desc(" Libraries to link dynamically" ),
80
- llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::CommaSeparated,
81
- llvm::cl::cat(clOptionsCategory));
82
-
83
- // CLI variables for debugging.
84
- static llvm::cl::opt<bool > dumpObjectFile (
85
- " dump-object-file" ,
86
- llvm::cl::desc (" Dump JITted-compiled object to file specified with "
87
- " -object-filename (<input file>.o by default)." ));
88
-
89
- static llvm::cl::opt<std::string> objectFilename (
90
- " object-filename" ,
91
- llvm::cl::desc (" Dump JITted-compiled object to file <input file>.o" ));
44
+ namespace {
45
+ // / This options struct prevents the need for global static initializers, and
46
+ // / is only initialized if the JITRunner is invoked.
47
+ struct Options {
48
+ llvm::cl::opt<std::string> inputFilename{llvm::cl::Positional,
49
+ llvm::cl::desc (" <input file>" ),
50
+ llvm::cl::init (" -" )};
51
+ llvm::cl::opt<std::string> mainFuncName{
52
+ " e" , llvm::cl::desc (" The function to be called" ),
53
+ llvm::cl::value_desc (" <function name>" ), llvm::cl::init (" main" )};
54
+ llvm::cl::opt<std::string> mainFuncType{
55
+ " entry-point-result" ,
56
+ llvm::cl::desc (" Textual description of the function type to be called" ),
57
+ llvm::cl::value_desc (" f32 | void" ), llvm::cl::init (" f32" )};
58
+
59
+ llvm::cl::OptionCategory optFlags{" opt-like flags" };
60
+
61
+ // CLI list of pass information
62
+ llvm::cl::list<const llvm::PassInfo *, bool , llvm::PassNameParser> llvmPasses{
63
+ llvm::cl::desc (" LLVM optimizing passes to run" ), llvm::cl::cat (optFlags)};
64
+
65
+ // CLI variables for -On options.
66
+ llvm::cl::opt<bool > optO0{" O0" ,
67
+ llvm::cl::desc (" Run opt passes and codegen at O0" ),
68
+ llvm::cl::cat (optFlags)};
69
+ llvm::cl::opt<bool > optO1{" O1" ,
70
+ llvm::cl::desc (" Run opt passes and codegen at O1" ),
71
+ llvm::cl::cat (optFlags)};
72
+ llvm::cl::opt<bool > optO2{" O2" ,
73
+ llvm::cl::desc (" Run opt passes and codegen at O2" ),
74
+ llvm::cl::cat (optFlags)};
75
+ llvm::cl::opt<bool > optO3{" O3" ,
76
+ llvm::cl::desc (" Run opt passes and codegen at O3" ),
77
+ llvm::cl::cat (optFlags)};
78
+
79
+ llvm::cl::OptionCategory clOptionsCategory{" linking options" };
80
+ llvm::cl::list<std::string> clSharedLibs{
81
+ " shared-libs" , llvm::cl::desc (" Libraries to link dynamically" ),
82
+ llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::CommaSeparated,
83
+ llvm::cl::cat (clOptionsCategory)};
84
+
85
+ // / CLI variables for debugging.
86
+ llvm::cl::opt<bool > dumpObjectFile{
87
+ " dump-object-file" ,
88
+ llvm::cl::desc (" Dump JITted-compiled object to file specified with "
89
+ " -object-filename (<input file>.o by default)." )};
90
+
91
+ llvm::cl::opt<std::string> objectFilename{
92
+ " object-filename" ,
93
+ llvm::cl::desc (" Dump JITted-compiled object to file <input file>.o" )};
94
+ };
95
+ } // end anonymous namespace
92
96
93
97
static OwningModuleRef parseMLIRInput (StringRef inputFilename,
94
98
MLIRContext *context) {
@@ -110,10 +114,10 @@ static inline Error make_string_error(const Twine &message) {
110
114
llvm::inconvertibleErrorCode ());
111
115
}
112
116
113
- static Optional<unsigned > getCommandLineOptLevel () {
117
+ static Optional<unsigned > getCommandLineOptLevel (Options &options ) {
114
118
Optional<unsigned > optLevel;
115
119
SmallVector<std::reference_wrapper<llvm::cl::opt<bool >>, 4 > optFlags{
116
- optO0, optO1, optO2, optO3};
120
+ options. optO0 , options. optO1 , options. optO2 , options. optO3 };
117
121
118
122
// Determine if there is an optimization flag present.
119
123
for (unsigned j = 0 ; j < 4 ; ++j) {
@@ -128,14 +132,15 @@ static Optional<unsigned> getCommandLineOptLevel() {
128
132
129
133
// JIT-compile the given module and run "entryPoint" with "args" as arguments.
130
134
static Error
131
- compileAndExecute (ModuleOp module , StringRef entryPoint,
135
+ compileAndExecute (Options &options, ModuleOp module , StringRef entryPoint,
132
136
std::function<llvm::Error(llvm::Module *)> transformer,
133
137
void **args) {
134
138
Optional<llvm::CodeGenOpt::Level> jitCodeGenOptLevel;
135
- if (auto clOptLevel = getCommandLineOptLevel ())
139
+ if (auto clOptLevel = getCommandLineOptLevel (options ))
136
140
jitCodeGenOptLevel =
137
141
static_cast <llvm::CodeGenOpt::Level>(clOptLevel.getValue ());
138
- SmallVector<StringRef, 4 > libs (clSharedLibs.begin (), clSharedLibs.end ());
142
+ SmallVector<StringRef, 4 > libs (options.clSharedLibs .begin (),
143
+ options.clSharedLibs .end ());
139
144
auto expectedEngine = mlir::ExecutionEngine::create (module , transformer,
140
145
jitCodeGenOptLevel, libs);
141
146
if (!expectedEngine)
@@ -146,9 +151,10 @@ compileAndExecute(ModuleOp module, StringRef entryPoint,
146
151
if (!expectedFPtr)
147
152
return expectedFPtr.takeError ();
148
153
149
- if (dumpObjectFile)
150
- engine->dumpToObjectFile (objectFilename.empty () ? inputFilename + " .o"
151
- : objectFilename);
154
+ if (options.dumpObjectFile )
155
+ engine->dumpToObjectFile (options.objectFilename .empty ()
156
+ ? options.inputFilename + " .o"
157
+ : options.objectFilename );
152
158
153
159
void (*fptr)(void **) = *expectedFPtr;
154
160
(*fptr)(args);
@@ -157,17 +163,17 @@ compileAndExecute(ModuleOp module, StringRef entryPoint,
157
163
}
158
164
159
165
static Error compileAndExecuteVoidFunction (
160
- ModuleOp module , StringRef entryPoint,
166
+ Options &options, ModuleOp module , StringRef entryPoint,
161
167
std::function<llvm::Error(llvm::Module *)> transformer) {
162
168
auto mainFunction = module .lookupSymbol <LLVM::LLVMFuncOp>(entryPoint);
163
169
if (!mainFunction || mainFunction.getBlocks ().empty ())
164
170
return make_string_error (" entry point not found" );
165
171
void *empty = nullptr ;
166
- return compileAndExecute (module , entryPoint, transformer, &empty);
172
+ return compileAndExecute (options, module , entryPoint, transformer, &empty);
167
173
}
168
174
169
175
static Error compileAndExecuteSingleFloatReturnFunction (
170
- ModuleOp module , StringRef entryPoint,
176
+ Options &options, ModuleOp module , StringRef entryPoint,
171
177
std::function<llvm::Error(llvm::Module *)> transformer) {
172
178
auto mainFunction = module .lookupSymbol <LLVM::LLVMFuncOp>(entryPoint);
173
179
if (!mainFunction || mainFunction.isExternal ())
@@ -184,28 +190,30 @@ static Error compileAndExecuteSingleFloatReturnFunction(
184
190
void *data;
185
191
} data;
186
192
data.data = &res;
187
- if (auto error =
188
- compileAndExecute ( module , entryPoint, transformer, (void **)&data))
193
+ if (auto error = compileAndExecute (options, module , entryPoint, transformer,
194
+ (void **)&data))
189
195
return error;
190
196
191
197
// Intentional printing of the output so we can test.
192
198
llvm::outs () << res << ' \n ' ;
193
-
194
199
return Error::success ();
195
200
}
196
201
197
- // Entry point for all CPU runners. Expects the common argc/argv arguments for
198
- // standard C++ main functions and an mlirTransformer.
199
- // The latter is applied after parsing the input into MLIR IR and before passing
200
- // the MLIR module to the ExecutionEngine.
202
+ // / Entry point for all CPU runners. Expects the common argc/argv arguments for
203
+ // / standard C++ main functions and an mlirTransformer.
204
+ // / The latter is applied after parsing the input into MLIR IR and before
205
+ // / passing the MLIR module to the ExecutionEngine.
201
206
int mlir::JitRunnerMain (
202
207
int argc, char **argv,
203
208
function_ref<LogicalResult(mlir::ModuleOp)> mlirTransformer) {
209
+ // Create the options struct containing the command line options for the
210
+ // runner. This must come before the command line options are parsed.
211
+ Options options;
204
212
llvm::cl::ParseCommandLineOptions (argc, argv, " MLIR CPU execution driver\n " );
205
213
206
- Optional<unsigned > optLevel = getCommandLineOptLevel ();
214
+ Optional<unsigned > optLevel = getCommandLineOptLevel (options );
207
215
SmallVector<std::reference_wrapper<llvm::cl::opt<bool >>, 4 > optFlags{
208
- optO0, optO1, optO2, optO3};
216
+ options. optO0 , options. optO1 , options. optO2 , options. optO3 };
209
217
unsigned optCLIPosition = 0 ;
210
218
// Determine if there is an optimization flag present, and its CLI position
211
219
// (optCLIPosition).
@@ -220,16 +228,16 @@ int mlir::JitRunnerMain(
220
228
// insert any optimization passes in that vector (optPosition).
221
229
SmallVector<const llvm::PassInfo *, 4 > passes;
222
230
unsigned optPosition = 0 ;
223
- for (unsigned i = 0 , e = llvmPasses.size (); i < e; ++i) {
224
- passes.push_back (llvmPasses[i]);
225
- if (optCLIPosition < llvmPasses.getPosition (i)) {
231
+ for (unsigned i = 0 , e = options. llvmPasses .size (); i < e; ++i) {
232
+ passes.push_back (options. llvmPasses [i]);
233
+ if (optCLIPosition < options. llvmPasses .getPosition (i)) {
226
234
optPosition = i;
227
235
optCLIPosition = UINT_MAX; // To ensure we never insert again
228
236
}
229
237
}
230
238
231
239
MLIRContext context;
232
- auto m = parseMLIRInput (inputFilename, &context);
240
+ auto m = parseMLIRInput (options. inputFilename , &context);
233
241
if (!m) {
234
242
llvm::errs () << " could not parse the input IR\n " ;
235
243
return 1 ;
@@ -254,17 +262,19 @@ int mlir::JitRunnerMain(
254
262
passes, optLevel, /* targetMachine=*/ tmOrError->get (), optPosition);
255
263
256
264
// Get the function used to compile and execute the module.
257
- using CompileAndExecuteFnT = Error (*)(
258
- ModuleOp, StringRef, std::function<llvm::Error (llvm::Module *)>);
265
+ using CompileAndExecuteFnT =
266
+ Error (*)(Options &, ModuleOp, StringRef,
267
+ std::function<llvm::Error (llvm::Module *)>);
259
268
auto compileAndExecuteFn =
260
- llvm::StringSwitch<CompileAndExecuteFnT>(mainFuncType.getValue ())
269
+ llvm::StringSwitch<CompileAndExecuteFnT>(options. mainFuncType .getValue ())
261
270
.Case (" f32" , compileAndExecuteSingleFloatReturnFunction)
262
271
.Case (" void" , compileAndExecuteVoidFunction)
263
272
.Default (nullptr );
264
273
265
274
Error error =
266
275
compileAndExecuteFn
267
- ? compileAndExecuteFn (m.get (), mainFuncName.getValue (), transformer)
276
+ ? compileAndExecuteFn (options, m.get (),
277
+ options.mainFuncName .getValue (), transformer)
268
278
: make_string_error (" unsupported function type" );
269
279
270
280
int exitCode = EXIT_SUCCESS;
0 commit comments