1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#include "include/runtime.h"
17b1994897Sopenharmony_ci#include "include/thread.h"
18b1994897Sopenharmony_ci#include "include/thread_scopes.h"
19b1994897Sopenharmony_ci#include "runtime/include/locks.h"
20b1994897Sopenharmony_ci#include "runtime/include/method-inl.h"
21b1994897Sopenharmony_ci#include "runtime/include/class.h"
22b1994897Sopenharmony_ci#include "utils/pandargs.h"
23b1994897Sopenharmony_ci#include "compiler/compiler_options.h"
24b1994897Sopenharmony_ci#include "compiler/compiler_logger.h"
25b1994897Sopenharmony_ci#include "compiler_events_gen.h"
26b1994897Sopenharmony_ci#include "mem/mem_stats.h"
27b1994897Sopenharmony_ci#include "libpandabase/os/mutex.h"
28b1994897Sopenharmony_ci#include "libpandabase/os/native_stack.h"
29b1994897Sopenharmony_ci#include "generated/base_options.h"
30b1994897Sopenharmony_ci
31b1994897Sopenharmony_ci#include "ark_version.h"
32b1994897Sopenharmony_ci
33b1994897Sopenharmony_ci#include "verification/jobs/thread_pool.h"
34b1994897Sopenharmony_ci#include "verification/jobs/cache.h"
35b1994897Sopenharmony_ci
36b1994897Sopenharmony_ci#include "utils/span.h"
37b1994897Sopenharmony_ci
38b1994897Sopenharmony_ci#include "utils/logger.h"
39b1994897Sopenharmony_ci
40b1994897Sopenharmony_ci#include <limits>
41b1994897Sopenharmony_ci#include <iostream>
42b1994897Sopenharmony_ci#include <vector>
43b1994897Sopenharmony_ci#include <chrono>
44b1994897Sopenharmony_ci#include <ctime>
45b1994897Sopenharmony_ci#include <csignal>
46b1994897Sopenharmony_ci
47b1994897Sopenharmony_cinamespace panda {
48b1994897Sopenharmony_ciconst panda_file::File *GetPandaFile(const ClassLinker &class_linker, std::string_view file_name)
49b1994897Sopenharmony_ci{
50b1994897Sopenharmony_ci    const panda_file::File *res = nullptr;
51b1994897Sopenharmony_ci    class_linker.EnumerateBootPandaFiles([&res, file_name](const panda_file::File &pf) {
52b1994897Sopenharmony_ci        if (pf.GetFilename() == file_name) {
53b1994897Sopenharmony_ci            res = &pf;
54b1994897Sopenharmony_ci            return false;
55b1994897Sopenharmony_ci        }
56b1994897Sopenharmony_ci        return true;
57b1994897Sopenharmony_ci    });
58b1994897Sopenharmony_ci    return res;
59b1994897Sopenharmony_ci}
60b1994897Sopenharmony_ci
61b1994897Sopenharmony_civoid BlockSignals()
62b1994897Sopenharmony_ci{
63b1994897Sopenharmony_ci#if defined(PANDA_TARGET_UNIX)
64b1994897Sopenharmony_ci    sigset_t set;
65b1994897Sopenharmony_ci    if (sigemptyset(&set) == -1) {
66b1994897Sopenharmony_ci        LOG(ERROR, RUNTIME) << "sigemptyset failed";
67b1994897Sopenharmony_ci        return;
68b1994897Sopenharmony_ci    }
69b1994897Sopenharmony_ci    int rc = 0;
70b1994897Sopenharmony_ci#ifdef PANDA_TARGET_MOBILE
71b1994897Sopenharmony_ci    rc += sigaddset(&set, SIGPIPE);
72b1994897Sopenharmony_ci    rc += sigaddset(&set, SIGQUIT);
73b1994897Sopenharmony_ci    rc += sigaddset(&set, SIGUSR1);
74b1994897Sopenharmony_ci    rc += sigaddset(&set, SIGUSR2);
75b1994897Sopenharmony_ci#endif  // PANDA_TARGET_MOBILE
76b1994897Sopenharmony_ci    if (rc < 0) {
77b1994897Sopenharmony_ci        LOG(ERROR, RUNTIME) << "sigaddset failed";
78b1994897Sopenharmony_ci        return;
79b1994897Sopenharmony_ci    }
80b1994897Sopenharmony_ci
81b1994897Sopenharmony_ci    if (os::native_stack::g_PandaThreadSigmask(SIG_BLOCK, &set, nullptr) != 0) {
82b1994897Sopenharmony_ci        LOG(ERROR, RUNTIME) << "g_PandaThreadSigmask failed";
83b1994897Sopenharmony_ci    }
84b1994897Sopenharmony_ci#endif  // PANDA_TARGET_UNIX
85b1994897Sopenharmony_ci}
86b1994897Sopenharmony_ci
87b1994897Sopenharmony_civoid PrintHelp(const panda::PandArgParser &pa_parser)
88b1994897Sopenharmony_ci{
89b1994897Sopenharmony_ci    std::cerr << pa_parser.GetErrorString() << std::endl;
90b1994897Sopenharmony_ci    std::cerr << "Usage: "
91b1994897Sopenharmony_ci              << "panda"
92b1994897Sopenharmony_ci              << " [OPTIONS] [file] [entrypoint] -- [arguments]" << std::endl;
93b1994897Sopenharmony_ci    std::cerr << std::endl;
94b1994897Sopenharmony_ci    std::cerr << "optional arguments:" << std::endl;
95b1994897Sopenharmony_ci    std::cerr << pa_parser.GetHelpString() << std::endl;
96b1994897Sopenharmony_ci}
97b1994897Sopenharmony_ci
98b1994897Sopenharmony_cibool PrepareArguments(panda::PandArgParser *pa_parser, const RuntimeOptions &runtime_options,
99b1994897Sopenharmony_ci                      const panda::PandArg<std::string> &file, const panda::PandArg<std::string> &entrypoint,
100b1994897Sopenharmony_ci                      const panda::PandArg<bool> &help, int argc, const char **argv)
101b1994897Sopenharmony_ci{
102b1994897Sopenharmony_ci    auto start_time =
103b1994897Sopenharmony_ci        std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch())
104b1994897Sopenharmony_ci            .count();
105b1994897Sopenharmony_ci
106b1994897Sopenharmony_ci    if (!pa_parser->Parse(argc, argv)) {
107b1994897Sopenharmony_ci        PrintHelp(*pa_parser);
108b1994897Sopenharmony_ci        return false;
109b1994897Sopenharmony_ci    }
110b1994897Sopenharmony_ci
111b1994897Sopenharmony_ci    if (runtime_options.IsVersion()) {
112b1994897Sopenharmony_ci        PrintPandaVersion();
113b1994897Sopenharmony_ci        return false;
114b1994897Sopenharmony_ci    }
115b1994897Sopenharmony_ci
116b1994897Sopenharmony_ci    if (file.GetValue().empty() || entrypoint.GetValue().empty() || help.GetValue()) {
117b1994897Sopenharmony_ci        PrintHelp(*pa_parser);
118b1994897Sopenharmony_ci        return false;
119b1994897Sopenharmony_ci    }
120b1994897Sopenharmony_ci
121b1994897Sopenharmony_ci    if (runtime_options.IsStartupTime()) {
122b1994897Sopenharmony_ci        std::cout << "\n"
123b1994897Sopenharmony_ci                  << "Startup start time: " << start_time << std::endl;
124b1994897Sopenharmony_ci    }
125b1994897Sopenharmony_ci
126b1994897Sopenharmony_ci    auto runtime_options_err = runtime_options.Validate();
127b1994897Sopenharmony_ci    if (runtime_options_err) {
128b1994897Sopenharmony_ci        std::cerr << "Error: " << runtime_options_err.value().GetMessage() << std::endl;
129b1994897Sopenharmony_ci        return false;
130b1994897Sopenharmony_ci    }
131b1994897Sopenharmony_ci
132b1994897Sopenharmony_ci    auto compiler_options_err = compiler::options.Validate();
133b1994897Sopenharmony_ci    if (compiler_options_err) {
134b1994897Sopenharmony_ci        std::cerr << "Error: " << compiler_options_err.value().GetMessage() << std::endl;
135b1994897Sopenharmony_ci        return false;
136b1994897Sopenharmony_ci    }
137b1994897Sopenharmony_ci
138b1994897Sopenharmony_ci    return true;
139b1994897Sopenharmony_ci}
140b1994897Sopenharmony_ci
141b1994897Sopenharmony_ciint ExecutePandaFile(panda::PandArg<bool> &options, panda::PandArgParser &pa_parser, panda::PandArg<std::string> &file,
142b1994897Sopenharmony_ci                     panda::PandArg<std::string> &entrypoint, RuntimeOptions &runtime_options)
143b1994897Sopenharmony_ci{
144b1994897Sopenharmony_ci    if (!Runtime::Create(runtime_options)) {
145b1994897Sopenharmony_ci        std::cerr << "Error: cannot create runtime" << std::endl;
146b1994897Sopenharmony_ci        return -1;
147b1994897Sopenharmony_ci    }
148b1994897Sopenharmony_ci
149b1994897Sopenharmony_ci    int ret = 0;
150b1994897Sopenharmony_ci
151b1994897Sopenharmony_ci    if (options.GetValue()) {
152b1994897Sopenharmony_ci        std::cout << pa_parser.GetRegularArgs() << std::endl;
153b1994897Sopenharmony_ci    }
154b1994897Sopenharmony_ci
155b1994897Sopenharmony_ci    std::string file_name = file.GetValue();
156b1994897Sopenharmony_ci    std::string entry = entrypoint.GetValue();
157b1994897Sopenharmony_ci
158b1994897Sopenharmony_ci    auto &runtime = *Runtime::GetCurrent();
159b1994897Sopenharmony_ci    auto &verif_opts = runtime.GetVerificationOptions();
160b1994897Sopenharmony_ci    ASSERT(!verif_opts.IsOnlyVerify());
161b1994897Sopenharmony_ci
162b1994897Sopenharmony_ci    if (verif_opts.IsEnabled()) {
163b1994897Sopenharmony_ci        verifier::ThreadPool::GetCache()->FastAPI().ProcessFiles(runtime.GetClassLinker()->GetBootPandaFiles());
164b1994897Sopenharmony_ci    }
165b1994897Sopenharmony_ci
166b1994897Sopenharmony_ci    arg_list_t arguments = pa_parser.GetRemainder();
167b1994897Sopenharmony_ci    auto res = runtime.ExecutePandaFile(file_name, entry, arguments);
168b1994897Sopenharmony_ci    if (!res) {
169b1994897Sopenharmony_ci        std::cerr << "Cannot execute panda file '" << file_name << "' with entry '" << entry << "'" << std::endl;
170b1994897Sopenharmony_ci        ret = -1;
171b1994897Sopenharmony_ci    } else {
172b1994897Sopenharmony_ci        ret = res.Value();
173b1994897Sopenharmony_ci    }
174b1994897Sopenharmony_ci
175b1994897Sopenharmony_ci    if (runtime_options.IsPrintMemoryStatistics()) {
176b1994897Sopenharmony_ci        std::cout << runtime.GetMemoryStatistics();
177b1994897Sopenharmony_ci    }
178b1994897Sopenharmony_ci    if (runtime_options.IsPrintGcStatistics()) {
179b1994897Sopenharmony_ci        std::cout << runtime.GetFinalStatistics();
180b1994897Sopenharmony_ci    }
181b1994897Sopenharmony_ci    if (!Runtime::Destroy()) {
182b1994897Sopenharmony_ci        std::cerr << "Error: cannot destroy runtime" << std::endl;
183b1994897Sopenharmony_ci        return -1;
184b1994897Sopenharmony_ci    }
185b1994897Sopenharmony_ci    pa_parser.DisableTail();
186b1994897Sopenharmony_ci    return ret;
187b1994897Sopenharmony_ci}
188b1994897Sopenharmony_ci
189b1994897Sopenharmony_ciint Main(int argc, const char **argv)
190b1994897Sopenharmony_ci{
191b1994897Sopenharmony_ci    BlockSignals();
192b1994897Sopenharmony_ci    Span<const char *> sp(argv, argc);
193b1994897Sopenharmony_ci    RuntimeOptions runtime_options(sp[0]);
194b1994897Sopenharmony_ci    base_options::Options base_options(sp[0]);
195b1994897Sopenharmony_ci    panda::PandArgParser pa_parser;
196b1994897Sopenharmony_ci
197b1994897Sopenharmony_ci    panda::PandArg<bool> help("help", false, "Print this message and exit");
198b1994897Sopenharmony_ci    panda::PandArg<bool> options("options", false, "Print compiler and runtime options");
199b1994897Sopenharmony_ci    // tail arguments
200b1994897Sopenharmony_ci    panda::PandArg<std::string> file("file", "", "path to pandafile");
201b1994897Sopenharmony_ci    panda::PandArg<std::string> entrypoint("entrypoint", "", "full name of entrypoint function or method");
202b1994897Sopenharmony_ci
203b1994897Sopenharmony_ci    runtime_options.AddOptions(&pa_parser);
204b1994897Sopenharmony_ci    base_options.AddOptions(&pa_parser);
205b1994897Sopenharmony_ci    compiler::options.AddOptions(&pa_parser);
206b1994897Sopenharmony_ci
207b1994897Sopenharmony_ci    pa_parser.Add(&help);
208b1994897Sopenharmony_ci    pa_parser.Add(&options);
209b1994897Sopenharmony_ci    pa_parser.PushBackTail(&file);
210b1994897Sopenharmony_ci    pa_parser.PushBackTail(&entrypoint);
211b1994897Sopenharmony_ci    pa_parser.EnableTail();
212b1994897Sopenharmony_ci    pa_parser.EnableRemainder();
213b1994897Sopenharmony_ci
214b1994897Sopenharmony_ci    if (!panda::PrepareArguments(&pa_parser, runtime_options, file, entrypoint, help, argc, argv)) {
215b1994897Sopenharmony_ci        return 1;
216b1994897Sopenharmony_ci    }
217b1994897Sopenharmony_ci
218b1994897Sopenharmony_ci    compiler::options.AdjustCpuFeatures(false);
219b1994897Sopenharmony_ci
220b1994897Sopenharmony_ci    Logger::Initialize(base_options);
221b1994897Sopenharmony_ci
222b1994897Sopenharmony_ci    runtime_options.SetVerificationMode(runtime_options.IsVerificationEnabled() ? VerificationMode::ON_THE_FLY
223b1994897Sopenharmony_ci                                                                                : VerificationMode::DISABLED);
224b1994897Sopenharmony_ci
225b1994897Sopenharmony_ci    panda::compiler::CompilerLogger::SetComponents(panda::compiler::options.GetCompilerLog());
226b1994897Sopenharmony_ci    if (compiler::options.IsCompilerEnableEvents()) {
227b1994897Sopenharmony_ci        panda::compiler::EventWriter::Init(panda::compiler::options.GetCompilerEventsPath());
228b1994897Sopenharmony_ci    }
229b1994897Sopenharmony_ci
230b1994897Sopenharmony_ci    auto boot_panda_files = runtime_options.GetBootPandaFiles();
231b1994897Sopenharmony_ci
232b1994897Sopenharmony_ci    if (runtime_options.GetPandaFiles().empty()) {
233b1994897Sopenharmony_ci        boot_panda_files.push_back(file.GetValue());
234b1994897Sopenharmony_ci    } else {
235b1994897Sopenharmony_ci        auto panda_files = runtime_options.GetPandaFiles();
236b1994897Sopenharmony_ci        auto found_iter = std::find_if(panda_files.begin(), panda_files.end(),
237b1994897Sopenharmony_ci                                       [&](auto &file_name) { return file_name == file.GetValue(); });
238b1994897Sopenharmony_ci        if (found_iter == panda_files.end()) {
239b1994897Sopenharmony_ci            panda_files.push_back(file.GetValue());
240b1994897Sopenharmony_ci            runtime_options.SetPandaFiles(panda_files);
241b1994897Sopenharmony_ci        }
242b1994897Sopenharmony_ci    }
243b1994897Sopenharmony_ci
244b1994897Sopenharmony_ci    runtime_options.SetBootPandaFiles(boot_panda_files);
245b1994897Sopenharmony_ci
246b1994897Sopenharmony_ci    return ExecutePandaFile(options, pa_parser, file, entrypoint, runtime_options);
247b1994897Sopenharmony_ci}
248b1994897Sopenharmony_ci}  // namespace panda
249b1994897Sopenharmony_ci
250b1994897Sopenharmony_ciint main(int argc, const char **argv)
251b1994897Sopenharmony_ci{
252b1994897Sopenharmony_ci    return panda::Main(argc, argv);
253b1994897Sopenharmony_ci}
254