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 ES2PANDA_COMPILER_CORE_PANDAGEN_H 17 #define ES2PANDA_COMPILER_CORE_PANDAGEN_H 18 19 #include <compiler/base/optionalChain.h> 20 #include <compiler/core/envScope.h> 21 #include <compiler/core/inlineCache.h> 22 #include <compiler/core/regAllocator.h> 23 #include <compiler/core/regScope.h> 24 #include <ir/irnode.h> 25 #include <lexer/token/tokenType.h> 26 #include <libpandafile/file_items.h> 27 #include <macros.h> 28 29 #include <regex> 30 31 namespace panda::es2panda::binder { 32 class FunctionScope; 33 class ModuleVaribale; 34 class ScopeFindResult; 35 class Scope; 36 } // namespace panda::es2panda::binder 37 38 namespace panda::es2panda::ir { 39 class AstNode; 40 class ScriptFunction; 41 class Statement; 42 class Expression; 43 class Identifier; 44 } // namespace panda::es2panda::ir 45 46 namespace panda::es2panda::compiler { 47 48 class FunctionBuilder; 49 class CompilerContext; 50 class LiteralBuffer; 51 class DynamicContext; 52 class CatchTable; 53 54 enum class Constant { 55 JS_NAN, 56 JS_HOLE, 57 JS_INFINITY, 58 JS_UNDEFINED, 59 JS_NULL, 60 JS_TRUE, 61 JS_FALSE, 62 JS_SYMBOL, 63 JS_GLOBAL, 64 }; 65 66 class DebugInfo { 67 public: DebugInfo(ArenaAllocator * allocator)68 explicit DebugInfo(ArenaAllocator *allocator) : variableDebugInfo(allocator->Adapter()) {}; 69 DEFAULT_COPY_SEMANTIC(DebugInfo); 70 DEFAULT_MOVE_SEMANTIC(DebugInfo); 71 ~DebugInfo() = default; 72 73 ArenaVector<const binder::Scope *> variableDebugInfo; 74 const ir::Statement *firstStmt {}; 75 }; 76 77 class PandaGen { 78 public: PandaGen(ArenaAllocator * allocator,CompilerContext * context,binder::FunctionScope * scope)79 explicit PandaGen(ArenaAllocator *allocator, CompilerContext *context, binder::FunctionScope *scope) 80 : allocator_(allocator), 81 context_(context), 82 builder_(nullptr), 83 debugInfo_(allocator_), 84 topScope_(scope), 85 scope_(topScope_), 86 rootNode_(scope->Node()), 87 insns_(allocator_->Adapter()), 88 typedInsns_(allocator_->Adapter()), 89 typedVars_(allocator_->Adapter()), 90 catchList_(allocator_->Adapter()), 91 strings_(allocator_->Adapter()), 92 buffStorage_(allocator_->Adapter()), 93 ra_(this) 94 { 95 } 96 ~PandaGen() = default; 97 NO_COPY_SEMANTIC(PandaGen); 98 NO_MOVE_SEMANTIC(PandaGen); 99 Allocator()100 inline ArenaAllocator *Allocator() const 101 { 102 return allocator_; 103 } 104 Context()105 inline CompilerContext *Context() const 106 { 107 return context_; 108 } 109 Strings()110 const ArenaSet<util::StringView> &Strings() const 111 { 112 return strings_; 113 } 114 CatchList()115 const ArenaVector<CatchTable *> &CatchList() const 116 { 117 return catchList_; 118 } 119 TopScope()120 binder::FunctionScope *TopScope() const 121 { 122 return topScope_; 123 } 124 Scope()125 binder::Scope *Scope() const 126 { 127 return scope_; 128 } 129 RootNode()130 const ir::AstNode *RootNode() const 131 { 132 return rootNode_; 133 } 134 Insns()135 ArenaList<IRNode *> &Insns() 136 { 137 return insns_; 138 } 139 Insns()140 const ArenaList<IRNode *> &Insns() const 141 { 142 return insns_; 143 } 144 SetInsns(ArenaList<IRNode * > & newInsns)145 void SetInsns(ArenaList<IRNode *> &newInsns) 146 { 147 insns_.assign(newInsns.begin(), newInsns.end()); 148 } 149 TypedInsns()150 ArenaMap<const IRNode *, int64_t> &TypedInsns() 151 { 152 return typedInsns_; 153 } 154 TypedInsns()155 const ArenaMap<const IRNode *, int64_t> &TypedInsns() const 156 { 157 return typedInsns_; 158 } 159 TypedVars()160 ArenaUnorderedSet<const binder::LocalVariable *> &TypedVars() 161 { 162 return typedVars_; 163 } 164 TypedVars()165 const ArenaUnorderedSet<const binder::LocalVariable *> &TypedVars() const 166 { 167 return typedVars_; 168 } 169 TypedFunc()170 std::pair<int64_t, int64_t> &TypedFunc() 171 { 172 return typedFunc_; 173 } 174 TypedFunc()175 const std::pair<int64_t, int64_t> &TypedFunc() const 176 { 177 return typedFunc_; 178 } 179 AllocReg()180 VReg AllocReg() 181 { 182 if (usedRegs_ > UINT16_MAX) { 183 throw Error(ErrorType::GENERIC, "Can't alloc new reg because all regs ran out"); 184 } 185 return usedRegs_++; 186 } 187 NextReg()188 VReg NextReg() const 189 { 190 return usedRegs_; 191 } 192 TotalRegsNum()193 uint32_t TotalRegsNum() const 194 { 195 return totalRegs_; 196 } 197 LabelCount()198 size_t LabelCount() const 199 { 200 return labelId_; 201 } 202 Debuginfo()203 const DebugInfo &Debuginfo() const 204 { 205 return debugInfo_; 206 } 207 FuncBuilder()208 FunctionBuilder *FuncBuilder() const 209 { 210 return builder_; 211 } 212 GetEnvScope()213 EnvScope *GetEnvScope() const 214 { 215 return envScope_; 216 } 217 BuffStorage()218 const ArenaVector<compiler::LiteralBuffer *> &BuffStorage() const 219 { 220 return buffStorage_; 221 } 222 GetOptionalChain()223 OptionalChain *GetOptionalChain() const 224 { 225 return optionalChain_; 226 } 227 IcSize()228 uint32_t IcSize() const 229 { 230 return ic_.Size(); 231 } 232 SetSourceLocationFlag(lexer::SourceLocationFlag flag)233 void SetSourceLocationFlag(lexer::SourceLocationFlag flag) 234 { 235 ra_.SetSourceLocationFlag(flag); 236 } 237 AdjustSpillInsns()238 void AdjustSpillInsns() 239 { 240 ra_.AdjustInsRegWhenHasSpill(); 241 totalRegs_ += ra_.GetSpillRegsCount(); 242 } 243 GetFunctionKind()244 panda::panda_file::FunctionKind GetFunctionKind() const 245 { 246 return funcKind_; 247 } 248 IsConcurrent()249 bool IsConcurrent() const 250 { 251 return funcKind_ == panda::panda_file::FunctionKind::CONCURRENT_FUNCTION; 252 } 253 254 void SetFunctionKind(); 255 256 bool IsDebug() const; 257 bool isDebuggerEvaluateExpressionMode() const; 258 std::string SourceFile() const; 259 uint32_t ParamCount() const; 260 uint32_t FormalParametersCount() const; 261 uint32_t InternalParamCount() const; 262 const util::StringView &InternalName() const; 263 const util::StringView &FunctionName() const; 264 binder::Binder *Binder() const; 265 266 Label *AllocLabel(); 267 268 bool FunctionHasFinalizer() const; 269 bool IsAsyncFunction() const; 270 void FunctionInit(CatchTable* catchTable); 271 void FunctionEnter(); 272 void FunctionExit(); 273 274 LiteralBuffer *NewLiteralBuffer(); 275 int32_t AddLiteralBuffer(LiteralBuffer *buf); 276 int32_t AddLexicalVarNamesForDebugInfo(ArenaMap<uint32_t, std::pair<util::StringView, int>> &lexicalVars); 277 278 void InitializeLexEnv(const ir::AstNode *node); 279 void CopyFunctionArguments(const ir::AstNode *node); 280 void GetFunctionObject(const ir::AstNode *node); 281 void GetNewTarget(const ir::AstNode *node); 282 void GetThis(const ir::AstNode *node); 283 void SetThis(const ir::AstNode *node); 284 void LoadVar(const ir::Identifier *node, const binder::ScopeFindResult &result); 285 void StoreVar(const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDeclaration); 286 287 void StLetOrClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name); 288 void StConstToGlobalRecord(const ir::AstNode *node, const util::StringView &name); 289 290 void StoreAccumulator(const ir::AstNode *node, VReg vreg); 291 void StoreAccumulatorWithType(const ir::AstNode *node, int64_t typeIndex, VReg vreg); 292 void LoadAccFromArgs(const ir::AstNode *node); 293 void LoadObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop); 294 295 void LoadObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop); 296 297 void StoreObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop); 298 void StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop, bool nameSetting = false); 299 void DeleteObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop); 300 void LoadAccumulator(const ir::AstNode *node, VReg reg); 301 void LoadGlobalVar(const ir::AstNode *node, const util::StringView &name); 302 void StoreGlobalVar(const ir::AstNode *node, const util::StringView &name); 303 304 void TryLoadGlobalByValue(const ir::AstNode *node, VReg key); 305 void TryStoreGlobalByValue(const ir::AstNode *node, VReg key); 306 void LoadObjByNameViaDebugger(const ir::AstNode *node, const util::StringView &name, bool throwUndefinedIfHole); 307 void TryLoadGlobalByName(const ir::AstNode *node, const util::StringView &name); 308 void StoreObjByNameViaDebugger(const ir::AstNode *node, const util::StringView &name); 309 void TryStoreGlobalByName(const ir::AstNode *node, const util::StringView &name); 310 311 void LoadAccFromLexEnv(const ir::AstNode *node, const binder::ScopeFindResult &result); 312 void StoreAccToLexEnv(const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDeclaration); 313 314 void LoadAccumulatorString(const ir::AstNode *node, const util::StringView &str); 315 void LoadAccumulatorFloat(const ir::AstNode *node, double num); 316 void LoadAccumulatorInt(const ir::AstNode *node, int32_t num); 317 void LoadAccumulatorInt(const ir::AstNode *node, size_t num); 318 void LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &num); 319 320 void LoadConst(const ir::AstNode *node, Constant id); 321 void StoreConst(const ir::AstNode *node, VReg reg, Constant id); 322 void MoveVreg(const ir::AstNode *node, VReg vd, VReg vs); 323 324 void SetLabel(const ir::AstNode *node, Label *label); 325 void Branch(const ir::AstNode *node, class Label *label); 326 bool CheckControlFlowChange() const; 327 Label *ControlFlowChangeBreak(const ir::Identifier *label = nullptr); 328 Label *ControlFlowChangeContinue(const ir::Identifier *label); 329 void ControlFlowChangeReturn(); 330 331 void Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, class Label *ifFalse); 332 void Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand); 333 void Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs); 334 void Equal(const ir::AstNode *node, VReg lhs); 335 void NotEqual(const ir::AstNode *node, VReg lhs); 336 void StrictEqual(const ir::AstNode *node, VReg lhs); 337 void StrictNotEqual(const ir::AstNode *node, VReg lhs); 338 void LessThan(const ir::AstNode *node, VReg lhs); 339 void LessEqual(const ir::AstNode *node, VReg lhs); 340 void GreaterThan(const ir::AstNode *node, VReg lhs); 341 void GreaterEqual(const ir::AstNode *node, VReg lhs); 342 void IsTrue(const ir::AstNode *node); 343 344 void BranchIfUndefined(const ir::AstNode *node, class Label *target); 345 void BranchIfStrictUndefined(const ir::AstNode *node, class Label *target); 346 void BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target); 347 void BranchIfNotUndefined(const ir::AstNode *node, class Label *target); 348 void BranchIfHole(const ir::AstNode *node, class Label *target); 349 void BranchIfTrue(const ir::AstNode *node, class Label *target); 350 void BranchIfNotTrue(const ir::AstNode *node, class Label *target); 351 void BranchIfFalse(const ir::AstNode *node, class Label *target); 352 void BranchIfNotFalse(const ir::AstNode *node, class Label *target); 353 void BranchIfStrictNull(const ir::AstNode *node, class Label *target); 354 355 void EmitThrow(const ir::AstNode *node); 356 void EmitRethrow(const ir::AstNode *node); 357 void EmitReturn(const ir::AstNode *node); 358 void EmitReturnUndefined(const ir::AstNode *node); 359 void ValidateClassDirectReturn(const ir::AstNode *node); 360 void DirectReturn(const ir::AstNode *node); 361 void ExplicitReturn(const ir::AstNode *node); 362 void ImplicitReturn(const ir::AstNode *node); 363 void EmitAwait(const ir::AstNode *node); 364 365 void CallThis(const ir::AstNode *node, VReg startReg, size_t argCount); 366 void Call(const ir::AstNode *node, VReg startReg, size_t argCount); 367 void CallSpread(const ir::AstNode *node, VReg func, VReg thisReg, VReg args); 368 void SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount); 369 void SuperCallSpread(const ir::AstNode *node, VReg vs); 370 void NotifyConcurrentResult(const ir::AstNode *node); 371 372 void NewObject(const ir::AstNode *node, VReg startReg, size_t argCount); 373 void DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name); 374 375 void TypeOf(const ir::AstNode *node); 376 void NewObjSpread(const ir::AstNode *node, VReg obj); 377 void GetUnmappedArgs(const ir::AstNode *node); 378 379 void Negate(const ir::AstNode *node); 380 void ToNumber(const ir::AstNode *node, VReg arg); 381 void ToNumeric(const ir::AstNode *node, VReg arg); 382 383 void CreateGeneratorObj(const ir::AstNode *node, VReg funcObj); 384 void ResumeGenerator(const ir::AstNode *node, VReg genObj); 385 void GetResumeMode(const ir::AstNode *node, VReg genObj); 386 387 void AsyncFunctionEnter(const ir::AstNode *node); 388 void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj); 389 void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj); 390 void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj); 391 392 void GeneratorYield(const ir::AstNode *node, VReg genObj); 393 void GeneratorComplete(const ir::AstNode *node, VReg genObj); 394 void CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj); 395 void CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done); 396 void SuspendGenerator(const ir::AstNode *node, VReg genObj); 397 void SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj); 398 399 void AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj, VReg value, VReg canSuspend); 400 void AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj); 401 402 void GetTemplateObject(const ir::AstNode *node, VReg value); 403 void CopyRestArgs(const ir::AstNode *node, uint32_t index); 404 405 void GetPropIterator(const ir::AstNode *node); 406 void GetNextPropName(const ir::AstNode *node, VReg iter); 407 void CreateEmptyObject(const ir::AstNode *node); 408 void CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx); 409 void SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj); 410 void CopyDataProperties(const ir::AstNode *node, VReg dst); 411 void DefineGetterSetterByValue(const ir::AstNode *node, VReg obj, VReg name, VReg getter, VReg setter, 412 bool setName); 413 void CreateEmptyArray(const ir::AstNode *node); 414 void CreateArray(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements, VReg obj); 415 void CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx); 416 void StoreArraySpread(const ir::AstNode *node, VReg array, VReg index); 417 418 void ThrowIfNotObject(const ir::AstNode *node, VReg obj); 419 void ThrowThrowNotExist(const ir::AstNode *node); 420 void GetIterator(const ir::AstNode *node); 421 void GetAsyncIterator(const ir::AstNode *node); 422 423 void CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, VReg argStart, size_t argCount); 424 void ThrowObjectNonCoercible(const ir::AstNode *node); 425 void CloseIterator(const ir::AstNode *node, VReg iter); 426 void DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg base); 427 428 void LoadLocalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable); 429 void LoadExternalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable); 430 void StoreModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable); 431 void GetModuleNamespace(const ir::AstNode *node, uint32_t index); 432 void DynamicImportCall(const ir::AstNode *node); 433 434 void StSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key); 435 void LdSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key); 436 void StSuperByValue(const ir::AstNode *node, VReg obj, VReg prop); 437 void LdSuperByValue(const ir::AstNode *node, VReg obj); 438 void StoreSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop); 439 void LoadSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop); 440 441 void PopLexEnv(const ir::AstNode *node); 442 void CopyLexEnv(const ir::AstNode *node); 443 void NewLexicalEnv(const ir::AstNode *node, uint32_t num, binder::VariableScope *scope); 444 void NewLexEnv(const ir::AstNode *node, uint32_t num); 445 void NewLexEnvWithScopeInfo(const ir::AstNode *node, uint32_t num, int32_t scopeInfoIdx); 446 void LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot); 447 void LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const util::StringView &name); 448 void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot); 449 void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const binder::LocalVariable *local); 450 void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg value); 451 452 void ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num); 453 void ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringView &name); 454 void ThrowConstAssignment(const ir::AstNode *node, const util::StringView &name); 455 456 uint32_t TryDepth() const; 457 CatchTable *CreateCatchTable(); 458 void SortCatchTables(); 459 460 void LoadObjByIndex(const ir::AstNode *node, VReg obj, int64_t index); 461 void LoadObjByValue(const ir::AstNode *node, VReg obj); 462 463 void StoreObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop); 464 void StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index); 465 void StoreObjByValue(const ir::AstNode *node, VReg obj, VReg prop); 466 467 void StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop, bool nameSetting = false); 468 void StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop, bool nameSetting = false); 469 void StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index); 470 471 Operand ToNamedPropertyKey(const ir::Expression *prop, bool isComputed); 472 Operand ToPropertyKey(const ir::Expression *prop, bool isComputed); 473 VReg LoadPropertyKey(const ir::Expression *prop, bool isComputed); 474 475 /* 476 * Since the [Function] is not implemented yet, We compile the test262's framework code 477 * which obtains the [global] Object as following into [LoadConst.Global] directly. 478 * ``` 479 * var __globalObject = Function("return this;")(); 480 * var __globalObject = new Function("return this;")(); 481 * ``` 482 */ 483 bool TryCompileFunctionCallOrNewExpression(const ir::Expression *expr); 484 SetFirstStmt(const ir::Statement * stmt)485 void SetFirstStmt(const ir::Statement *stmt) 486 { 487 debugInfo_.firstStmt = stmt; 488 } 489 Unimplemented()490 [[noreturn]] static void Unimplemented() 491 { 492 throw Error(ErrorType::GENERIC, "Unimplemented code path"); 493 } 494 GetCurrentSlot()495 IcSizeType GetCurrentSlot() const 496 { 497 return currentSlot_; 498 } 499 IncreaseCurrentSlot(ICSlot inc)500 void IncreaseCurrentSlot(ICSlot inc) 501 { 502 currentSlot_ += inc; 503 } 504 505 private: 506 ArenaAllocator *allocator_; 507 CompilerContext *context_; 508 FunctionBuilder *builder_; 509 DebugInfo debugInfo_; 510 binder::FunctionScope *topScope_; 511 binder::Scope *scope_; 512 const ir::AstNode *rootNode_; 513 ArenaList<IRNode *> insns_; 514 ArenaMap<const IRNode *, int64_t> typedInsns_; 515 ArenaUnorderedSet<const binder::LocalVariable *> typedVars_; 516 std::pair<int64_t, int64_t> typedFunc_ {}; 517 ArenaVector<CatchTable *> catchList_; 518 ArenaSet<util::StringView> strings_; 519 ArenaVector<LiteralBuffer *> buffStorage_; 520 EnvScope *envScope_ {}; 521 DynamicContext *dynamicContext_ {}; 522 OptionalChain *optionalChain_ {}; 523 InlineCache ic_; 524 RegAllocator ra_; 525 IcSizeType currentSlot_ {0}; 526 527 uint32_t usedRegs_ {0}; 528 uint32_t totalRegs_ {0}; 529 friend class ScopeContext; 530 friend class RegScope; 531 friend class LocalRegScope; 532 friend class LoopRegScope; 533 friend class ParamRegScope; 534 friend class FunctionRegScope; 535 friend class EnvScope; 536 friend class LoopEnvScope; 537 friend class DynamicContext; 538 friend class OptionalChain; 539 size_t labelId_ {0}; 540 panda::panda_file::FunctionKind funcKind_ {panda::panda_file::FunctionKind::NONE}; 541 }; 542 } // namespace panda::es2panda::compiler 543 544 #endif 545