• 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 "bytecode_optimizer/bytecodeopt_options.h"
17 #include "bytecode_optimizer/optimize_bytecode.h"
18 #include "compiler/compiler_logger.h"
19 #include "mem/arena_allocator.h"
20 #include "mem/pool_manager.h"
21 #include "es2panda.h"
22 #include "util/arktsconfig.h"
23 #include "util/diagnosticEngine.h"
24 #include "util/generateBin.h"
25 #include "util/options.h"
26 #include "util/plugin.h"
27 #include "libpandabase/os/stacktrace.h"
28 #include "generated/diagnostic.h"
29 
30 #include <iostream>
31 #include <memory>
32 #include <optional>
33 
34 namespace ark::es2panda::aot {
35 using mem::MemConfig;
36 
37 class MemManager {
38 public:
MemManager()39     explicit MemManager()
40     {
41         MemConfig::Initialize(0, 0, COMPILER_SIZE, 0, 0, 0);
42         PoolManager::Initialize(PoolType::MMAP);
43     }
44 
45     NO_COPY_SEMANTIC(MemManager);
46     NO_MOVE_SEMANTIC(MemManager);
47 
~MemManager()48     ~MemManager()
49     {
50         PoolManager::Finalize();
51         MemConfig::Finalize();
52     }
53 };
54 
CompileFromSource(es2panda::Compiler & compiler,es2panda::SourceFile & input,const util::Options & options,util::DiagnosticEngine & diagnosticEngine)55 static int CompileFromSource(es2panda::Compiler &compiler, es2panda::SourceFile &input, const util::Options &options,
56                              util::DiagnosticEngine &diagnosticEngine)
57 {
58     auto program = std::unique_ptr<pandasm::Program> {compiler.Compile(input, options, diagnosticEngine)};
59     if (program == nullptr) {
60         const auto &err = compiler.GetError();
61 
62         if (err.Type() == util::DiagnosticType::INVALID) {
63             if (diagnosticEngine.IsAnyError()) {
64                 return 1;
65             }
66             // Intentional exit or --parse-only option usage.
67             return 0;
68         }
69         diagnosticEngine.Log(err);
70         return 1;
71     }
72 
73     return util::GenerateProgram(
74         program.get(), options,
75         [&diagnosticEngine](const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams &params) {
76             diagnosticEngine.LogDiagnostic(kind, params);
77         });
78 }
79 
80 using StringPairVector = std::vector<std::pair<std::string, std::string>>;
81 
CompileMultipleFiles(es2panda::Compiler & compiler,std::vector<SourceFile> & inputs,util::Options * options,util::DiagnosticEngine & diagnosticEngine)82 static int CompileMultipleFiles(es2panda::Compiler &compiler, std::vector<SourceFile> &inputs, util::Options *options,
83                                 util::DiagnosticEngine &diagnosticEngine)
84 {
85     std::vector<pandasm::Program *> result;
86     auto overallRes = compiler.CompileM(inputs, *options, diagnosticEngine, result);
87     for (size_t i = 0; i < result.size(); i++) {
88         auto *program = result[i];
89         if (program == nullptr) {
90             overallRes |= 1U;
91             continue;
92         }
93         options->SetOutput(std::string(inputs[i].dest));
94         overallRes |= (unsigned int)util::GenerateProgram(
95             program, *options,
96             [&diagnosticEngine](const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams &params) {
97                 diagnosticEngine.LogDiagnostic(kind, params);
98             });
99     }
100     return overallRes;
101 }
102 
ReleaseInputsAndReturn(std::vector<std::string * > & parserInputs,unsigned int returnCode)103 static unsigned int ReleaseInputsAndReturn(std::vector<std::string *> &parserInputs, unsigned int returnCode)
104 {
105     for (auto *input : parserInputs) {
106         delete input;
107     }
108     parserInputs.clear();
109     return returnCode;
110 }
111 
CompileFromConfig(es2panda::Compiler & compiler,util::Options * options,util::DiagnosticEngine & diagnosticEngine)112 static unsigned int CompileFromConfig(es2panda::Compiler &compiler, util::Options *options,
113                                       util::DiagnosticEngine &diagnosticEngine)
114 {
115     auto compilationList = FindProjectSources(options->ArkTSConfig());
116     if (compilationList.empty()) {
117         diagnosticEngine.LogDiagnostic(diagnostic::NO_INPUT, util::DiagnosticMessageParams {});
118         return 1;
119     }
120 
121     std::vector<SourceFile> inputs {};
122     std::vector<std::string *> parserInputs;
123     unsigned int overallRes = 0;
124     for (auto &[src, dst] : compilationList) {
125         std::ifstream inputStream(src);
126         if (inputStream.fail()) {
127             diagnosticEngine.LogDiagnostic(diagnostic::OPEN_FAILED, util::DiagnosticMessageParams {src});
128             return 1;
129         }
130         std::stringstream ss;
131         ss << inputStream.rdbuf();
132         parserInputs.push_back(new std::string(ss.str()));
133         inputStream.close();
134         es2panda::SourceFile input(src, *parserInputs.back(), options->IsModule(), std::string_view(dst));
135         inputs.push_back(input);
136     }
137 
138     if (options->IsPermArena() && (options->GetExtension() == util::gen::extension::ETS)) {
139         return ReleaseInputsAndReturn(parserInputs, CompileMultipleFiles(compiler, inputs, options, diagnosticEngine));
140     }
141 
142     for (auto &input : inputs) {
143         LOG_IF(options->IsListFiles(), INFO, ES2PANDA)
144             << "> es2panda: compiling from '" << input.filePath << "' to '" << input.dest << "'";
145         options->SetOutput(std::string(input.dest));
146         auto res = CompileFromSource(compiler, input, *options, diagnosticEngine);
147         if (res != 0) {
148             diagnosticEngine.LogDiagnostic(diagnostic::COMPILE_FAILED,
149                                            util::DiagnosticMessageParams {input.filePath, input.dest});
150             overallRes |= static_cast<unsigned>(res);
151         }
152     }
153     return ReleaseInputsAndReturn(parserInputs, overallRes);
154 }
155 
InitializePlugins(std::vector<std::string> const & names,util::DiagnosticEngine & diagnosticEngine)156 static std::optional<std::vector<util::Plugin>> InitializePlugins(std::vector<std::string> const &names,
157                                                                   util::DiagnosticEngine &diagnosticEngine)
158 {
159     std::vector<util::Plugin> res;
160     for (auto &name : names) {
161         auto plugin = util::Plugin(util::StringView {name});
162         if (!plugin.IsOk()) {
163             diagnosticEngine.LogDiagnostic(diagnostic::PLUGIN_LOAD_FAILED,
164                                            util::DiagnosticMessageParams {util::StringView(name)});
165             return std::nullopt;
166         }
167         plugin.Initialize();
168         res.push_back(std::move(plugin));
169     }
170     return {std::move(res)};
171 }
172 
Run(Span<const char * const> args)173 static int Run(Span<const char *const> args)
174 {
175     auto diagnosticEngine = util::DiagnosticEngine();
176     auto options = std::make_unique<util::Options>(args[0], diagnosticEngine);
177     if (!options->Parse(args)) {
178         diagnosticEngine.FlushDiagnostic();
179         return 1;
180     }
181     diagnosticEngine.SetWError(options->IsEtsWarningsWerror());
182     ark::Logger::ComponentMask mask {};
183     mask.set(ark::Logger::Component::ES2PANDA);
184     ark::Logger::InitializeStdLogging(options->LogLevel(), mask);
185     util::DiagnosticEngine::InitializeSignalHandlers();
186 
187     auto pluginsOpt = InitializePlugins(options->GetPlugins(), diagnosticEngine);
188     if (!pluginsOpt.has_value()) {
189         diagnosticEngine.FlushDiagnostic();
190         return 1;
191     }
192 
193     es2panda::Compiler compiler(options->GetExtension(), options->GetThread(), std::move(pluginsOpt.value()));
194     if (options->IsListPhases()) {
195         std::cerr << "Available phases:" << std::endl;
196         std::cerr << compiler.GetPhasesList();
197         diagnosticEngine.FlushDiagnostic();
198         return 1;
199     }
200 
201     int res;
202     if (options->GetCompilationMode() == CompilationMode::PROJECT) {
203         res = CompileFromConfig(compiler, options.get(), diagnosticEngine);
204     } else {
205         std::string sourceFile;
206         std::string_view parserInput;
207         if (options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) {
208             sourceFile = "etsstdlib.ets";
209             parserInput = "";
210         } else {
211             sourceFile = options->SourceFileName();
212             auto [buf, size] = options->CStrParserInputContents();
213             parserInput = std::string_view(buf, size);
214         }
215         es2panda::SourceFile input(sourceFile, parserInput, options->IsModule(), options->GetOutput());
216         res = CompileFromSource(compiler, input, *options.get(), diagnosticEngine);
217     }
218     diagnosticEngine.FlushDiagnostic();
219     return res;
220 }
221 }  // namespace ark::es2panda::aot
222 
main(int argc,const char * argv[])223 int main(int argc, const char *argv[])
224 {
225     ark::es2panda::aot::MemManager mm;
226     return ark::es2panda::aot::Run(ark::Span<const char *const>(argv, argc));
227 }
228