• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 #include "phase.h"
17 
18 #include "checker/checker.h"
19 #include "compiler/lowering/checkerPhase.h"
20 #include "compiler/lowering/ets/asyncMethodLowering.h"
21 #include "compiler/lowering/ets/ambientLowering.h"
22 #include "compiler/lowering/ets/arrayLiteralLowering.h"
23 #include "compiler/lowering/ets/bigintLowering.h"
24 #include "compiler/lowering/ets/boxedTypeLowering.h"
25 #include "compiler/lowering/ets/boxingForLocals.h"
26 #include "compiler/lowering/ets/capturedVariables.h"
27 #include "compiler/lowering/ets/constantExpressionLowering.h"
28 #include "compiler/lowering/ets/convertPrimitiveCastMethodCall.h"
29 #include "compiler/lowering/ets/declareOverloadLowering.h"
30 #include "compiler/lowering/ets/cfgBuilderPhase.h"
31 #include "compiler/lowering/ets/defaultParametersInConstructorLowering.h"
32 #include "compiler/lowering/ets/defaultParametersLowering.h"
33 #include "compiler/lowering/ets/dynamicImportLowering.h"
34 #include "compiler/lowering/ets/enumLowering.h"
35 #include "compiler/lowering/ets/enumPostCheckLowering.h"
36 #include "compiler/lowering/ets/restTupleLowering.h"
37 #include "compiler/lowering/ets/expandBrackets.h"
38 #include "compiler/lowering/ets/exportAnonymousConst.h"
39 #include "compiler/lowering/ets/expressionLambdaLowering.h"
40 #include "compiler/lowering/ets/extensionAccessorLowering.h"
41 #include "compiler/lowering/ets/genericBridgesLowering.h"
42 #include "compiler/lowering/ets/insertOptionalParametersAnnotation.h"
43 #include "compiler/lowering/ets/interfaceObjectLiteralLowering.h"
44 #include "compiler/lowering/ets/interfacePropertyDeclarations.h"
45 #include "compiler/lowering/ets/lambdaLowering.h"
46 #include "compiler/lowering/ets/objectIndexAccess.h"
47 #include "compiler/lowering/ets/objectIterator.h"
48 #include "compiler/lowering/ets/objectLiteralLowering.h"
49 #include "compiler/lowering/ets/opAssignment.h"
50 #include "compiler/lowering/ets/optionalArgumentsLowering.h"
51 #include "compiler/lowering/ets/optionalLowering.h"
52 #include "compiler/lowering/ets/packageImplicitImport.h"
53 #include "compiler/lowering/ets/partialExportClassGen.h"
54 #include "compiler/lowering/ets/promiseVoid.h"
55 #include "compiler/lowering/ets/recordLowering.h"
56 #include "compiler/lowering/ets/resizableArrayLowering.h"
57 #include "compiler/lowering/ets/lateInitialization.h"
58 #include "compiler/lowering/ets/restArgsLowering.h"
59 #include "compiler/lowering/ets/setJumpTarget.h"
60 #include "compiler/lowering/ets/spreadLowering.h"
61 #include "compiler/lowering/ets/stringComparison.h"
62 #include "compiler/lowering/ets/stringConstantsLowering.h"
63 #include "compiler/lowering/ets/stringConstructorLowering.h"
64 #include "compiler/lowering/ets/topLevelStmts/topLevelStmts.h"
65 #include "compiler/lowering/ets/unionLowering.h"
66 #include "compiler/lowering/ets/typeFromLowering.h"
67 #include "compiler/lowering/plugin_phase.h"
68 #include "compiler/lowering/resolveIdentifiers.h"
69 #include "compiler/lowering/scopesInit/scopesInitPhase.h"
70 #include "generated/diagnostic.h"
71 #include "lexer/token/sourceLocation.h"
72 #include "public/es2panda_lib.h"
73 #include "util/options.h"
74 
75 namespace ark::es2panda::compiler {
76 
77 static CheckerPhase g_checkerPhase;
78 static SetJumpTargetPhase g_setJumpTargetPhase;
79 static CFGBuilderPhase g_cfgBuilderPhase;
80 static ResolveIdentifiers g_resolveIdentifiers {};
81 static AmbientLowering g_ambientLowering;
82 static ArrayLiteralLowering g_arrayLiteralLowering {};
83 static BigIntLowering g_bigintLowering;
84 static StringConstructorLowering g_stringConstructorLowering;
85 static ConstantExpressionLowering g_constantExpressionLowering;
86 static InterfacePropertyDeclarationsPhase g_interfacePropDeclPhase;  // NOLINT(fuchsia-statically-constructed-objects)
87 static EnumLoweringPhase g_enumLoweringPhase;
88 static EnumPostCheckLoweringPhase g_enumPostCheckLoweringPhase;
89 static RestTupleConstructionPhase g_restTupleConstructionPhase;
90 static SpreadConstructionPhase g_spreadConstructionPhase;
91 static ExtensionAccessorPhase g_extensionAccessorPhase;
92 static ExpressionLambdaConstructionPhase g_expressionLambdaConstructionPhase;
93 static OpAssignmentLowering g_opAssignmentLowering;
94 static BoxingForLocals g_boxingForLocals;
95 static CapturedVariables g_capturedVariables {};
96 static LambdaConversionPhase g_lambdaConversionPhase;
97 static ObjectIndexLowering g_objectIndexLowering;
98 static ObjectIteratorLowering g_objectIteratorLowering;
99 static ObjectLiteralLowering g_objectLiteralLowering;
100 static InterfaceObjectLiteralLowering g_interfaceObjectLiteralLowering;
101 static UnionLowering g_unionLowering;
102 static OptionalLowering g_optionalLowering;
103 static ExpandBracketsPhase g_expandBracketsPhase;
104 static ExportAnonymousConstPhase g_exportAnonymousConstPhase;
105 static PromiseVoidInferencePhase g_promiseVoidInferencePhase;
106 static RecordLowering g_recordLowering;
107 static DeclareOverloadLowering g_declareOverloadLowering;
108 static DefaultParametersLowering g_defaultParametersLowering;
109 static DefaultParametersInConstructorLowering g_defaultParametersInConstructorLowering;
110 static OptionalArgumentsLowering g_optionalArgumentsLowering;
111 static TopLevelStatements g_topLevelStatements;
112 static StringComparisonLowering g_stringComparisonLowering;
113 static StringConstantsLowering g_stringConstantsLowering;
114 static PartialExportClassGen g_partialExportClassGen;
115 static PackageImplicitImport g_packageImplicitImport;
116 static GenericBridgesPhase g_genericBridgesLowering;
117 static BoxedTypeLowering g_boxedTypeLowering;
118 static AsyncMethodLowering g_asyncMethodLowering;
119 static TypeFromLowering g_typeFromLowering;
120 static ResizableArrayConvert g_resizableArrayConvert;
121 static RestArgsLowering g_restArgsLowering;
122 static LateInitializationConvert g_lateInitializationConvert;
123 static InsertOptionalParametersAnnotation g_insertOptionalParametersAnnotation;
124 static ConvertPrimitiveCastMethodCall g_convertPrimitiveCastMethodCall;
125 static PluginPhase g_pluginsAfterParse {"plugins-after-parse", ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse};
126 static PluginPhase g_pluginsAfterBind {"plugins-after-bind", ES2PANDA_STATE_BOUND, &util::Plugin::AfterBind};
127 static PluginPhase g_pluginsAfterCheck {"plugins-after-check", ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck};
128 static PluginPhase g_pluginsAfterLowerings {"plugins-after-lowering", ES2PANDA_STATE_LOWERED,
129                                             &util::Plugin::AfterLowerings};
130 // NOLINTBEGIN(fuchsia-statically-constructed-objects)
131 static InitScopesPhaseETS g_initScopesPhaseEts;
132 static InitScopesPhaseAS g_initScopesPhaseAs;
133 static InitScopesPhaseTs g_initScopesPhaseTs;
134 static InitScopesPhaseJs g_initScopesPhaseJs;
135 // NOLINTEND(fuchsia-statically-constructed-objects)
136 static DynamicImportLowering g_dynamicImportLowering;
137 
138 // CC-OFFNXT(huge_method, G.FUN.01-CPP) long initialization list
GetETSPhaseList()139 std::vector<Phase *> GetETSPhaseList()
140 {
141     // clang-format off
142     // NOLINTBEGIN
143     return {
144         &g_pluginsAfterParse,
145         &g_stringConstantsLowering,
146         &g_packageImplicitImport,
147         &g_exportAnonymousConstPhase,
148         &g_topLevelStatements,
149         &g_resizableArrayConvert,
150         &g_expressionLambdaConstructionPhase,
151         &g_insertOptionalParametersAnnotation,
152         &g_defaultParametersInConstructorLowering,
153         &g_defaultParametersLowering,
154         &g_ambientLowering,
155         &g_restTupleConstructionPhase,
156         &g_initScopesPhaseEts,
157         &g_optionalLowering,
158         &g_promiseVoidInferencePhase,
159         &g_interfacePropDeclPhase,
160         &g_constantExpressionLowering,
161         &g_enumLoweringPhase,
162         &g_resolveIdentifiers,
163         &g_pluginsAfterBind,
164         &g_capturedVariables,
165         &g_setJumpTargetPhase,
166         &g_cfgBuilderPhase,
167         &g_checkerPhase,        // please DO NOT change order of these two phases: checkerPhase and pluginsAfterCheck
168         &g_pluginsAfterCheck,   // pluginsAfterCheck has to go right after checkerPhase, nothing should be between them
169         &g_convertPrimitiveCastMethodCall,
170         &g_dynamicImportLowering,
171         &g_asyncMethodLowering,
172         &g_declareOverloadLowering,
173         &g_enumPostCheckLoweringPhase,
174         &g_spreadConstructionPhase,
175         &g_restArgsLowering,
176         &g_arrayLiteralLowering,
177         &g_bigintLowering,
178         &g_opAssignmentLowering,
179         &g_lateInitializationConvert,
180         &g_extensionAccessorPhase,
181         &g_boxingForLocals,
182         &g_recordLowering,
183         &g_boxedTypeLowering,
184         &g_objectIndexLowering,
185         &g_objectIteratorLowering,
186         &g_lambdaConversionPhase,
187         &g_unionLowering,
188         &g_expandBracketsPhase,
189         &g_partialExportClassGen,
190         &g_interfaceObjectLiteralLowering, // this lowering should be put after all classs generated.
191         &g_objectLiteralLowering,
192         &g_stringConstructorLowering,
193         &g_stringComparisonLowering,
194         &g_optionalArgumentsLowering, // #22952 could be moved to earlier phase
195         &g_genericBridgesLowering,
196         &g_typeFromLowering,
197         &g_pluginsAfterLowerings,  // pluginsAfterLowerings has to come at the very end, nothing should go after it
198     };
199     // NOLINTEND
200     // clang-format on
201 }
202 
GetASPhaseList()203 std::vector<Phase *> GetASPhaseList()
204 {
205     return {
206         &g_initScopesPhaseAs,
207         &g_checkerPhase,
208     };
209 }
210 
GetTSPhaseList()211 std::vector<Phase *> GetTSPhaseList()
212 {
213     return {
214         &g_initScopesPhaseTs,
215         &g_checkerPhase,
216     };
217 }
218 
GetJSPhaseList()219 std::vector<Phase *> GetJSPhaseList()
220 {
221     return {
222         &g_initScopesPhaseJs,
223         &g_checkerPhase,
224     };
225 }
226 
227 thread_local PhaseManager *g_phaseManager {nullptr};
228 
GetPhaseManager()229 PhaseManager *GetPhaseManager()
230 {
231     ES2PANDA_ASSERT(g_phaseManager != nullptr && g_phaseManager->IsInitialized());
232     return g_phaseManager;
233 }
234 
SetPhaseManager(PhaseManager * phaseManager)235 void SetPhaseManager(PhaseManager *phaseManager)
236 {
237     g_phaseManager = phaseManager;
238 }
239 
Apply(public_lib::Context * ctx,parser::Program * program)240 bool Phase::Apply(public_lib::Context *ctx, parser::Program *program)
241 {
242     SetPhaseManager(ctx->phaseManager);
243     GetPhaseManager()->SetCurrentPhaseId(id_);
244 
245 #ifndef NDEBUG
246     if (!Precondition(ctx, program)) {
247         ctx->checker->LogError(diagnostic::PRECOND_FAILED, {Name()}, lexer::SourcePosition {});
248         return false;
249     }
250 #endif
251 
252     if (!Perform(ctx, program)) {
253         return false;  // NOLINT(readability-simplify-boolean-expr)
254     }
255 
256 #ifndef NDEBUG
257     if (!Postcondition(ctx, program)) {
258         ctx->checker->LogError(diagnostic::POSTCOND_FAILED, {Name()}, lexer::SourcePosition {});
259         return false;
260     }
261 #endif
262 
263     return true;
264 }
265 
Precondition(public_lib::Context * ctx,const parser::Program * program)266 bool PhaseForDeclarations::Precondition(public_lib::Context *ctx, const parser::Program *program)
267 {
268     for (auto &[_, extPrograms] : program->ExternalSources()) {
269         (void)_;
270         for (auto *extProg : extPrograms) {
271             if (!Precondition(ctx, extProg)) {
272                 return false;
273             }
274         }
275     }
276 
277     return PreconditionForModule(ctx, program);
278 }
279 
Perform(public_lib::Context * ctx,parser::Program * program)280 bool PhaseForDeclarations::Perform(public_lib::Context *ctx, parser::Program *program)
281 {
282     bool result = true;
283     for (auto &[_, extPrograms] : program->ExternalSources()) {
284         (void)_;
285         for (auto *extProg : extPrograms) {
286             result &= Perform(ctx, extProg);
287         }
288     }
289 
290     result &= PerformForModule(ctx, program);
291     return result;
292 }
293 
Postcondition(public_lib::Context * ctx,const parser::Program * program)294 bool PhaseForDeclarations::Postcondition(public_lib::Context *ctx, const parser::Program *program)
295 {
296     for (auto &[_, extPrograms] : program->ExternalSources()) {
297         (void)_;
298         for (auto *extProg : extPrograms) {
299             if (!Postcondition(ctx, extProg)) {
300                 return false;
301             }
302         }
303     }
304 
305     return PostconditionForModule(ctx, program);
306 }
307 
308 // CC-OFFNXT(huge_method, huge_depth) solid logic
Precondition(public_lib::Context * ctx,const parser::Program * program)309 bool PhaseForBodies::Precondition(public_lib::Context *ctx, const parser::Program *program)
310 {
311     auto cMode = ctx->config->options->GetCompilationMode();
312 
313     auto iterateExternal = [&cMode, this](public_lib::Context *context, const parser::Program *localProgram) {
314         for (auto &[_, extPrograms] : localProgram->ExternalSources()) {
315             (void)_;
316             for (auto *prog : extPrograms) {
317                 if (!prog->IsGenAbcForExternal() && cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) {
318                     continue;
319                 }
320 
321                 if (!Precondition(context, prog)) {
322                     return false;
323                 }
324             }
325         }
326         return true;
327     };
328     if (cMode == CompilationMode::GEN_STD_LIB || cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) {
329         if (!iterateExternal(ctx, program)) {
330             return false;
331         }
332     }
333 
334     return PreconditionForModule(ctx, program);
335 }
336 
337 // CC-OFFNXT(huge_method, huge_depth) solid logic
Perform(public_lib::Context * ctx,parser::Program * program)338 bool PhaseForBodies::Perform(public_lib::Context *ctx, parser::Program *program)
339 {
340     bool result = true;
341     auto cMode = ctx->config->options->GetCompilationMode();
342     auto iterateExternal = [&result, &cMode, this](public_lib::Context *context, parser::Program *localProgram) {
343         for (auto &[_, extPrograms] : localProgram->ExternalSources()) {
344             (void)_;
345             for (auto *extProg : extPrograms) {
346                 if (!extProg->IsGenAbcForExternal() && cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) {
347                     continue;
348                 }
349                 result &= Perform(context, extProg);
350             }
351         }
352     };
353     if (cMode == CompilationMode::GEN_STD_LIB || cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) {
354         iterateExternal(ctx, program);
355     }
356 
357     result &= PerformForModule(ctx, program);
358     return result;
359 }
360 
361 // CC-OFFNXT(huge_method, huge_depth) solid logic
Postcondition(public_lib::Context * ctx,const parser::Program * program)362 bool PhaseForBodies::Postcondition(public_lib::Context *ctx, const parser::Program *program)
363 {
364     auto cMode = ctx->config->options->GetCompilationMode();
365     auto iterateExternal = [&cMode, this](public_lib::Context *context, const parser::Program *localProgram) {
366         for (auto &[_, extPrograms] : localProgram->ExternalSources()) {
367             (void)_;
368             for (auto *prog : extPrograms) {
369                 if (!prog->IsGenAbcForExternal() && cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) {
370                     continue;
371                 }
372 
373                 if (!Postcondition(context, prog)) {
374                     return false;
375                 }
376             }
377         }
378         return true;
379     };
380     if (cMode == CompilationMode::GEN_STD_LIB || cMode == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE) {
381         if (!iterateExternal(ctx, program)) {
382             return false;
383         }
384     }
385 
386     return PostconditionForModule(ctx, program);
387 }
388 
InitializePhases()389 void PhaseManager::InitializePhases()
390 {
391     switch (ext_) {
392         case ScriptExtension::ETS:
393             phases_ = GetETSPhaseList();
394             break;
395         case ScriptExtension::AS:
396             phases_ = GetASPhaseList();
397             break;
398         case ScriptExtension::TS:
399             phases_ = GetTSPhaseList();
400             break;
401         case ScriptExtension::JS:
402             phases_ = GetJSPhaseList();
403             break;
404         default:
405             ES2PANDA_UNREACHABLE();
406     }
407 
408     int id = 0;
409     for (auto phase : phases_) {
410         phase->id_ = id++;
411     }
412 }
413 
AllPhases()414 std::vector<Phase *> PhaseManager::AllPhases()
415 {
416     ES2PANDA_ASSERT(IsInitialized());
417     return phases_;
418 }
419 
RebindPhases()420 std::vector<Phase *> PhaseManager::RebindPhases()
421 {
422     ES2PANDA_ASSERT(IsInitialized());
423     return {
424         &g_initScopesPhaseEts,
425         &g_resolveIdentifiers,
426     };
427 }
428 
RecheckPhases()429 std::vector<Phase *> PhaseManager::RecheckPhases()
430 {
431     ES2PANDA_ASSERT(IsInitialized());
432     return {
433         &g_initScopesPhaseEts,
434         &g_resolveIdentifiers,
435         &g_capturedVariables,
436         &g_checkerPhase,
437     };
438 }
439 
440 }  // namespace ark::es2panda::compiler
441