1 /**
2 * Copyright (c) 2024 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 "graph_analyzer.h"
17
18 #include "compiler/optimizer/ir/basicblock.h"
19
20 #include "function.h"
21 #include "util/assert_util.h"
22
23 using namespace panda::guard;
24
25 namespace {
26 constexpr std::string_view TAG = "[Graph]";
27 constexpr std::string_view UI_COMPONENT_BASE_CLASS_VIEW_PU = "ViewPU";
28 constexpr std::string_view UI_COMPONENT_BASE_CLASS_VIEW_V2 = "ViewV2";
29 constexpr size_t PARAM_COUNT_THRESHOLD = 2;
30
31 using IntrinsicId = panda::compiler::RuntimeInterface::IntrinsicId;
32 using InstIdFilterList = std::vector<IntrinsicId>;
33 struct InstParam {
34 public:
35 unsigned index; // Target instruction: Index in the input instruction register list
36 InstIdFilterList filterList; // Input instruction: Type list
37 };
38
39 const InstIdFilterList INST_ID_LIST_DYNAMICIMPORT = {
40 IntrinsicId::DYNAMICIMPORT,
41 };
42 const InstIdFilterList INST_ID_LIST_STLEXVAR = {IntrinsicId::STLEXVAR_IMM4_IMM4, IntrinsicId::STLEXVAR_IMM8_IMM8};
43 const InstIdFilterList INST_ID_LIST_LDOBJBYVALUE = {
44 IntrinsicId::LDOBJBYVALUE_IMM8_V8,
45 IntrinsicId::LDOBJBYVALUE_IMM16_V8,
46 };
47 const InstIdFilterList INST_ID_LIST_STOBJBYVALUE = {
48 IntrinsicId::STOBJBYVALUE_IMM8_V8_V8,
49 IntrinsicId::STOBJBYVALUE_IMM16_V8_V8,
50 };
51 const InstIdFilterList INST_ID_LIST_DEFINEGETTERSETTERBYVALUE = {
52 IntrinsicId::DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8,
53 };
54 const InstIdFilterList INST_ID_LIST_ISIN = {
55 IntrinsicId::ISIN_IMM8_V8,
56 };
57 const InstIdFilterList INST_ID_LIST_LDSUPERBYVALUE = {
58 IntrinsicId::LDSUPERBYVALUE_IMM16_V8,
59 IntrinsicId::LDSUPERBYVALUE_IMM8_V8,
60 };
61 const InstIdFilterList INST_ID_LIST_STSUPERBYVALUE = {
62 IntrinsicId::STSUPERBYVALUE_IMM16_V8_V8,
63 IntrinsicId::STSUPERBYVALUE_IMM8_V8_V8,
64 };
65 const InstIdFilterList INST_ID_LIST_STOWNBYNAME = {
66 IntrinsicId::STOWNBYNAME_IMM16_ID16_V8,
67 IntrinsicId::STOWNBYNAME_IMM8_ID16_V8,
68 };
69 const InstIdFilterList INST_ID_LIST_STOWNBYNAMEWITHNAMESET = {
70 IntrinsicId::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8,
71 IntrinsicId::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8,
72 };
73 const InstIdFilterList INST_ID_LIST_STOWNBYVALUE = {
74 IntrinsicId::STOWNBYVALUE_IMM16_V8_V8,
75 IntrinsicId::STOWNBYVALUE_IMM8_V8_V8,
76 };
77 const InstIdFilterList INST_ID_LIST_STOWNBYVALUEWITHNAMESET = {
78 IntrinsicId::STOWNBYVALUEWITHNAMESET_IMM16_V8_V8,
79 IntrinsicId::STOWNBYVALUEWITHNAMESET_IMM8_V8_V8,
80 };
81 const InstIdFilterList INST_ID_LIST_DEFINEFUNC = {
82 IntrinsicId::DEFINEFUNC_IMM8_ID16_IMM8,
83 IntrinsicId::DEFINEFUNC_IMM16_ID16_IMM8,
84 };
85 const InstIdFilterList INST_ID_LIST_DEFINEMETHOD = {
86 IntrinsicId::DEFINEMETHOD_IMM16_ID16_IMM8,
87 IntrinsicId::DEFINEMETHOD_IMM8_ID16_IMM8,
88 };
89 const InstIdFilterList INST_ID_LIST_CREATEOBJECTWITHBUFFER = {
90 IntrinsicId::CREATEOBJECTWITHBUFFER_IMM16_ID16,
91 IntrinsicId::CREATEOBJECTWITHBUFFER_IMM8_ID16,
92 };
93 const InstIdFilterList INST_ID_LIST_DEFINECLASSWITHBUFFER = {
94 IntrinsicId::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8,
95 IntrinsicId::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8,
96 };
97 const InstIdFilterList INST_ID_LIST_LDOBJBYNAME = {
98 IntrinsicId::LDOBJBYNAME_IMM16_ID16,
99 IntrinsicId::LDOBJBYNAME_IMM8_ID16,
100 };
101 const InstIdFilterList INST_ID_LIST_CALLRUNTIME_TOPROPERTYKEY = {
102 IntrinsicId::CALLRUNTIME_TOPROPERTYKEY_PREF_NONE,
103 };
104 const InstIdFilterList INST_ID_LIST_TRYLDGLOBALBYNAME = {
105 IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16,
106 IntrinsicId ::TRYLDGLOBALBYNAME_IMM16_ID16,
107 };
108 const InstIdFilterList INST_ID_LIST_DEFINEPROPERTYBYNAME = {
109 IntrinsicId::DEFINEPROPERTYBYNAME_IMM8_ID16_V8,
110 };
111 const InstIdFilterList INST_ID_LIST_CALLRUNTIME_DEFINESENDABLECLASS = {
112 IntrinsicId::CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8,
113 };
114 const InstIdFilterList INST_ID_LIST_STMODULEVAR = {
115 IntrinsicId::STMODULEVAR_IMM8,
116 IntrinsicId::WIDE_STMODULEVAR_PREF_IMM16,
117 };
118
119 const InstIdFilterList INST_ID_LIST_STOBJBYNAME = {
120 IntrinsicId::STOBJBYNAME_IMM8_ID16_V8,
121 IntrinsicId::STOBJBYNAME_IMM16_ID16_V8,
122 };
123 const InstIdFilterList INST_ID_LIST_NEWOBJRANGE = {
124 IntrinsicId::NEWOBJRANGE_IMM8_IMM8_V8,
125 IntrinsicId::NEWOBJRANGE_IMM16_IMM8_V8,
126 };
127 const InstIdFilterList INST_ID_LIST_CALLTHIS1 = {
128 IntrinsicId::CALLTHIS1_IMM8_V8_V8,
129 };
130 const InstIdFilterList INST_ID_LIST_CALLTHIS2 = {
131 IntrinsicId::CALLTHIS2_IMM8_V8_V8_V8,
132 };
133 const InstIdFilterList INST_ID_LIST_CALLTHIS3 = {
134 IntrinsicId::CALLTHIS3_IMM8_V8_V8_V8_V8,
135 };
136 const InstIdFilterList INST_ID_LIST_CALLARG0 = {
137 IntrinsicId::CALLARG0_IMM8,
138 };
139 const InstIdFilterList INST_ID_LIST_CALLARG1 = {
140 IntrinsicId::CALLARG1_IMM8_V8,
141 };
142 const InstIdFilterList INST_ID_LIST_CALLARGS2 = {
143 IntrinsicId::CALLARGS2_IMM8_V8_V8,
144 };
145 const InstIdFilterList INST_ID_LIST_CALLARGS3 = {
146 IntrinsicId::CALLARGS3_IMM8_V8_V8_V8,
147 };
148 const InstIdFilterList INST_ID_LIST_CALLRANGE = {
149 IntrinsicId::CALLRANGE_IMM8_IMM8_V8,
150 };
151 const InstIdFilterList INST_ID_LIST_CALLRUNTIME_ISFALSE = {
152 IntrinsicId::CALLRUNTIME_ISFALSE_PREF_IMM8,
153 };
154
155 const std::map<panda::pandasm::Opcode, InstIdFilterList> CALL_INST_MAP = {
156 {panda::pandasm::Opcode::CALLTHIS1, INST_ID_LIST_CALLTHIS1},
157 {panda::pandasm::Opcode::CALLTHIS2, INST_ID_LIST_CALLTHIS2},
158 {panda::pandasm::Opcode::CALLTHIS3, INST_ID_LIST_CALLTHIS3},
159 {panda::pandasm::Opcode::CALLARG1, INST_ID_LIST_CALLARG1},
160 {panda::pandasm::Opcode::CALLARGS2, INST_ID_LIST_CALLARGS2},
161 {panda::pandasm::Opcode::CALLARGS3, INST_ID_LIST_CALLARGS3},
162 {panda::pandasm::Opcode::CALLRANGE, INST_ID_LIST_CALLRANGE},
163 };
164
165 const std::map<panda::pandasm::Opcode, InstParam> LDA_STA_INST_PARAM_MAP = {
166 {panda::pandasm::Opcode::DYNAMICIMPORT, {0, INST_ID_LIST_DYNAMICIMPORT}},
167 {panda::pandasm::Opcode::STLEXVAR, {0, INST_ID_LIST_STLEXVAR}},
168 {panda::pandasm::Opcode::LDOBJBYVALUE, {1, INST_ID_LIST_LDOBJBYVALUE}},
169 {panda::pandasm::Opcode::STOBJBYVALUE, {1, INST_ID_LIST_STOBJBYVALUE}},
170 {panda::pandasm::Opcode::DEFINEGETTERSETTERBYVALUE, {1, INST_ID_LIST_DEFINEGETTERSETTERBYVALUE}},
171 {panda::pandasm::Opcode::ISIN, {0, INST_ID_LIST_ISIN}},
172 {panda::pandasm::Opcode::LDSUPERBYVALUE, {1, INST_ID_LIST_LDSUPERBYVALUE}},
173 {panda::pandasm::Opcode::STSUPERBYVALUE, {1, INST_ID_LIST_STSUPERBYVALUE}},
174 {panda::pandasm::Opcode::STOWNBYVALUE, {1, INST_ID_LIST_STOWNBYVALUE}},
175 {panda::pandasm::Opcode::STOWNBYVALUEWITHNAMESET, {1, INST_ID_LIST_STOWNBYVALUEWITHNAMESET}}};
176
177 const std::vector<InstIdFilterList> DEFINE_INST_PASS_THROUGH_LIST = {
178 INST_ID_LIST_DEFINEGETTERSETTERBYVALUE,
179 INST_ID_LIST_DEFINEMETHOD,
180 };
181 const std::vector<InstIdFilterList> DEFINE_INST_ID_LIST = {
182 INST_ID_LIST_DEFINEFUNC,
183 INST_ID_LIST_DEFINECLASSWITHBUFFER,
184 INST_ID_LIST_CREATEOBJECTWITHBUFFER,
185 INST_ID_LIST_LDOBJBYNAME, // XXX.prototype: get define ins by ldobjbyname of XXX object
186 INST_ID_LIST_CALLRUNTIME_DEFINESENDABLECLASS,
187 };
188 const std::vector<InstIdFilterList> METHOD_NAME_INST_ID_LIST = {
189 INST_ID_LIST_DEFINEGETTERSETTERBYVALUE, INST_ID_LIST_STOWNBYNAME,
190 INST_ID_LIST_STOWNBYNAMEWITHNAMESET, INST_ID_LIST_STOWNBYVALUE,
191 INST_ID_LIST_STOWNBYVALUEWITHNAMESET,
192 };
193
194 /**
195 * Is the instruction type in the list
196 */
IsInstIdMatched(const panda::compiler::Inst * inst,const InstIdFilterList & list)197 bool IsInstIdMatched(const panda::compiler::Inst *inst, const InstIdFilterList &list)
198 {
199 if (!inst->IsIntrinsic()) {
200 return false;
201 }
202
203 IntrinsicId instId = inst->CastToIntrinsic()->GetIntrinsicId();
204 return std::any_of(list.begin(), list.end(), [&instId](IntrinsicId filter) -> bool { return instId == filter; });
205 }
206
IsInstIdMatched(const panda::compiler::Inst * inst,const std::vector<InstIdFilterList> & list)207 bool IsInstIdMatched(const panda::compiler::Inst *inst, const std::vector<InstIdFilterList> &list)
208 {
209 return std::any_of(list.begin(), list.end(),
210 [&](const InstIdFilterList &filter) -> bool { return IsInstIdMatched(inst, filter); });
211 }
212
213 /**
214 * Does the current instruction match the requirement, Consistent with InstructionInfo
215 * @param inst Graph instruction to be checked
216 * @param list The instruction type that should be matched
217 * @param targetIns The InstructionInfo that should be matched
218 */
IsInstMatched(const panda::compiler::Inst * inst,const InstructionInfo & targetIns,const InstIdFilterList & list)219 bool IsInstMatched(const panda::compiler::Inst *inst, const InstructionInfo &targetIns, const InstIdFilterList &list)
220 {
221 if (!IsInstIdMatched(inst, list)) {
222 return false;
223 }
224
225 const uint32_t pcVal = inst->GetPc();
226 auto &pcInstMap = targetIns.function_->pcInstMap_;
227 if (pcInstMap.find(pcVal) == pcInstMap.end() || pcInstMap.at(pcVal) != targetIns.index_) {
228 return false;
229 }
230
231 return true;
232 }
233
234 /**
235 * Traverse the Graph to find matching instructions, Converting InstructionInfo to Graph Instruction
236 * @param inIns Instructions to be found
237 * @param list instruction type
238 * @param outInst Corresponding instructions in the graph
239 */
VisitGraph(const InstructionInfo & inIns,const InstIdFilterList & list,const panda::compiler::Inst * & outInst)240 void VisitGraph(const InstructionInfo &inIns, const InstIdFilterList &list, const panda::compiler::Inst *&outInst)
241 {
242 Function *func = inIns.function_;
243 panda::compiler::Graph *graph;
244 func->GetGraph(graph);
245
246 for (const panda::compiler::BasicBlock *bb : graph->GetBlocksLinearOrder()) {
247 for (const panda::compiler::Inst *inst : bb->AllInsts()) {
248 if (!IsInstMatched(inst, inIns, list)) {
249 continue;
250 }
251 outInst = inst;
252 return;
253 }
254 }
255
256 PANDA_GUARD_ABORT_PRINT(TAG, ErrorCode::GENERIC_ERROR, "not find inst: " << inIns.index_ << " in " << func->idx_);
257 }
258
259 /**
260 * Fill the graph instruction into InstructionInfo, Convert Graph instruction to InstructionInfo
261 * @param inIns Used to obtain background information of InstructionInfo
262 * @param target graph instruction
263 * @param outIns InstructionInfo for filling
264 */
FillInstInfo(const InstructionInfo & inIns,const panda::compiler::Inst * target,InstructionInfo & outIns)265 void FillInstInfo(const InstructionInfo &inIns, const panda::compiler::Inst *target, InstructionInfo &outIns)
266 {
267 const uint32_t pcVal = target->GetPc();
268 Function *func = inIns.function_;
269 PANDA_GUARD_ASSERT_PRINT(func->pcInstMap_.find(pcVal) == func->pcInstMap_.end(), TAG, ErrorCode::GENERIC_ERROR,
270 "no valid target ins: " << func->idx_ << ", " << inIns.index_);
271 func->FillInstInfo(func->pcInstMap_.at(pcVal), outIns);
272 }
273
274 /**
275 * Print Graph instruction content
276 */
PrintInst(const panda::compiler::Inst * ins)277 std::string PrintInst(const panda::compiler::Inst *ins)
278 {
279 std::stringstream stream;
280 ins->Dump(&stream, false);
281 return stream.str();
282 }
283
284 /**
285 * Find the lda.str instruction corresponding to the input command
286 */
FindLdaStr(const panda::compiler::Inst * prevInst,const panda::compiler::Inst * & outIns)287 void FindLdaStr(const panda::compiler::Inst *prevInst, const panda::compiler::Inst *&outIns)
288 {
289 if (IsInstIdMatched(prevInst, INST_ID_LIST_CALLRUNTIME_TOPROPERTYKEY)) {
290 prevInst = prevInst->GetInput(0).GetInst();
291 }
292
293 if (prevInst->GetOpcode() != panda::compiler::Opcode::CastValueToAnyType) {
294 return;
295 }
296 const panda::compiler::Inst *targetInst = prevInst->GetInput(0).GetInst();
297 if (targetInst->GetOpcode() != panda::compiler::Opcode::LoadString) {
298 return;
299 }
300
301 outIns = targetInst;
302 }
303
FillLdaStrInst(const InstructionInfo & inIns,const panda::compiler::Inst * curInst,uint32_t targetIndex,InstructionInfo & out)304 void FillLdaStrInst(const InstructionInfo &inIns, const panda::compiler::Inst *curInst, uint32_t targetIndex,
305 InstructionInfo &out)
306 {
307 const panda::compiler::Inst *prevInst = curInst->GetInput(targetIndex).GetInst();
308 const panda::compiler::Inst *targetInst = nullptr;
309 FindLdaStr(prevInst, targetInst);
310 if (targetInst == nullptr) {
311 LOG(INFO, PANDAGUARD) << TAG << "FillLdaStrInst failed: " << inIns.function_->idx_ << ", " << inIns.index_
312 << ";" << PrintInst(prevInst);
313 return;
314 }
315
316 FillInstInfo(inIns, targetInst, out);
317 }
318
319 /**
320 * Find the object definition instruction corresponding to the input instruction
321 */
FindDefineInst(const panda::compiler::Inst * prevInst,const panda::compiler::Inst * & outIns)322 void FindDefineInst(const panda::compiler::Inst *prevInst, const panda::compiler::Inst *&outIns)
323 {
324 if (IsInstIdMatched(prevInst, {INST_ID_LIST_CREATEOBJECTWITHBUFFER, INST_ID_LIST_DEFINECLASSWITHBUFFER,
325 INST_ID_LIST_CALLRUNTIME_DEFINESENDABLECLASS})) {
326 outIns = prevInst;
327 return;
328 }
329
330 // Try to find class define in prototype instance
331 if (!IsInstIdMatched(prevInst, INST_ID_LIST_LDOBJBYNAME)) {
332 return;
333 }
334
335 const panda::compiler::Inst *targetIns = prevInst->GetInput(0).GetInst();
336 if (!IsInstIdMatched(targetIns, INST_ID_LIST_DEFINECLASSWITHBUFFER)) {
337 return;
338 }
339 outIns = targetIns;
340 }
341 } // namespace
342
GetLdaStr(const InstructionInfo & inIns,InstructionInfo & outIns,int index)343 void GraphAnalyzer::GetLdaStr(const InstructionInfo &inIns, InstructionInfo &outIns, int index /* = -1 */)
344 {
345 const auto it = LDA_STA_INST_PARAM_MAP.find(inIns.ins_->opcode);
346 PANDA_GUARD_ASSERT_PRINT(it == LDA_STA_INST_PARAM_MAP.end(), TAG, ErrorCode::GENERIC_ERROR,
347 "unsupported lda.str scene: " << inIns.ins_->ToString());
348
349 const compiler::Inst *inst;
350 VisitGraph(inIns, it->second.filterList, inst);
351
352 const unsigned targetIndex = index >= 0 ? index : it->second.index;
353 FillLdaStrInst(inIns, inst, targetIndex, outIns);
354 }
355
HandleDefineMethod(const InstructionInfo & inIns,InstructionInfo & defineIns,InstructionInfo & nameIns)356 void GraphAnalyzer::HandleDefineMethod(const InstructionInfo &inIns, InstructionInfo &defineIns,
357 InstructionInfo &nameIns)
358 {
359 const compiler::Inst *inst;
360 VisitGraph(inIns, INST_ID_LIST_DEFINEMETHOD, inst);
361
362 for (const auto &userIns : inst->GetUsers()) {
363 if (IsInstIdMatched(userIns.GetInst(), METHOD_NAME_INST_ID_LIST)) {
364 FillInstInfo(inIns, userIns.GetInst(), nameIns);
365 break;
366 }
367 }
368
369 do {
370 inst = inst->GetInput(0).GetInst();
371 } while (IsInstIdMatched(inst, DEFINE_INST_PASS_THROUGH_LIST));
372 PANDA_GUARD_ASSERT_PRINT(!IsInstIdMatched(inst, DEFINE_INST_ID_LIST), TAG, ErrorCode::GENERIC_ERROR,
373 "unexpect defineMethod scene: " << inIns.function_->idx_ << ", " << inIns.index_ << ";"
374 << PrintInst(inst));
375
376 const compiler::Inst *targetInst = nullptr;
377 FindDefineInst(inst, targetInst);
378 PANDA_GUARD_ASSERT_PRINT(targetInst == nullptr, TAG, ErrorCode::GENERIC_ERROR,
379 "HandleDefineMethod failed: " << inIns.function_->idx_ << ", " << inIns.index_ << ";"
380 << PrintInst(inst));
381
382 FillInstInfo(inIns, targetInst, defineIns);
383 }
384
HandleDefineProperty(const InstructionInfo & inIns,InstructionInfo & defineIns)385 void GraphAnalyzer::HandleDefineProperty(const InstructionInfo &inIns, InstructionInfo &defineIns)
386 {
387 const compiler::Inst *inst;
388 VisitGraph(inIns, INST_ID_LIST_DEFINEPROPERTYBYNAME, inst);
389
390 const compiler::Inst *target = nullptr;
391 FindDefineInst(inst->GetInput(0).GetInst(), target);
392 if (target == nullptr) {
393 return;
394 }
395
396 FillInstInfo(inIns, target, defineIns);
397 }
398
IsComponentClass(const InstructionInfo & inIns)399 bool GraphAnalyzer::IsComponentClass(const InstructionInfo &inIns)
400 {
401 if (inIns.ins_->opcode != pandasm::Opcode::DEFINECLASSWITHBUFFER) {
402 return false;
403 }
404
405 const compiler::Inst *inst;
406 VisitGraph(inIns, INST_ID_LIST_DEFINECLASSWITHBUFFER, inst);
407
408 const compiler::Inst *tryldglobalbyname = inst->GetInput(0).GetInst();
409 if (!IsInstIdMatched(tryldglobalbyname, INST_ID_LIST_TRYLDGLOBALBYNAME)) {
410 return false;
411 }
412
413 InstructionInfo out;
414 FillInstInfo(inIns, tryldglobalbyname, out);
415
416 const std::string baseClassName = out.ins_->GetId(0);
417 if (baseClassName != UI_COMPONENT_BASE_CLASS_VIEW_PU && baseClassName != UI_COMPONENT_BASE_CLASS_VIEW_V2) {
418 return false;
419 }
420
421 LOG(INFO, PANDAGUARD) << TAG << "found UI component:" << inIns.ins_->GetId(0);
422
423 return true;
424 }
425
GetStModuleVarDefineIns(const InstructionInfo & inIns,InstructionInfo & defineIns)426 void GraphAnalyzer::GetStModuleVarDefineIns(const InstructionInfo &inIns, InstructionInfo &defineIns)
427 {
428 if (inIns.ins_->opcode != pandasm::Opcode::STMODULEVAR && inIns.ins_->opcode != pandasm::Opcode::WIDE_STMODULEVAR) {
429 return;
430 }
431
432 const compiler::Inst *inst;
433 VisitGraph(inIns, INST_ID_LIST_STMODULEVAR, inst);
434
435 const compiler::Inst *target = inst->GetInput(0).GetInst();
436 PANDA_GUARD_ASSERT_PRINT(target == nullptr, TAG, ErrorCode::GENERIC_ERROR, "find define inst failed");
437 if (!IsInstIdMatched(target, {INST_ID_LIST_CREATEOBJECTWITHBUFFER, INST_ID_LIST_DEFINECLASSWITHBUFFER,
438 INST_ID_LIST_CALLRUNTIME_DEFINESENDABLECLASS})) {
439 return;
440 }
441
442 FillInstInfo(inIns, target, defineIns);
443 }
444
GetStObjByNameDefineIns(const InstructionInfo & inIns,InstructionInfo & defineIns)445 void GraphAnalyzer::GetStObjByNameDefineIns(const InstructionInfo &inIns, InstructionInfo &defineIns)
446 {
447 if (inIns.notEqualToOpcode(pandasm::Opcode::STOBJBYNAME)) {
448 return;
449 }
450
451 const compiler::Inst *inst;
452 VisitGraph(inIns, INST_ID_LIST_STOBJBYNAME, inst);
453 const compiler::Inst *target = inst->GetInput(1).GetInst();
454 if (!IsInstIdMatched(target, DEFINE_INST_ID_LIST)) {
455 return;
456 }
457
458 FillInstInfo(inIns, target, defineIns);
459 }
460
GetStObjByNameInput(const InstructionInfo & inIns,InstructionInfo & out)461 void GraphAnalyzer::GetStObjByNameInput(const InstructionInfo &inIns, InstructionInfo &out)
462 {
463 const compiler::Inst *inst;
464 VisitGraph(inIns, INST_ID_LIST_STOBJBYNAME, inst);
465
466 const compiler::Inst *target = inst->GetInput(INDEX_1).GetInst();
467 if (!IsInstIdMatched(target, {INST_ID_LIST_NEWOBJRANGE, INST_ID_LIST_CALLTHIS2, INST_ID_LIST_CALLTHIS3})) {
468 return;
469 }
470 FillInstInfo(inIns, target, out);
471 }
472
GetNewObjRangeInfo(const InstructionInfo & inIns,std::string & name,InstructionInfo & out)473 void GraphAnalyzer::GetNewObjRangeInfo(const InstructionInfo &inIns, std::string &name, InstructionInfo &out)
474 {
475 const compiler::Inst *inst;
476 VisitGraph(inIns, INST_ID_LIST_NEWOBJRANGE, inst);
477
478 const compiler::Inst *tryInst = inst->GetInput(INDEX_0).GetInst();
479 if (!IsInstIdMatched(tryInst, INST_ID_LIST_TRYLDGLOBALBYNAME)) {
480 return;
481 }
482 InstructionInfo tryInstInfo;
483 FillInstInfo(inIns, tryInst, tryInstInfo);
484 name = tryInstInfo.ins_->GetId(INDEX_0);
485 if (name.empty()) {
486 return;
487 }
488
489 FillLdaStrInst(inIns, inst, INDEX_3, out);
490 }
491
GetCallName(const InstructionInfo & inIns)492 std::string GraphAnalyzer::GetCallName(const InstructionInfo &inIns)
493 {
494 const auto it = CALL_INST_MAP.find(inIns.ins_->opcode);
495 PANDA_GUARD_ASSERT_PRINT(it == CALL_INST_MAP.end(), TAG, ErrorCode::GENERIC_ERROR,
496 "unsupported call name scene: " << inIns.ins_->ToString());
497
498 const compiler::Inst *callInst;
499 VisitGraph(inIns, it->second, callInst);
500
501 uint32_t inputCnt = callInst->GetInputsCount();
502 PANDA_GUARD_ASSERT_PRINT(inputCnt < PARAM_COUNT_THRESHOLD, TAG, ErrorCode::GENERIC_ERROR,
503 "unexpected call param count scene: " << inIns.ins_->ToString());
504
505 const compiler::Inst *callNameInst = callInst->GetInput(inputCnt - 2).GetInst();
506 if (IsInstIdMatched(callNameInst, {INST_ID_LIST_CALLARG0, INST_ID_LIST_CALLARG1})) {
507 inputCnt = callNameInst->GetInputsCount();
508 PANDA_GUARD_ASSERT_PRINT(inputCnt < PARAM_COUNT_THRESHOLD, TAG, ErrorCode::GENERIC_ERROR,
509 "unexpected call args param count scene: " << inIns.ins_->ToString());
510 callNameInst = callNameInst->GetInput(inputCnt - PARAM_COUNT_THRESHOLD).GetInst();
511 }
512 if (!IsInstIdMatched(callNameInst, {INST_ID_LIST_LDOBJBYNAME, INST_ID_LIST_TRYLDGLOBALBYNAME})) {
513 return "";
514 }
515
516 InstructionInfo nameIns;
517 FillInstInfo(inIns, callNameInst, nameIns);
518 return nameIns.ins_->GetId(INDEX_0);
519 }
520
GetCallLdaStrParam(const InstructionInfo & inIns,uint32_t paramIndex,InstructionInfo & out)521 void GraphAnalyzer::GetCallLdaStrParam(const InstructionInfo &inIns, uint32_t paramIndex, InstructionInfo &out)
522 {
523 const auto it = CALL_INST_MAP.find(inIns.ins_->opcode);
524 PANDA_GUARD_ASSERT_PRINT(it == CALL_INST_MAP.end(), TAG, ErrorCode::GENERIC_ERROR,
525 "unsupported get call lda str param scene: " << inIns.ins_->ToString());
526
527 const compiler::Inst *callInst;
528 VisitGraph(inIns, it->second, callInst);
529
530 FillLdaStrInst(inIns, callInst, paramIndex, out);
531 }
GetCallTryLdGlobalByNameParam(const InstructionInfo & inIns,uint32_t paramIndex,InstructionInfo & out)532 void GraphAnalyzer::GetCallTryLdGlobalByNameParam(const InstructionInfo &inIns, uint32_t paramIndex,
533 InstructionInfo &out)
534 {
535 const auto it = CALL_INST_MAP.find(inIns.ins_->opcode);
536 PANDA_GUARD_ASSERT_PRINT(it == CALL_INST_MAP.end(), TAG, ErrorCode::GENERIC_ERROR,
537 "unsupported get call tryldblobalbyname param scene: " << inIns.ins_->ToString());
538
539 const compiler::Inst *callInst;
540 VisitGraph(inIns, it->second, callInst);
541
542 const compiler::Inst *target = callInst->GetInput(paramIndex).GetInst();
543 if (!IsInstIdMatched(target, INST_ID_LIST_TRYLDGLOBALBYNAME)) {
544 return;
545 }
546 FillInstInfo(inIns, target, out);
547 }
548
GetCallLdObjByNameParam(const InstructionInfo & inIns,uint32_t paramIndex,InstructionInfo & out)549 void GraphAnalyzer::GetCallLdObjByNameParam(const InstructionInfo &inIns, uint32_t paramIndex, InstructionInfo &out)
550 {
551 const auto it = CALL_INST_MAP.find(inIns.ins_->opcode);
552 PANDA_GUARD_ASSERT_PRINT(it == CALL_INST_MAP.end(), TAG, ErrorCode::GENERIC_ERROR,
553 "unsupported get call ldobjbyname param scene: " << inIns.ins_->ToString());
554
555 const compiler::Inst *callInst;
556 VisitGraph(inIns, it->second, callInst);
557
558 const compiler::Inst *target = callInst->GetInput(paramIndex).GetInst();
559 if (!IsInstIdMatched(target, INST_ID_LIST_LDOBJBYNAME)) {
560 return;
561 }
562 FillInstInfo(inIns, target, out);
563 }
564
GetIsInInfo(const InstructionInfo & inIns,std::vector<InstructionInfo> & out)565 void GraphAnalyzer::GetIsInInfo(const InstructionInfo &inIns, std::vector<InstructionInfo> &out)
566 {
567 const compiler::Inst *isinInst;
568 VisitGraph(inIns, INST_ID_LIST_ISIN, isinInst);
569
570 InstructionInfo ldStrInstInfo;
571 FillLdaStrInst(inIns, isinInst, INDEX_0, ldStrInstInfo);
572 if (!ldStrInstInfo.IsValid()) {
573 return;
574 }
575
576 const compiler::Inst *isFalseInst = isinInst->GetUsers().Front().GetInst();
577 if (!IsInstIdMatched(isFalseInst, INST_ID_LIST_CALLRUNTIME_ISFALSE)) {
578 return;
579 }
580
581 const compiler::Inst *ldInst = nullptr;
582 auto falseBlock = isinInst->GetBasicBlock()->GetFalseSuccessor();
583 for (const compiler::Inst *inst : falseBlock->AllInsts()) {
584 if (!IsInstIdMatched(inst, INST_ID_LIST_LDOBJBYNAME)) {
585 ldInst = inst;
586 break;
587 }
588 }
589 if (!ldInst) {
590 return;
591 }
592 InstructionInfo ldInstInfo;
593 FillInstInfo(inIns, ldInst, ldInstInfo);
594 if (!ldInstInfo.IsValid()) {
595 return;
596 }
597
598 const compiler::Inst *phiInst = ldInst->GetUsers().Front().GetInst();
599 if (!phiInst->IsPhi()) {
600 return;
601 }
602
603 const compiler::Inst *stInst = phiInst->GetUsers().Front().GetInst();
604 if (!IsInstIdMatched(stInst, INST_ID_LIST_STOBJBYNAME)) {
605 return;
606 }
607 InstructionInfo stInstInfo;
608 FillInstInfo(inIns, stInst, stInstInfo);
609 if (!stInstInfo.IsValid()) {
610 return;
611 }
612
613 if ((ldStrInstInfo.ins_->GetId(INDEX_0) == ldInstInfo.ins_->GetId(INDEX_0)) &&
614 (ldInstInfo.ins_->GetId(INDEX_0) == stInstInfo.ins_->GetId(INDEX_0))) {
615 out.emplace_back(ldStrInstInfo);
616 out.emplace_back(ldInstInfo);
617 out.emplace_back(stInstInfo);
618 }
619 }
GetCallCreateObjectWithBufferParam(const InstructionInfo & inIns,uint32_t paramIndex,InstructionInfo & out)620 void GraphAnalyzer::GetCallCreateObjectWithBufferParam(const InstructionInfo &inIns, uint32_t paramIndex,
621 InstructionInfo &out)
622 {
623 const auto it = CALL_INST_MAP.find(inIns.ins_->opcode);
624 PANDA_GUARD_ASSERT_PRINT(it == CALL_INST_MAP.end(), TAG, ErrorCode::GENERIC_ERROR,
625 "unsupported get call createobjectwithbuffer param scene: " << inIns.ins_->ToString());
626
627 const compiler::Inst *callInst;
628 VisitGraph(inIns, it->second, callInst);
629
630 const compiler::Inst *target = callInst->GetInput(paramIndex).GetInst();
631 if (!IsInstIdMatched(target, INST_ID_LIST_CREATEOBJECTWITHBUFFER)) {
632 return;
633 }
634 FillInstInfo(inIns, target, out);
635 }
636
GetDefinePropertyByNameFunction(const InstructionInfo & inIns,InstructionInfo & out)637 void GraphAnalyzer::GetDefinePropertyByNameFunction(const InstructionInfo &inIns, InstructionInfo &out)
638 {
639 if (inIns.notEqualToOpcode(pandasm::Opcode::DEFINEPROPERTYBYNAME)) {
640 return;
641 }
642
643 const compiler::Inst *inst;
644 VisitGraph(inIns, INST_ID_LIST_DEFINEPROPERTYBYNAME, inst);
645
646 const compiler::Inst *target = inst->GetInput(INDEX_1).GetInst();
647 if (!IsInstIdMatched(target, INST_ID_LIST_DEFINEFUNC)) {
648 return;
649 }
650 FillInstInfo(inIns, target, out);
651 }
652