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 "verification.h"
17 #include "mir_nodes.h"
18 #include "class_hierarchy.h"
19 #include "utils.h"
20
21 namespace maple {
22 #ifdef NOT_USED
Run(MIRModule * module,ModuleResultMgr * mgr)23 AnalysisResult *DoVerification::Run(MIRModule *module, ModuleResultMgr *mgr)
24 {
25 LogInfo::MapleLogger() << "========== Starting Verify Module =====================" << '\n';
26 CHECK_FATAL(module != nullptr, "Module should be not null");
27 LogInfo::MapleLogger() << "Current module = " << module->GetFileName() << std::endl;
28
29 auto chaAnalysis = mgr->GetAnalysisResult(MoPhase_CHA, module);
30 if (chaAnalysis == nullptr) {
31 LogInfo::MapleLogger() << "Can't find class hierarchy result" << '\n';
32 return nullptr;
33 }
34 KlassHierarchy *klassHierarchy = static_cast<KlassHierarchy *>(chaAnalysis);
35
36 MemPool *memPool = NewMemPool();
37 auto *verifyResult = memPool->New<VerifyResult>(*module, *klassHierarchy, *memPool);
38 VerifyModule(*module, *verifyResult);
39 if (verifyResult->HasErrorNotDeferred()) {
40 LogInfo::MapleLogger() << "Warning: Verify MIR failed! " << '\n';
41 }
42
43 CheckExtendFinalClass(*verifyResult);
44
45 auto *result = memPool->New<VerificationPhaseResult>(*memPool, *verifyResult);
46 mgr->AddResult(GetPhaseID(), *module, *result);
47 LogInfo::MapleLogger() << "========== Finished Verify Module =====================" << '\n';
48 return result;
49 }
50
CheckExtendFinalClass(VerifyResult & result) const51 void DoVerification::CheckExtendFinalClass(VerifyResult &result) const
52 {
53 const KlassHierarchy &klassHierarchy = result.GetKlassHierarchy();
54 std::stack<const Klass *> classesToMark;
55 for (auto klass : klassHierarchy.GetTopoSortedKlasses()) {
56 if (klass == nullptr || !klass->HasSubKlass()) {
57 continue;
58 }
59 const MIRStructType *mirStructType = klass->GetMIRStructType();
60 if ((mirStructType == nullptr) || (!mirStructType->IsMIRClassType()) ||
61 (!static_cast<const MIRClassType *>(mirStructType)->IsFinal())) {
62 continue;
63 }
64 classesToMark.push(klass);
65 while (!classesToMark.empty()) {
66 const auto &subKlasses = classesToMark.top()->GetSubKlasses();
67 classesToMark.pop();
68 for (auto subKlass : subKlasses) {
69 if (subKlass == nullptr) {
70 continue;
71 }
72 std::string errMsg =
73 "Class " + subKlass->GetKlassName() + " cannot inherit from final class " + klass->GetKlassName();
74 result.AddPragmaVerifyError(subKlass->GetKlassName(), std::move(errMsg));
75 if (subKlass->HasSubKlass()) {
76 classesToMark.push(subKlass);
77 }
78 }
79 }
80 }
81 }
82
NeedRuntimeFinalCheck(const KlassHierarchy & klassHierarchy,const std::string & className) const83 bool DoVerification::NeedRuntimeFinalCheck(const KlassHierarchy &klassHierarchy, const std::string &className) const
84 {
85 const Klass *klass = klassHierarchy.GetKlassFromName(className);
86 if (klass == nullptr || klass->GetMIRStructType() == nullptr || !klass->HasSuperKlass()) {
87 return false;
88 }
89 return klass->GetMIRStructType()->IsLocal();
90 }
91
DeferredCheckFinalClassAndMethod(VerifyResult & result) const92 void DoVerification::DeferredCheckFinalClassAndMethod(VerifyResult &result) const
93 {
94 const auto &functionList = result.GetMIRModule().GetFunctionList();
95 std::set<std::string> classesAdded;
96 for (size_t index = 0; index < functionList.size(); ++index) {
97 result.SetCurrentFunction(index);
98 const auto &className = result.GetCurrentClassName();
99 if (classesAdded.find(className) != classesAdded.end()) {
100 continue;
101 }
102
103 if (!NeedRuntimeFinalCheck(result.GetKlassHierarchy(), className)) {
104 continue;
105 }
106 // do not extend final parent class
107 result.AddPragmaExtendFinalCheck(className);
108 // do not override final method
109 result.AddPragmaOverrideFinalCheck(className);
110 LogInfo::MapleLogger() << "Check Final class and method for class " << className << '\n';
111 (void)classesAdded.insert(className);
112 }
113 }
114
VerifyModule(MIRModule & module,VerifyResult & result) const115 void DoVerification::VerifyModule(MIRModule &module, VerifyResult &result) const
116 {
117 const auto &resultMap = result.GetResultMap();
118
119 // theModule is needed by verify() functions in mir_nodes.cpp
120 theMIRModule = &module;
121 const auto &functionList = result.GetMIRModule().GetFunctionList();
122 for (size_t index = 0; index < functionList.size(); ++index) {
123 result.SetCurrentFunction(index);
124 MIRFunction *currentFunction = functionList[index];
125 const BlockNode *block = currentFunction->GetBody();
126
127 // For verify() functions compatibility
128 theMIRModule->SetCurFunction(currentFunction);
129
130 if (block == nullptr) {
131 continue;
132 }
133 bool blockResult = block->Verify(result);
134
135 const auto &className = result.GetCurrentClassName();
136 auto iter = resultMap.find(className);
137 if (iter == resultMap.end()) {
138 result.SetClassCorrectness(className, blockResult);
139 } else {
140 result.SetClassCorrectness(className, iter->second && blockResult);
141 }
142 }
143 }
144 #endif
145
HasVerifyError(const std::vector<const VerifyPragmaInfo * > & pragmaInfoPtrVec) const146 bool VerifyResult::HasVerifyError(const std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec) const
147 {
148 if (pragmaInfoPtrVec.empty()) {
149 return false;
150 }
151 return (utils::ToRef(pragmaInfoPtrVec.front()).IsVerifyError());
152 }
153
HasSamePragmaInfo(const std::vector<const VerifyPragmaInfo * > & pragmaInfoPtrVec,const VerifyPragmaInfo & verifyPragmaInfo) const154 bool VerifyResult::HasSamePragmaInfo(const std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec,
155 const VerifyPragmaInfo &verifyPragmaInfo) const
156 {
157 for (auto &pragmaInfoPtr : pragmaInfoPtrVec) {
158 const VerifyPragmaInfo &pragmaInfoRef = utils::ToRef(pragmaInfoPtr);
159 if (!verifyPragmaInfo.IsEqualTo(pragmaInfoRef)) {
160 continue;
161 }
162 if (!verifyPragmaInfo.IsAssignableCheck()) {
163 return true;
164 }
165 if (static_cast<const AssignableCheckPragma &>(verifyPragmaInfo)
166 .IsEqualTo(static_cast<const AssignableCheckPragma &>(pragmaInfoRef))) {
167 return true;
168 }
169 }
170 return false;
171 }
172
AddPragmaVerifyError(const std::string & className,std::string errMsg)173 void VerifyResult::AddPragmaVerifyError(const std::string &className, std::string errMsg)
174 {
175 classesCorrectness[className] = false;
176 auto classIter = classesPragma.find(className);
177 if (classIter != classesPragma.end() && HasVerifyError(classIter->second)) {
178 return;
179 }
180 const VerifyPragmaInfo *verifyError = allocator.GetMemPool()->New<ThrowVerifyErrorPragma>(std::move(errMsg));
181 if (classIter == classesPragma.end()) {
182 classesPragma[className].push_back(verifyError);
183 return;
184 }
185 std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec = classIter->second;
186 pragmaInfoPtrVec.clear();
187 pragmaInfoPtrVec.push_back(verifyError);
188 }
189
AddPragmaAssignableCheck(const std::string & className,std::string fromType,std::string toType)190 void VerifyResult::AddPragmaAssignableCheck(const std::string &className, std::string fromType, std::string toType)
191 {
192 classesCorrectness[className] = false;
193 auto classIter = classesPragma.find(className);
194 if (classIter != classesPragma.end() && HasVerifyError(classIter->second)) {
195 return;
196 }
197 const VerifyPragmaInfo *assignableCheck =
198 allocator.GetMemPool()->New<AssignableCheckPragma>(std::move(fromType), std::move(toType));
199 if (classIter == classesPragma.end()) {
200 classesPragma[className].push_back(assignableCheck);
201 return;
202 }
203 std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec = classIter->second;
204 if (HasSamePragmaInfo(pragmaInfoPtrVec, *assignableCheck)) {
205 return;
206 }
207 pragmaInfoPtrVec.push_back(assignableCheck);
208 }
209
AddPragmaExtendFinalCheck(const std::string & className)210 void VerifyResult::AddPragmaExtendFinalCheck(const std::string &className)
211 {
212 classesCorrectness[className] = false;
213 auto classIter = classesPragma.find(className);
214 if (classIter != classesPragma.end() && HasVerifyError(classIter->second)) {
215 return;
216 }
217
218 const VerifyPragmaInfo *extendFinalCheck = allocator.GetMemPool()->New<ExtendFinalCheckPragma>();
219 if (classIter == classesPragma.end()) {
220 classesPragma[className].push_back(extendFinalCheck);
221 return;
222 }
223 std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec = classIter->second;
224 if (HasSamePragmaInfo(pragmaInfoPtrVec, *extendFinalCheck)) {
225 return;
226 }
227 pragmaInfoPtrVec.push_back(extendFinalCheck);
228 }
229
AddPragmaOverrideFinalCheck(const std::string & className)230 void VerifyResult::AddPragmaOverrideFinalCheck(const std::string &className)
231 {
232 classesCorrectness[className] = false;
233 auto classIter = classesPragma.find(className);
234 if (classIter != classesPragma.end() && HasVerifyError(classIter->second)) {
235 return;
236 }
237
238 const VerifyPragmaInfo *overrideFinalCheck = allocator.GetMemPool()->New<OverrideFinalCheckPragma>();
239 if (classIter == classesPragma.end()) {
240 classesPragma[className].push_back(overrideFinalCheck);
241 return;
242 }
243 std::vector<const VerifyPragmaInfo *> &pragmaInfoPtrVec = classIter->second;
244 if (HasSamePragmaInfo(pragmaInfoPtrVec, *overrideFinalCheck)) {
245 return;
246 }
247 pragmaInfoPtrVec.push_back(overrideFinalCheck);
248 }
249 } // namespace maple
250