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