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