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 ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_HELPER_H 17 #define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_HELPER_H 18 19 #include "ecmascript/compiler/circuit_builder.h" 20 21 namespace panda::ecmascript { 22 class JSRuntimeOptions; 23 } // namespace panda::ecmascript 24 25 namespace panda::ecmascript::kungfu { 26 27 class CompilationConfig { 28 public: 29 explicit CompilationConfig(const std::string &triple, const JSRuntimeOptions *options = nullptr); 30 ~CompilationConfig() = default; 31 Is32Bit() const32 inline bool Is32Bit() const 33 { 34 return triple_ == Triple::TRIPLE_ARM32; 35 } 36 IsAArch64() const37 inline bool IsAArch64() const 38 { 39 return triple_ == Triple::TRIPLE_AARCH64; 40 } 41 IsAmd64() const42 inline bool IsAmd64() const 43 { 44 return triple_ == Triple::TRIPLE_AMD64; 45 } 46 Is64Bit() const47 inline bool Is64Bit() const 48 { 49 return IsAArch64() || IsAmd64(); 50 } 51 GetTriple() const52 Triple GetTriple() const 53 { 54 return triple_; 55 } 56 GetTripleStr() const57 std::string GetTripleStr() const 58 { 59 return tripleStr_; 60 } 61 IsTraceBC() const62 bool IsTraceBC() const 63 { 64 return isTraceBc_; 65 } 66 IsProfiling() const67 bool IsProfiling() const 68 { 69 return profiling_; 70 } 71 IsStressDeopt() const72 bool IsStressDeopt() const 73 { 74 return stressDeopt_; 75 } 76 IsVerifyVTbale() const77 bool IsVerifyVTbale() const 78 { 79 return verifyVTable_; 80 } 81 IsTypedOpProfiling() const82 bool IsTypedOpProfiling() const 83 { 84 return typedOpProfiling_; 85 } 86 87 private: GetTripleFromString(const std::string &triple)88 inline Triple GetTripleFromString(const std::string &triple) 89 { 90 if (triple.compare(TARGET_X64) == 0) { 91 return Triple::TRIPLE_AMD64; 92 } 93 94 if (triple.compare(TARGET_AARCH64) == 0) { 95 return Triple::TRIPLE_AARCH64; 96 } 97 98 if (triple.compare(TARGET_ARM32) == 0) { 99 return Triple::TRIPLE_ARM32; 100 } 101 LOG_ECMA(FATAL) << "this branch is unreachable"; 102 UNREACHABLE(); 103 } 104 std::string tripleStr_; 105 Triple triple_; 106 bool isTraceBc_ {false}; 107 bool profiling_ {false}; 108 bool stressDeopt_ {false}; 109 bool verifyVTable_ {false}; 110 bool typedOpProfiling_ {false}; 111 }; 112 113 class Label { 114 public: 115 Label() = default; 116 explicit Label(Environment *env); 117 explicit Label(CircuitBuilder *cirBuilder); 118 ~Label() = default; 119 Label(Label const &label) = default; 120 Label &operator=(Label const &label) = default; 121 Label(Label &&label) = default; 122 Label &operator=(Label &&label) = default; Seal()123 inline void Seal() 124 { 125 return impl_->Seal(); 126 } WriteVariable(Variable *var, GateRef value)127 inline void WriteVariable(Variable *var, GateRef value) 128 { 129 impl_->WriteVariable(var, value); 130 } ReadVariable(Variable *var)131 inline GateRef ReadVariable(Variable *var) 132 { 133 return impl_->ReadVariable(var); 134 } Bind()135 inline void Bind() 136 { 137 impl_->Bind(); 138 } MergeAllControl()139 inline void MergeAllControl() 140 { 141 impl_->MergeAllControl(); 142 } MergeAllDepend()143 inline void MergeAllDepend() 144 { 145 impl_->MergeAllDepend(); 146 } AppendPredecessor(const Label *predecessor)147 inline void AppendPredecessor(const Label *predecessor) 148 { 149 impl_->AppendPredecessor(predecessor->GetRawLabel()); 150 } GetPredecessors() const151 inline std::vector<Label> GetPredecessors() const 152 { 153 std::vector<Label> labels; 154 for (auto rawlabel : impl_->GetPredecessors()) { 155 labels.emplace_back(Label(rawlabel)); 156 } 157 return labels; 158 } SetControl(GateRef control)159 inline void SetControl(GateRef control) 160 { 161 impl_->SetControl(control); 162 } SetPreControl(GateRef control)163 inline void SetPreControl(GateRef control) 164 { 165 impl_->SetPreControl(control); 166 } MergeControl(GateRef control)167 inline void MergeControl(GateRef control) 168 { 169 impl_->MergeControl(control); 170 } GetControl() const171 inline GateRef GetControl() const 172 { 173 return impl_->GetControl(); 174 } GetDepend() const175 inline GateRef GetDepend() const 176 { 177 return impl_->GetDepend(); 178 } SetDepend(GateRef depend)179 inline void SetDepend(GateRef depend) 180 { 181 return impl_->SetDepend(depend); 182 } 183 184 private: 185 class LabelImpl { 186 public: LabelImpl(Environment *env, GateRef control)187 LabelImpl(Environment *env, GateRef control) 188 : env_(env), control_(control), predeControl_(-1), isSealed_(false) 189 { 190 } 191 ~LabelImpl() = default; 192 NO_MOVE_SEMANTIC(LabelImpl); 193 NO_COPY_SEMANTIC(LabelImpl); 194 void Seal(); 195 void WriteVariable(Variable *var, GateRef value); 196 GateRef ReadVariable(Variable *var); 197 void Bind(); 198 void MergeAllControl(); 199 void MergeAllDepend(); 200 void AppendPredecessor(LabelImpl *predecessor); GetPredecessors() const201 std::vector<LabelImpl *> GetPredecessors() const 202 { 203 return predecessors_; 204 } SetControl(GateRef control)205 void SetControl(GateRef control) 206 { 207 control_ = control; 208 } SetPreControl(GateRef control)209 void SetPreControl(GateRef control) 210 { 211 predeControl_ = control; 212 } MergeControl(GateRef control)213 void MergeControl(GateRef control) 214 { 215 if (predeControl_ == Circuit::NullGate()) { 216 predeControl_ = control; 217 control_ = predeControl_; 218 } else { 219 otherPredeControls_.push_back(control); 220 } 221 } GetControl() const222 GateRef GetControl() const 223 { 224 return control_; 225 } SetDepend(GateRef depend)226 void SetDepend(GateRef depend) 227 { 228 depend_ = depend; 229 } GetDepend() const230 GateRef GetDepend() const 231 { 232 return depend_; 233 } 234 235 private: 236 bool IsNeedSeal() const; IsSealed() const237 bool IsSealed() const 238 { 239 return isSealed_; 240 } 241 bool IsLoopHead() const; 242 bool IsControlCase() const; 243 GateRef ReadVariableRecursive(Variable *var); 244 Environment *env_; 245 GateRef control_; 246 GateRef predeControl_ {Circuit::NullGate()}; 247 GateRef depend_ {Circuit::NullGate()}; 248 GateRef loopDepend_ {Circuit::NullGate()}; 249 std::vector<GateRef> otherPredeControls_; 250 bool isSealed_ {false}; 251 std::map<Variable *, GateRef> valueMap_; 252 std::vector<GateRef> phi; 253 std::vector<LabelImpl *> predecessors_; 254 std::map<Variable *, GateRef> incompletePhis_; 255 }; 256 Label(LabelImpl *impl)257 explicit Label(LabelImpl *impl) : impl_(impl) {} 258 friend class Environment; GetRawLabel() const259 LabelImpl *GetRawLabel() const 260 { 261 return impl_; 262 } 263 LabelImpl *impl_ {nullptr}; 264 }; 265 266 class Environment { 267 public: 268 using LabelImpl = Label::LabelImpl; 269 Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder); 270 Environment(GateRef stateEntry, GateRef dependEntry, const std::initializer_list<GateRef>& args, 271 Circuit *circuit, CircuitBuilder *builder); 272 Environment(size_t arguments, CircuitBuilder *builder); 273 ~Environment(); GetCurrentLabel() const274 Label *GetCurrentLabel() const 275 { 276 return currentLabel_; 277 } SetCurrentLabel(Label *label)278 void SetCurrentLabel(Label *label) 279 { 280 currentLabel_ = label; 281 } GetBuilder() const282 CircuitBuilder *GetBuilder() const 283 { 284 return circuitBuilder_; 285 } GetCircuit() const286 Circuit *GetCircuit() const 287 { 288 return circuit_; 289 } NextVariableId()290 int NextVariableId() 291 { 292 return nextVariableId_++; 293 } SetCompilationConfig(const CompilationConfig *cfg)294 void SetCompilationConfig(const CompilationConfig *cfg) 295 { 296 ccfg_ = cfg; 297 } GetCompilationConfig() const298 const CompilationConfig *GetCompilationConfig() const 299 { 300 return ccfg_; 301 } Is32Bit() const302 inline bool Is32Bit() const 303 { 304 return ccfg_->Is32Bit(); 305 } IsAArch64() const306 inline bool IsAArch64() const 307 { 308 return ccfg_->IsAArch64(); 309 } IsAmd64() const310 inline bool IsAmd64() const 311 { 312 return ccfg_->IsAmd64(); 313 } IsArch64Bit() const314 inline bool IsArch64Bit() const 315 { 316 return ccfg_->IsAmd64() || ccfg_->IsAArch64(); 317 } IsAsmInterp() const318 inline bool IsAsmInterp() const 319 { 320 return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME; 321 } IsBaselineBuiltin() const322 inline bool IsBaselineBuiltin() const 323 { 324 return circuit_->GetFrameType() == FrameType::BASELINE_BUILTIN_FRAME; 325 } IsArch32Bit() const326 inline bool IsArch32Bit() const 327 { 328 return ccfg_->Is32Bit(); 329 } GetArgument(size_t index) const330 inline GateRef GetArgument(size_t index) const 331 { 332 return arguments_.at(index); 333 } GetLabelFromSelector(GateRef sel)334 inline Label GetLabelFromSelector(GateRef sel) 335 { 336 Label::LabelImpl *rawlabel = phiToLabels_[sel]; 337 return Label(rawlabel); 338 } AddSelectorToLabel(GateRef sel, Label label)339 inline void AddSelectorToLabel(GateRef sel, Label label) 340 { 341 phiToLabels_[sel] = label.GetRawLabel(); 342 } NewLabel(Environment *env, GateRef control = -1)343 inline LabelImpl *NewLabel(Environment *env, GateRef control = -1) 344 { 345 auto impl = new Label::LabelImpl(env, control); 346 rawLabels_.emplace_back(impl); 347 return impl; 348 } SubCfgEntry(Label *entry)349 void SubCfgEntry(Label *entry) 350 { 351 if (currentLabel_ != nullptr) { 352 GateRef control = currentLabel_->GetControl(); 353 GateRef depend = currentLabel_->GetDepend(); 354 stack_.push(currentLabel_); 355 currentLabel_ = entry; 356 currentLabel_->SetControl(control); 357 currentLabel_->SetDepend(depend); 358 } 359 } SubCfgExit()360 void SubCfgExit() 361 { 362 if (currentLabel_ != nullptr) { 363 GateRef control = currentLabel_->GetControl(); 364 GateRef depend = currentLabel_->GetDepend(); 365 if (!stack_.empty()) { 366 currentLabel_ = stack_.top(); 367 currentLabel_->SetControl(control); 368 currentLabel_->SetDepend(depend); 369 stack_.pop(); 370 } 371 } 372 } GetInput(size_t index) const373 inline GateRef GetInput(size_t index) const 374 { 375 return inputList_.at(index); 376 } 377 378 private: 379 Label *currentLabel_ {nullptr}; 380 Circuit *circuit_ {nullptr}; 381 CircuitBuilder *circuitBuilder_ {nullptr}; 382 std::unordered_map<GateRef, LabelImpl *> phiToLabels_; 383 std::vector<GateRef> inputList_; 384 Label entry_; 385 std::vector<LabelImpl *> rawLabels_; 386 std::stack<Label *> stack_; 387 int nextVariableId_ {0}; 388 std::vector<GateRef> arguments_; 389 const CompilationConfig *ccfg_ {nullptr}; 390 }; 391 392 class Variable { 393 public: Variable(Environment *env, VariableType type, uint32_t id, GateRef value)394 Variable(Environment *env, VariableType type, uint32_t id, GateRef value) : id_(id), type_(type), env_(env) 395 { 396 Bind(value); 397 env_->GetCurrentLabel()->WriteVariable(this, value); 398 } Variable(CircuitBuilder *cirbuilder, VariableType type, uint32_t id, GateRef value)399 Variable(CircuitBuilder *cirbuilder, VariableType type, uint32_t id, GateRef value) 400 : id_(id), type_(type), env_(cirbuilder->GetCurrentEnvironment()) 401 { 402 Bind(value); 403 env_->GetCurrentLabel()->WriteVariable(this, value); 404 } 405 ~Variable() = default; 406 NO_MOVE_SEMANTIC(Variable); 407 NO_COPY_SEMANTIC(Variable); Bind(GateRef value)408 void Bind(GateRef value) 409 { 410 currentValue_ = value; 411 } Value() const412 GateRef Value() const 413 { 414 return currentValue_; 415 } Type() const416 VariableType Type() const 417 { 418 return type_; 419 } IsBound() const420 bool IsBound() const 421 { 422 return currentValue_ != 0; 423 } operator =(const GateRef value)424 Variable &operator=(const GateRef value) 425 { 426 env_->GetCurrentLabel()->WriteVariable(this, value); 427 Bind(value); 428 return *this; 429 } operator *()430 GateRef operator*() 431 { 432 return env_->GetCurrentLabel()->ReadVariable(this); 433 } ReadVariable()434 GateRef ReadVariable() 435 { 436 return env_->GetCurrentLabel()->ReadVariable(this); 437 } WriteVariable(GateRef value)438 void WriteVariable(GateRef value) 439 { 440 env_->GetCurrentLabel()->WriteVariable(this, value); 441 Bind(value); 442 } 443 GateRef AddPhiOperand(GateRef val); 444 GateRef AddOperandToSelector(GateRef val, size_t idx, GateRef in); 445 GateRef TryRemoveTrivialPhi(GateRef phi); GetId() const446 uint32_t GetId() const 447 { 448 return id_; 449 } 450 451 private: GetCircuit() const452 Circuit* GetCircuit() const 453 { 454 return env_->GetCircuit(); 455 } 456 457 uint32_t id_; 458 VariableType type_; 459 GateRef currentValue_ {0}; 460 Environment *env_; 461 }; 462 463 } 464 465 #endif // ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H 466