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 
24 namespace art {
25 
26 template<>
27 struct CmdlineType<InstructionSet> : CmdlineTypeParser<InstructionSet> {
Parseart::CmdlineType28   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 
Nameart::CmdlineType36   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 
52 using M = Dex2oatArgumentMap;
53 using Parser = CmdlineParser<Dex2oatArgumentMap, Dex2oatArgumentMap::Key>;
54 using Builder = Parser::Builder;
55 
AddInputMappings(Builder & builder)56 static 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 
AddGeneratedArtifactMappings(Builder & builder)75 static 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::string>()
97           .IntoKey(M::OatFile)
98       .Define("--oat-symbols=_")
99           .WithType<std::string>()
100           .IntoKey(M::OatSymbols)
101       .Define("--strip")
102           .IntoKey(M::Strip)
103       .Define("--oat-fd=_")
104           .WithType<int>()
105           .IntoKey(M::OatFd)
106       .Define("--oat-location=_")
107           .WithType<std::string>()
108           .IntoKey(M::OatLocation);
109 }
110 
AddImageMappings(Builder & builder)111 static void AddImageMappings(Builder& builder) {
112   builder.
113       Define("--image=_")
114           .WithType<std::string>()
115           .IntoKey(M::ImageFilename)
116       .Define("--image-fd=_")
117           .WithType<int>()
118           .IntoKey(M::ImageFd)
119       .Define("--base=_")
120           .WithType<std::string>()
121           .IntoKey(M::Base)
122       .Define("--app-image-file=_")
123           .WithType<std::string>()
124           .IntoKey(M::AppImageFile)
125       .Define("--app-image-fd=_")
126           .WithType<int>()
127           .IntoKey(M::AppImageFileFd)
128       .Define({"--multi-image", "--single-image"})
129           .WithValues({true, false})
130           .IntoKey(M::MultiImage)
131       .Define("--dirty-image-objects=_")
132           .WithType<std::string>()
133           .IntoKey(M::DirtyImageObjects)
134       .Define("--updatable-bcp-packages-file=_")
135           .WithType<std::string>()
136           .IntoKey(M::UpdatableBcpPackagesFile)
137       .Define("--image-format=_")
138           .WithType<ImageHeader::StorageMode>()
139           .WithValueMap({{"lz4", ImageHeader::kStorageModeLZ4},
140                          {"lz4hc", ImageHeader::kStorageModeLZ4HC},
141                          {"uncompressed", ImageHeader::kStorageModeUncompressed}})
142           .IntoKey(M::ImageFormat);
143 }
144 
AddSwapMappings(Builder & builder)145 static void AddSwapMappings(Builder& builder) {
146   builder.
147       Define("--swap-file=_")
148           .WithType<std::string>()
149           .IntoKey(M::SwapFile)
150       .Define("--swap-fd=_")
151           .WithType<int>()
152           .IntoKey(M::SwapFileFd)
153       .Define("--swap-dex-size-threshold=_")
154           .WithType<unsigned int>()
155           .IntoKey(M::SwapDexSizeThreshold)
156       .Define("--swap-dex-count-threshold=_")
157           .WithType<unsigned int>()
158           .IntoKey(M::SwapDexCountThreshold);
159 }
160 
AddCompilerMappings(Builder & builder)161 static void AddCompilerMappings(Builder& builder) {
162   builder.
163       Define("--run-passes=_")
164           .WithType<std::string>()
165           .IntoKey(M::Passes)
166       .Define("--profile-file=_")
167           .WithType<std::string>()
168           .IntoKey(M::Profile)
169       .Define("--profile-file-fd=_")
170           .WithType<int>()
171           .IntoKey(M::ProfileFd)
172       .Define("--no-inline-from=_")
173           .WithType<std::string>()
174           .IntoKey(M::NoInlineFrom);
175 }
176 
AddTargetMappings(Builder & builder)177 static void AddTargetMappings(Builder& builder) {
178   builder.
179       Define("--instruction-set=_")
180           .WithType<InstructionSet>()
181           .IntoKey(M::TargetInstructionSet)
182       .Define("--instruction-set-variant=_")
183           .WithType<std::string>()
184           .IntoKey(M::TargetInstructionSetVariant)
185       .Define("--instruction-set-features=_")
186           .WithType<std::string>()
187           .IntoKey(M::TargetInstructionSetFeatures);
188 }
189 
CreateArgumentParser()190 static Parser CreateArgumentParser() {
191   std::unique_ptr<Builder> parser_builder = std::make_unique<Builder>();
192 
193   AddInputMappings(*parser_builder);
194   AddGeneratedArtifactMappings(*parser_builder);
195   AddImageMappings(*parser_builder);
196   AddSwapMappings(*parser_builder);
197   AddCompilerMappings(*parser_builder);
198   AddTargetMappings(*parser_builder);
199 
200   parser_builder->
201       Define({"--watch-dog", "--no-watch-dog"})
202           .WithValues({true, false})
203           .IntoKey(M::Watchdog)
204       .Define("--watchdog-timeout=_")
205           .WithType<int>()
206           .IntoKey(M::WatchdogTimeout)
207       .Define("-j_")
208           .WithType<unsigned int>()
209           .IntoKey(M::Threads)
210       .Define("--cpu-set=_")
211           .WithType<std::vector<int32_t>>()
212           .IntoKey(M::CpuSet)
213       .Define("--android-root=_")
214           .WithType<std::string>()
215           .IntoKey(M::AndroidRoot)
216       .Define("--compiler-backend=_")
217           .WithType<Compiler::Kind>()
218           .WithValueMap({{"Quick", Compiler::Kind::kQuick},
219                          {"Optimizing", Compiler::Kind::kOptimizing}})
220           .IntoKey(M::Backend)
221       .Define("--host")
222           .IntoKey(M::Host)
223       .Define("--avoid-storing-invocation")
224           .IntoKey(M::AvoidStoringInvocation)
225       .Define("--very-large-app-threshold=_")
226           .WithType<unsigned int>()
227           .IntoKey(M::VeryLargeAppThreshold)
228       .Define("--force-determinism")
229           .IntoKey(M::ForceDeterminism)
230       .Define("--copy-dex-files=_")
231           .WithType<linker::CopyOption>()
232           .WithValueMap({{"true", linker::CopyOption::kOnlyIfCompressed},
233                          {"false", linker::CopyOption::kNever},
234                          {"always", linker::CopyOption::kAlways}})
235           .IntoKey(M::CopyDexFiles)
236       .Define("--write-invocation-to=_")
237           .WithType<std::string>()
238           .IntoKey(M::InvocationFile)
239       .Define("--classpath-dir=_")
240           .WithType<std::string>()
241           .IntoKey(M::ClasspathDir)
242       .Define("--class-loader-context=_")
243           .WithType<std::string>()
244           .IntoKey(M::ClassLoaderContext)
245       .Define("--class-loader-context-fds=_")
246           .WithType<std::string>()
247           .IntoKey(M::ClassLoaderContextFds)
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 
Parse(int argc,const char ** argv,std::string * error_msg)270 std::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::make_unique<Dex2oatArgumentMap>(parser.ReleaseArgumentsMap());
281 }
282 
283 #pragma GCC diagnostic pop
284 }  // namespace art
285