1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "cg_option.h"
17 #include "cg_options.h"
18 #include "triple.h"
19 #include "option.h"
20
21 namespace maplebe {
22 using namespace maple;
23
24 const std::string kMplcgVersion = "";
25
26 bool CGOptions::timePhases = false;
27 std::string CGOptions::targetArch = "";
28 std::unordered_set<std::string> CGOptions::dumpPhases = {};
29 std::unordered_set<std::string> CGOptions::skipPhases = {};
30 std::unordered_map<std::string, std::vector<std::string>> CGOptions::cyclePatternMap = {};
31 std::string CGOptions::skipFrom = "";
32 std::string CGOptions::skipAfter = "";
33 std::string CGOptions::dumpFunc = "*";
34 std::string CGOptions::globalVarProfile = "";
35 std::string CGOptions::profileData = "";
36 std::string CGOptions::profileFuncData = "";
37 std::string CGOptions::profileClassData = "";
38 #ifdef TARGARM32
39 std::string CGOptions::duplicateAsmFile = "";
40 #else
41 std::string CGOptions::duplicateAsmFile = "maple/mrt/codetricks/arch/arm64/duplicateFunc.s";
42 #endif
43 Range CGOptions::range = Range();
44 Range CGOptions::spillRanges = Range();
45 uint64 CGOptions::lsraBBOptSize = 150000;
46 uint64 CGOptions::lsraInsnOptSize = 200000;
47 uint64 CGOptions::overlapNum = 28;
48 bool CGOptions::optForSize = false;
49 bool CGOptions::enableHotColdSplit = false;
50 uint32 CGOptions::funcAlignPow = 5;
51 bool CGOptions::doOptimizedFrameLayout = true;
52 bool CGOptions::supportFuncSymbol = false;
53 bool CGOptions::doEBO = false;
54 bool CGOptions::doCGSSA = false;
55 bool CGOptions::doLocalSchedule = false;
56 bool CGOptions::doCGRegCoalesce = false;
57 bool CGOptions::doIPARA = true;
58 bool CGOptions::doCFGO = false;
59 bool CGOptions::doICO = false;
60 bool CGOptions::doStoreLoadOpt = false;
61 bool CGOptions::doGlobalOpt = false;
62 bool CGOptions::doPrePeephole = false;
63 bool CGOptions::doPeephole = false;
64 bool CGOptions::doSchedule = false;
65 bool CGOptions::doWriteRefFieldOpt = false;
66 bool CGOptions::noDupBB = false;
67 bool CGOptions::noCalleeCFI = true;
68 bool CGOptions::lazyBinding = false;
69 bool CGOptions::hotFix = false;
70 bool CGOptions::useFramePointer = false;
71 bool CGOptions::gcOnly = false;
72 bool CGOptions::doPreSchedule = false;
73 bool CGOptions::emitBlockMarker = true;
74 bool CGOptions::inRange = false;
75 bool CGOptions::doPreLSRAOpt = false;
76 bool CGOptions::doRegSavesOpt = false;
77 bool CGOptions::useSsaPreSave = false;
78 bool CGOptions::useSsuPreRestore = false;
79 bool CGOptions::generalRegOnly = false;
80 bool CGOptions::cgBigEndian = false;
81 bool CGOptions::arm64ilp32 = false;
82 bool CGOptions::doCgirVerify = false;
83 bool CGOptions::useJitCodeSign = false;
84
GetInstance()85 CGOptions &CGOptions::GetInstance()
86 {
87 static CGOptions instance;
88 return instance;
89 }
90
GetLogStream() const91 std::ostream& CGOptions::GetLogStream() const
92 {
93 return LogInfo::MapleLogger();
94 }
95
96
SolveOptions()97 bool CGOptions::SolveOptions()
98 {
99 if (opts::cg::supportFuncSymbol.IsEnabledByUser()) {
100 opts::cg::supportFuncSymbol ? EnableSupportFuncSymbol() : DisableSupportFuncSymbol();
101 }
102
103 if (opts::cg::verboseAsm.IsEnabledByUser()) {
104 opts::cg::verboseAsm ? SetOption(CGOptions::kVerboseAsm) : ClearOption(CGOptions::kVerboseAsm);
105 SetAsmEmitterEnable(true);
106 }
107
108 if (opts::cg::verboseCg.IsEnabledByUser()) {
109 opts::cg::verboseCg ? SetOption(CGOptions::kVerboseCG) : ClearOption(CGOptions::kVerboseCG);
110 }
111
112 if (opts::cg::spillRange.IsEnabledByUser()) {
113 #ifdef ARK_LITECG_DEBUG
114 SetRange(opts::cg::spillRange, "--pill-range", GetSpillRanges());
115 #endif
116 }
117
118 if (opts::cg::range.IsEnabledByUser()) {
119 #ifdef ARK_LITECG_DEBUG
120 SetRange(opts::cg::range, "--range", GetRange());
121 #endif
122 }
123
124 if (opts::cg::timePhases.IsEnabledByUser()) {
125 opts::cg::timePhases ? EnableTimePhases() : DisableTimePhases();
126 }
127
128 if (opts::cg::dumpFunc.IsEnabledByUser()) {
129 SetDumpFunc(opts::cg::dumpFunc);
130 }
131
132 if (opts::cg::debug.IsEnabledByUser()) {
133 SetOption(kDebugFriendly);
134 SetOption(kWithLoc);
135 ClearOption(kSuppressFileInfo);
136 }
137
138 if (opts::cg::gdwarf.IsEnabledByUser()) {
139 SetOption(kDebugFriendly);
140 SetOption(kWithLoc);
141 SetOption(kWithDwarf);
142 SetParserOption(kWithDbgInfo);
143 ClearOption(kSuppressFileInfo);
144 }
145
146 if (opts::cg::gsrc.IsEnabledByUser()) {
147 SetOption(kDebugFriendly);
148 SetOption(kWithLoc);
149 SetOption(kWithSrc);
150 ClearOption(kWithMpl);
151 }
152
153 if (opts::cg::gmixedsrc.IsEnabledByUser()) {
154 SetOption(kDebugFriendly);
155 SetOption(kWithLoc);
156 SetOption(kWithSrc);
157 SetOption(kWithMpl);
158 }
159
160 if (opts::cg::gmixedasm.IsEnabledByUser()) {
161 SetOption(kDebugFriendly);
162 SetOption(kWithLoc);
163 SetOption(kWithSrc);
164 SetOption(kWithMpl);
165 SetOption(kWithAsm);
166 }
167
168 if (opts::cg::withRaLinearScan.IsEnabledByUser()) {
169 SetOption(kDoLinearScanRegAlloc);
170 }
171
172 if (opts::cg::suppressFileinfo.IsEnabledByUser()) {
173 SetOption(kSuppressFileInfo);
174 }
175
176 if (opts::cg::dumpCfg.IsEnabledByUser()) {
177 SetOption(kDumpCFG);
178 }
179
180 if (opts::cg::yieldpoint.IsEnabledByUser()) {
181 SetOrClear(GetGenerateFlags(), CGOptions::kGenYieldPoint, opts::cg::yieldpoint);
182 }
183
184 if (opts::cg::localRc.IsEnabledByUser()) {
185 SetOrClear(GetGenerateFlags(), CGOptions::kGenLocalRc, opts::cg::localRc);
186 }
187
188 if (opts::cg::cg.IsEnabledByUser()) {
189 SetRunCGFlag(opts::cg::cg);
190 opts::cg::cg ? SetOption(CGOptions::kDoCg) : ClearOption(CGOptions::kDoCg);
191 }
192
193 if (opts::cg::generalRegOnly.IsEnabledByUser()) {
194 opts::cg::generalRegOnly ? EnableGeneralRegOnly() : DisableGeneralRegOnly();
195 }
196
197 if (opts::cg::lazyBinding.IsEnabledByUser()) {
198 opts::cg::lazyBinding ? EnableLazyBinding() : DisableLazyBinding();
199 }
200
201 if (opts::cg::hotFix.IsEnabledByUser()) {
202 opts::cg::hotFix ? EnableHotFix() : DisableHotFix();
203 }
204
205 if (opts::cg::dupBb.IsEnabledByUser()) {
206 opts::cg::dupBb ? DisableNoDupBB() : EnableNoDupBB();
207 }
208
209 if (opts::cg::calleeCfi.IsEnabledByUser()) {
210 opts::cg::calleeCfi ? DisableNoCalleeCFI() : EnableNoCalleeCFI();
211 }
212
213 if (opts::cg::tailcall.IsEnabledByUser()) {
214 opts::cg::tailcall ? SetOption(CGOptions::kTailCallOpt) : ClearOption(CGOptions::kTailCallOpt);
215 }
216
217 if (opts::cg::lsraBb.IsEnabledByUser()) {
218 SetLSRABBOptSize(opts::cg::lsraBb);
219 }
220
221 if (opts::cg::lsraInsn.IsEnabledByUser()) {
222 SetLSRAInsnOptSize(opts::cg::lsraInsn);
223 }
224
225 if (opts::cg::lsraOverlap.IsEnabledByUser()) {
226 SetOverlapNum(opts::cg::lsraOverlap);
227 }
228
229 if (opts::cg::dumpPhases.IsEnabledByUser()) {
230 #ifdef ARK_LITECG_DEBUG
231 SplitPhases(opts::cg::dumpPhases, GetDumpPhases());
232 #endif
233 }
234
235 if (opts::cg::target.IsEnabledByUser()) {
236 #ifdef ARK_LITECG_DEBUG
237 SetTargetMachine(opts::cg::target);
238 #endif
239 }
240
241 if (opts::cg::skipPhases.IsEnabledByUser()) {
242 #ifdef ARK_LITECG_DEBUG
243 SplitPhases(opts::cg::skipPhases, GetSkipPhases());
244 #endif
245 }
246
247 if (opts::cg::skipFrom.IsEnabledByUser()) {
248 SetSkipFrom(opts::cg::skipFrom);
249 }
250
251 if (opts::cg::skipAfter.IsEnabledByUser()) {
252 SetSkipAfter(opts::cg::skipAfter);
253 }
254
255 if (opts::cg::omitFramePointer.IsEnabledByUser()) {
256 opts::cg::omitFramePointer ? DisableFramePointer() : EnableFramePointer();
257 }
258
259 /* big endian can be set with several options: --target, -Be.
260 * Triple takes to account all these options and allows to detect big endian with IsBigEndian() interface */
261 Triple::GetTriple().IsBigEndian() ? EnableBigEndianInCG() : DisableBigEndianInCG();
262 (maple::Triple::GetTriple().GetEnvironment() == Triple::GNUILP32) ? EnableArm64ilp32() : DisableArm64ilp32();
263
264 if (opts::cg::cgSsa.IsEnabledByUser()) {
265 opts::cg::cgSsa ? EnableCGSSA() : DisableCGSSA();
266 }
267
268 if (opts::cg::funcAlignPow.IsEnabledByUser()) {
269 SetFuncAlignPow(opts::cg::funcAlignPow);
270 }
271
272 /* override some options when loc, dwarf is generated */
273 if (WithLoc()) {
274 DisableSchedule();
275 SetOption(kWithSrc);
276 }
277
278 return true;
279 }
280
281 #ifdef ARK_LITECG_DEBUG
SetRange(const std::string & str,const std::string & cmd,Range & subRange)282 void CGOptions::SetRange(const std::string &str, const std::string &cmd, Range &subRange)
283 {
284 const std::string &tmpStr = str;
285 size_t comma = tmpStr.find_first_of(",", 0);
286 subRange.enable = true;
287
288 if (comma != std::string::npos) {
289 subRange.begin = std::stoul(tmpStr.substr(0, comma), nullptr);
290 subRange.end = std::stoul(tmpStr.substr(comma + 1, std::string::npos - (comma + 1)), nullptr);
291 }
292 CHECK_FATAL(range.begin < range.end, "invalid values for %s=%lu,%lu", cmd.c_str(), subRange.begin, subRange.end);
293 }
294
EnableO0()295 void CGOptions::EnableO0()
296 {
297 optimizeLevel = kLevel0;
298 doEBO = false;
299 doCGSSA = false;
300 doLocalSchedule = false;
301 doCFGO = false;
302 doICO = false;
303 doPrePeephole = false;
304 doPeephole = false;
305 doStoreLoadOpt = false;
306 doGlobalOpt = false;
307 doPreLSRAOpt = false;
308 doPreSchedule = false;
309 doSchedule = false;
310 doRegSavesOpt = false;
311 useSsaPreSave = false;
312 useSsuPreRestore = false;
313 doWriteRefFieldOpt = false;
314
315 ClearOption(kTailCallOpt);
316 }
317
EnableO1()318 void CGOptions::EnableO1()
319 {
320 optimizeLevel = kLevel1;
321 doPreLSRAOpt = true;
322 SetOption(kTailCallOpt);
323 }
324
EnableO2()325 void CGOptions::EnableO2()
326 {
327 optimizeLevel = kLevel2;
328 doEBO = true;
329 doCGSSA = true;
330 doLocalSchedule = true;
331 doCFGO = true;
332 doICO = true;
333 doPrePeephole = true;
334 doPeephole = true;
335 doStoreLoadOpt = true;
336 doGlobalOpt = true;
337 doPreSchedule = true;
338 doSchedule = true;
339 #if TARGARM32
340 doPreLSRAOpt = false;
341 doWriteRefFieldOpt = false;
342 ClearOption(kTailCallOpt);
343 #else
344 doPreLSRAOpt = true;
345 doRegSavesOpt = false;
346 useSsaPreSave = false;
347 useSsuPreRestore = true;
348 doWriteRefFieldOpt = true;
349 SetOption(kTailCallOpt);
350 #endif
351 }
352 #endif
353
EnableLiteCG()354 void CGOptions::EnableLiteCG()
355 {
356 optimizeLevel = kLevelLiteCG;
357 doEBO = false;
358 doCGSSA = false;
359 doLocalSchedule = false;
360 doCGRegCoalesce = false;
361 doCFGO = true;
362 doICO = false;
363 doPrePeephole = false;
364 doPeephole = true;
365 doStoreLoadOpt = false;
366 doGlobalOpt = false;
367 doPreLSRAOpt = false;
368 doPreSchedule = false;
369 doSchedule = false;
370 doRegSavesOpt = false;
371 useSsaPreSave = false;
372 useSsuPreRestore = false;
373 doWriteRefFieldOpt = false;
374 supportFuncSymbol = true;
375
376 ClearOption(kTailCallOpt);
377 SetOption(kDoLinearScanRegAlloc);
378 }
379
380 #ifdef ARK_LITECG_DEBUG
SetTargetMachine(const std::string & str)381 void CGOptions::SetTargetMachine(const std::string &str)
382 {
383 // this is a temporary plan, all ilp32 logic follow the same path with aarch64
384 if (str == "aarch64" || str == "aarch64_be-linux-gnu_ilp32" || str == "aarch64_be-linux-gnu") {
385 targetArch = "aarch64";
386 } else if (str == "x86_64") {
387 targetArch = "x86_64";
388 } else {
389 CHECK_FATAL_FALSE("unsupported target!!");
390 }
391 }
392
SplitPhases(const std::string & str,std::unordered_set<std::string> & set)393 void CGOptions::SplitPhases(const std::string &str, std::unordered_set<std::string> &set)
394 {
395 const std::string &tmpStr {str};
396 if ((tmpStr.compare("*") == 0) || (tmpStr.compare("cgir") == 0)) {
397 (void)set.insert(tmpStr);
398 return;
399 }
400 StringUtils::Split(tmpStr, set, ',');
401 }
402 #endif
403
DumpPhase(const std::string & phase)404 bool CGOptions::DumpPhase(const std::string &phase)
405 {
406 return (IS_STR_IN_SET(dumpPhases, "*") || IS_STR_IN_SET(dumpPhases, "cgir") || IS_STR_IN_SET(dumpPhases, phase));
407 }
408
409 /* match sub std::string of function name */
FuncFilter(const std::string & name)410 bool CGOptions::FuncFilter(const std::string &name)
411 {
412 return dumpFunc == "*" || dumpFunc == name;
413 }
414 } /* namespace maplebe */
415