1 /*
2  * Copyright (c) 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 ES2PANDA_EVALUATE_SCOPED_DEBUG_INFO_PLUGIN_H
17 #define ES2PANDA_EVALUATE_SCOPED_DEBUG_INFO_PLUGIN_H
18 
19 #include "evaluate/debugInfoStorage.h"
20 #include "evaluate/evaluateContext.h"
21 #include "evaluate/helpers.h"
22 #include "evaluate/irCheckHelper.h"
23 #include "evaluate/proxyProgramsCache.h"
24 #include "evaluate/pathResolver.h"
25 #include "evaluate/entityDeclarator.h"
26 #include "evaluate/debugInfoDeserialization/debugInfoDeserializer.h"
27 
28 namespace ark::es2panda::ir {
29 class BlockStatement;
30 class Statement;
31 }  // namespace ark::es2panda::ir
32 
33 namespace ark::es2panda::varbinder {
34 class ETSBinder;
35 class Variable;
36 }  // namespace ark::es2panda::varbinder
37 
38 namespace ark::es2panda::evaluate {
39 
40 /// @brief Context-dependent debug info plugin. Must be created before parsing phase.
41 class ScopedDebugInfoPlugin final {
42 public:
43     explicit ScopedDebugInfoPlugin(parser::Program *globalProgram, checker::ETSChecker *checker,
44                                    const CompilerOptions &options);
45 
46     NO_COPY_SEMANTIC(ScopedDebugInfoPlugin);
47     NO_MOVE_SEMANTIC(ScopedDebugInfoPlugin);
48 
49     ~ScopedDebugInfoPlugin() = default;
50 
51     /**
52      * @brief Searches debug-info for the given identifier
53      * @param ident node with name of either a local or global variable or a class
54      */
55     varbinder::Variable *FindIdentifier(ir::Identifier *ident);
56 
57     /**
58      * @brief Searches debug-info for the given class
59      * On success creates IR for this and all dependencies.
60      */
61     varbinder::Variable *FindClass(ir::Identifier *ident);
62 
63     /**
64      * @brief Adds collected prologue and epilogue statements in the block
65      * In effect, previously collected prologue-epilogue statements are dropped.
66      */
67     void AddPrologueEpilogue(ir::BlockStatement *block);
68 
69     /**
70      * @brief Save \p stmt node to be pushed later at the beginning or end of the \p block depending on the IS_PROLOGUE
71      * parameter
72      */
73     template <bool IS_PROLOGUE>
74     void RegisterPrologueEpilogue(ir::BlockStatement *block, ir::Statement *stmt);
75 
76     /**
77      * @brief Initialization before ETSChecker starts checking AST
78      * Since we can resolve references like `new A()`, that resolved before ETSChecker was started,
79      * we need such a precheck call.
80      */
81     void PreCheck();
82 
83     /**
84      * @brief Finalization after ETSChecker checks the main program
85      */
86     void PostCheck();
87 
GetPathResolver()88     PathResolver *GetPathResolver()
89     {
90         return &pathResolver_;
91     }
92 
GetPathResolver() const93     const PathResolver *GetPathResolver() const
94     {
95         return &pathResolver_;
96     }
97 
GetIrCheckHelper()98     IrCheckHelper *GetIrCheckHelper()
99     {
100         return &irCheckHelper_;
101     }
102 
GetIrCheckHelper() const103     const IrCheckHelper *GetIrCheckHelper() const
104     {
105         return &irCheckHelper_;
106     }
107 
GetDebugInfoStorage()108     DebugInfoStorage *GetDebugInfoStorage()
109     {
110         return &debugInfoStorage_;
111     }
112 
GetDebugInfoStorage() const113     const DebugInfoStorage *GetDebugInfoStorage() const
114     {
115         return &debugInfoStorage_;
116     }
117 
GetProxyProgramsCache()118     ProxyProgramsCache *GetProxyProgramsCache()
119     {
120         return &proxyProgramsCache_;
121     }
122 
GetProxyProgramsCache() const123     const ProxyProgramsCache *GetProxyProgramsCache() const
124     {
125         return &proxyProgramsCache_;
126     }
127 
GetEntityDeclarator()128     EntityDeclarator *GetEntityDeclarator()
129     {
130         return &entityDeclarator_;
131     }
132 
GetEntityDeclarator() const133     const EntityDeclarator *GetEntityDeclarator() const
134     {
135         return &entityDeclarator_;
136     }
137 
GetDebugInfoDeserializer()138     DebugInfoDeserializer *GetDebugInfoDeserializer()
139     {
140         return &debugInfoDeserializer_;
141     }
142 
GetDebugInfoDeserializer() const143     const DebugInfoDeserializer *GetDebugInfoDeserializer() const
144     {
145         return &debugInfoDeserializer_;
146     }
147 
148     varbinder::ETSBinder *GetETSBinder();
149 
150 private:
151     using PrologueEpiloguePair = std::pair<ArenaVector<ir::Statement *>, ArenaVector<ir::Statement *>>;
152     using PrologueEpilogueMap = ArenaUnorderedMap<ir::BlockStatement *, PrologueEpiloguePair>;
153 
154 private:
155     /**
156      * @brief Asserts correctness of input options.
157      */
158     void ValidateEvaluationOptions(const CompilerOptions &options);
159 
160     /**
161      * @brief Creates `Program` instances for each input context .abc file.
162      */
163     void CreateContextPrograms();
164 
165     /**
166      * @brief Creates a program with the given package name and adds it as external for the given global program.
167      * This method must be called once and before running any compiler phases.
168      * @param sourceFilePath corresponding to source code of one of the provided .abc files.
169      * @param moduleName of source file, extracted from .abc file encoding.
170      * @returns pointer to initialized program.
171      */
172     parser::Program *CreateEmptyProgram(std::string_view sourceFilePath, std::string_view moduleName);
173 
174     /**
175      * @brief Returns non-null program for the given source file path.
176      */
177     parser::Program *GetProgram(util::StringView fileName);
178 
179     parser::Program *GetEvaluatedExpressionProgram();
180 
181     /// Search methods.
182     varbinder::Variable *FindGlobalVariable(ir::Identifier *ident);
183     varbinder::Variable *FindGlobalFunction(ir::Identifier *ident);
184     varbinder::Variable *FindLocalVariable(ir::Identifier *ident);
185 
186     /**
187      * @brief Pushes back return statement into the evaluation method
188      * if its last statement potentially returns a primitive value.
189      * @returns true if insertion took place, false otherwise.
190      */
191     bool InsertReturnStatement();
192 
193     ArenaAllocator *Allocator();
194 
195 private:
196     parser::Program *globalProgram_ {nullptr};
197     checker::ETSChecker *checker_ {nullptr};
198 
199     EvaluateContext context_;
200 
201     IrCheckHelper irCheckHelper_;
202     DebugInfoStorage debugInfoStorage_;
203     DebugInfoDeserializer debugInfoDeserializer_;
204     PathResolver pathResolver_;
205     PrologueEpilogueMap prologueEpilogueMap_;
206     ProxyProgramsCache proxyProgramsCache_;
207     EntityDeclarator entityDeclarator_;
208 };
209 
210 }  // namespace ark::es2panda::evaluate
211 
212 #endif  // ES2PANDA_EVALUATE_SCOPED_DEBUG_INFO_PLUGIN_H
213