• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2019-2023 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "pipeline/jit/pi/graph_compiler/parser/byte_code_parser.h"
18 #include <memory>
19 #include <string>
20 #include <utility>
21 #include "pipeline/jit/pi/graph_compiler/pi_ir/debug_info.h"
22 #include "utils/log_adapter.h"
23 
24 namespace mindspore {
25 namespace pijit {
26 namespace {
27 template <typename T>
var_init(PyObject * obj)28 T var_init(PyObject *obj) {
29   if (obj == nullptr) {
30     return T();
31   }
32   if (py::isinstance<py::module>(obj)) {
33     obj = PyObject_GetAttrString(obj, "__dict__");
34   }
35   return py::cast<T>(obj);
36 }
37 
GetFunctionObject(const py::object & func)38 const PyFunctionObject &GetFunctionObject(const py::object &func) {
39   if (PyMethod_Check(func.ptr())) {
40     return *reinterpret_cast<PyFunctionObject *>(PyMethod_GET_FUNCTION(func.ptr()));
41   }
42   return *reinterpret_cast<PyFunctionObject *>(func.ptr());
43 }
44 }  // namespace
45 
ByteCodeParser(const py::object & func)46 ByteCodeParser::ByteCodeParser(const py::object &func) : ByteCodeParser(GetFunctionObject(func)) {}
47 
ByteCodeParser(const PyFunctionObject & func)48 ByteCodeParser::ByteCodeParser(const PyFunctionObject &func)
49     : func_(std::make_shared<ir::FunctionNode>(
50         py::cast<std::string>((reinterpret_cast<PyCodeObject *>(func.func_code))->co_name))),
51       code_(*reinterpret_cast<PyCodeObject *>(func.func_code)),
52       globals_(var_init<py::dict>(func.func_globals)),
53       builtins_(var_init<py::dict>(PyDict_GetItemString(func.func_globals, "__builtins__"))),
54       clousre_(var_init<py::tuple>(func.func_closure)),
55       kwdefaults_(var_init<py::dict>(func.func_kwdefaults)),
56       defaults_(var_init<py::tuple>(func.func_defaults)) {
57   func_->AddFileName(py::cast<std::string>((reinterpret_cast<PyCodeObject *>(func.func_code))->co_filename));
58   BuildMethodMap();
59   Register(&func_->GetNodes());
60 }
61 
BuildMethodMap()62 void ByteCodeParser::BuildMethodMap() {
63   BuildStackMethodMap();
64   BuildLoadStoreMethodMap();
65   BuildMathMethodMap();
66   BuildBitwiseMethodMap();
67   BuildContainerMethodMap();
68   BuildContrlFlowMethodMap();
69   BuildOtherMethodMap();
70 }
71 
BuildStackMethodMap()72 void ByteCodeParser::BuildStackMethodMap() {
73   // op : 1, opname : POP_TOP
74   instr_method_map_[POP_TOP] = &ByteCodeParser::ParsePopTop;
75   // op : 2, opname : ROT_TWO
76   instr_method_map_[ROT_TWO] = &ByteCodeParser::ParseRotTwo;
77   // op : 3, opname : ROT_THREE
78   instr_method_map_[ROT_THREE] = &ByteCodeParser::ParseRotThree;
79   // op : 4, opname : DUP_TOP
80   instr_method_map_[DUP_TOP] = &ByteCodeParser::ParseDupTop;
81   // op : 5, opname : DUP_TOP_TWO
82   instr_method_map_[DUP_TOP_TWO] = &ByteCodeParser::ParseDupTwo;
83   // op : 6, opname : ROT_FOUR
84   instr_method_map_[ROT_FOUR] = &ByteCodeParser::ParseRotFour;
85   // op : 9, opname : NOP
86   instr_method_map_[NOP] = &ByteCodeParser::ParseNop;
87   // op : 61, opname : DELETE_SUBSCR
88   instr_method_map_[DELETE_SUBSCR] = &ByteCodeParser::ParseDeleteSubscr;
89   // op : 91, opname : DELETE_NAME
90   instr_method_map_[DELETE_NAME] = &ByteCodeParser::ParseDeleteName;
91   // op : 96, opname : DELETE_ATTR
92   instr_method_map_[DELETE_ATTR] = &ByteCodeParser::ParseDeleteAttr;
93   // op : 98, opname : DELETE_GLOBAL
94   instr_method_map_[DELETE_GLOBAL] = &ByteCodeParser::ParseDeleteName;
95   // op : 126, opname : DELETE_FAST
96   instr_method_map_[DELETE_FAST] = &ByteCodeParser::ParseDeleteName;
97   // op : 138, opname : DELETE_DEREF
98   instr_method_map_[DELETE_DEREF] = &ByteCodeParser::ParseDeleteName;
99 }
100 
BuildLoadStoreMethodMap()101 void ByteCodeParser::BuildLoadStoreMethodMap() {
102   // op : 60, opname : STORE_SUBSCR
103   instr_method_map_[STORE_SUBSCR] = &ByteCodeParser::ParseStoreSubscr;
104   // op : 71, opname : LOAD_BUILD_CLASS
105   instr_method_map_[LOAD_BUILD_CLASS] = &ByteCodeParser::ParseUnaryOpertion;
106   // op : 74, opname : LOAD_ASSERTION_ERROR
107   instr_method_map_[LOAD_ASSERTION_ERROR] = &ByteCodeParser::ParseLoadAssertError;
108   // op : 84, opname : IMPORT_STAR
109   instr_method_map_[IMPORT_STAR] = &ByteCodeParser::ParseImport;
110   // op : 90, opname : STORE_NAME
111   instr_method_map_[STORE_NAME] = &ByteCodeParser::ParseStoreName;
112   // op : 95, opname : STORE_ATTR
113   instr_method_map_[STORE_ATTR] = &ByteCodeParser::ParseStoreAttr;
114   // op : 97, opname : STORE_GLOBAL
115   instr_method_map_[STORE_GLOBAL] = &ByteCodeParser::ParseStoreName;
116   // op : 100, opname : LOAD_CONST
117   instr_method_map_[LOAD_CONST] = &ByteCodeParser::ParseLoadConst;
118   // op : 101, opname : LOAD_NAME
119   instr_method_map_[LOAD_NAME] = &ByteCodeParser::ParseLoadName;
120   // op : 106, opname : LOAD_ATTR
121   instr_method_map_[LOAD_ATTR] = &ByteCodeParser::ParseLoadAttr;
122   // op : 108, opname : IMPORT_NAME
123   instr_method_map_[IMPORT_NAME] = &ByteCodeParser::ParseImport;
124   // op : 109, opname : IMPORT_FROM
125   instr_method_map_[IMPORT_FROM] = &ByteCodeParser::ParseImport;
126   // op : 116, opname : LOAD_GLOBAL
127   instr_method_map_[LOAD_GLOBAL] = &ByteCodeParser::ParseLoadGlobal;
128   // op : 124, opname : LOAD_FAST
129   instr_method_map_[LOAD_FAST] = &ByteCodeParser::ParseLoadFast;
130   // op : 125, opname : STORE_FAST
131   instr_method_map_[STORE_FAST] = &ByteCodeParser::ParseStoreName;
132   // op : 135, opname : LOAD_CLOSURE
133   instr_method_map_[LOAD_CLOSURE] = &ByteCodeParser::ParseLoadClosure;
134   // op : 136, opname : LOAD_DEREF
135   instr_method_map_[LOAD_DEREF] = &ByteCodeParser::ParseLoadClosure;
136   // op : 137, opname : STORE_DEREF
137   instr_method_map_[STORE_DEREF] = &ByteCodeParser::ParseStoreName;
138   // op : 148, opname : LOAD_CLASSDEREF
139   instr_method_map_[LOAD_CLASSDEREF] = &ByteCodeParser::ParseLoadClosure;
140   // op : 160, opname : LOAD_METHOD
141   instr_method_map_[LOAD_METHOD] = &ByteCodeParser::ParseLoadMethod;
142 }
143 
BuildMathMethodMap()144 void ByteCodeParser::BuildMathMethodMap() {
145   // op : 10, opname : UNARY_POSITIVE
146   instr_method_map_[UNARY_POSITIVE] = &ByteCodeParser::ParseNop;
147   // op : 11, opname : UNARY_NEGATIVE
148   instr_method_map_[UNARY_NEGATIVE] = &ByteCodeParser::ParseUnaryNegative;
149   // op : 16, opname : BINARY_MATRIX_MULTIPLY
150   instr_method_map_[BINARY_MATRIX_MULTIPLY] = &ByteCodeParser::ParseMul;
151   // op : 17, opname : INPLACE_MATRIX_MULTIPLY
152   instr_method_map_[INPLACE_MATRIX_MULTIPLY] = &ByteCodeParser::ParseMul;
153   // op : 19, opname : BINARY_POWER
154   instr_method_map_[BINARY_POWER] = &ByteCodeParser::ParseBinaryOpertion;
155   // op : 20, opname : BINARY_MULTIPLY
156   instr_method_map_[BINARY_MULTIPLY] = &ByteCodeParser::ParseMul;
157   // op : 22, opname : BINARY_MODULO
158   instr_method_map_[BINARY_MODULO] = &ByteCodeParser::ParseBinaryOpertion;
159   // op : 23, opname : BINARY_ADD
160   instr_method_map_[BINARY_ADD] = &ByteCodeParser::ParseAdd;
161   // op : 24, opname : BINARY_SUBTRACT
162   instr_method_map_[BINARY_SUBTRACT] = &ByteCodeParser::ParseSub;
163   // op : 26, opname : BINARY_FLOOR_DIVIDE
164   instr_method_map_[BINARY_FLOOR_DIVIDE] = &ByteCodeParser::ParseDiv;
165   // op : 27, opname : BINARY_TRUE_DIVIDE
166   instr_method_map_[BINARY_TRUE_DIVIDE] = &ByteCodeParser::ParseDiv;
167   // op : 28, opname : INPLACE_FLOOR_DIVIDE
168   instr_method_map_[INPLACE_FLOOR_DIVIDE] = &ByteCodeParser::ParseDiv;
169   // op : 29, opname : INPLACE_TRUE_DIVIDE
170   instr_method_map_[INPLACE_TRUE_DIVIDE] = &ByteCodeParser::ParseDiv;
171   // op : 55, opname : INPLACE_ADD
172   instr_method_map_[INPLACE_ADD] = &ByteCodeParser::ParseAdd;
173   // op : 56, opname : INPLACE_SUBTRACT
174   instr_method_map_[INPLACE_SUBTRACT] = &ByteCodeParser::ParseSub;
175   // op : 57, opname : INPLACE_MULTIPLY
176   instr_method_map_[INPLACE_MULTIPLY] = &ByteCodeParser::ParseMul;
177   // op : 59, opname : INPLACE_MODULO
178   instr_method_map_[INPLACE_MODULO] = &ByteCodeParser::ParseBinaryOpertion;
179   // op : 67, opname : INPLACE_POWER
180   instr_method_map_[INPLACE_POWER] = &ByteCodeParser::ParseBinaryOpertion;
181 }
182 
BuildBitwiseMethodMap()183 void ByteCodeParser::BuildBitwiseMethodMap() {
184   // op : 12, opname : UNARY_NOT
185   instr_method_map_[UNARY_NOT] = &ByteCodeParser::ParseUnaryNot;
186   // op : 15, opname : UNARY_INVERT
187   instr_method_map_[UNARY_INVERT] = &ByteCodeParser::ParseUnaryInvert;
188   // op : 62, opname : BINARY_LSHIFT
189   instr_method_map_[BINARY_LSHIFT] = &ByteCodeParser::ParseBitwise;
190   // op : 63, opname : BINARY_RSHIFT
191   instr_method_map_[BINARY_RSHIFT] = &ByteCodeParser::ParseBitwise;
192   // op : 64, opname : BINARY_AND
193   instr_method_map_[BINARY_AND] = &ByteCodeParser::ParseBitwise;
194   // op : 65, opname : BINARY_XOR
195   instr_method_map_[BINARY_XOR] = &ByteCodeParser::ParseBitwise;
196   // op : 66, opname : BINARY_OR
197   instr_method_map_[BINARY_OR] = &ByteCodeParser::ParseBitwise;
198   // op : 75, opname : INPLACE_LSHIFT
199   instr_method_map_[INPLACE_LSHIFT] = &ByteCodeParser::ParseBitwise;
200   // op : 76, opname : INPLACE_RSHIFT
201   instr_method_map_[INPLACE_RSHIFT] = &ByteCodeParser::ParseBitwise;
202   // op : 77, opname : INPLACE_AND
203   instr_method_map_[INPLACE_AND] = &ByteCodeParser::ParseBitwise;
204   // op : 78, opname : INPLACE_XOR
205   instr_method_map_[INPLACE_XOR] = &ByteCodeParser::ParseBitwise;
206   // op : 79, opname : INPLACE_OR
207   instr_method_map_[INPLACE_OR] = &ByteCodeParser::ParseBitwise;
208 }
209 
BuildContainerMethodMap()210 void ByteCodeParser::BuildContainerMethodMap() {
211   // op : 82, opname : LIST_TO_TUPLE
212   instr_method_map_[LIST_TO_TUPLE] = &ByteCodeParser::ParseListToTuple;
213   // op : 102, opname : BUILD_TUPLE
214   instr_method_map_[BUILD_TUPLE] = &ByteCodeParser::ParseBuild;
215   // op : 103, opname : BUILD_LIST
216   instr_method_map_[BUILD_LIST] = &ByteCodeParser::ParseBuild;
217   // op : 104, opname : BUILD_SET
218   instr_method_map_[BUILD_SET] = &ByteCodeParser::ParseBuild;
219   // op : 105, opname : BUILD_MAP
220   instr_method_map_[BUILD_MAP] = &ByteCodeParser::ParseBuild;
221   // op : 133, opname : BUILD_SLICE
222   instr_method_map_[BUILD_SLICE] = &ByteCodeParser::ParseBuild;
223   // op : 145, opname : LIST_APPEND
224   instr_method_map_[LIST_APPEND] = &ByteCodeParser::ParseContainerUpdate;
225   // op : 146, opname : SET_ADD
226   instr_method_map_[SET_ADD] = &ByteCodeParser::ParseContainerUpdate;
227   // op : 147, opname : MAP_ADD
228   instr_method_map_[MAP_ADD] = &ByteCodeParser::ParseContainerUpdate;
229   // op : 156, opname : BUILD_CONST_KEY_MAP
230   instr_method_map_[BUILD_CONST_KEY_MAP] = &ByteCodeParser::ParseBuild;
231   // op : 157, opname : BUILD_STRING
232   instr_method_map_[BUILD_STRING] = &ByteCodeParser::ParseBuild;
233   // op : 162, opname : LIST_EXTEND
234   instr_method_map_[LIST_EXTEND] = &ByteCodeParser::ParseContainerUpdate;
235   // op : 163, opname : SET_UPDATE
236   instr_method_map_[SET_UPDATE] = &ByteCodeParser::ParseContainerUpdate;
237   // op : 164, opname : DICT_MERGE
238   instr_method_map_[DICT_MERGE] = &ByteCodeParser::ParseContainerUpdate;
239   // op : 165, opname : DICT_UPDATE
240   instr_method_map_[DICT_UPDATE] = &ByteCodeParser::ParseContainerUpdate;
241 }
242 
BuildContrlFlowMethodMap()243 void ByteCodeParser::BuildContrlFlowMethodMap() {
244   // op : 48, opname : RERAISE
245   instr_method_map_[RERAISE] = &ByteCodeParser::ParseUnaryOpertion;
246   // op : 49, opname : WITH_EXCEPT_START
247   instr_method_map_[WITH_EXCEPT_START] = &ByteCodeParser::ParseWithExceptStart;
248   // op : 87, opname : POP_BLOCK
249   instr_method_map_[POP_BLOCK] = &ByteCodeParser::ParseNoArgOperation;
250   // op : 89, opname : POP_EXCEPT
251   instr_method_map_[POP_EXCEPT] = &ByteCodeParser::ParseNoArgOperation;
252   // op : 93, opname : FOR_ITER
253   instr_method_map_[FOR_ITER] = &ByteCodeParser::ParseJump;
254   // op : 110, opname : JUMP_FORWARD
255   instr_method_map_[JUMP_FORWARD] = &ByteCodeParser::ParseJump;
256   // op : 111, opname : JUMP_IF_FALSE_OR_POP
257   instr_method_map_[JUMP_IF_FALSE_OR_POP] = &ByteCodeParser::ParseJump;
258   // op : 112, opname : JUMP_IF_TRUE_OR_POP
259   instr_method_map_[JUMP_IF_TRUE_OR_POP] = &ByteCodeParser::ParseJump;
260   // op : 113, opname : JUMP_ABSOLUTE
261   instr_method_map_[JUMP_ABSOLUTE] = &ByteCodeParser::ParseJump;
262   // op : 114, opname : POP_JUMP_IF_FALSE
263   instr_method_map_[POP_JUMP_IF_FALSE] = &ByteCodeParser::ParseJump;
264   // op : 115, opname : POP_JUMP_IF_TRUE
265   instr_method_map_[POP_JUMP_IF_TRUE] = &ByteCodeParser::ParseJump;
266   // op : 121, opname : JUMP_IF_NOT_EXC_MATCH
267   instr_method_map_[JUMP_IF_NOT_EXC_MATCH] = &ByteCodeParser::ParseJump;
268   // op : 122, opname : SETUP_FINALLY
269   instr_method_map_[SETUP_FINALLY] = &ByteCodeParser::ParseNoArgOperation;
270   // op : 130, opname : RAISE_VARARGS
271   instr_method_map_[RAISE_VARARGS] = &ByteCodeParser::ParseRaiseVarargs;
272 }
273 
BuildOtherMethodMap()274 void ByteCodeParser::BuildOtherMethodMap() {
275   // op : 25, opname : BINARY_SUBSCR
276   instr_method_map_[BINARY_SUBSCR] = &ByteCodeParser::ParseBinarySubscr;
277   // op : 50, opname : GET_AITER
278   instr_method_map_[GET_AITER] = &ByteCodeParser::ParseGet;
279   // op : 51, opname : GET_ANEXT
280   instr_method_map_[GET_ANEXT] = &ByteCodeParser::ParseGet;
281   // op : 68, opname : GET_ITER
282   instr_method_map_[GET_ITER] = &ByteCodeParser::ParseGet;
283   // op : 69, opname : GET_YIELD_FROM_ITER
284   instr_method_map_[GET_YIELD_FROM_ITER] = &ByteCodeParser::ParseGet;
285   // op : 70, opname : PRINT_EXPR
286   instr_method_map_[PRINT_EXPR] = &ByteCodeParser::ParseUnaryOpertion;
287   // op : 72, opname : YIELD_FROM
288   instr_method_map_[YIELD_FROM] = &ByteCodeParser::ParseUnaryOpertion;
289   // op : 73, opname : GET_AWAITABLE
290   instr_method_map_[GET_AWAITABLE] = &ByteCodeParser::ParseGet;
291   // op : 83, opname : RETURN_VALUE
292   instr_method_map_[RETURN_VALUE] = &ByteCodeParser::ParseReturnValue;
293   // op : 85, opname : SETUP_ANNOTATIONS
294   instr_method_map_[SETUP_ANNOTATIONS] = &ByteCodeParser::ParseNoArgOperation;
295   // op : 86, opname : YIELD_VALUE
296   instr_method_map_[YIELD_VALUE] = &ByteCodeParser::ParseUnaryOpertion;
297   // op : 92, opname : UNPACK_SEQUENCE
298   instr_method_map_[UNPACK_SEQUENCE] = &ByteCodeParser::ParseUnpack;
299   // op : 94, opname : UNPACK_EX
300   instr_method_map_[UNPACK_EX] = &ByteCodeParser::ParseUnpack;
301   // op : 107, opname : COMPARE_OP
302   instr_method_map_[COMPARE_OP] = &ByteCodeParser::ParseCompareOp;
303   // op : 117, opname : IS_OP
304   instr_method_map_[IS_OP] = &ByteCodeParser::ParseIsOp;
305   // op : 118, opname : CONTAINS_OP
306   instr_method_map_[CONTAINS_OP] = &ByteCodeParser::ParseContainsOp;
307   // op : 131, opname : CALL_FUNCTION
308   instr_method_map_[CALL_FUNCTION] = &ByteCodeParser::ParseCallFunction;
309   // op : 132, opname : MAKE_FUNCTION
310   instr_method_map_[MAKE_FUNCTION] = &ByteCodeParser::ParseMakeFunction;
311   // op : 141, opname : CALL_FUNCTION_KW
312   instr_method_map_[CALL_FUNCTION_KW] = &ByteCodeParser::ParseCallFunction;
313   // op : 142, opname : CALL_FUNCTION_EX
314   instr_method_map_[CALL_FUNCTION_EX] = &ByteCodeParser::ParseCallFunction;
315   // op : 143, opname : SETUP_WITH
316   instr_method_map_[SETUP_WITH] = &ByteCodeParser::ParseSetupWith;
317   // op : 155, opname : FORMAT_VALUE
318   instr_method_map_[FORMAT_VALUE] = &ByteCodeParser::ParseFormatValue;
319   // op : 161, opname : CALL_METHOD
320   instr_method_map_[CALL_METHOD] = &ByteCodeParser::ParseCallFunction;
321 }
322 
SaveNode(const ir::NodePtr & node)323 void ByteCodeParser::SaveNode(const ir::NodePtr &node) {
324   latest_gen_node_ = node;
325   nodes_.back()->push_back(node);
326 }
327 
PopStack()328 ir::NodePtr ByteCodeParser::PopStack() {
329   ir::NodePtr node = stack_.back();
330   stack_.pop_back();
331   return node;
332 }
333 
PushStack(const ir::NodePtr & node)334 void ByteCodeParser::PushStack(const ir::NodePtr &node) {
335   latest_gen_node_ = node;
336   stack_.emplace_back(node);
337 }
338 
Parse()339 ir::FunctionNodePtr ByteCodeParser::Parse() {
340   GenerateFunctionParameters();
341   py::object code = py::cast<py::object>(reinterpret_cast<PyObject *>(const_cast<PyCodeObject *>(&code_)));
342   const py::object instructions = py::module::import("dis").attr("get_instructions")(code);
343   ParseInstructions(instructions);
344   for (auto &[key, value] : jump_nodes_map_) {
345     MS_EXCEPTION_IF_CHECK_FAIL(targets_map_.find(key) != targets_map_.end(), "Jump no target.");
346     for (auto &node : value) {
347       node->SetTarget(targets_map_.at(key));
348     }
349   }
350   return func_;
351 }
352 
IsConditionJump(ir::OpCode op)353 bool ByteCodeParser::IsConditionJump(ir::OpCode op) {
354   return op == POP_JUMP_IF_TRUE || op == POP_JUMP_IF_FALSE || op == JUMP_IF_NOT_EXC_MATCH ||
355          op == JUMP_IF_TRUE_OR_POP || op == JUMP_IF_FALSE_OR_POP;
356 }
357 
CallInstrMethod(const InstrPtr & instr)358 void ByteCodeParser::CallInstrMethod(const InstrPtr &instr) {
359   bool need_ext_instr = (instr->GetArg() > 255);
360   (this->*instr_method_map_[instr->GetOpCode()])(instr);
361   latest_gen_node_->SetNeedExtInstr(need_ext_instr);
362   if (instr->IsJumpTarget()) {
363     MS_EXCEPTION_IF_CHECK_FAIL(latest_gen_node_ != nullptr, "Jump Target must not be nullptr.");
364     targets_map_[instr->GetOffset()] = latest_gen_node_;
365   }
366 }
367 
ParseInstructions(const py::list & instrs)368 void ByteCodeParser::ParseInstructions(const py::list &instrs) {
369   const unsigned int bits_per_byte = 8;
370   unsigned int extended_arg = 0;
371   for (size_t index = 0; index < instrs.size(); index++) {
372     InstrPtr instr = std::make_unique<Instr>(instrs[index]);
373     MS_LOG(DEBUG) << "Start parse instruction : " << instr->ToString();
374     int op_code = instr->GetOpCode();
375     if (op_code == EXTENDED_ARG) {
376       extended_arg = IntToSize(instr->GetArg());
377       continue;
378     }
379     if (extended_arg != 0) {
380       instr->SetArg(extended_arg << bits_per_byte | IntToSize(instr->GetArg()));
381       extended_arg = 0;
382     }
383     if (instr_method_map_.find(op_code) == instr_method_map_.end()) {
384       MS_LOG_EXCEPTION << "OpCode : " << instr->GetOpName() << " Not Implemented.";
385     }
386     if (IsConditionJump(op_code)) {
387       index++;
388       int size = (instr->GetArg() - instr->GetOffset()) / 2;
389       py::list then_ = instrs[py::slice(index, index + (size_t)size - 1, 1)];
390       index += then_.size();
391       InstrPtr may_jump = std::make_unique<Instr>(then_[then_.size() - 1]);
392       py::list else_;
393       if (may_jump->GetOpCode() == JUMP_ABSOLUTE) {
394         if (may_jump->GetArg() < may_jump->GetOffset()) {
395           ParseWhile(instr, then_);
396         } else {
397           else_ = instrs[py::slice(index, instrs.size(), 1)];
398           index += else_.size();
399           ParseIf(instr, then_, else_);
400         }
401       } else {
402         if (may_jump->GetOpCode() == JUMP_FORWARD) {
403           else_ = instrs[py::slice(index, index + (size_t)(may_jump->GetArg() / 2), 1)];
404           index += else_.size();
405         }
406         ParseIf(instr, then_, else_);
407       }
408     }
409     if (op_code == FOR_ITER) {
410       index++;
411       size_t size = (size_t)(instr->GetArg() / 2);
412       py::list body = instrs[py::slice(index, index + size, 1)];
413       index += size;
414       ParseWhile(instr, body);
415     }
416     if (index >= instrs.size()) {
417       break;
418     }
419     instr = std::make_unique<Instr>(instrs[index]);
420     CallInstrMethod(instr);
421     MS_LOG(DEBUG) << "Instruction " << instr->GetOpName() << " parse finished.";
422   }
423 }
424 
ParseIf(const InstrPtr & cond,const py::list & then_,const py::list & else_)425 void ByteCodeParser::ParseIf(const InstrPtr &cond, const py::list &then_, const py::list &else_) {
426   CallInstrMethod(cond);
427   ir::IfNodePtr node = std::make_shared<ir::IfNode>(PopStack());
428   Register(&node->GetThen());
429   ParseInstructions(then_);
430   Restore();
431   Register(&node->GetElse());
432   ir::OpCode op_code = cond->GetOpCode();
433   if (op_code == JUMP_IF_TRUE_OR_POP || op_code == JUMP_IF_FALSE_OR_POP) {
434     stack_.emplace_back(node->GetCondition());
435   }
436   ParseInstructions(else_);
437   Restore();
438   SaveNode(node);
439 }
440 
ParseWhile(const InstrPtr & cond,const py::list & body)441 void ByteCodeParser::ParseWhile(const InstrPtr &cond, const py::list &body) {
442   CallInstrMethod(cond);
443   // TOS is an iterator. Call its __next__() method.
444   // If this yields a new value, push it on the stack (leaving the iterator below it).
445   // If the iterator indicates it is exhausted, TOS is popped
446   ir::WhileNodePtr node = std::make_shared<ir::WhileNode>(PopStack());
447   PushStack(std::make_shared<ir::RefNode>(node->GetCondition()));
448   Register(&node->GetBody());
449   ParseInstructions(body);
450   Restore();
451   SaveNode(node);
452 }
453 
GeneratePostionalParameters()454 void ByteCodeParser::GeneratePostionalParameters() {
455   MS_LOG(DEBUG) << "Generate function postional parameters ...";
456   for (size_t index = 0; index < (size_t)code_.co_argcount; index++) {
457     std::string name = py::cast<std::string>(PyTuple_GET_ITEM(code_.co_varnames, index));
458     ir::ParameterPtr param = std::make_shared<ir::Parameter>(index, name);
459     // Set arg as positional parameter
460     param->SetCategory(ir::Parameter::POSITIONAL);
461     // Parameter with default values ​​are placed back position in the positional parameters list
462     if (index >= (size_t)code_.co_argcount - defaults_.size()) {
463       size_t defalut_value_index = index + defaults_.size() - (size_t)code_.co_argcount;
464       ir::ValuePtr defalut_value = std::make_shared<ir::Value>(defaults_[defalut_value_index]);
465       param->SetDefaultValue(defalut_value);
466     }
467     func_->AddParameter(param);
468   }
469 }
470 
GenerateVariableParameter()471 void ByteCodeParser::GenerateVariableParameter() {
472   if ((IntToSize(code_.co_flags) & CO_VARARGS) == 0x0) {
473     return;
474   }
475   MS_LOG(DEBUG) << "Generate function variable parameter ...";
476   // Arguments order : { postional args, keyword only args, variable arg, keyword arg }
477   auto index = code_.co_argcount + code_.co_kwonlyargcount;
478   std::string name = py::cast<std::string>(PyTuple_GET_ITEM(code_.co_varnames, index));
479   // Parameters order : { postional parameters, keyword only parameters, variable parameter, keyword parameter }
480   ir::ParameterPtr param = std::make_shared<ir::Parameter>(code_.co_argcount, name);
481   // set arg as var arg
482   param->SetCategory(ir::Parameter::VARIABLE);
483   func_->AddParameter(param);
484 }
485 
GenerateKeywordOnlyParameters()486 void ByteCodeParser::GenerateKeywordOnlyParameters() {
487   if (code_.co_kwonlyargcount == 0) {
488     return;
489   }
490   MS_LOG(DEBUG) << "Generate function keyword only parameters ...";
491   // Parameters order : { postional parameters, keyword only parameters, variable parameter, keyword parameter }
492   int index = code_.co_argcount + (func_->HasVarArg() ? 1 : 0);
493   for (auto &[key, value] : kwdefaults_) {
494     auto name = py::cast<std::string>(key);
495     ir::ParameterPtr param = std::make_shared<ir::Parameter>(index, name);
496     index++;
497     // set arg as kwonly arg
498     param->SetCategory(ir::Parameter::KEYWORD_ONLY);
499     ir::ValuePtr defalut_value = std::make_shared<ir::Value>(py::cast<py::object>(value));
500     param->SetDefaultValue(defalut_value);
501     func_->AddParameter(param);
502   }
503 }
504 
GenerateKeywordParameter()505 void ByteCodeParser::GenerateKeywordParameter() {
506   if ((IntToSize(code_.co_flags) & CO_VARKEYWORDS) == 0x0) {
507     return;
508   }
509   MS_LOG(DEBUG) << "Generate function keyword parameter ...";
510   auto index = code_.co_argcount + code_.co_kwonlyargcount;
511   index += (func_->HasVarArg() ? 1 : 0);
512   std::string name = py::cast<std::string>(PyTuple_GET_ITEM(code_.co_varnames, index));
513   ir::ParameterPtr param = std::make_shared<ir::Parameter>(index, name);
514   // set arg as kw arg
515   param->SetCategory(ir::Parameter::KEYWORD);
516   func_->AddParameter(param);
517 }
518 
GenerateFunctionParameters()519 void ByteCodeParser::GenerateFunctionParameters() {
520   func_->SetPosArgsCnt(code_.co_argcount);
521   func_->SetKwOnlyArgsCnt(code_.co_kwonlyargcount);
522   func_->SetFlags(code_.co_flags);
523   func_->SetFirstLineNo(code_.co_firstlineno);
524   func_->SetStackSize(code_.co_stacksize);
525   func_->AddFileName(py::cast<std::string>(code_.co_filename));
526   GeneratePostionalParameters();
527   GenerateVariableParameter();
528   GenerateKeywordOnlyParameters();
529   GenerateKeywordParameter();
530 }
531 
ParsePopTop(const InstrPtr & instr)532 void ByteCodeParser::ParsePopTop(const InstrPtr &instr) {
533   MS_EXCEPTION_IF_CHECK_FAIL(!stack_.empty(), "There is no item arg to pop at the top of stack.");
534   ir::NodePtr node = std::make_shared<ir::UnaryOperation>(instr->GetOpCode(), PopStack());
535   node->SetDebugInfo(GetNodeDebugInfo(instr));
536   SaveNode(node);
537 }
538 
DoRot(const int & cnt)539 void ByteCodeParser::DoRot(const int &cnt) {
540   MS_EXCEPTION_IF_CHECK_FAIL((stack_.size() >= (size_t)cnt), "There is no item arg to pop at the top of stack.");
541   auto top = PopStack();
542   ir::NodePtrList stack;
543   for (int idx = 0; idx < (cnt - 1); idx++) {
544     stack.push_back(PopStack());
545   }
546   stack_.push_back(top);
547   while (!stack.empty()) {
548     stack_.push_back(stack.back());
549     stack.pop_back();
550   }
551 }
552 
ParseRotTwo(const InstrPtr & instr)553 void ByteCodeParser::ParseRotTwo(const InstrPtr &instr) { DoRot(2); }
554 
ParseRotThree(const InstrPtr & instr)555 void ByteCodeParser::ParseRotThree(const InstrPtr &instr) { DoRot(3); }
556 
ParseRotFour(const InstrPtr & instr)557 void ByteCodeParser::ParseRotFour(const InstrPtr &instr) { DoRot(4); }
558 
ParseNop(const InstrPtr & instr)559 void ByteCodeParser::ParseNop(const InstrPtr &instr) {}
560 
ParseDupTop(const InstrPtr & instr)561 void ByteCodeParser::ParseDupTop(const InstrPtr &instr) { PushStack(stack_.back()); }
562 
ParseDupTwo(const InstrPtr & instr)563 void ByteCodeParser::ParseDupTwo(const InstrPtr &instr) {
564   auto iter = stack_.end();
565   auto first = *(--iter);
566   auto second = *(--iter);
567   PushStack(second);
568   PushStack(first);
569 }
570 
571 // Parse unary operators, eg: `not a`, `-a`, etc.
ParseUnaryOpertion(const InstrPtr & instr)572 void ByteCodeParser::ParseUnaryOpertion(const InstrPtr &instr) {
573   auto top = PopStack();
574   ir::NodePtr node = std::make_shared<ir::UnaryOperation>(instr->GetOpCode(), top);
575   node->SetDebugInfo(GetNodeDebugInfo(instr));
576   if (instr->GetOpCode() == RERAISE) {
577     SaveNode(node);
578   } else {
579     PushStack(node);
580   }
581 }
582 
583 // Parse unary operators, eg: `-a`.
ParseUnaryNegative(const InstrPtr & instr)584 void ByteCodeParser::ParseUnaryNegative(const InstrPtr &instr) {
585   auto top = PopStack();
586   ir::NodePtr node = std::make_shared<ir::NegativeNode>(top);
587   node->SetDebugInfo(GetNodeDebugInfo(instr));
588   PushStack(node);
589 }
590 
591 // Parse unary operators, eg: `not a`.
ParseUnaryNot(const InstrPtr & instr)592 void ByteCodeParser::ParseUnaryNot(const InstrPtr &instr) {
593   auto top = PopStack();
594   ir::NodePtr node = std::make_shared<ir::NotNode>(top);
595   node->SetDebugInfo(GetNodeDebugInfo(instr));
596   PushStack(node);
597 }
598 
599 // Parse unary operators, eg: `~a`.
ParseUnaryInvert(const InstrPtr & instr)600 void ByteCodeParser::ParseUnaryInvert(const InstrPtr &instr) {
601   auto top = PopStack();
602   ir::NodePtr node = std::make_shared<ir::InvertNode>(top);
603   node->SetDebugInfo(GetNodeDebugInfo(instr));
604   PushStack(node);
605 }
606 
607 // Process binary operators, eg: `a + b`, `a | b`, etc.
ParseBinaryOpertion(const InstrPtr & instr)608 void ByteCodeParser::ParseBinaryOpertion(const InstrPtr &instr) {
609   auto right = PopStack();
610   auto left = PopStack();
611   ir::NodePtr node = std::make_shared<ir::BinaryOperation>(instr->GetOpCode(), left, right);
612   node->SetDebugInfo(GetNodeDebugInfo(instr));
613   PushStack(node);
614 }
615 
616 // Process binary operators, eg: `a + b`, `a | b`, etc.
ParseBitwise(const InstrPtr & instr)617 void ByteCodeParser::ParseBitwise(const InstrPtr &instr) {
618   auto right = PopStack();
619   auto left = PopStack();
620   ir::NodePtr node = std::make_shared<ir::BitwiseNode>(instr->GetOpCode(), left, right);
621   node->SetDebugInfo(GetNodeDebugInfo(instr));
622   PushStack(node);
623 }
624 
ParseAdd(const InstrPtr & instr)625 void ByteCodeParser::ParseAdd(const InstrPtr &instr) {
626   auto right = PopStack();
627   auto left = PopStack();
628   ir::NodePtr node = std::make_shared<ir::AddNode>(instr->GetOpCode(), left, right);
629   node->SetDebugInfo(GetNodeDebugInfo(instr));
630   PushStack(node);
631 }
632 
ParseSub(const InstrPtr & instr)633 void ByteCodeParser::ParseSub(const InstrPtr &instr) {
634   auto right = PopStack();
635   auto left = PopStack();
636   ir::NodePtr node = std::make_shared<ir::SubNode>(instr->GetOpCode(), left, right);
637   node->SetDebugInfo(GetNodeDebugInfo(instr));
638   PushStack(node);
639 }
640 
ParseMul(const InstrPtr & instr)641 void ByteCodeParser::ParseMul(const InstrPtr &instr) {
642   auto right = PopStack();
643   auto left = PopStack();
644   ir::NodePtr node = std::make_shared<ir::MulNode>(instr->GetOpCode(), left, right);
645   node->SetDebugInfo(GetNodeDebugInfo(instr));
646   PushStack(node);
647 }
648 
ParseDiv(const InstrPtr & instr)649 void ByteCodeParser::ParseDiv(const InstrPtr &instr) {
650   auto right = PopStack();
651   auto left = PopStack();
652   ir::NodePtr node = std::make_shared<ir::DivNode>(instr->GetOpCode(), left, right);
653   node->SetDebugInfo(GetNodeDebugInfo(instr));
654   PushStack(node);
655 }
656 
657 // Process binary operators, eg: `TOS = TOS1[TOS]`.
ParseBinarySubscr(const InstrPtr & instr)658 void ByteCodeParser::ParseBinarySubscr(const InstrPtr &instr) {
659   auto subscr = PopStack();
660   auto base = PopStack();
661   ir::NodePtr node = std::make_shared<ir::BinaryOperation>(instr->GetOpCode(), base, subscr);
662   node->SetDebugInfo(GetNodeDebugInfo(instr));
663   PushStack(node);
664 }
665 
666 // Process binary operators, eg: `a > b`, `a < b`, etc.
ParseCompareOp(const InstrPtr & instr)667 void ByteCodeParser::ParseCompareOp(const InstrPtr &instr) {
668   auto right = PopStack();
669   auto left = PopStack();
670   ir::NodePtr node = std::make_shared<ir::CompareNode>(instr->GetArg(), left, right);
671   node->SetDebugInfo(GetNodeDebugInfo(instr));
672   PushStack(node);
673 }
674 
ParseJump(const InstrPtr & instr)675 void ByteCodeParser::ParseJump(const InstrPtr &instr) {
676   ir::OpCode op_code = instr->GetOpCode();
677   ir::NodePtr condition = nullptr;
678   if (op_code != JUMP_FORWARD && op_code != JUMP_ABSOLUTE) {
679     condition = PopStack();
680   }
681   if (op_code == JUMP_IF_NOT_EXC_MATCH) {
682     condition = std::make_shared<ir::PairNode>(condition, PopStack());
683   }
684   ir::JumpNodePtr node = std::make_shared<ir::JumpNode>(op_code, condition, nullptr);
685   node->SetDebugInfo(GetNodeDebugInfo(instr));
686   int target_offset = instr->GetArg();
687   if (op_code == JUMP_FORWARD || op_code == FOR_ITER) {
688     target_offset += instr->GetOffset() + 2;
689   }
690   jump_nodes_map_[target_offset].push_back(node);
691   if (op_code == JUMP_FORWARD || op_code == JUMP_ABSOLUTE) {
692     SaveNode(node);
693   } else {
694     PushStack(node);
695   }
696 }
697 
ParseListToTuple(const InstrPtr & instr)698 void ByteCodeParser::ParseListToTuple(const InstrPtr &instr) {
699   auto top = PopStack();
700   ir::NodePtr node = std::make_shared<ir::CastNode>(top);
701   node->SetDebugInfo(GetNodeDebugInfo(instr));
702   PushStack(node);
703 }
704 
ParseReturnValue(const InstrPtr & instr)705 void ByteCodeParser::ParseReturnValue(const InstrPtr &instr) {
706   auto top = PopStack();
707   ir::NodePtr node = std::make_shared<ir::ReturnNode>(top);
708   node->SetDebugInfo(GetNodeDebugInfo(instr));
709   PushStack(node);
710   SaveNode(node);
711 }
712 
ParseLoadConst(const InstrPtr & instr)713 void ByteCodeParser::ParseLoadConst(const InstrPtr &instr) {
714   py::object opnd = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_consts, instr->GetArg()));
715   ir::ValuePtr arg = std::make_shared<ir::Value>(opnd, py::str(opnd), ir::kScopeConst);
716   ir::NodePtr node = std::make_shared<ir::LoadValueNode>(instr->GetOpCode(), arg);
717   node->SetDebugInfo(GetNodeDebugInfo(instr));
718   PushStack(node);
719 }
720 
ParseLoadName(const InstrPtr & instr)721 void ByteCodeParser::ParseLoadName(const InstrPtr &instr) {
722   py::object name = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_names, instr->GetArg()));
723   ir::ValuePtr arg = std::make_shared<ir::Value>(name, name.cast<std::string>(), ir::kScopeName);
724   ir::NodePtr node = std::make_shared<ir::LoadValueNode>(instr->GetOpCode(), arg);
725   node->SetDebugInfo(GetNodeDebugInfo(instr));
726   PushStack(node);
727 }
728 
ParseMakeFunction(const InstrPtr & instr)729 void ByteCodeParser::ParseMakeFunction(const InstrPtr &instr) {
730   ir::NodePtrList args;
731   args.push_back(PopStack());
732   args.push_back(PopStack());
733   int flag = instr->GetArg();
734   // closure
735   if (IntToSize(flag) & 0x08) {
736     args.push_back(PopStack());
737   }
738   // annotations
739   if (IntToSize(flag) & 0x04) {
740     args.push_back(PopStack());
741   }
742   // kwdefaults
743   if (IntToSize(flag) & 0x02) {
744     args.push_back(PopStack());
745   }
746   // defaults
747   if (IntToSize(flag) & 0x01) {
748     args.push_back(PopStack());
749   }
750   std::reverse(args.begin(), args.end());
751   ir::NodePtr node = std::make_shared<ir::NaryWithFlagNode>(MAKE_FUNCTION, args, flag);
752   node->SetDebugInfo(GetNodeDebugInfo(instr));
753   PushStack(node);
754 }
755 
756 // Process operators, eg: Tuple, List, Dict, Slice
ParseBuild(const InstrPtr & instr)757 void ByteCodeParser::ParseBuild(const InstrPtr &instr) {
758   int size = instr->GetArg();
759   if (instr->GetOpCode() == BUILD_CONST_KEY_MAP) {
760     size++;
761   }
762   ir::NodePtrList opnds((instr->GetOpCode() == BUILD_MAP) ? (size + size) : size);
763   for (int i = size - 1; i >= 0; i--) {
764     if (instr->GetOpCode() != BUILD_MAP) {
765       opnds[i] = PopStack();
766     } else {
767       opnds[i + i] = PopStack();
768       opnds[i + i + 1] = PopStack();
769     }
770   }
771   ir::NodePtr node = std::make_shared<ir::BuildNode>(instr->GetOpCode(), opnds);
772   node->SetDebugInfo(GetNodeDebugInfo(instr));
773   PushStack(node);
774 }
775 
ParseLoadAttr(const InstrPtr & instr)776 void ByteCodeParser::ParseLoadAttr(const InstrPtr &instr) {
777   auto attr_name = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_names, instr->GetArg()));
778   ir::ValuePtr attr = std::make_shared<ir::Value>(attr_name, attr_name.cast<std::string>(), ir::kScopeName);
779   ir::NodePtr node = std::make_shared<ir::LoadFieldNode>(instr->GetOpCode(), PopStack(), attr);
780   node->SetDebugInfo(GetNodeDebugInfo(instr));
781   PushStack(node);
782 }
783 
ParseImport(const InstrPtr & instr)784 void ByteCodeParser::ParseImport(const InstrPtr &instr) {
785   ir::NodePtrList opnds = {PopStack()};
786   if (instr->GetOpCode() == IMPORT_NAME) {
787     opnds.insert(opnds.begin(), PopStack());
788   }
789   if (instr->GetOpCode() != IMPORT_STAR) {
790     auto attr_name = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_names, instr->GetArg()));
791     ir::ValuePtr attr = std::make_shared<ir::Value>(attr_name, attr_name.cast<std::string>(), ir::kScopeName);
792     opnds.push_back(attr);
793   }
794   ir::NodePtr node = std::make_shared<ir::NaryOperation>(instr->GetOpCode(), opnds);
795   node->SetDebugInfo(GetNodeDebugInfo(instr));
796   PushStack(node);
797 }
798 
ParseLoadGlobal(const InstrPtr & instr)799 void ByteCodeParser::ParseLoadGlobal(const InstrPtr &instr) {
800   py::object name = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_names, instr->GetArg()));
801   bool is_global = globals_.contains(name);
802   py::object global = is_global ? globals_[name] : builtins_[name];
803   ir::Scope scope = is_global ? ir::kScopeGlobal : ir::kScopeBuiltIn;
804   ir::ValuePtr value = std::make_shared<ir::Value>(global, name.cast<std::string>(), scope);
805   ir::NodePtr node = std::make_shared<ir::LoadValueNode>(instr->GetOpCode(), value);
806   node->SetDebugInfo(GetNodeDebugInfo(instr));
807   PushStack(node);
808 }
809 
ParseIsOp(const InstrPtr & instr)810 void ByteCodeParser::ParseIsOp(const InstrPtr &instr) {
811   auto right = PopStack();
812   auto left = PopStack();
813   ir::IsNodePtr node = std::make_shared<ir::IsNode>(left, right, instr->GetArg());
814   node->SetDebugInfo(GetNodeDebugInfo(instr));
815   PushStack(node);
816 }
817 
ParseContainsOp(const InstrPtr & instr)818 void ByteCodeParser::ParseContainsOp(const InstrPtr &instr) {
819   auto right = PopStack();
820   auto left = PopStack();
821   ir::ContainsNodePtr node = std::make_shared<ir::ContainsNode>(left, right, instr->GetArg());
822   node->SetDebugInfo(GetNodeDebugInfo(instr));
823   PushStack(node);
824 }
825 
ParseLoadFast(const InstrPtr & instr)826 void ByteCodeParser::ParseLoadFast(const InstrPtr &instr) {
827   auto name = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_varnames, instr->GetArg()));
828   ir::ValuePtr value = std::make_shared<ir::Value>(name, name.cast<std::string>(), ir::kScopeLocal);
829   ir::NodePtr node = std::make_shared<ir::LoadValueNode>(instr->GetOpCode(), value);
830   node->SetDebugInfo(GetNodeDebugInfo(instr));
831   PushStack(node);
832 }
833 
ParseStoreName(const InstrPtr & instr)834 void ByteCodeParser::ParseStoreName(const InstrPtr &instr) {
835   ir::OpCode op_code = instr->GetOpCode();
836   bool is_free_var = (instr->GetArg() > PyTuple_GET_SIZE(code_.co_cellvars));
837   auto names = (op_code == STORE_FAST)
838                  ? code_.co_varnames
839                  : (op_code == STORE_DEREF) ? (is_free_var ? code_.co_freevars : code_.co_cellvars) : code_.co_names;
840   int index = is_free_var ? instr->GetArg() - PyTuple_GET_SIZE(code_.co_cellvars) : instr->GetArg();
841   py::object name = py::cast<py::object>(PyTuple_GET_ITEM(names, index));
842   auto scope = (op_code == STORE_FAST)
843                  ? ir::kScopeLocal
844                  : (op_code == STORE_DEREF) ? (is_free_var ? ir::kScopeFreeVar : ir::kScopeCellVar) : ir::kScopeName;
845   ir::ValuePtr value = std::make_shared<ir::Value>(name, name.cast<std::string>(), scope);
846   auto top = PopStack();
847   ir::NodePtr node = std::make_shared<ir::StoreNode>(op_code, top, value);
848   node->SetDebugInfo(GetNodeDebugInfo(instr));
849   SaveNode(node);
850 }
851 
ParseStoreSubscr(const InstrPtr & instr)852 void ByteCodeParser::ParseStoreSubscr(const InstrPtr &instr) {
853   auto subscr = PopStack();
854   auto base = PopStack();
855   ir::NodePtr target = std::make_shared<ir::SubscrNode>(base, subscr);
856   auto source = PopStack();
857   ir::NodePtr node = std::make_shared<ir::StoreNode>(instr->GetOpCode(), source, target);
858   node->SetDebugInfo(GetNodeDebugInfo(instr));
859   SaveNode(node);
860 }
861 
ParseStoreAttr(const InstrPtr & instr)862 void ByteCodeParser::ParseStoreAttr(const InstrPtr &instr) {
863   py::object name = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_names, instr->GetArg()));
864   ir::NodePtr target = std::make_shared<ir::Value>(name, ir::kScopeName);
865   target = std::make_shared<ir::AttrNode>(PopStack(), target);
866   auto source = PopStack();
867   ir::NodePtr node = std::make_shared<ir::StoreNode>(instr->GetOpCode(), source, target);
868   node->SetDebugInfo(GetNodeDebugInfo(instr));
869   SaveNode(node);
870 }
871 
872 // Process function call, eg : f1(x, y) ...
ParseCallFunction(const InstrPtr & instr)873 void ByteCodeParser::ParseCallFunction(const InstrPtr &instr) {
874   // The number of args of the called function object, except CALL_FUNCTION_EX
875   // CALL_FUNCTION_EX :size is the flag bit of whether it has kwargs
876   int size = instr->GetArg();
877   if (instr->GetOpCode() == CALL_FUNCTION_EX) {
878     // The Value of size must be 0 or 1
879     // the number of parameters is 2 when flag is 1
880     // Otherwise, the number of parameters is 1
881     MS_EXCEPTION_IF_CHECK_FAIL((size == 0 || size == 1), "The flag of CALL_FUNCTION_EX must be 0 or 1.");
882     size = 1;
883     if (IntToSize(size) & 0x1) {
884       size += 1;
885     }
886   }
887   // The tuple of keys occupies a position
888   if (instr->GetOpCode() == CALL_FUNCTION_KW) {
889     size++;
890   }
891   // The function object occupies a position
892   size++;
893   ir::NodePtrList args;
894   for (int index = 0; index < size; index++) {
895     args.push_back(PopStack());
896   }
897   std::reverse(args.begin(), args.end());
898   ir::NodePtr node = std::make_shared<ir::CallNode>(instr->GetOpCode(), args);
899   node->SetDebugInfo(GetNodeDebugInfo(instr));
900   PushStack(node);
901 }
902 
ParseLoadClosure(const InstrPtr & instr)903 void ByteCodeParser::ParseLoadClosure(const InstrPtr &instr) {
904   int cell_var_size = PyTuple_GET_SIZE(code_.co_cellvars);
905   int index = instr->GetArg();
906   ir::NodePtr opnd;
907   // if index is less than the length of co_cellvars, then closure is co_cellvars[index]
908   // else closure is co_freevars[index - len(co_cellvars)]
909   if (cell_var_size > index) {
910     auto name = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_cellvars, index));
911     opnd = std::make_shared<ir::Value>(name, name.cast<std::string>(), ir::kScopeCellVar);
912   } else {
913     index -= cell_var_size;
914     auto name = py::cast<std::string>(PyTuple_GET_ITEM(code_.co_freevars, index));
915     opnd = std::make_shared<ir::Value>(clousre_[index], name, ir::kScopeClousre);
916   }
917   ir::NodePtr node = std::make_shared<ir::LoadValueNode>(instr->GetOpCode(), opnd);
918   node->SetDebugInfo(GetNodeDebugInfo(instr));
919   PushStack(node);
920 }
921 
922 // This opcode performs several operations before a with block starts.
923 // First, it loads __exit__() from the context manager and pushes it onto the stack for later use by WITH_EXCEPT_START.
924 // Then, __enter__() is called, and a finally block pointing to delta is pushed.
925 // Finally, the result of calling the __enter__() method is pushed onto the stack.
926 // The next opcode will either ignore it (POP_TOP), or store it in (a) variable(s) (STORE_FAST, STORE_NAME, or
927 // UNPACK_SEQUENCE).
ParseSetupWith(const InstrPtr & instr)928 void ByteCodeParser::ParseSetupWith(const InstrPtr &instr) {
929   auto node = std::make_shared<ir::JumpNode>(instr->GetOpCode(), PopStack(), nullptr);
930   int target_offset = instr->GetArg() + instr->GetOffset() + 2;
931   jump_nodes_map_[target_offset].push_back(node);
932   node->SetDebugInfo(GetNodeDebugInfo(instr));
933   SaveNode(node);
934   ir::NodePtr ph = std::make_shared<ir::PlaceHolder>("SETUP_WITH EXIT");
935   PushStack(ph);
936   ph = std::make_shared<ir::PlaceHolder>("SETUP_WITH FINALLY BLOCK");
937   PushStack(ph);
938   ph = std::make_shared<ir::PlaceHolder>("SETUP_WITH ENTER");
939   PushStack(ph);
940 }
941 
ParseFormatValue(const InstrPtr & instr)942 void ByteCodeParser::ParseFormatValue(const InstrPtr &instr) {
943   ir::NodePtrList opnds;
944   opnds.push_back(PopStack());
945   if ((IntToSize(instr->GetArg()) & 0x04) == 0x04) {
946     opnds.push_back(PopStack());
947   }
948   ir::NodePtr node = std::make_shared<ir::FormatNode>(opnds, instr->GetArg());
949   node->SetDebugInfo(GetNodeDebugInfo(instr));
950   PushStack(node);
951 }
952 
ParseLoadMethod(const InstrPtr & instr)953 void ByteCodeParser::ParseLoadMethod(const InstrPtr &instr) {
954   auto name = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_names, instr->GetArg()));
955   ir::ValuePtr method = std::make_shared<ir::Value>(name, name.cast<std::string>(), ir::kScopeName);
956   ir::NodePtr node = std::make_shared<ir::LoadFieldNode>(instr->GetOpCode(), PopStack(), method);
957   node->SetDebugInfo(GetNodeDebugInfo(instr));
958   PushStack(node);
959 }
960 
ParseContainerUpdate(const InstrPtr & instr)961 void ByteCodeParser::ParseContainerUpdate(const InstrPtr &instr) {
962   auto right = PopStack();
963   MS_EXCEPTION_IF_CHECK_FAIL((instr->GetArg() == 1), "Not Excepted Update.");
964   auto left = PopStack();
965   ir::NodePtr node = std::make_shared<ir::UpdateNode>(instr->GetOpCode(), left, right, instr->GetArg());
966   node->SetDebugInfo(GetNodeDebugInfo(instr));
967   PushStack(node);
968 }
969 
ParseNoArgOperation(const InstrPtr & instr)970 void ByteCodeParser::ParseNoArgOperation(const InstrPtr &instr) {
971   ir::NodePtr node = std::make_shared<ir::NaryOperation>(instr->GetOpCode());
972   node->SetDebugInfo(GetNodeDebugInfo(instr));
973   PushStack(node);
974 }
975 
ParseWithExceptStart(const InstrPtr & instr)976 void ByteCodeParser::ParseWithExceptStart(const InstrPtr &instr) {
977   auto top = PopStack();
978   bool is_exit = top->isa<ir::PlaceHolder>() && top->cast<ir::PlaceHolderPtr>()->GetTag() == "SETUP_WITH FINALLY BLOCK";
979   MS_EXCEPTION_IF_CHECK_FAIL(is_exit, "Not Excepted args for with except start.");
980   for (size_t index = 0; index < 6; index++) {
981     ir::NodePtr node = std::make_shared<ir::PlaceHolder>("WITH_EXCEPT_START " + std::to_string(index));
982     PushStack(node);
983   }
984   ir::NodePtr node = std::make_shared<ir::NaryOperation>(instr->GetOpCode());
985   node->SetDebugInfo(GetNodeDebugInfo(instr));
986   SaveNode(node);
987 }
988 
ParseGet(const InstrPtr & instr)989 void ByteCodeParser::ParseGet(const InstrPtr &instr) {
990   auto top = PopStack();
991   ir::NodePtr node = std::make_shared<ir::GetNode>(instr->GetOpCode(), top);
992   node->SetDebugInfo(GetNodeDebugInfo(instr));
993   PushStack(node);
994 }
995 
ParseLoadAssertError(const InstrPtr & instr)996 void ByteCodeParser::ParseLoadAssertError(const InstrPtr &instr) {
997   ir::NodePtr node = std::make_shared<ir::NaryOperation>(instr->GetOpCode());
998   node->SetDebugInfo(GetNodeDebugInfo(instr));
999   PushStack(node);
1000 }
1001 
ParseDeleteSubscr(const InstrPtr & instr)1002 void ByteCodeParser::ParseDeleteSubscr(const InstrPtr &instr) {
1003   auto subscr = PopStack();
1004   auto base = PopStack();
1005   ir::NodePtr opnd = std::make_shared<ir::SubscrNode>(base, subscr);
1006   ir::NodePtr node = std::make_shared<ir::DeleteNode>(instr->GetOpCode(), opnd);
1007   node->SetDebugInfo(GetNodeDebugInfo(instr));
1008   SaveNode(node);
1009 }
1010 
ParseDeleteName(const InstrPtr & instr)1011 void ByteCodeParser::ParseDeleteName(const InstrPtr &instr) {
1012   auto names = (instr->GetOpCode() == DELETE_FAST)
1013                  ? code_.co_varnames
1014                  : (instr->GetOpCode() == DELETE_DEREF) ? code_.co_cellvars : code_.co_names;
1015   py::object name = py::cast<py::object>(PyTuple_GET_ITEM(names, instr->GetArg()));
1016   auto scope = (instr->GetOpCode() == DELETE_FAST)
1017                  ? ir::kScopeLocal
1018                  : (instr->GetOpCode() == DELETE_DEREF) ? ir::kScopeCellVar : ir::kScopeName;
1019   ir::NodePtr opnd = std::make_shared<ir::Value>(name, scope);
1020   ir::NodePtr node = std::make_shared<ir::DeleteNode>(instr->GetOpCode(), opnd);
1021   node->SetDebugInfo(GetNodeDebugInfo(instr));
1022   SaveNode(node);
1023 }
1024 
ParseDeleteAttr(const InstrPtr & instr)1025 void ByteCodeParser::ParseDeleteAttr(const InstrPtr &instr) {
1026   py::object name = py::cast<py::object>(PyTuple_GET_ITEM(code_.co_names, instr->GetArg()));
1027   ir::NodePtr opnd = std::make_shared<ir::Value>(name, ir::kScopeName);
1028   opnd = std::make_shared<ir::AttrNode>(PopStack(), opnd);
1029   ir::NodePtr node = std::make_shared<ir::DeleteNode>(instr->GetOpCode(), opnd);
1030   node->SetDebugInfo(GetNodeDebugInfo(instr));
1031   SaveNode(node);
1032 }
1033 
ParseUnpack(const InstrPtr & instr)1034 void ByteCodeParser::ParseUnpack(const InstrPtr &instr) {
1035   ir::NodePtrList args = {PopStack()};
1036   for (int index = instr->GetArg(); index > 0; index--) {
1037     auto subscr = std::make_shared<ir::Value>(py::int_(index - 1), ir::kScopeConst);
1038     ir::NodePtr top = std::make_shared<ir::SubscrNode>(args[0], subscr);
1039     top = std::make_shared<ir::RefNode>(top);
1040     PushStack(top);
1041     args.push_back(top);
1042   }
1043   ir::NodePtr unpack = std::make_shared<ir::NaryWithFlagNode>(instr->GetOpCode(), args, instr->GetArg());
1044   unpack->SetDebugInfo(GetNodeDebugInfo(instr));
1045   SaveNode(unpack);
1046 }
1047 
ParseRaiseVarargs(const InstrPtr & instr)1048 void ByteCodeParser::ParseRaiseVarargs(const InstrPtr &instr) {
1049   int flag = instr->GetArg();
1050   ir::NodePtrList args;
1051   if (flag == 1 || flag == 2) {
1052     args.push_back(PopStack());
1053   }
1054   if (flag == 2) {
1055     args.push_back(PopStack());
1056   }
1057   ir::NodePtr node = std::make_shared<ir::NaryWithFlagNode>(RAISE_VARARGS, args, flag);
1058   node->SetDebugInfo(GetNodeDebugInfo(instr));
1059   SaveNode(node);
1060 }
1061 
GetNodeDebugInfo(const InstrPtr & instr)1062 ir::DebugInfoPtr ByteCodeParser::GetNodeDebugInfo(const InstrPtr &instr) {
1063   return std::move(std::make_shared<ir::DebugInfo>(instr->GetArgRepr(), func_->GetFileName(), instr->GetStartsLine()));
1064 }
1065 }  // namespace pijit
1066 }  // namespace mindspore
1067