• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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