• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2021 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_LITE_MICRO_CODER_OPCODERS_SERIALIZERS_SERIALIZER_H_
18 #define MINDSPORE_LITE_MICRO_CODER_OPCODERS_SERIALIZERS_SERIALIZER_H_
19 
20 #include <vector>
21 #include <string>
22 #include <sstream>
23 #include "coder/allocator/allocator.h"
24 #include "coder/opcoders/serializers/nnacl_serializer/nnacl_stream_utils.h"
25 
26 namespace mindspore::lite::micro {
27 
28 /*
29  *  convert array T[] to string
30  *  std::ostream &operator<<(std::ostream &, const ::T &) must exist
31  *  arr shouldn't be pointer, T* is not valid
32  *  example:
33  *      int arr[] = {1, 2, 3};
34  *      ToString(arr);
35  *  the code above would produce:
36  *      "{1, 2, 3}"
37  */
38 template <typename T, unsigned int N>
ToString(const T (& arr)[N])39 std::string ToString(const T (&arr)[N]) {
40   std::stringstream code;
41   int n = N;
42   while (n > 0 && arr[n - 1] == 0) {
43     n--;
44   }
45   code << "{";
46   for (int i = 0; i < n - 1; ++i) {
47     code << arr[i] << ", ";
48   }
49   if (n > 0) {
50     code << arr[n - 1];
51   }
52   code << "}";
53   return code.str();
54 }
55 
56 class Serializer {
57  public:
58   Serializer() = default;
59   virtual ~Serializer() = default;
60 
61   /*
62    * Code function call to generated code
63    * First parameter is the function name, the rest are the parameters of the function
64    * example:
65    *    CodeFunction("function", "foo", "bar", "foobar", 42);
66    * the code above would produce:
67    *    "function("foo", "bar", "foobar", 42);\n"
68    */
69   template <typename... PARAMETERS>
CodeFunction(const std::string & name,PARAMETERS...parameters)70   void CodeFunction(const std::string &name, PARAMETERS... parameters) {
71     code << name << "(";
72     GenCode(parameters...);
73     code << ");\n";
74   }
75 
76   /*
77    * Code function call to generated code, with checking the return code
78    * First parameter is the function name, the rest are the parameters of the function
79    * example:
80    *    CodeFunctionWithCheck("function", "foo", "bar", "foobar", 42);
81    * the code above would produce:
82    * """
83    *    if(function("foo", "bar", "foobar", 42) != 0) {\n
84    *       return -1;
85    *    }
86    * """
87    */
88   template <typename... PARAMETERS>
CodeFunctionWithCheck(const std::string & name,PARAMETERS...parameters)89   void CodeFunctionWithCheck(const std::string &name, PARAMETERS... parameters) {
90     code << "if(" << name << "(";
91     GenCode(parameters...);
92     code << ") != RET_OK) {\n";
93     code << "  return RET_ERROR;\n";
94     code << "}\n";
95   }
96 
97   /*
98    * helper function for coding
99    * example:
100    *    int bar[] = {1 ,3, 2};
101    *    CodeArray("bar", bar, 3);
102    * the code above would produce:
103    *    "int bar[3] = {1 ,3, 2};\n"
104    */
105   template <typename T>
106   void CodeArray(const std::string &name, T *data, int length, bool is_const = true) {
107     std::string type = GetVariableTypeName<T>();
108     if (is_const) {
109       code << "const " << type << " " << name << "[" << length << "] = {";
110     } else {
111       code << type << " " << name << "[" << length << "] = {";
112     }
113     for (int i = 0; i < length - 1; ++i) {
114       code << data[i] << ", ";
115     }
116     if (length > 0) {
117       code << data[length - 1];
118     }
119     code << "};\n";
120   }
121 
122   template <typename T>
CodeMallocExpression(T t,size_t size)123   void CodeMallocExpression(T t, size_t size) {
124     if (size == 0) {
125       MS_LOG(ERROR) << "CodeMallocExpression size is zero";
126       exit(1);
127     }
128     GenCode(t);
129     code << " = malloc(" << size << ");\n";
130     code << "if (";
131     GenCode(t);
132     code << " == NULL) {\n";
133     code << "  return RET_ERROR;\n";
134     code << "}\n";
135   }
136 
precision(std::streamsize size)137   std::streamsize precision(std::streamsize size) {
138     std::streamsize old = code.precision(size);
139     return old;
140   }
141 
str()142   std::string str() const { return code.str(); }
143 
144   template <typename T>
145   Serializer &operator<<(T t) {
146     code << t;
147     return *this;
148   }
149 
150   /*
151    * helper function for CodeStruct
152    * all parameters should be
153    * example:
154    * given:
155    *    typedef struct Foo {
156    *      int array[5];
157    *      int *pointer;
158    *      int count;
159    *    } Foo;
160    *    int pointer[] = {1 ,3, 2, 42};
161    *    Foo foo = {{1, 2, 3}, pointer, 4};
162    *    the CodeStruct should be written as:
163    *    CodeStruct(const string &name, const Foo &foo) {
164    *      CodeArray("pointer_gen", foo.pointer, foo.count);
165    *      CodeBaseStruct("Foo", "foo_gen", ToString(foo.array), "pointer_gen", foo.count);
166    *    }
167    * the code above would produce:
168    *    "int pointer_gen[4] = {1 ,3, 2, 42};\n
169    *    const Foo foo_gen = {{1, 2, 3}, pointer_gen, 4};\n"
170    */
171   template <bool immutable = true, typename... PARAMETERS>
CodeBaseStruct(const std::string & type,const std::string & name,PARAMETERS...parameters)172   void CodeBaseStruct(const std::string &type, const std::string &name, PARAMETERS... parameters) {
173     if constexpr (immutable) {
174       code << "const " << type << " " << name << " = {";
175     } else {
176       code << type << " " << name << " = {";
177     }
178     GenCode(parameters...);
179     code << "};\n";
180   }
181 
182  protected:
183   std::ostringstream code;
184 
185  private:
186   /*
187    *   function GenCode(Args... args)
188    *   Convert all parameters to string, and join connect them with comma ", "
189    *   example:
190    *      GenCode(true, false, static_cast<int8_t>(12), static_cast<uint8_t>(57), 'c', 5567);
191    *   the code above would produce:
192    *      "true, false, 12, 57, c, 5567"
193    */
194   template <typename T, typename... REST>
GenCode(T t,REST...args)195   void GenCode(T t, REST... args) {
196     GenCode(t);
197     code << ", ";
198     GenCode(args...);
199   }
200   template <typename T>
GenCode(T t)201   void GenCode(T t) {
202     code << t;
203   }
204 
205   /*
206    *  Convert pointer to string when it's in MemoryAllocator (and it should be)
207    *  if t is not in the table of MemoryAllocator, it would return empty string ""
208    *  then the coder would generate something like
209    *    {foo, , bar}
210    *  and make the generated code
211    *  not compilable rather than generating code like
212    *    {foo, 0x7ffed0cd377c, bar}
213    *  which would bring the hard coded address to the runtime and make it harder to debug
214    *
215    *  if t is nullptr, "NULL" would be coded to generated code because some pointer might
216    *  be nullptr in some cases and we want to code it.
217    *  In this function, passing nullptr **would not** be regarded as a bug or mistake
218    */
219   template <typename T>
GenCode(T * t)220   void GenCode(T *t) {
221     if (t == nullptr) {
222       code << "NULL";
223     } else {
224       std::string name = MemoryAllocator::GetInstance()->GetRuntimeAddr(t, true);
225       if (name.empty()) {
226         MS_LOG(ERROR) << "pointer is not allocated by the allocator";
227         exit(1);
228       }
229       code << name;
230     }
231   }
232 
233   // std::boolalpha converts bool to string literals {"true", "false"} instead of {1, 0}
GenCode(bool t)234   void GenCode(bool t) { code << std::boolalpha << t; }
GenCode(int8_t t)235   void GenCode(int8_t t) { code << std::to_string(t); }
GenCode(uint8_t t)236   void GenCode(uint8_t t) { code << std::to_string(t); }
GenCode(decltype (nullptr)t)237   void GenCode(decltype(nullptr) t) { code << "NULL"; }
GenCode(const char * t)238   void GenCode(const char *t) { code << t; }
GenCode(LiteDataType t)239   void GenCode(LiteDataType t) { code << "(LiteDataType)" << t; }
240 };
241 }  // namespace mindspore::lite::micro
242 #endif  // MINDSPORE_LITE_MICRO_CODER_SERIALIZERS_SERIALIZER_H_
243