• 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 "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