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
31namespace ark::es2panda::aot {
32using mem::MemConfig;
33
34class MemManager {
35public:
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
47    ~MemManager()
48    {
49        PoolManager::Finalize();
50        MemConfig::Finalize();
51    }
52};
53
54static 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
78static 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
113static 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
128static 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
169int main(int argc, const char **argv)
170{
171    ark::es2panda::aot::MemManager mm;
172    return ark::es2panda::aot::Run(argc, argv);
173}
174