• 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_BYTE_CODE_GENERATOR_H_
18 #define MINDSPORE_PI_JIT_BYTE_CODE_GENERATOR_H_
19 
20 #include <Python.h>
21 #include <map>
22 #include <memory>
23 #include <string>
24 #include <unordered_map>
25 #include <utility>
26 #include <vector>
27 #include "pipeline/jit/pi/graph_compiler/pi_ir/ir_visitor.h"
28 #include "utils/convert_utils_base.h"
29 
30 namespace mindspore {
31 namespace pijit {
32 namespace py = pybind11;
33 
34 // ByteCodeGenerator to parse python byte code
35 class ByteCodeGenerator : public ir::IRVisitor {
36  public:
37   virtual ~ByteCodeGenerator() = default;
38   static py::object GenFunction(const ir::FunctionNodePtr &func);
39   py::object Generate(const ir::FunctionNodePtr &func);
40 
41   // overloadable Mutate function.
42   void Visit_(const ir::ParameterPtr &node) override;
43   void Visit_(const ir::ValuePtr &node) override;
44   void Visit_(const ir::UnaryOperationPtr &node) override;
45   void Visit_(const ir::BinaryOperationPtr &node) override;
46   void Visit_(const ir::NaryOperationPtr &node) override;
47   void Visit_(const ir::NegativeNodePtr &node) override;
48   void Visit_(const ir::NotNodePtr &node) override;
49   void Visit_(const ir::InvertNodePtr &node) override;
50   void Visit_(const ir::ReturnNodePtr &node) override;
51   void Visit_(const ir::CastNodePtr &node) override;
52   void Visit_(const ir::DeleteNodePtr &node) override;
53   void Visit_(const ir::GetNodePtr &node) override;
54   void Visit_(const ir::FormatNodePtr &node) override;
55   void Visit_(const ir::AddNodePtr &node) override;
56   void Visit_(const ir::SubNodePtr &node) override;
57   void Visit_(const ir::MulNodePtr &node) override;
58   void Visit_(const ir::DivNodePtr &node) override;
59   void Visit_(const ir::BitwiseNodePtr &node) override;
60   void Visit_(const ir::IsNodePtr &node) override;
61   void Visit_(const ir::ContainsNodePtr &node) override;
62   void Visit_(const ir::StoreNodePtr &node) override;
63   void Visit_(const ir::JumpNodePtr &node) override;
64   void Visit_(const ir::CompareNodePtr &node) override;
65   void Visit_(const ir::UpdateNodePtr &node) override;
66   void Visit_(const ir::LoadValueNodePtr &node) override;
67   void Visit_(const ir::LoadFieldNodePtr &node) override;
68   void Visit_(const ir::BuildNodePtr &node) override;
69   void Visit_(const ir::CallNodePtr &node) override;
70   void Visit_(const ir::NaryWithFlagNodePtr &node) override;
71 
72  private:
73   class CellVarCounter : public ir::IRVisitor {
74    public:
GetCount(const ir::NodePtr node)75     static int GetCount(const ir::NodePtr node) {
76       auto counter = std::make_shared<CellVarCounter>();
77       counter->Visit(node);
78       return counter->GetCount();
79     }
80 
81    private:
GetCount()82     int GetCount() const { return cell_var_cnt_; }
83 
Visit_(const ir::ValuePtr & node)84     void Visit_(const ir::ValuePtr &node) override {
85       if (node->GetScope() == ir::kScopeCellVar) {
86         cell_var_cnt_++;
87       }
88     }
89 
90     int cell_var_cnt_{0};
91   };
92 
93   int GetValueIndex(const ir::ValuePtr &node);
94   void CheckInstrOffset(const ir::NodePtr &node);
95   void GenerateInstr(ir::OpCode op, int arg = 0);
96   void SetStartsLine(const ir::NodePtr &node);
97 
98   PyFunctionObject *func_graph_{nullptr};
99   std::vector<_Py_CODEUNIT> co_code_;
100   // A string encoding the mapping from bytecode offsets to line numbers.
101   std::vector<char> co_lnotab_;
102   int first_line_no_{0};
103   ir::NodePtr last_starts_instr_{nullptr};
104   py::dict globals_;
105   py::dict builtins_;
106   py::list co_consts_;
107   std::unordered_map<std::string, int> co_consts_map_;
108   py::list co_var_names_;
109   std::unordered_map<std::string, int> co_var_names_map_;
110   py::list co_names_;
111   std::unordered_map<std::string, int> co_names_map_;
112   py::list co_free_vars_;
113   std::unordered_map<std::string, int> co_free_vars_map_;
114   py::list co_cell_vars_;
115   std::unordered_map<std::string, int> co_cell_vars_map_;
116   py::list clousre_;
117   std::unordered_map<std::string, int> clousre_map_;
118   py::list defaults_;
119   py::dict kwdefaults_;
120   const std::map<ir::Scope, std::unordered_map<std::string, int> *> scope_inquire_map_ = {
121     {ir::kScopeConst, &co_consts_map_},      {ir::kScopeLocal, &co_var_names_map_},
122     {ir::kScopeName, &co_names_map_},        {ir::kScopeFreeVar, &co_free_vars_map_},
123     {ir::kScopeCellVar, &co_cell_vars_map_}, {ir::kScopeClousre, &co_free_vars_map_},
124     {ir::kScopeBuiltIn, &co_names_map_},     {ir::kScopeGlobal, &co_names_map_}};
125   const std::map<ir::Scope, std::pair<py::list, py::object>> scope_value_list_ = {
126     {ir::kScopeConst, {co_consts_, co_consts_}},
127     {ir::kScopeLocal, {co_var_names_, co_var_names_}},
128     {ir::kScopeName, {co_names_, co_names_}},
129     {ir::kScopeFreeVar, {co_free_vars_, co_free_vars_}},
130     {ir::kScopeCellVar, {co_cell_vars_, co_cell_vars_}},
131     {ir::kScopeClousre, {co_free_vars_, clousre_}},
132     {ir::kScopeBuiltIn, {co_names_, builtins_}},
133     {ir::kScopeGlobal, {co_names_, globals_}}};
134   int cell_var_cnt_{0};
135 };
136 
137 using ByteCodeGeneratorPtr = std::shared_ptr<ByteCodeGenerator>;
138 }  // namespace pijit
139 }  // namespace mindspore
140 
141 #endif  // MINDSPORE_PI_JIT_BYTE_CODE_GENERATOR_H_
142