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