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