• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_PLUGINS_ETS_TYPEAPI_CREATE_H
17 #define PANDA_PLUGINS_ETS_TYPEAPI_CREATE_H
18 
19 #include "assembly-function.h"
20 #include "assembly-program.h"
21 #include "class_linker_context.h"
22 #include "ets_typeapi_create_panda_constants.h"
23 #include "types/ets_type.h"
24 
25 namespace ark {
26 template <typename T>
27 class VMHandle;
28 }  // namespace ark
29 
30 namespace ark::coretypes {
31 class Array;
32 }  // namespace ark::coretypes
33 
34 namespace ark::ets {
35 class EtsCoroutine;
36 class EtsArray;
37 }  // namespace ark::ets
38 
39 namespace ark::ets {
40 class TypeCreatorCtx {
41 public:
Program()42     pandasm::Program &Program()
43     {
44         return prog_;
45     }
46 
47     template <typename T, typename... A>
Alloc(A &&...a)48     T *Alloc(A &&...a)
49     {
50         auto p = std::make_shared<T>(std::forward<A>(a)...);
51         auto ret = p.get();
52         datas_.push_back(std::move(p));
53         return ret;
54     }
55 
56     /**
57      * Adds field with permanent data used in TypeAPI$CtxData$_
58      * also adds intializer into TypeAPI$CtxData$_.cctor that loads that id
59      * from
60      * @param id index of filed in init array
61      * @param type type of that field
62      * @returns field id that can be passed into pandasm instructions to access it
63      */
64     std::string AddInitField(uint32_t id, const pandasm::Type &type);
65 
66     /**
67      * Adds TypeAPI$CtxData$_ to program if it was used
68      * also emplaces necessary cctors
69      */
70     void FlushTypeAPICtxDataRecordsToProgram();
71 
72     /**
73      * Saves objects into current context to provide them to TypeAPI$CtxData$_.cctor
74      * @param objects must live until end of call to `InitializeCtxDataRecord` and may be changed inside this function
75      */
76     void SaveObjects(EtsCoroutine *coro, VMHandle<EtsArray> &objects, ClassLinkerContext *ctx);
77 
78     EtsArray *GetObjects(EtsCoroutine *coro);
79 
80     /// Initializes TypeAPI$CtxData$_
81     [[nodiscard]] bool InitializeCtxDataRecord(EtsCoroutine *coro, ClassLinkerContext *ctx, const panda_file::File *pf);
82 
83     /**
84      * Creates TypeAPI$CtxData record if it wasn't created before
85      * @returns TypeAPI$CtxData record
86      */
87     pandasm::Record &GetTypeAPICtxDataRecord();
88 
89     pandasm::Record &AddRefTypeAsExternal(const std::string &name);
90 
91     std::pair<pandasm::Record &, bool> AddPandasmRecord(pandasm::Record &&record);
92 
93     /**
94      * Lazily declares primitive reference wrapper
95      * @returns pair of constructor and unwrapper
96      */
97     const std::pair<std::string, std::string> &DeclarePrimitive(const std::string &primTypeName);
98 
AddError(std::string_view err)99     void AddError(std::string_view err)
100     {
101         error_ += err;
102     }
103 
GetError()104     std::optional<std::string_view> GetError() const
105     {
106         if (error_.empty()) {
107             return std::nullopt;
108         }
109         return error_;
110     }
111 
112 private:
113     void LoadCreatedClasses(ClassLinkerContext *ctx, const panda_file::File *pf);
114 
115 private:
116     pandasm::Program prog_;
117     pandasm::Record ctxDataRecord_ {"", panda_file::SourceLang::ETS};
118     std::string ctxDataRecordName_ {};
119     pandasm::Function ctxDataRecordCctor_ {"", panda_file::SourceLang::ETS};
120     std::map<std::string, std::pair<std::string, std::string>> primitiveTypesCtorDtor_;
121     std::vector<std::shared_ptr<void>> datas_;
122     std::string error_;
123     std::vector<std::string> createdRecords_;
124 
125     coretypes::Array *initArrObject_ {};
126 };
127 
128 enum class TypeCreatorKind {
129     CLASS,
130     INTERFACE,
131     LAMBDA_TYPE,
132 };
133 
134 class TypeCreator {
135 public:
136     virtual TypeCreatorKind GetKind() const = 0;
137     virtual pandasm::Type GetType() const = 0;
138 
TypeCreator(TypeCreatorCtx * ctx)139     explicit TypeCreator(TypeCreatorCtx *ctx) : ctx_(ctx) {}
140 
GetCtx()141     TypeCreatorCtx *GetCtx() const
142     {
143         return ctx_;
144     }
145 
146 private:
147     TypeCreatorCtx *ctx_;
148 };
149 
150 class ClassCreator final : public TypeCreator {
151 public:
ClassCreator(pandasm::Record * rec,TypeCreatorCtx * ctx)152     explicit ClassCreator(pandasm::Record *rec, TypeCreatorCtx *ctx) : TypeCreator(ctx), rec_(rec) {}
153 
GetKind()154     TypeCreatorKind GetKind() const override
155     {
156         return TypeCreatorKind::CLASS;
157     }
158 
GetType()159     pandasm::Type GetType() const override
160     {
161         return pandasm::Type {rec_->name, 0, true};
162     }
163 
GetRec()164     pandasm::Record *GetRec() const
165     {
166         return rec_;
167     }
168 
169 private:
170     pandasm::Record *rec_;
171 };
172 
173 class InterfaceCreator final : public TypeCreator {
174 public:
InterfaceCreator(pandasm::Record * rec,TypeCreatorCtx * ctx)175     explicit InterfaceCreator(pandasm::Record *rec, TypeCreatorCtx *ctx) : TypeCreator(ctx), rec_(rec) {}
176 
GetKind()177     TypeCreatorKind GetKind() const override
178     {
179         return TypeCreatorKind::INTERFACE;
180     }
181 
GetType()182     pandasm::Type GetType() const override
183     {
184         return pandasm::Type {rec_->name, 0, true};
185     }
186 
GetRec()187     pandasm::Record *GetRec() const
188     {
189         return rec_;
190     }
191 
192 private:
193     pandasm::Record *rec_;
194 };
195 
196 class LambdaTypeCreator final : public TypeCreator {
197 public:
LambdaTypeCreator(TypeCreatorCtx * ctx)198     explicit LambdaTypeCreator(TypeCreatorCtx *ctx) : TypeCreator(ctx)
199     {
200         for (const auto &attr : typeapi_create_consts::ATTR_INTERFACE) {
201             rec_.metadata->SetAttribute(attr);
202         }
203         rec_.metadata->SetAttributeValue(typeapi_create_consts::ATTR_ACCESS,
204                                          typeapi_create_consts::ATTR_ACCESS_VAL_PUBLIC);
205     }
206 
GetKind()207     TypeCreatorKind GetKind() const override
208     {
209         return TypeCreatorKind::LAMBDA_TYPE;
210     }
211 
GetType()212     pandasm::Type GetType() const override
213     {
214         ASSERT(finished_);
215         return pandasm::Type {name_, 0};
216     }
217 
GetFunctionName()218     const std::string &GetFunctionName() const
219     {
220         ASSERT(finished_);
221         return fnName_;
222     }
223 
224     void AddParameter(pandasm::Type param);
225 
226     void AddResult(const pandasm::Type &type);
227 
228     void Create();
229 
230 private:
231     std::string name_ = STD_CORE_FUNCTION_PREFIX;
232     std::string fnName_ = STD_CORE_FUNCTION_INVOKE_PREFIX;
233     pandasm::Record rec_ {name_, SourceLanguage::ETS};
234     pandasm::Function fn_ {fnName_, SourceLanguage::ETS};
235     bool finished_ = false;
236 };
237 
238 class PandasmMethodCreator {
239 public:
PandasmMethodCreator(std::string name,TypeCreatorCtx * ctx)240     PandasmMethodCreator(std::string name, TypeCreatorCtx *ctx)
241         : ctx_(ctx), name_(name), fn_(std::move(name), SourceLanguage::ETS)
242     {
243     }
244 
245     void AddParameter(pandasm::Type param);
246 
247     void AddResult(pandasm::Type type);
248 
249     void Create();
250 
GetFunctionName()251     const std::string &GetFunctionName() const
252     {
253         ASSERT(finished_);
254         return name_;
255     }
256 
GetFn()257     pandasm::Function &GetFn()
258     {
259         ASSERT(!finished_);
260         return fn_;
261     }
262 
Ctx()263     TypeCreatorCtx *Ctx() const
264     {
265         return ctx_;
266     }
267 
268 private:
269     TypeCreatorCtx *ctx_;
270     std::string name_;
271     pandasm::Function fn_;
272     bool finished_ = false;
273 };
274 
275 }  // namespace ark::ets
276 
277 #endif  // PANDA_PLUGINS_ETS_TYPEAPI_CREATE_H
278