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