• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <set>
17 #include "emit.h"
18 
19 namespace maplebe {
20 using namespace maple;
21 
22 uint32 VregInfo::virtualRegCount = kBaseVirtualRegNO;
23 uint32 VregInfo::maxRegCount = 0;
24 std::vector<VirtualRegNode> VregInfo::vRegTable;
25 std::unordered_map<regno_t, RegOperand *> VregInfo::vRegOperandTable;
26 /*  There are two builders, cgfunc builder (original code selector) and irbuilder (abstract).
27  *  This is to prevent conflict between the two for VregInfo as for arm64 both co-exists.
28  *  When switching to irbuilder completely, then this bool can go away.
29  */
30 bool VregInfo::initialized = false;
31 
SetTarget(CG & target)32 void Globals::SetTarget(CG &target)
33 {
34     cg = &target;
35 }
GetTarget() const36 const CG *Globals::GetTarget() const
37 {
38     DEBUG_ASSERT(cg, " set target info please ");
39     return cg;
40 }
41 
42 CGFunc *CG::currentCGFunction = nullptr;
43 std::map<MIRFunction *, std::pair<LabelIdx, LabelIdx>> CG::funcWrapLabels;
44 
~CG()45 CG::~CG()
46 {
47     Emit([](Emitter *emitter) {
48         emitter->CloseOutput();
49     });
50     delete memPool;
51     memPool = nullptr;
52     mirModule = nullptr;
53     emitters.clear();
54     currentCGFunction = nullptr;
55     instrumentationFunction = nullptr;
56     dbgTraceEnter = nullptr;
57     dbgTraceExit = nullptr;
58     dbgFuncProfile = nullptr;
59 }
60 /* This function intends to be a more general form of GenFieldOffsetmap. */
GenExtraTypeMetadata(const std::string & classListFileName,const std::string & outputBaseName)61 void CG::GenExtraTypeMetadata(const std::string &classListFileName, const std::string &outputBaseName)
62 {
63     const std::string &cMacroDefSuffix = ".macros.def";
64     BECommon *beCommon = Globals::GetInstance()->GetBECommon();
65     std::vector<MIRClassType *> classesToGenerate;
66 
67     if (classListFileName.empty()) {
68         /*
69          * Class list not specified. Visit all classes.
70          */
71         std::set<std::string> visited;
72 
73         for (const auto &tyId : mirModule->GetClassList()) {
74             MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyId);
75             if ((mirType->GetKind() != kTypeClass) && (mirType->GetKind() != kTypeClassIncomplete)) {
76                 continue; /* Skip non-class. Too paranoid. We just enumerated classlist_! */
77             }
78             MIRClassType *classType = static_cast<MIRClassType *>(mirType);
79             const std::string &name = classType->GetName();
80 
81             if (visited.find(name) != visited.end()) {
82                 continue; /* Skip duplicated class definitions. */
83             }
84 
85             (void)visited.insert(name);
86             classesToGenerate.emplace_back(classType);
87         }
88     } else {
89         /* Visit listed classes. */
90         std::ifstream inFile(classListFileName);
91         CHECK_FATAL(inFile.is_open(), "Failed to open file: %s", classListFileName.c_str());
92         std::string str;
93 
94         /* check each class name first and expose all unknown classes */
95         while (inFile >> str) {
96             MIRType *type = GlobalTables::GetTypeTable().GetOrCreateClassType(str, *mirModule);
97             MIRClassType *classType = static_cast<MIRClassType *>(type);
98             if (classType == nullptr) {
99                 LogInfo::MapleLogger() << " >>>>>>>> unknown class: " << str.c_str() << "\n";
100                 return;
101             }
102 
103             classesToGenerate.emplace_back(classType);
104         }
105     }
106 
107     if (cgOption.GenDef()) {
108         const std::string &outputFileName = outputBaseName + cMacroDefSuffix;
109         FILE *outputFile = fopen(outputFileName.c_str(), "w");
110         if (outputFile == nullptr) {
111             FATAL(kLncFatal, "open file failed in CG::GenExtraTypeMetadata");
112         }
113 
114         for (auto classType : classesToGenerate) {
115             beCommon->GenObjSize(*classType, *outputFile);
116             beCommon->GenFieldOffsetMap(*classType, *outputFile);
117         }
118         fclose(outputFile);
119     }
120 
121     if (cgOption.GenGctib()) {
122         maple::LogInfo::MapleLogger(kLlErr) << "--gen-gctib-file option not implemented";
123     }
124 }
125 
GenPrimordialObjectList(const std::string & outputBaseName)126 void CG::GenPrimordialObjectList(const std::string &outputBaseName)
127 {
128     const std::string &kPrimorListSuffix = ".primordials.txt";
129     if (!cgOption.GenPrimorList()) {
130         return;
131     }
132 
133     const std::string &outputFileName = outputBaseName + kPrimorListSuffix;
134     FILE *outputFile = fopen(outputFileName.c_str(), "w");
135     if (outputFile == nullptr) {
136         FATAL(kLncFatal, "open file failed in CG::GenPrimordialObjectList");
137     }
138 
139     for (StIdx stIdx : mirModule->GetSymbolSet()) {
140         MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(stIdx.Idx());
141         DEBUG_ASSERT(symbol != nullptr, "get symbol from st idx failed");
142         if (symbol->IsPrimordialObject()) {
143             const std::string &name = symbol->GetName();
144             fprintf(outputFile, "%s\n", name.c_str());
145         }
146     }
147 
148     fclose(outputFile);
149 }
150 
AddStackGuardvar()151 void CG::AddStackGuardvar()
152 {
153     MIRSymbol *chkGuard = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal);
154     chkGuard->SetNameStrIdx(std::string("__stack_chk_guard"));
155     chkGuard->SetStorageClass(kScExtern);
156     chkGuard->SetSKind(kStVar);
157     CHECK_FATAL(GlobalTables::GetTypeTable().GetTypeTable().size() > PTY_u64, "out of vector range");
158     chkGuard->SetTyIdx(GlobalTables::GetTypeTable().GetTypeTable()[PTY_u64]->GetTypeIndex());
159     GlobalTables::GetGsymTable().AddToStringSymbolMap(*chkGuard);
160 
161     MIRFunction *func = GetMIRModule()->GetMIRBuilder()->GetOrCreateFunction(
162         "__stack_chk_fail", GlobalTables::GetTypeTable().GetVoid()->GetTypeIndex());
163     MIRSymbol *chkFuncSym = func->GetFuncSymbol();
164     DEBUG_ASSERT(chkFuncSym != nullptr, "nullptr check");
165     chkFuncSym->SetAppearsInCode(true);
166     chkFuncSym->SetStorageClass(kScExtern);
167     GlobalTables::GetGsymTable().AddToStringSymbolMap(*chkFuncSym);
168 }
169 
SetInstrumentationFunction(const std::string & name)170 void CG::SetInstrumentationFunction(const std::string &name)
171 {
172     instrumentationFunction = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal);
173     instrumentationFunction->SetNameStrIdx(std::string("__").append(name).append("__"));
174     instrumentationFunction->SetStorageClass(kScText);
175     instrumentationFunction->SetSKind(kStFunc);
176 }
177 
178 #define DBG_TRACE_ENTER MplDtEnter
179 #define DBG_TRACE_EXIT MplDtExit
180 #define XSTR(s) str(s)
181 #define str(s) #s
182 
DefineDebugTraceFunctions()183 void CG::DefineDebugTraceFunctions()
184 {
185     dbgTraceEnter = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal);
186     dbgTraceEnter->SetNameStrIdx(std::string("__" XSTR(DBG_TRACE_ENTER) "__"));
187     dbgTraceEnter->SetStorageClass(kScText);
188     dbgTraceEnter->SetSKind(kStFunc);
189 
190     dbgTraceExit = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal);
191     dbgTraceExit->SetNameStrIdx(std::string("__" XSTR(DBG_TRACE_EXIT) "__"));
192     dbgTraceExit->SetStorageClass(kScText);
193     dbgTraceExit->SetSKind(kStFunc);
194 
195     dbgFuncProfile = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal);
196     dbgFuncProfile->SetNameStrIdx(std::string("__" XSTR(MplFuncProfile) "__"));
197     dbgFuncProfile->SetStorageClass(kScText);
198     dbgFuncProfile->SetSKind(kStFunc);
199 }
200 
201 /*
202  * Add the fields of curStructType to the result. Used to handle recursive
203  * structures.
204  */
AppendReferenceOffsets64(const BECommon & beCommon,MIRStructType & curStructType,int64 & curOffset,std::vector<int64> & result)205 static void AppendReferenceOffsets64(const BECommon &beCommon, MIRStructType &curStructType, int64 &curOffset,
206                                      std::vector<int64> &result)
207 {
208     /*
209      * We are going to reimplement BECommon::GetFieldOffset so that we can do
210      * this in one pass through all fields.
211      *
212      * The tricky part is to make sure the object layout described here is
213      * compatible with the rest of the system. This implies that we need
214      * something like a "Maple ABI" documented for each platform.
215      */
216     if (curStructType.GetKind() == kTypeClass) {
217         MIRClassType &curClassTy = static_cast<MIRClassType &>(curStructType);
218         auto maybeParent = GlobalTables::GetTypeTable().GetTypeFromTyIdx(curClassTy.GetParentTyIdx());
219         if (maybeParent != nullptr) {
220             if (maybeParent->GetKind() == kTypeClass) {
221                 auto parentClassType = static_cast<MIRClassType *>(maybeParent);
222                 AppendReferenceOffsets64(beCommon, *parentClassType, curOffset, result);
223             } else {
224                 LogInfo::MapleLogger() << "WARNING:: generating objmap for incomplete class\n";
225             }
226         }
227     }
228 
229     for (const auto &fieldPair : curStructType.GetFields()) {
230         auto fieldNameIdx = fieldPair.first;
231         auto fieldTypeIdx = fieldPair.second.first;
232 
233         auto &fieldName = GlobalTables::GetStrTable().GetStringFromStrIdx(fieldNameIdx);
234         auto fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fieldTypeIdx);
235         auto &fieldTypeName = GlobalTables::GetStrTable().GetStringFromStrIdx(fieldType->GetNameStrIdx());
236         auto fieldTypeKind = fieldType->GetKind();
237 
238         auto fieldSize = beCommon.GetTypeSize(fieldTypeIdx);
239         auto fieldAlign = beCommon.GetTypeAlign(fieldTypeIdx);
240         int64 myOffset = static_cast<int64>(RoundUp(curOffset, fieldAlign));
241         int64 nextOffset = myOffset + static_cast<int64>(fieldSize);
242 
243         if (!CGOptions::IsQuiet()) {
244             LogInfo::MapleLogger() << "    field: " << fieldName << "\n";
245             LogInfo::MapleLogger() << "      type: " << fieldTypeIdx << ": " << fieldTypeName << "\n";
246             LogInfo::MapleLogger() << "      type kind: " << fieldTypeKind << "\n";
247             LogInfo::MapleLogger() << "      size: " << fieldSize << "\n";                        /* int64 */
248             LogInfo::MapleLogger() << "      align: " << static_cast<uint32>(fieldAlign) << "\n"; /* int8_t */
249             LogInfo::MapleLogger() << "      field offset:" << myOffset << "\n";                  /* int64 */
250         }
251 
252         if (fieldTypeKind == kTypePointer) {
253             if (!CGOptions::IsQuiet()) {
254                 LogInfo::MapleLogger() << "      ** Is a pointer field.\n";
255             }
256             result.emplace_back(myOffset);
257         }
258 
259         if ((fieldTypeKind == kTypeArray) || (fieldTypeKind == kTypeStruct) || (fieldTypeKind == kTypeClass) ||
260             (fieldTypeKind == kTypeInterface)) {
261             if (!CGOptions::IsQuiet()) {
262                 LogInfo::MapleLogger() << "    ** ERROR: We are not expecting nested aggregate type. ";
263                 LogInfo::MapleLogger() << "All J classes are flat -- no nested structs. ";
264                 LogInfo::MapleLogger() << "Please extend me if we are going to work with non-j languages.\n";
265             }
266         }
267 
268         curOffset = nextOffset;
269     }
270 }
271 
272 /* Return a list of offsets of reference fields. */
GetReferenceOffsets64(const BECommon & beCommon,MIRStructType & structType)273 std::vector<int64> CG::GetReferenceOffsets64(const BECommon &beCommon, MIRStructType &structType)
274 {
275     std::vector<int64> result;
276     if (structType.GetKind() == kTypeClass) {
277         for (auto fieldInfo : beCommon.GetJClassLayout(static_cast<MIRClassType &>(structType))) {
278             if (fieldInfo.IsRef()) {
279                 result.emplace_back(static_cast<int64>(fieldInfo.GetOffset()));
280             }
281         }
282     } else if (structType.GetKind() != kTypeInterface) { /* interface doesn't have reference fields */
283         int64 curOffset = 0;
284         AppendReferenceOffsets64(beCommon, structType, curOffset, result);
285     }
286 
287     return result;
288 }
289 
ExtractFuncName(const std::string & str)290 const std::string CG::ExtractFuncName(const std::string &str)
291 {
292     /* 3: length of "_7C" */
293     size_t offset = 3;
294     size_t pos1 = str.find("_7C");
295     if (pos1 == std::string::npos) {
296         return str;
297     }
298     size_t pos2 = str.find("_7C", pos1 + offset);
299     if (pos2 == std::string::npos) {
300         return str;
301     }
302     std::string funcName = str.substr(pos1 + offset, pos2 - pos1 - offset);
303     /* avoid funcName like __LINE__ and __FILE__ which will be resolved by assembler */
304     if (funcName.find("__") != std::string::npos) {
305         return str;
306     }
307     if (funcName == "_3Cinit_3E") {
308         return "init";
309     }
310     if (funcName == "_3Cclinit_3E") {
311         return "clinit";
312     }
313     return funcName;
314 }
315 
EmitAllEmitters(const std::function<void (Emitter *)> & cb) const316 void CG::EmitAllEmitters(const std::function<void(Emitter *)>& cb) const
317 {
318     DEBUG_ASSERT(!emitters.empty(), "Emitter were not set");
319     DEBUG_ASSERT(emitters.size() <= 2U, "Emitters number isn't correct");
320     for (auto emitter: emitters) {
321         cb(emitter);
322     }
323 }
324 
EmitAsmEmitters(const std::function<void (Emitter *)> & cb) const325 void CG::EmitAsmEmitters(const std::function<void(Emitter *)>& cb) const
326 {
327     if (emitters.size() == 2U) {
328         cb(emitters[1]);
329     }
330 }
331 
EmitObjEmitters(const std::function<void (Emitter *)> & cb) const332 void CG::EmitObjEmitters(const std::function<void(Emitter *)>& cb) const
333 {
334     DEBUG_ASSERT(!emitters.empty(), "ObjEmmiter wasn't set");
335     cb(emitters[0]);
336 }
337 
338 } /* namespace maplebe */
339