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