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