1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "dex2oat_options.h"
18
19#include <memory>
20
21#include "cmdline_parser.h"
22#include "driver/compiler_options_map-inl.h"
23
24namespace art {
25
26template<>
27struct CmdlineType<InstructionSet> : CmdlineTypeParser<InstructionSet> {
28  Result Parse(const std::string& option) {
29    InstructionSet set = GetInstructionSetFromString(option.c_str());
30    if (set == InstructionSet::kNone) {
31      return Result::Failure(std::string("Not a valid instruction set: '") + option + "'");
32    }
33    return Result::Success(set);
34  }
35
36  static const char* Name() { return "InstructionSet"; }
37};
38
39#define COMPILER_OPTIONS_MAP_TYPE Dex2oatArgumentMap
40#define COMPILER_OPTIONS_MAP_KEY_TYPE Dex2oatArgumentMapKey
41#include "driver/compiler_options_map-storage.h"
42
43// Specify storage for the Dex2oatOptions keys.
44
45#define DEX2OAT_OPTIONS_KEY(Type, Name, ...) \
46  const Dex2oatArgumentMap::Key<Type> Dex2oatArgumentMap::Name {__VA_ARGS__};
47#include "dex2oat_options.def"
48
49#pragma GCC diagnostic push
50#pragma GCC diagnostic ignored "-Wframe-larger-than="
51
52using M = Dex2oatArgumentMap;
53using Parser = CmdlineParser<Dex2oatArgumentMap, Dex2oatArgumentMap::Key>;
54using Builder = Parser::Builder;
55
56static void AddInputMappings(Builder& builder) {
57  builder.
58      Define("--dex-file=_")
59          .WithType<std::vector<std::string>>().AppendValues()
60          .IntoKey(M::DexFiles)
61      .Define("--dex-location=_")
62          .WithType<std::vector<std::string>>().AppendValues()
63          .IntoKey(M::DexLocations)
64      .Define("--zip-fd=_")
65          .WithType<int>()
66          .IntoKey(M::ZipFd)
67      .Define("--zip-location=_")
68          .WithType<std::string>()
69          .IntoKey(M::ZipLocation)
70      .Define("--boot-image=_")
71          .WithType<std::string>()
72          .IntoKey(M::BootImage);
73}
74
75static void AddGeneratedArtifactMappings(Builder& builder) {
76  builder.
77      Define("--input-vdex-fd=_")
78          .WithType<int>()
79          .IntoKey(M::InputVdexFd)
80      .Define("--input-vdex=_")
81          .WithType<std::string>()
82          .IntoKey(M::InputVdex)
83      .Define("--output-vdex-fd=_")
84          .WithType<int>()
85          .IntoKey(M::OutputVdexFd)
86      .Define("--output-vdex=_")
87          .WithType<std::string>()
88          .IntoKey(M::OutputVdex)
89      .Define("--dm-fd=_")
90          .WithType<int>()
91          .IntoKey(M::DmFd)
92      .Define("--dm-file=_")
93          .WithType<std::string>()
94          .IntoKey(M::DmFile)
95      .Define("--oat-file=_")
96          .WithType<std::vector<std::string>>().AppendValues()
97          .IntoKey(M::OatFiles)
98      .Define("--oat-symbols=_")
99          .WithType<std::vector<std::string>>().AppendValues()
100          .IntoKey(M::OatSymbols)
101      .Define("--oat-fd=_")
102          .WithType<int>()
103          .IntoKey(M::OatFd)
104      .Define("--oat-location=_")
105          .WithType<std::string>()
106          .IntoKey(M::OatLocation);
107}
108
109static void AddImageMappings(Builder& builder) {
110  builder.
111      Define("--image=_")
112          .WithType<std::vector<std::string>>().AppendValues()
113          .IntoKey(M::ImageFilenames)
114      .Define("--image-classes=_")
115          .WithType<std::string>()
116          .IntoKey(M::ImageClasses)
117      .Define("--image-classes-zip=_")
118          .WithType<std::string>()
119          .IntoKey(M::ImageClassesZip)
120      .Define("--base=_")
121          .WithType<std::string>()
122          .IntoKey(M::Base)
123      .Define("--app-image-file=_")
124          .WithType<std::string>()
125          .IntoKey(M::AppImageFile)
126      .Define("--app-image-fd=_")
127          .WithType<int>()
128          .IntoKey(M::AppImageFileFd)
129      .Define("--multi-image")
130          .IntoKey(M::MultiImage)
131      .Define("--dirty-image-objects=_")
132          .WithType<std::string>()
133          .IntoKey(M::DirtyImageObjects)
134      .Define("--image-format=_")
135          .WithType<ImageHeader::StorageMode>()
136          .WithValueMap({{"lz4", ImageHeader::kStorageModeLZ4},
137                         {"lz4hc", ImageHeader::kStorageModeLZ4HC},
138                         {"uncompressed", ImageHeader::kStorageModeUncompressed}})
139          .IntoKey(M::ImageFormat);
140}
141
142static void AddSwapMappings(Builder& builder) {
143  builder.
144      Define("--swap-file=_")
145          .WithType<std::string>()
146          .IntoKey(M::SwapFile)
147      .Define("--swap-fd=_")
148          .WithType<int>()
149          .IntoKey(M::SwapFileFd)
150      .Define("--swap-dex-size-threshold=_")
151          .WithType<unsigned int>()
152          .IntoKey(M::SwapDexSizeThreshold)
153      .Define("--swap-dex-count-threshold=_")
154          .WithType<unsigned int>()
155          .IntoKey(M::SwapDexCountThreshold);
156}
157
158static void AddCompilerMappings(Builder& builder) {
159  builder.
160      Define("--compiled-classes=_")
161          .WithType<std::string>()
162          .IntoKey(M::CompiledClasses)
163      .Define("--compiled-classes-zip=_")
164          .WithType<std::string>()
165          .IntoKey(M::CompiledClassesZip)
166      .Define("--compiled-methods=_")
167          .WithType<std::string>()
168          .IntoKey(M::CompiledMethods)
169      .Define("--compiled-methods-zip=_")
170          .WithType<std::string>()
171          .IntoKey(M::CompiledMethodsZip)
172      .Define("--run-passes=_")
173          .WithType<std::string>()
174          .IntoKey(M::Passes)
175      .Define("--profile-file=_")
176          .WithType<std::string>()
177          .IntoKey(M::Profile)
178      .Define("--profile-file-fd=_")
179          .WithType<int>()
180          .IntoKey(M::ProfileFd)
181      .Define("--no-inline-from=_")
182          .WithType<std::string>()
183          .IntoKey(M::NoInlineFrom);
184}
185
186static void AddTargetMappings(Builder& builder) {
187  builder.
188      Define("--instruction-set=_")
189          .WithType<InstructionSet>()
190          .IntoKey(M::TargetInstructionSet)
191      .Define("--instruction-set-variant=_")
192          .WithType<std::string>()
193          .IntoKey(M::TargetInstructionSetVariant)
194      .Define("--instruction-set-features=_")
195          .WithType<std::string>()
196          .IntoKey(M::TargetInstructionSetFeatures);
197}
198
199static Parser CreateArgumentParser() {
200  std::unique_ptr<Builder> parser_builder = std::unique_ptr<Builder>(new Builder());
201
202  AddInputMappings(*parser_builder);
203  AddGeneratedArtifactMappings(*parser_builder);
204  AddImageMappings(*parser_builder);
205  AddSwapMappings(*parser_builder);
206  AddCompilerMappings(*parser_builder);
207  AddTargetMappings(*parser_builder);
208
209  parser_builder->
210      Define({"--watch-dog", "--no-watch-dog"})
211          .WithValues({true, false})
212          .IntoKey(M::Watchdog)
213      .Define("--watchdog-timeout=_")
214          .WithType<int>()
215          .IntoKey(M::WatchdogTimeout)
216      .Define("-j_")
217          .WithType<unsigned int>()
218          .IntoKey(M::Threads)
219      .Define("--android-root=_")
220          .WithType<std::string>()
221          .IntoKey(M::AndroidRoot)
222      .Define("--compiler-backend=_")
223          .WithType<Compiler::Kind>()
224          .WithValueMap({{"Quick", Compiler::Kind::kQuick},
225                         {"Optimizing", Compiler::Kind::kOptimizing}})
226          .IntoKey(M::Backend)
227      .Define("--host")
228          .IntoKey(M::Host)
229      .Define("--avoid-storing-invocation")
230          .IntoKey(M::AvoidStoringInvocation)
231      .Define("--very-large-app-threshold=_")
232          .WithType<unsigned int>()
233          .IntoKey(M::VeryLargeAppThreshold)
234      .Define("--force-determinism")
235          .IntoKey(M::ForceDeterminism)
236      .Define("--copy-dex-files=_")
237          .WithType<CopyOption>()
238          .WithValueMap({{"true", CopyOption::kOnlyIfCompressed},
239                         {"false", CopyOption::kNever},
240                         {"always", CopyOption::kAlways}})
241          .IntoKey(M::CopyDexFiles)
242      .Define("--classpath-dir=_")
243          .WithType<std::string>()
244          .IntoKey(M::ClasspathDir)
245      .Define("--class-loader-context=_")
246          .WithType<std::string>()
247          .IntoKey(M::ClassLoaderContext)
248      .Define("--stored-class-loader-context=_")
249          .WithType<std::string>()
250          .IntoKey(M::StoredClassLoaderContext)
251      .Define("--compact-dex-level=_")
252          .WithType<CompactDexLevel>()
253          .WithValueMap({{"none", CompactDexLevel::kCompactDexLevelNone},
254                         {"fast", CompactDexLevel::kCompactDexLevelFast}})
255          .IntoKey(M::CompactDexLevel)
256      .Define("--runtime-arg _")
257          .WithType<std::vector<std::string>>().AppendValues()
258          .IntoKey(M::RuntimeOptions)
259      .Define("--compilation-reason=_")
260          .WithType<std::string>()
261          .IntoKey(M::CompilationReason);
262
263  AddCompilerOptionsArgumentParserOptions<Dex2oatArgumentMap>(*parser_builder);
264
265  parser_builder->IgnoreUnrecognized(false);
266
267  return parser_builder->Build();
268}
269
270std::unique_ptr<Dex2oatArgumentMap> Dex2oatArgumentMap::Parse(int argc,
271                                                              const char** argv,
272                                                              std::string* error_msg) {
273  Parser parser = CreateArgumentParser();
274  CmdlineResult parse_result = parser.Parse(argv, argc);
275  if (!parse_result.IsSuccess()) {
276    *error_msg = parse_result.GetMessage();
277    return nullptr;
278  }
279
280  return std::unique_ptr<Dex2oatArgumentMap>(new Dex2oatArgumentMap(parser.ReleaseArgumentsMap()));
281}
282
283#pragma GCC diagnostic pop
284}  // namespace art
285