1 /**
2 * Copyright (c) 2021-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 #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/generateBin.h"
24 #include "util/options.h"
25 #include "util/plugin.h"
26
27 #include <iostream>
28 #include <memory>
29 #include <optional>
30
31 namespace ark::es2panda::aot {
32 using mem::MemConfig;
33
34 class MemManager {
35 public:
MemManager()36 explicit MemManager()
37 {
38 constexpr auto COMPILER_SIZE = sizeof(size_t) <= 4 ? 2_GB : 32_GB;
39
40 MemConfig::Initialize(0, 0, COMPILER_SIZE, 0, 0, 0);
41 PoolManager::Initialize(PoolType::MMAP);
42 }
43
44 NO_COPY_SEMANTIC(MemManager);
45 NO_MOVE_SEMANTIC(MemManager);
46
~MemManager()47 ~MemManager()
48 {
49 PoolManager::Finalize();
50 MemConfig::Finalize();
51 }
52 };
53
CompileFromSource(es2panda::Compiler & compiler,es2panda::SourceFile & input,util::Options * options)54 static int CompileFromSource(es2panda::Compiler &compiler, es2panda::SourceFile &input, util::Options *options)
55 {
56 auto program = std::unique_ptr<pandasm::Program> {compiler.Compile(input, *options)};
57 if (program == nullptr) {
58 const auto &err = compiler.GetError();
59
60 if (err.Type() == ErrorType::INVALID) {
61 if (compiler.IsAnyError()) {
62 return 1;
63 }
64 // Intentional exit or --parse-only option usage.
65 return 0;
66 }
67
68 std::cout << err.TypeString() << ": " << err.Message();
69 std::cout << " [" << (err.File().empty() ? util::BaseName(options->SourceFile()) : util::BaseName(err.File()))
70 << ":" << err.Line() << ":" << err.Col() << "]" << std::endl;
71
72 return err.ErrorCode();
73 }
74
75 return util::GenerateProgram(program.get(), options, [](std::string const &str) { std::cerr << str << std::endl; });
76 }
77
CompileFromConfig(es2panda::Compiler & compiler,util::Options * options)78 static int CompileFromConfig(es2panda::Compiler &compiler, util::Options *options)
79 {
80 auto compilationList = FindProjectSources(options->CompilerOptions().arktsConfig);
81 if (compilationList.empty()) {
82 std::cerr << "Error: No files to compile" << std::endl;
83 return 1;
84 }
85
86 unsigned overallRes = 0;
87 for (auto &[src, dst] : compilationList) {
88 std::ifstream inputStream(src);
89 if (inputStream.fail()) {
90 std::cerr << "Error: Failed to open file: " << src << std::endl;
91 return 1;
92 }
93
94 std::stringstream ss;
95 ss << inputStream.rdbuf();
96 std::string parserInput = ss.str();
97 inputStream.close();
98 es2panda::SourceFile input(src, parserInput, options->ParseModule());
99 options->SetCompilerOutput(dst);
100
101 options->ListFiles() && std::cout << "> es2panda: compiling from '" << src << "' to '" << dst << "'"
102 << std::endl;
103 auto res = CompileFromSource(compiler, input, options);
104 if (res != 0) {
105 std::cout << "> es2panda: failed to compile from " << src << " to " << dst << std::endl;
106 overallRes |= static_cast<unsigned>(res);
107 }
108 }
109
110 return overallRes;
111 }
112
InitializePlugins(std::vector<std::string> const & names)113 static std::optional<std::vector<util::Plugin>> InitializePlugins(std::vector<std::string> const &names)
114 {
115 std::vector<util::Plugin> res;
116 for (auto &name : names) {
117 auto plugin = util::Plugin(util::StringView {name});
118 if (!plugin.IsOk()) {
119 std::cerr << "Error: Failed to load plugin " << name << std::endl;
120 return {};
121 }
122 plugin.Initialize();
123 res.push_back(std::move(plugin));
124 }
125 return {std::move(res)};
126 }
127
Run(int argc,const char ** argv)128 static int Run(int argc, const char **argv)
129 {
130 auto options = std::make_unique<util::Options>();
131 if (!options->Parse(argc, argv)) {
132 std::cerr << options->ErrorMsg() << std::endl;
133 return 1;
134 }
135
136 Logger::ComponentMask mask {};
137 mask.set(Logger::Component::ES2PANDA);
138 Logger::InitializeStdLogging(Logger::LevelFromString(options->LogLevel()), mask);
139 auto pluginsOpt = InitializePlugins(options->CompilerOptions().plugins);
140 if (!pluginsOpt.has_value()) {
141 return 1;
142 }
143 es2panda::Compiler compiler(options->Extension(), options->ThreadCount(), std::move(pluginsOpt.value()));
144
145 if (options->ListPhases()) {
146 std::cerr << "Available phases:" << std::endl;
147 std::cerr << compiler.GetPhasesList();
148 return 1;
149 }
150
151 if (options->CompilerOptions().compilationMode == CompilationMode::PROJECT) {
152 return CompileFromConfig(compiler, options.get());
153 }
154
155 std::string_view sourceFile;
156 std::string_view parserInput;
157 if (options->CompilerOptions().compilationMode == CompilationMode::GEN_STD_LIB) {
158 sourceFile = "etsstdlib.sts";
159 parserInput = "";
160 } else {
161 sourceFile = options->SourceFile();
162 parserInput = options->ParserInput();
163 }
164 es2panda::SourceFile input(sourceFile, parserInput, options->ParseModule());
165 return CompileFromSource(compiler, input, options.get());
166 }
167 } // namespace ark::es2panda::aot
168
main(int argc,const char ** argv)169 int main(int argc, const char **argv)
170 {
171 ark::es2panda::aot::MemManager mm;
172 return ark::es2panda::aot::Run(argc, argv);
173 }
174