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_phasemanager.h"
17 #include <vector>
18 #include <string>
19 #include "cg_option.h"
20 #include "args.h"
21 #include "label_creation.h"
22 #include "isel.h"
23 #include "offset_adjust.h"
24 #include "alignment.h"
25 #include "yieldpoint.h"
26 #include "emit.h"
27 #include "reg_alloc.h"
28 #if TARGAARCH64
29 #include "aarch64_emitter.h"
30 #include "aarch64_obj_emitter.h"
31 #include "aarch64_cg.h"
32 #endif
33 #if defined(TARGRISCV64)
34 #include "riscv64_emitter.h"
35 #endif
36 #if defined(TARGX86_64)
37 #include "x64_cg.h"
38 #include "x64_emitter.h"
39 #include "string_utils.h"
40 #endif
41 #include "triple.h"
42
43 namespace maplebe {
44 #define CLANG (module.GetSrcLang() == kSrcLangC)
45
46 #define RELEASE(pointer) \
47 do { \
48 if ((pointer) != nullptr) { \
49 delete (pointer); \
50 (pointer) = nullptr; \
51 } \
52 } while (0)
53
54 namespace {
55
DumpMIRFunc(MIRFunction & func,const char * msg,bool printAlways=false,const char * extraMsg=nullptr)56 void DumpMIRFunc(MIRFunction &func, const char *msg, bool printAlways = false, const char *extraMsg = nullptr)
57 {
58 bool dumpAll = (CGOptions::GetDumpPhases().find("*") != CGOptions::GetDumpPhases().end());
59 bool dumpFunc = CGOptions::FuncFilter(func.GetName());
60 if (printAlways || (dumpAll && dumpFunc)) {
61 LogInfo::MapleLogger() << msg << '\n';
62 func.Dump();
63
64 if (extraMsg) {
65 LogInfo::MapleLogger() << extraMsg << '\n';
66 }
67 }
68 }
69
70 } /* anonymous namespace */
71
GenerateOutPutFile(MIRModule & m)72 void CgFuncPM::GenerateOutPutFile(MIRModule &m)
73 {
74 CHECK_FATAL(cg != nullptr, "cg is null");
75 CHECK_FATAL(Triple::GetTriple().GetArch() != Triple::ArchType::UnknownArch, "should have triple init before!");
76 auto codegen = cg;
77 if (Triple::GetTriple().GetArch() == Triple::ArchType::x64) {
78 cg->Emit([codegen, &m](Emitter *emitter) {
79 assembler::Assembler &objAssm = static_cast<X64Emitter &>(*emitter).GetAssembler();
80 if (!codegen->GetCGOptions().SuppressFileInfo()) {
81 objAssm.InitialFileInfo(m.GetInputFileName());
82 }
83 if (codegen->GetCGOptions().WithDwarf()) {
84 objAssm.EmitDIHeader();
85 }
86 });
87 } else if (Triple::GetTriple().GetArch() == Triple::ArchType::aarch64) {
88 cg->template Emit<CG::EmitterType::AsmEmitter>([codegen, &m](Emitter *emitter) {
89 if (!codegen->GetCGOptions().SuppressFileInfo()) {
90 emitter->EmitFileInfo(m.GetInputFileName());
91 }
92 if (codegen->GetCGOptions().WithDwarf()) {
93 emitter->EmitDIHeader();
94 }
95 });
96 } else {
97 CHECK_FATAL(false, "unsupportted target!");
98 }
99 InitProfile(m);
100 }
101
FuncLevelRun(CGFunc & cgFunc,AnalysisDataManager & serialADM)102 bool CgFuncPM::FuncLevelRun(CGFunc &cgFunc, AnalysisDataManager &serialADM)
103 {
104 bool changed = false;
105 for (size_t i = 0; i < phasesSequence.size(); ++i) {
106 SolveSkipFrom(CGOptions::GetSkipFromPhase(), i);
107 const MaplePhaseInfo *curPhase = MaplePhaseRegister::GetMaplePhaseRegister()->GetPhaseByID(phasesSequence[i]);
108 if (!IsQuiet()) {
109 LogInfo::MapleLogger() << "---Run MplCG " << (curPhase->IsAnalysis() ? "analysis" : "transform")
110 << " Phase [ " << curPhase->PhaseName() << " ]---\n";
111 }
112 if (curPhase->IsAnalysis()) {
113 changed |= RunAnalysisPhase<MapleFunctionPhase<CGFunc>, CGFunc>(*curPhase, serialADM, cgFunc);
114 } else {
115 changed |= RunTransformPhase<MapleFunctionPhase<CGFunc>, CGFunc>(*curPhase, serialADM, cgFunc);
116 DumpFuncCGIR(cgFunc, curPhase->PhaseName());
117 }
118 SolveSkipAfter(CGOptions::GetSkipAfterPhase(), i);
119 }
120 return changed;
121 }
122
PostOutPut(MIRModule & m)123 void CgFuncPM::PostOutPut(MIRModule &m)
124 {
125 if (Triple::GetTriple().GetArch() == Triple::ArchType::x64) {
126 cg->Emit([this](Emitter * emitter) {
127 X64Emitter *x64Emitter = static_cast<X64Emitter *>(emitter);
128 assembler::Assembler &assm = x64Emitter->GetAssembler();
129 if (cgOptions->WithDwarf()) {
130 assm.EmitDIFooter();
131 }
132 x64Emitter->EmitGlobalVariable(*cg);
133 x64Emitter->EmitDebugInfo(*cg);
134 assm.FinalizeFileInfo();
135 assm.CloseOutput();
136 });
137 } else if (Triple::GetTriple().GetArch() == Triple::ArchType::aarch64) {
138 cg->template Emit<CG::EmitterType::AsmEmitter>([this, &m](Emitter* emitter) {
139 emitter->EmitHugeSoRoutines(true);
140 if (cgOptions->WithDwarf()) {
141 emitter->EmitDIFooter();
142 }
143 /* Emit global info */
144 EmitGlobalInfo(m);
145 });
146 cg->template Emit<CG::EmitterType::ObjEmiter>([](Emitter* emitter) {
147 emitter->Finish();
148 emitter->CloseOutput();
149 });
150 } else {
151 CHECK_FATAL(false, "unsupported target");
152 }
153 }
154
155 void MarkUsedStaticSymbol(const StIdx &symbolIdx);
156 std::map<StIdx, bool> visitedSym;
157
CollectStaticSymbolInVar(MIRConst * mirConst)158 void CollectStaticSymbolInVar(MIRConst *mirConst)
159 {
160 if (mirConst->GetKind() == kConstAddrof) {
161 auto *addrSymbol = static_cast<MIRAddrofConst *>(mirConst);
162 MIRSymbol *sym = GlobalTables::GetGsymTable().GetSymbolFromStidx(addrSymbol->GetSymbolIndex().Idx(), true);
163 if (sym != nullptr) {
164 MarkUsedStaticSymbol(sym->GetStIdx());
165 }
166 } else if (mirConst->GetKind() == kConstAggConst) {
167 auto &constVec = static_cast<MIRAggConst *>(mirConst)->GetConstVec();
168 for (auto &cst : constVec) {
169 CollectStaticSymbolInVar(cst);
170 }
171 }
172 }
173
MarkUsedStaticSymbol(const StIdx & symbolIdx)174 void MarkUsedStaticSymbol(const StIdx &symbolIdx)
175 {
176 if (!symbolIdx.IsGlobal()) {
177 return;
178 }
179 MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolIdx.Idx(), true);
180 if (symbol == nullptr) {
181 return;
182 }
183 if (visitedSym[symbolIdx]) {
184 return;
185 } else {
186 visitedSym[symbolIdx] = true;
187 }
188 symbol->ResetIsDeleted();
189 if (symbol->IsConst()) {
190 auto *konst = symbol->GetKonst();
191 CollectStaticSymbolInVar(konst);
192 }
193 }
194
RecursiveMarkUsedStaticSymbol(const BaseNode * baseNode)195 void RecursiveMarkUsedStaticSymbol(const BaseNode *baseNode)
196 {
197 if (baseNode == nullptr) {
198 return;
199 }
200 Opcode op = baseNode->GetOpCode();
201 switch (op) {
202 case OP_block: {
203 const BlockNode *blk = static_cast<const BlockNode *>(baseNode);
204 for (auto &stmt : blk->GetStmtNodes()) {
205 RecursiveMarkUsedStaticSymbol(&stmt);
206 }
207 break;
208 }
209 case OP_dassign: {
210 const DassignNode *dassignNode = static_cast<const DassignNode *>(baseNode);
211 MarkUsedStaticSymbol(dassignNode->GetStIdx());
212 break;
213 }
214 case OP_addrof:
215 case OP_addrofoff:
216 case OP_dread: {
217 const AddrofNode *dreadNode = static_cast<const AddrofNode *>(baseNode);
218 MarkUsedStaticSymbol(dreadNode->GetStIdx());
219 break;
220 }
221 default: {
222 break;
223 }
224 }
225 for (size_t i = 0; i < baseNode->NumOpnds(); ++i) {
226 RecursiveMarkUsedStaticSymbol(baseNode->Opnd(i));
227 }
228 }
229
CollectStaticSymbolInFunction(MIRFunction & func)230 void CollectStaticSymbolInFunction(MIRFunction &func)
231 {
232 RecursiveMarkUsedStaticSymbol(func.GetBody());
233 }
234
SweepUnusedStaticSymbol(MIRModule & m)235 void CgFuncPM::SweepUnusedStaticSymbol(MIRModule &m)
236 {
237 if (!m.IsCModule()) {
238 return;
239 }
240 size_t size = GlobalTables::GetGsymTable().GetSymbolTableSize();
241 for (size_t i = 0; i < size; ++i) {
242 MIRSymbol *mirSymbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(static_cast<uint32>(i));
243 if (mirSymbol != nullptr && (mirSymbol->GetSKind() == kStVar || mirSymbol->GetSKind() == kStConst) &&
244 (mirSymbol->GetStorageClass() == kScFstatic || mirSymbol->GetStorageClass() == kScPstatic)) {
245 mirSymbol->SetIsDeleted();
246 }
247 }
248
249 visitedSym.clear();
250 /* scan all funtions */
251 std::vector<MIRFunction *> &funcTable = GlobalTables::GetFunctionTable().GetFuncTable();
252 /* don't optimize this loop to iterator or range-base loop
253 * because AddCallGraphNode(mirFunc) will change GlobalTables::GetFunctionTable().GetFuncTable()
254 */
255 for (size_t index = 0; index < funcTable.size(); ++index) {
256 MIRFunction *mirFunc = funcTable.at(index);
257 if (mirFunc == nullptr || mirFunc->GetBody() == nullptr) {
258 continue;
259 }
260 m.SetCurFunction(mirFunc);
261 CollectStaticSymbolInFunction(*mirFunc);
262 /* scan function symbol declaration
263 * find addrof static const */
264 MIRSymbolTable *funcSymTab = mirFunc->GetSymTab();
265 if (funcSymTab) {
266 size_t localSymSize = funcSymTab->GetSymbolTableSize();
267 for (uint32 i = 0; i < localSymSize; ++i) {
268 MIRSymbol *st = funcSymTab->GetSymbolFromStIdx(i);
269 if (st && st->IsConst()) {
270 MIRConst *mirConst = st->GetKonst();
271 CollectStaticSymbolInVar(mirConst);
272 }
273 }
274 }
275 }
276 /* scan global symbol declaration
277 * find addrof static const */
278 auto &symbolSet = m.GetSymbolSet();
279 for (auto sit = symbolSet.begin(); sit != symbolSet.end(); ++sit) {
280 MIRSymbol *s = GlobalTables::GetGsymTable().GetSymbolFromStidx(sit->Idx(), true);
281 DEBUG_ASSERT(s != nullptr, "s should not be nullptr");
282 if (s->IsConst()) {
283 MIRConst *mirConst = s->GetKonst();
284 CollectStaticSymbolInVar(mirConst);
285 }
286 }
287 }
288
289 /* =================== new phase manager =================== */
PhaseRun(MIRModule & m)290 bool CgFuncPM::PhaseRun(MIRModule &m)
291 {
292 // registry target based on build, cgfunc, emitter need to be registried.
293 InitializeAllTargetInfos(m.GetMemPool());
294 std::string compileTarget = "";
295 if (Triple::GetTriple().IsAarch64BeOrLe()) {
296 compileTarget = "aarch64";
297 } else if (Triple::GetTriple().GetArch() == Triple::ArchType::x64) {
298 compileTarget = "x86";
299 } else {
300 CHECK_FATAL(false, "unsupport");
301 }
302 const Target *TheTarget = nullptr;
303 TheTarget = TargetRegistry::lookupTarget(compileTarget);
304 // get target based on option
305 CreateCGAndBeCommon(m, TheTarget);
306 bool changed = false;
307 /* reserve static symbol for debugging */
308 if (!cgOptions->WithDwarf()) {
309 SweepUnusedStaticSymbol(m);
310 }
311 if (cgOptions->IsRunCG()) {
312 GenerateOutPutFile(m);
313
314 /* Run the cg optimizations phases */
315 PrepareLower(m);
316
317 uint32 countFuncId = 0;
318 unsigned long rangeNum = 0;
319
320 auto userDefinedOptLevel = cgOptions->GetOptimizeLevel();
321 cg->EnrollTargetPhases(this);
322
323 auto admMempool = AllocateMemPoolInPhaseManager("cg phase manager's analysis data manager mempool");
324 auto *serialADM = GetManagerMemPool()->New<AnalysisDataManager>(*(admMempool.get()));
325 for (auto it = m.GetFunctionList().begin(); it != m.GetFunctionList().end(); ++it) {
326 DEBUG_ASSERT(serialADM->CheckAnalysisInfoEmpty(), "clean adm before function run");
327 MIRFunction *mirFunc = *it;
328 if (mirFunc->GetBody() == nullptr) {
329 continue;
330 }
331 if (userDefinedOptLevel == CGOptions::kLevel2 && m.HasPartO2List()) {
332 if (m.IsInPartO2List(mirFunc->GetNameStrIdx())) {
333 cgOptions->EnableO2();
334 } else {
335 cgOptions->EnableO0();
336 }
337 ClearAllPhases();
338 cg->EnrollTargetPhases(this);
339 cg->UpdateCGOptions(*cgOptions);
340 Globals::GetInstance()->SetOptimLevel(cgOptions->GetOptimizeLevel());
341 }
342 if (!IsQuiet()) {
343 LogInfo::MapleLogger() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>> Optimizing Function < " << mirFunc->GetName()
344 << " id=" << mirFunc->GetPuidxOrigin() << " >---\n";
345 }
346 /* LowerIR. */
347 m.SetCurFunction(mirFunc);
348 if (cg->DoConstFold()) {
349 DumpMIRFunc(*mirFunc, "************* before ConstantFold **************");
350 ConstantFold cf(m);
351 (void)cf.Simplify(mirFunc->GetBody());
352 }
353
354 if (m.GetFlavor() != MIRFlavor::kFlavorLmbc) {
355 DoFuncCGLower(m, *mirFunc);
356 }
357 /* create CGFunc */
358 MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(mirFunc->GetStIdx().Idx());
359 CHECK_NULL_FATAL(funcSt);
360 auto funcMp = std::make_unique<ThreadLocalMemPool>(memPoolCtrler, funcSt->GetName());
361 auto stackMp = std::make_unique<StackMemPool>(funcMp->GetCtrler(), "");
362 MapleAllocator funcScopeAllocator(funcMp.get());
363 mirFunc->SetPuidxOrigin(++countFuncId);
364 CGFunc *cgFunc =
365 cg->CreateCGFunc(m, *mirFunc, *beCommon, *funcMp, *stackMp, funcScopeAllocator, countFuncId);
366 CHECK_FATAL(cgFunc != nullptr, "Create CG Function failed in cg_phase_manager");
367 CG::SetCurCGFunc(*cgFunc);
368
369 if (cgOptions->WithDwarf()) {
370 cgFunc->SetDebugInfo(m.GetDbgInfo());
371 }
372 /* Run the cg optimizations phases. */
373 if (CGOptions::UseRange() && rangeNum >= CGOptions::GetRangeBegin() &&
374 rangeNum <= CGOptions::GetRangeEnd()) {
375 CGOptions::EnableInRange();
376 }
377 changed = FuncLevelRun(*cgFunc, *serialADM);
378 /* Delete mempool. */
379 mirFunc->ReleaseCodeMemory();
380 ++rangeNum;
381 CGOptions::DisableInRange();
382 }
383 PostOutPut(m);
384 #ifdef RA_PERF_ANALYSIS
385 if (cgOptions->IsEnableTimePhases()) {
386 printLSRATime();
387 }
388 #endif
389 } else {
390 LogInfo::MapleLogger(kLlErr) << "Skipped generating .s because -no-cg is given" << '\n';
391 }
392 RELEASE(cg);
393 RELEASE(beCommon);
394 return changed;
395 }
396
DumpFuncCGIR(const CGFunc & f,const std::string & phaseName) const397 void CgFuncPM::DumpFuncCGIR(const CGFunc &f, const std::string &phaseName) const
398 {
399 if (CGOptions::DumpPhase(phaseName) && CGOptions::FuncFilter(f.GetName())) {
400 LogInfo::MapleLogger() << "\n******** CG IR After " << phaseName << ": *********\n";
401 f.DumpCGIR();
402 }
403 }
404
EmitGlobalInfo(MIRModule & m) const405 void CgFuncPM::EmitGlobalInfo(MIRModule &m) const
406 {
407 EmitDuplicatedAsmFunc(m);
408 if (cgOptions->IsGenerateObjectMap()) {
409 cg->GenerateObjectMaps(*beCommon);
410 }
411 cg->template Emit<CG::EmitterType::AsmEmitter>([this, &m](Emitter* emitter) {
412 emitter->EmitGlobalVariable();
413 EmitDebugInfo(m);
414 emitter->CloseOutput();
415 });
416 }
417
InitProfile(MIRModule & m) const418 void CgFuncPM::InitProfile(MIRModule &m) const
419 {
420 if (!CGOptions::IsProfileDataEmpty()) {
421 uint32 dexNameIdx = m.GetFileinfo(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName("INFO_filename"));
422 const std::string &dexName = GlobalTables::GetStrTable().GetStringFromStrIdx(GStrIdx(dexNameIdx));
423 bool deCompressSucc = m.GetProfile().DeCompress(CGOptions::GetProfileData(), dexName);
424 if (!deCompressSucc) {
425 LogInfo::MapleLogger() << "WARN: DeCompress() " << CGOptions::GetProfileData() << "failed in mplcg()\n";
426 }
427 }
428 }
429
CreateCGAndBeCommon(MIRModule & m,const Target * t)430 void CgFuncPM::CreateCGAndBeCommon(MIRModule &m, const Target *t)
431 {
432 DEBUG_ASSERT(cgOptions != nullptr, "New cg phase manager running FAILED :: cgOptions unset");
433 auto outputFileName = m.GetOutputFileName();
434 Emitter *objEmitter = nullptr;
435 Emitter *asmEmitter = nullptr;
436 cg = t->createCG(m, *cgOptions, cgOptions->GetEHExclusiveFunctionNameVec(), CGOptions::GetCyclePatternMap());
437 CHECK_FATAL(cg, "you may not register the target");
438 if (Triple::GetTriple().GetArch() == Triple::ArchType::x64) {
439 assembler::Assembler *asmAssembler = nullptr;
440 if (cg->GetCGOptions().IsAsmEmitterEnable()) {
441 asmAssembler = new assembler::AsmAssembler(outputFileName);
442 asmEmitter = t->createDecoupledEmitter(*cg, *asmAssembler);
443 }
444 outputFileName = outputFileName.replace(outputFileName.length() - 1, 1, 1, 'o');
445 auto objAssembler = new assembler::ElfAssembler(outputFileName);
446 objEmitter = t->createDecoupledEmitter(*cg, *objAssembler);
447 } else if (Triple::GetTriple().GetArch() == Triple::ArchType::aarch64) {
448 if (cgOptions->IsAsmEmitterEnable()) {
449 asmEmitter = m.GetMemPool()->New<AArch64AsmEmitter>(*cg, outputFileName);
450 }
451 outputFileName = outputFileName.replace(outputFileName.length() - 1, 1, 1, 'o');
452 objEmitter = m.GetMemPool()->New<AArch64ObjEmitter>(*cg, outputFileName);
453 } else {
454 CHECK_FATAL(false, "unsupportted");
455 }
456 CHECK_FATAL(objEmitter, "you may not register emitter");
457 cg->SetObjEmitter(*objEmitter);
458 if (cg->GetCGOptions().IsAsmEmitterEnable()) {
459 CHECK_FATAL(asmEmitter, "you may not register emitter");
460 cg->SetAsmEmitter(*asmEmitter);
461 }
462 TargetMachine *targetMachine = t->createTargetMachine();
463 CHECK_FATAL(targetMachine, "you may not register targetMachine");
464 cg->SetTargetMachine(*targetMachine);
465
466 /*
467 * Must be done before creating any BECommon instances.
468 *
469 * BECommon, when constructed, will calculate the type, size and align of all types. As a side effect, it will also
470 * lower ptr and ref types into a64. That will drop the information of what a ptr or ref points to.
471 *
472 * All metadata generation passes which depend on the pointed-to type must be done here.
473 */
474 cg->GenPrimordialObjectList(m.GetBaseName());
475 /* We initialize a couple of BECommon's tables using the size information of GlobalTables.type_table_.
476 * So, BECommon must be allocated after all the parsing is done and user-defined types are all acounted.
477 */
478 beCommon = new BECommon(m);
479 Globals::GetInstance()->SetBECommon(*beCommon);
480 Globals::GetInstance()->SetTarget(*cg);
481
482 /* If a metadata generation pass depends on object layout it must be done after creating BECommon. */
483 cg->GenExtraTypeMetadata(cgOptions->GetClassListFile(), m.GetBaseName());
484
485 if (cg->NeedInsertInstrumentationFunction()) {
486 CHECK_FATAL(cgOptions->IsInsertCall(), "handling of --insert-call is not correct");
487 cg->SetInstrumentationFunction(cgOptions->GetInstrumentationFunction());
488 }
489 if (!m.IsCModule() && Triple::GetTriple().IsAarch64BeOrLe()) {
490 CGOptions::EnableFramePointer();
491 }
492 }
493
PrepareLower(MIRModule & m)494 void CgFuncPM::PrepareLower(MIRModule &m)
495 {
496 mirLower = GetManagerMemPool()->New<MIRLower>(m, nullptr);
497 mirLower->Init();
498 cgLower =
499 GetManagerMemPool()->New<CGLowerer>(m, *beCommon, cg->GenerateExceptionHandlingCode(), cg->GenerateVerboseCG());
500 cgLower->RegisterBuiltIns();
501 cgLower->RegisterExternalLibraryFunctions();
502 cgLower->SetCheckLoadStore(CGOptions::IsCheckArrayStore());
503 if (cg->IsStackProtectorStrong() || cg->IsStackProtectorAll() || m.HasPartO2List()) {
504 cg->AddStackGuardvar();
505 }
506 }
507
DoFuncCGLower(const MIRModule & m,MIRFunction & mirFunc)508 void CgFuncPM::DoFuncCGLower(const MIRModule &m, MIRFunction &mirFunc)
509 {
510 if (m.GetFlavor() <= kFeProduced) {
511 mirLower->SetLowerCG();
512 mirLower->SetMirFunc(&mirFunc);
513
514 DumpMIRFunc(mirFunc, "************* before MIRLowerer **************");
515 mirLower->LowerFunc(mirFunc);
516 }
517
518 bool isNotQuiet = !CGOptions::IsQuiet();
519 DumpMIRFunc(mirFunc, "************* before CGLowerer **************", isNotQuiet);
520
521 cgLower->LowerFunc(mirFunc);
522
523 DumpMIRFunc(mirFunc, "************* after CGLowerer **************", isNotQuiet,
524 "************* end CGLowerer **************");
525 }
526
EmitDuplicatedAsmFunc(MIRModule & m) const527 void CgFuncPM::EmitDuplicatedAsmFunc(MIRModule &m) const
528 {
529 if (CGOptions::IsDuplicateAsmFileEmpty()) {
530 return;
531 }
532
533 std::ifstream duplicateAsmFileFD(CGOptions::GetDuplicateAsmFile());
534
535 if (!duplicateAsmFileFD.is_open()) {
536 duplicateAsmFileFD.close();
537 ERR(kLncErr, " %s open failed!", CGOptions::GetDuplicateAsmFile().c_str());
538 return;
539 }
540 std::string contend;
541 bool onlyForFramework = false;
542 bool isFramework = IsFramework(m);
543
544 while (getline(duplicateAsmFileFD, contend)) {
545 if (!contend.compare("#Libframework_start")) {
546 onlyForFramework = true;
547 }
548
549 if (!contend.compare("#Libframework_end")) {
550 onlyForFramework = false;
551 }
552
553 if (onlyForFramework && !isFramework) {
554 continue;
555 }
556
557 cg->Emit([&contend](Emitter *emitter) {
558 emitter->Emit(contend + "\n");
559 });
560 }
561 duplicateAsmFileFD.close();
562 }
563
EmitDebugInfo(const MIRModule & m) const564 void CgFuncPM::EmitDebugInfo(const MIRModule &m) const
565 {
566 if (!cgOptions->WithDwarf()) {
567 return;
568 }
569 cg->Emit([&m](Emitter* emitter) {
570 emitter->SetupDBGInfo(m.GetDbgInfo());
571 emitter->EmitDIHeaderFileInfo();
572 emitter->EmitDIDebugInfoSection(m.GetDbgInfo());
573 emitter->EmitDIDebugAbbrevSection(m.GetDbgInfo());
574 emitter->EmitDIDebugARangesSection();
575 emitter->EmitDIDebugRangesSection();
576 emitter->EmitDIDebugLineSection();
577 emitter->EmitDIDebugStrSection();
578 });
579 }
580
IsFramework(MIRModule & m) const581 bool CgFuncPM::IsFramework([[maybe_unused]] MIRModule &m) const
582 {
583 return false;
584 }
585 MAPLE_TRANSFORM_PHASE_REGISTER(CgFuncPM, cgFuncPhaseManager)
586 /* register codegen common phases */
587 MAPLE_TRANSFORM_PHASE_REGISTER(CgLayoutFrame, layoutstackframe)
588 MAPLE_TRANSFORM_PHASE_REGISTER(CgCreateLabel, createstartendlabel)
589 MAPLE_TRANSFORM_PHASE_REGISTER(InstructionSelector, instructionselector)
590 MAPLE_TRANSFORM_PHASE_REGISTER(CgMoveRegArgs, moveargs)
591 MAPLE_TRANSFORM_PHASE_REGISTER(CgRegAlloc, regalloc)
592 MAPLE_TRANSFORM_PHASE_REGISTER(CgAlignAnalysis, alignanalysis)
593 MAPLE_TRANSFORM_PHASE_REGISTER(CgFrameFinalize, framefinalize)
594 MAPLE_TRANSFORM_PHASE_REGISTER(CgYieldPointInsertion, yieldpoint)
595 MAPLE_TRANSFORM_PHASE_REGISTER(CgGenProEpiLog, generateproepilog)
596 } /* namespace maplebe */
597