• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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