1 /* 2 * Copyright (c) 2021-2022 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 panda { 24 template <typename T> 25 class VMHandle; 26 } // namespace panda 27 28 namespace panda::coretypes { 29 class Array; 30 } // namespace panda::coretypes 31 32 namespace panda::ets { 33 class EtsCoroutine; 34 class EtsArray; 35 } // namespace panda::ets 36 37 namespace panda::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 std::string GetRefVoidInstanceName(); 90 91 /** 92 * Lazily declares primitive reference wrapper 93 * @returns pair of constructor and unwrapper 94 */ 95 const std::pair<std::string, std::string> &DeclarePrimitive(const std::string &primTypeName); 96 AddError(std::string_view err)97 void AddError(std::string_view err) 98 { 99 error_ += err; 100 } 101 GetError()102 std::optional<std::string_view> GetError() const 103 { 104 if (error_.empty()) { 105 return std::nullopt; 106 } 107 return error_; 108 } 109 110 private: 111 pandasm::Program prog_; 112 pandasm::Record ctxDataRecord_ {"", panda_file::SourceLang::ETS}; 113 std::string ctxDataRecordName_ {}; 114 pandasm::Function ctxDataRecordCctor_ {"", panda_file::SourceLang::ETS}; 115 std::map<std::string, std::pair<std::string, std::string>> primitiveTypesCtorDtor_; 116 std::vector<std::shared_ptr<void>> datas_; 117 std::string error_; 118 119 coretypes::Array *initArrObject_ {}; 120 }; 121 122 enum class TypeCreatorKind { 123 CLASS, 124 INTERFACE, 125 LAMBDA_TYPE, 126 }; 127 128 class TypeCreator { 129 public: 130 virtual TypeCreatorKind GetKind() const = 0; 131 virtual pandasm::Type GetType() const = 0; 132 TypeCreator(TypeCreatorCtx * ctx)133 explicit TypeCreator(TypeCreatorCtx *ctx) : ctx_(ctx) {} 134 GetCtx()135 TypeCreatorCtx *GetCtx() const 136 { 137 return ctx_; 138 } 139 140 private: 141 TypeCreatorCtx *ctx_; 142 }; 143 144 class ClassCreator final : public TypeCreator { 145 public: ClassCreator(pandasm::Record * rec,TypeCreatorCtx * ctx)146 explicit ClassCreator(pandasm::Record *rec, TypeCreatorCtx *ctx) : TypeCreator(ctx), rec_(rec) {} 147 GetKind()148 TypeCreatorKind GetKind() const override 149 { 150 return TypeCreatorKind::CLASS; 151 } 152 GetType()153 pandasm::Type GetType() const override 154 { 155 return pandasm::Type {rec_->name, 0, true}; 156 } 157 GetRec()158 pandasm::Record *GetRec() const 159 { 160 return rec_; 161 } 162 163 private: 164 pandasm::Record *rec_; 165 }; 166 167 class InterfaceCreator final : public TypeCreator { 168 public: InterfaceCreator(pandasm::Record * rec,TypeCreatorCtx * ctx)169 explicit InterfaceCreator(pandasm::Record *rec, TypeCreatorCtx *ctx) : TypeCreator(ctx), rec_(rec) {} 170 GetKind()171 TypeCreatorKind GetKind() const override 172 { 173 return TypeCreatorKind::INTERFACE; 174 } 175 GetType()176 pandasm::Type GetType() const override 177 { 178 return pandasm::Type {rec_->name, 0, true}; 179 } 180 GetRec()181 pandasm::Record *GetRec() const 182 { 183 return rec_; 184 } 185 186 private: 187 pandasm::Record *rec_; 188 }; 189 190 class LambdaTypeCreator final : public TypeCreator { 191 public: LambdaTypeCreator(TypeCreatorCtx * ctx)192 explicit LambdaTypeCreator(TypeCreatorCtx *ctx) : TypeCreator(ctx) 193 { 194 for (const auto &attr : typeapi_create_consts::ATTR_INTERFACE) { 195 rec_.metadata->SetAttribute(attr); 196 } 197 rec_.metadata->SetAttributeValue(typeapi_create_consts::ATTR_ACCESS, 198 typeapi_create_consts::ATTR_ACCESS_VAL_PUBLIC); 199 } 200 GetKind()201 TypeCreatorKind GetKind() const override 202 { 203 return TypeCreatorKind::LAMBDA_TYPE; 204 } 205 GetType()206 pandasm::Type GetType() const override 207 { 208 ASSERT(finished_); 209 return pandasm::Type {name_, 0}; 210 } 211 GetFunctionName()212 const std::string &GetFunctionName() const 213 { 214 ASSERT(finished_); 215 return fnName_; 216 } 217 218 void AddParameter(pandasm::Type param); 219 220 void AddResult(const pandasm::Type &type); 221 222 void Create(); 223 224 private: 225 std::string name_ = "FunctionalInterface"; 226 std::string fnName_ = "invoke"; 227 pandasm::Record rec_ {name_, SourceLanguage::ETS}; 228 pandasm::Function fn_ {fnName_, SourceLanguage::ETS}; 229 bool finished_ = false; 230 }; 231 232 class PandasmMethodCreator { 233 public: PandasmMethodCreator(std::string name,TypeCreatorCtx * ctx)234 PandasmMethodCreator(std::string name, TypeCreatorCtx *ctx) 235 : ctx_(ctx), name_(name), fn_(std::move(name), SourceLanguage::ETS) 236 { 237 } 238 239 void AddParameter(pandasm::Type param); 240 241 void AddResult(pandasm::Type type); 242 243 void Create(); 244 GetFunctionName()245 const std::string &GetFunctionName() const 246 { 247 ASSERT(finished_); 248 return name_; 249 } 250 GetFn()251 pandasm::Function &GetFn() 252 { 253 ASSERT(!finished_); 254 return fn_; 255 } 256 Ctx()257 TypeCreatorCtx *Ctx() const 258 { 259 return ctx_; 260 } 261 262 private: 263 TypeCreatorCtx *ctx_; 264 std::string name_; 265 pandasm::Function fn_; 266 bool finished_ = false; 267 }; 268 269 } // namespace panda::ets 270 271 #endif // PANDA_PLUGINS_ETS_TYPEAPI_CREATE_H 272