• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 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 #ifndef MINDSPORE_PI_JIT_BYTECODE_PARSER_H_
18 #define MINDSPORE_PI_JIT_BYTECODE_PARSER_H_
19 
20 #include <map>
21 #include <memory>
22 #include <string>
23 #include <vector>
24 #include "pybind11/pybind11.h"
25 #include "pipeline/jit/pi/graph_compiler/pi_ir/ctrl_flow.h"
26 #include "pipeline/jit/pi/graph_compiler/pi_ir/custom_nodes.h"
27 #include "pipeline/jit/pi/graph_compiler/pi_ir/debug_info.h"
28 #include "pipeline/jit/pi/graph_compiler/pi_ir/value.h"
29 #include "utils/convert_utils_base.h"
30 
31 namespace mindspore {
32 namespace pijit {
33 namespace py = pybind11;
34 
35 // ByteCodeParser to parse python byte code
36 class ByteCodeParser {
37  public:
38   explicit ByteCodeParser(const py::object &func);
39   explicit ByteCodeParser(const PyFunctionObject &func);
40   ir::FunctionNodePtr Parse();
SetEnableTupleBroaden(bool enable)41   void SetEnableTupleBroaden(bool enable) { func_->SetAttr("enable_tuple_broaden", enable); }
42 
43  private:
44   class Instr {
45    public:
Instr(const py::object & instr)46     explicit Instr(const py::object &instr)
47         : op_code_(CastToInt(instr.attr("opcode"))),
48           op_name_(instr.attr("opname").cast<std::string>()),
49           arg_(CastToInt(instr.attr("arg"))),
50           arg_repr_(instr.attr("argrepr").cast<std::string>()),
51           offset_(CastToInt(instr.attr("offset"))),
52           starts_line_(CastToInt(instr.attr("starts_line"))),
53           is_jump_target_(instr.attr("is_jump_target").cast<bool>()) {}
54 
GetOpCode()55     int GetOpCode() const { return op_code_; }
GetOpName()56     const std::string &GetOpName() const { return op_name_; }
GetArg()57     int GetArg() const { return arg_; }
SetArg(int arg)58     void SetArg(int arg) { arg_ = arg; }
GetArgRepr()59     const std::string &GetArgRepr() const { return arg_repr_; }
GetOffset()60     int GetOffset() const { return offset_; }
GetStartsLine()61     int GetStartsLine() const { return starts_line_; }
IsJumpTarget()62     bool IsJumpTarget() const { return is_jump_target_; }
ToString()63     std::string ToString() const {
64       return op_name_ + " " + std::to_string(arg_) + (arg_repr_.empty() ? "" : (" (" + arg_repr_) + ")");
65     }
66 
67    private:
CastToInt(const py::object & obj)68     int CastToInt(const py::object &obj) const { return py::isinstance<py::none>(obj) ? 0 : obj.cast<int>(); }
69 
70     int op_code_;
71     std::string op_name_;
72     int arg_;
73     std::string arg_repr_;
74     int offset_;
75     int starts_line_;
76     bool is_jump_target_;
77   };
78   using InstrPtr = std::unique_ptr<Instr>;
79 
80   // Bind op code to it's handle function
81   void BuildMethodMap();
82   void BuildStackMethodMap();
83   void BuildLoadStoreMethodMap();
84   void BuildMathMethodMap();
85   void BuildBitwiseMethodMap();
86   void BuildContainerMethodMap();
87   void BuildContrlFlowMethodMap();
88   void BuildOtherMethodMap();
89   void CallInstrMethod(const InstrPtr &instr);
Register(ir::NodePtrList * list)90   void Register(ir::NodePtrList *list) { nodes_.push_back(list); }
Restore()91   void Restore() { nodes_.pop_back(); }
92   void SaveNode(const ir::NodePtr &node);
93   bool IsConditionJump(ir::OpCode op);
94   void ParseInstructions(const py::list &instrs);
95   void ParseIf(const InstrPtr &cond, const py::list &then, const py::list &els);
96   void ParseWhile(const InstrPtr &cond, const py::list &body);
97   ir::NodePtr PopStack();
98   void PushStack(const ir::NodePtr &node);
99   // Process parameters, create place holder and set abstract(type info)
100   void GeneratePostionalParameters();
101   void GenerateVariableParameter();
102   void GenerateKeywordOnlyParameters();
103   void GenerateKeywordParameter();
104   void GenerateFunctionParameters();
105   void ParsePopTop(const InstrPtr &instr);
106   void DoRot(const int &cnt);
107   void ParseRotTwo(const InstrPtr &instr);
108   void ParseRotThree(const InstrPtr &instr);
109   void ParseRotFour(const InstrPtr &instr);
110   void ParseNop(const InstrPtr &instr);
111   void ParseDupTop(const InstrPtr &instr);
112   void ParseDupTwo(const InstrPtr &instr);
113   void ParseUnaryOpertion(const InstrPtr &instr);
114   void ParseUnaryNegative(const InstrPtr &instr);
115   void ParseUnaryNot(const InstrPtr &instr);
116   void ParseUnaryInvert(const InstrPtr &instr);
117   void ParseBinaryOpertion(const InstrPtr &instr);
118   void ParseBitwise(const InstrPtr &instr);
119   void ParseAdd(const InstrPtr &instr);
120   void ParseSub(const InstrPtr &instr);
121   void ParseMul(const InstrPtr &instr);
122   void ParseDiv(const InstrPtr &instr);
123   void ParseBinarySubscr(const InstrPtr &instr);
124   void ParseCompareOp(const InstrPtr &instr);
125   void ParseJump(const InstrPtr &instr);
126   void ParseListToTuple(const InstrPtr &instr);
127   void ParseReturnValue(const InstrPtr &instr);
128   // Process Load Constant as value node
129   void ParseLoadConst(const InstrPtr &instr);
130   void ParseLoadName(const InstrPtr &instr);
131   void ParseMakeFunction(const InstrPtr &instr);
132   void ParseBuild(const InstrPtr &instr);
133   void ParseLoadAttr(const InstrPtr &instr);
134   void ParseImport(const InstrPtr &instr);
135   // Process Load a global module/class/function/method/variable etc.
136   void ParseLoadGlobal(const InstrPtr &instr);
137   // Whether two objects are the same
138   // Fold Python objects into constant values, relying on Gurad
139   void ParseIsOp(const InstrPtr &instr);
140   void ParseContainsOp(const InstrPtr &instr);
141   // Process Load a parameter or a local variable
142   void ParseLoadFast(const InstrPtr &instr);
143   void ParseStoreName(const InstrPtr &instr);
144   void ParseStoreSubscr(const InstrPtr &instr);
145   void ParseStoreAttr(const InstrPtr &instr);
146   void ParseCallFunction(const InstrPtr &instr);
147   void ParseLoadClosure(const InstrPtr &instr);
148   void ParseSetupWith(const InstrPtr &instr);
149   // Fold Python objects into constant values, relying on Gurad
150   void ParseFormatValue(const InstrPtr &instr);
151   void ParseLoadMethod(const InstrPtr &instr);
152   void ParseContainerUpdate(const InstrPtr &instr);
153   void ParseNoArgOperation(const InstrPtr &instr);
154   void ParseWithExceptStart(const InstrPtr &instr);
155   void ParseGet(const InstrPtr &instr);
156   void ParseLoadAssertError(const InstrPtr &instr);
157   void ParseDeleteSubscr(const InstrPtr &instr);
158   void ParseDeleteName(const InstrPtr &instr);
159   void ParseDeleteAttr(const InstrPtr &instr);
160   void ParseUnpack(const InstrPtr &instr);
161   void ParseRaiseVarargs(const InstrPtr &instr);
162   ir::DebugInfoPtr GetNodeDebugInfo(const InstrPtr &instr);
163 
164   ir::FunctionNodePtr func_;
165   const PyCodeObject &code_;
166   const py::dict globals_;
167   const py::dict builtins_;
168   const py::tuple clousre_;
169   const py::dict kwdefaults_;
170   const py::tuple defaults_;
171 
172   using InstrFunc = void (ByteCodeParser::*)(const InstrPtr &instr);
173   // Define the function map to parse ast expression
174   std::map<int, InstrFunc> instr_method_map_;
175   // variable's buffer used to analysis logic and build graph
176   ir::NodePtrList stack_;
177   std::map<int, std::vector<ir::JumpNodePtr>> jump_nodes_map_;
178   std::map<int, ir::NodePtr> targets_map_;
179   std::vector<ir::NodePtrList *> nodes_;
180   ir::NodePtr latest_gen_node_{nullptr};
181 };
182 }  // namespace pijit
183 }  // namespace mindspore
184 
185 #endif  // MINDSPORE_PI_JIT_BYTECODE_PARSER_H_
186