1 /* 2 * Copyright (c) 2021-2024 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 "ets_typeapi_create_panda_constants.h" 22 23 namespace ark { 24 template <typename T> 25 class VMHandle; 26 } // namespace ark 27 28 namespace ark::coretypes { 29 class Array; 30 } // namespace ark::coretypes 31 32 namespace ark::ets { 33 class EtsCoroutine; 34 class EtsArray; 35 } // namespace ark::ets 36 37 namespace ark::ets { 38 class TypeCreatorCtx { 39 public: Program()40 pandasm::Program &Program() 41 { 42 return prog_; 43 } 44 45 template <typename T, typename... A> Alloc(A &&...a)46 T *Alloc(A &&...a) 47 { 48 auto p = std::make_shared<T>(std::forward<A>(a)...); 49 auto ret = p.get(); 50 datas_.push_back(std::move(p)); 51 return ret; 52 } 53 54 /** 55 * Adds field with permanent data used in TypeAPI$CtxData$_ 56 * also adds intializer into TypeAPI$CtxData$_.cctor that loads that id 57 * from 58 * @param id index of filed in init array 59 * @param type type of that field 60 * @returns field id that can be passed into pandasm instructions to access it 61 */ 62 std::string AddInitField(uint32_t id, const pandasm::Type &type); 63 64 /** 65 * Adds TypeAPI$CtxData$_ to program if it was used 66 * also emplaces necessary cctors 67 */ 68 void FlushTypeAPICtxDataRecordsToProgram(); 69 70 /** 71 * Saves objects into current context to provide them to TypeAPI$CtxData$_.cctor 72 * @param objects must live until end of call to `InitializeCtxDataRecord` and may be changed inside this function 73 */ 74 void SaveObjects(EtsCoroutine *coro, VMHandle<EtsArray> &objects); 75 76 EtsArray *GetObjects(EtsCoroutine *coro); 77 78 /// Initializes TypeAPI$CtxData$_ 79 void InitializeCtxDataRecord(EtsCoroutine *coro); 80 81 /** 82 * Creates TypeAPI$CtxData record if it wasn't created before 83 * @returns TypeAPI$CtxData record 84 */ 85 pandasm::Record &GetTypeAPICtxDataRecord(); 86 87 pandasm::Record &AddRefTypeAsExternal(const std::string &name); 88 89 /** 90 * Lazily declares primitive reference wrapper 91 * @returns pair of constructor and unwrapper 92 */ 93 const std::pair<std::string, std::string> &DeclarePrimitive(const std::string &primTypeName); 94 AddError(std::string_view err)95 void AddError(std::string_view err) 96 { 97 error_ += err; 98 } 99 GetError()100 std::optional<std::string_view> GetError() const 101 { 102 if (error_.empty()) { 103 return std::nullopt; 104 } 105 return error_; 106 } 107 108 private: 109 pandasm::Program prog_; 110 pandasm::Record ctxDataRecord_ {"", panda_file::SourceLang::ETS}; 111 std::string ctxDataRecordName_ {}; 112 pandasm::Function ctxDataRecordCctor_ {"", panda_file::SourceLang::ETS}; 113 std::map<std::string, std::pair<std::string, std::string>> primitiveTypesCtorDtor_; 114 std::vector<std::shared_ptr<void>> datas_; 115 std::string error_; 116 117 coretypes::Array *initArrObject_ {}; 118 }; 119 120 enum class TypeCreatorKind { 121 CLASS, 122 INTERFACE, 123 LAMBDA_TYPE, 124 }; 125 126 class TypeCreator { 127 public: 128 virtual TypeCreatorKind GetKind() const = 0; 129 virtual pandasm::Type GetType() const = 0; 130 TypeCreator(TypeCreatorCtx * ctx)131 explicit TypeCreator(TypeCreatorCtx *ctx) : ctx_(ctx) {} 132 GetCtx()133 TypeCreatorCtx *GetCtx() const 134 { 135 return ctx_; 136 } 137 138 private: 139 TypeCreatorCtx *ctx_; 140 }; 141 142 class ClassCreator final : public TypeCreator { 143 public: ClassCreator(pandasm::Record * rec,TypeCreatorCtx * ctx)144 explicit ClassCreator(pandasm::Record *rec, TypeCreatorCtx *ctx) : TypeCreator(ctx), rec_(rec) {} 145 GetKind()146 TypeCreatorKind GetKind() const override 147 { 148 return TypeCreatorKind::CLASS; 149 } 150 GetType()151 pandasm::Type GetType() const override 152 { 153 return pandasm::Type {rec_->name, 0, true}; 154 } 155 GetRec()156 pandasm::Record *GetRec() const 157 { 158 return rec_; 159 } 160 161 private: 162 pandasm::Record *rec_; 163 }; 164 165 class InterfaceCreator final : public TypeCreator { 166 public: InterfaceCreator(pandasm::Record * rec,TypeCreatorCtx * ctx)167 explicit InterfaceCreator(pandasm::Record *rec, TypeCreatorCtx *ctx) : TypeCreator(ctx), rec_(rec) {} 168 GetKind()169 TypeCreatorKind GetKind() const override 170 { 171 return TypeCreatorKind::INTERFACE; 172 } 173 GetType()174 pandasm::Type GetType() const override 175 { 176 return pandasm::Type {rec_->name, 0, true}; 177 } 178 GetRec()179 pandasm::Record *GetRec() const 180 { 181 return rec_; 182 } 183 184 private: 185 pandasm::Record *rec_; 186 }; 187 188 class LambdaTypeCreator final : public TypeCreator { 189 public: LambdaTypeCreator(TypeCreatorCtx * ctx)190 explicit LambdaTypeCreator(TypeCreatorCtx *ctx) : TypeCreator(ctx) 191 { 192 for (const auto &attr : typeapi_create_consts::ATTR_INTERFACE) { 193 rec_.metadata->SetAttribute(attr); 194 } 195 rec_.metadata->SetAttributeValue(typeapi_create_consts::ATTR_ACCESS, 196 typeapi_create_consts::ATTR_ACCESS_VAL_PUBLIC); 197 } 198 GetKind()199 TypeCreatorKind GetKind() const override 200 { 201 return TypeCreatorKind::LAMBDA_TYPE; 202 } 203 GetType()204 pandasm::Type GetType() const override 205 { 206 ASSERT(finished_); 207 return pandasm::Type {name_, 0}; 208 } 209 GetFunctionName()210 const std::string &GetFunctionName() const 211 { 212 ASSERT(finished_); 213 return fnName_; 214 } 215 216 void AddParameter(pandasm::Type param); 217 218 void AddResult(const pandasm::Type &type); 219 220 void Create(); 221 222 private: 223 std::string name_ = "std.core.Function"; 224 std::string fnName_ = "invoke0"; 225 pandasm::Record rec_ {name_, SourceLanguage::ETS}; 226 pandasm::Function fn_ {fnName_, SourceLanguage::ETS}; 227 bool finished_ = false; 228 }; 229 230 class PandasmMethodCreator { 231 public: PandasmMethodCreator(std::string name,TypeCreatorCtx * ctx)232 PandasmMethodCreator(std::string name, TypeCreatorCtx *ctx) 233 : ctx_(ctx), name_(name), fn_(std::move(name), SourceLanguage::ETS) 234 { 235 } 236 237 void AddParameter(pandasm::Type param); 238 239 void AddResult(pandasm::Type type); 240 241 void Create(); 242 GetFunctionName()243 const std::string &GetFunctionName() const 244 { 245 ASSERT(finished_); 246 return name_; 247 } 248 GetFn()249 pandasm::Function &GetFn() 250 { 251 ASSERT(!finished_); 252 return fn_; 253 } 254 Ctx()255 TypeCreatorCtx *Ctx() const 256 { 257 return ctx_; 258 } 259 260 private: 261 TypeCreatorCtx *ctx_; 262 std::string name_; 263 pandasm::Function fn_; 264 bool finished_ = false; 265 }; 266 267 } // namespace ark::ets 268 269 #endif // PANDA_PLUGINS_ETS_TYPEAPI_CREATE_H 270