14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include <getopt.h>
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/base/string_helper.h"
194514f5e3Sopenharmony_ci#include "ecmascript/ecma_macros.h"
204514f5e3Sopenharmony_ci#include "ecmascript/log_wrapper.h"
214514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
224514f5e3Sopenharmony_ci#include "ecmascript/platform/file.h"
234514f5e3Sopenharmony_ci
244514f5e3Sopenharmony_cinamespace panda::ecmascript::pgo {
254514f5e3Sopenharmony_cistatic const std::string VERSION = "0.0.0.1";
264514f5e3Sopenharmony_cistatic const int MIN_PARAM_COUNT = 3;
274514f5e3Sopenharmony_ciusing ApGenMode = PGOProfilerEncoder::ApGenMode;
284514f5e3Sopenharmony_ci
294514f5e3Sopenharmony_ciclass Option {
304514f5e3Sopenharmony_cipublic:
314514f5e3Sopenharmony_ci    enum class Mode : uint8_t {
324514f5e3Sopenharmony_ci        VERSION_QUERY,
334514f5e3Sopenharmony_ci        TO_BINARY,
344514f5e3Sopenharmony_ci        TO_TEXT,
354514f5e3Sopenharmony_ci        MERGE,
364514f5e3Sopenharmony_ci    };
374514f5e3Sopenharmony_ci
384514f5e3Sopenharmony_ci    std::string GetProfInPath() const
394514f5e3Sopenharmony_ci    {
404514f5e3Sopenharmony_ci        return profInPath_;
414514f5e3Sopenharmony_ci    }
424514f5e3Sopenharmony_ci
434514f5e3Sopenharmony_ci    std::string GetProfOutPath() const
444514f5e3Sopenharmony_ci    {
454514f5e3Sopenharmony_ci        return profOutPath_;
464514f5e3Sopenharmony_ci    }
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ci    uint32_t GetHotnessThreshold() const
494514f5e3Sopenharmony_ci    {
504514f5e3Sopenharmony_ci        return hotnessThreshold_;
514514f5e3Sopenharmony_ci    }
524514f5e3Sopenharmony_ci
534514f5e3Sopenharmony_ci    Mode GetMode() const
544514f5e3Sopenharmony_ci    {
554514f5e3Sopenharmony_ci        return mode_;
564514f5e3Sopenharmony_ci    }
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_ci    bool ParseCommand(const int argc, const char **argv)
594514f5e3Sopenharmony_ci    {
604514f5e3Sopenharmony_ci        if (argc <= 1) {
614514f5e3Sopenharmony_ci            return false;
624514f5e3Sopenharmony_ci        }
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_ci        const struct option longOptions[] = {
654514f5e3Sopenharmony_ci            {"text", required_argument, nullptr, 't'},
664514f5e3Sopenharmony_ci            {"binary", required_argument, nullptr, 'b'},
674514f5e3Sopenharmony_ci            {"hotness-threshold", required_argument, nullptr, 's'},
684514f5e3Sopenharmony_ci            {"merge", no_argument, nullptr, 'm'},
694514f5e3Sopenharmony_ci            {"help", no_argument, nullptr, 'h'},
704514f5e3Sopenharmony_ci            {"version", no_argument, nullptr, 'v'},
714514f5e3Sopenharmony_ci            {nullptr, 0, nullptr, 0},
724514f5e3Sopenharmony_ci        };
734514f5e3Sopenharmony_ci
744514f5e3Sopenharmony_ci        const char *optstr = "tbs:hv";
754514f5e3Sopenharmony_ci        int opt;
764514f5e3Sopenharmony_ci        while ((opt = getopt_long_only(argc, const_cast<char **>(argv), optstr, longOptions, nullptr)) != -1) {
774514f5e3Sopenharmony_ci            switch (opt) {
784514f5e3Sopenharmony_ci                case 't':
794514f5e3Sopenharmony_ci                    mode_ = Mode::TO_TEXT;
804514f5e3Sopenharmony_ci                    break;
814514f5e3Sopenharmony_ci                case 'b':
824514f5e3Sopenharmony_ci                    mode_ = Mode::TO_BINARY;
834514f5e3Sopenharmony_ci                    break;
844514f5e3Sopenharmony_ci                case 's':
854514f5e3Sopenharmony_ci                    if (!base::StringHelper::StrToUInt32(optarg, &hotnessThreshold_)) {
864514f5e3Sopenharmony_ci                        LOG_NO_TAG(ERROR) << "hotness-threshold parse failure";
874514f5e3Sopenharmony_ci                        return false;
884514f5e3Sopenharmony_ci                    }
894514f5e3Sopenharmony_ci                    break;
904514f5e3Sopenharmony_ci                case 'm':
914514f5e3Sopenharmony_ci                    mode_ = Mode::MERGE;
924514f5e3Sopenharmony_ci                    break;
934514f5e3Sopenharmony_ci                case 'h':
944514f5e3Sopenharmony_ci                    return false;
954514f5e3Sopenharmony_ci                case 'v':
964514f5e3Sopenharmony_ci                    mode_ = Mode::VERSION_QUERY;
974514f5e3Sopenharmony_ci                    return true;
984514f5e3Sopenharmony_ci                default:
994514f5e3Sopenharmony_ci                    LOG_NO_TAG(ERROR) << "Invalid option";
1004514f5e3Sopenharmony_ci                    return false;
1014514f5e3Sopenharmony_ci            }
1024514f5e3Sopenharmony_ci        }
1034514f5e3Sopenharmony_ci        if (optind != argc - MIN_PARAM_COUNT + 1) {
1044514f5e3Sopenharmony_ci            return false;
1054514f5e3Sopenharmony_ci        }
1064514f5e3Sopenharmony_ci        profInPath_ = argv[optind];
1074514f5e3Sopenharmony_ci        profOutPath_ = argv[optind + 1];
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_ci        return true;
1104514f5e3Sopenharmony_ci    }
1114514f5e3Sopenharmony_ci
1124514f5e3Sopenharmony_ci    std::string GetHelper() const
1134514f5e3Sopenharmony_ci    {
1144514f5e3Sopenharmony_ci        const std::string PROF_DUMP_HELP_HEAD_MSG =
1154514f5e3Sopenharmony_ci            "Usage: profdump... SOURCE... DEST... [OPTIONS]\n"
1164514f5e3Sopenharmony_ci            "\n"
1174514f5e3Sopenharmony_ci            "optional arguments:\n";
1184514f5e3Sopenharmony_ci        const std::string PROF_DUMP_HELP_OPTION_MSG =
1194514f5e3Sopenharmony_ci            "-t, --text                binary to text.\n"
1204514f5e3Sopenharmony_ci            "-b, --binary              text to binary.\n"
1214514f5e3Sopenharmony_ci            "-s, --hotness-threshold   set minimum number of calls to filter method. default: 2\n"
1224514f5e3Sopenharmony_ci            "-m, --merge               merge multi binary ap files into one.\n"
1234514f5e3Sopenharmony_ci            "-h, --help                display this help and exit\n"
1244514f5e3Sopenharmony_ci            "-v, --version             output version information and exit\n";
1254514f5e3Sopenharmony_ci        return PROF_DUMP_HELP_HEAD_MSG + PROF_DUMP_HELP_OPTION_MSG;
1264514f5e3Sopenharmony_ci    }
1274514f5e3Sopenharmony_ci
1284514f5e3Sopenharmony_ci    const std::string GetVersion() const
1294514f5e3Sopenharmony_ci    {
1304514f5e3Sopenharmony_ci        return VERSION;
1314514f5e3Sopenharmony_ci    }
1324514f5e3Sopenharmony_ci
1334514f5e3Sopenharmony_ciprivate:
1344514f5e3Sopenharmony_ci    Mode mode_ { Mode::TO_TEXT };
1354514f5e3Sopenharmony_ci    uint32_t hotnessThreshold_ { 1 };
1364514f5e3Sopenharmony_ci    std::string profInPath_;
1374514f5e3Sopenharmony_ci    std::string profOutPath_;
1384514f5e3Sopenharmony_ci};
1394514f5e3Sopenharmony_ci
1404514f5e3Sopenharmony_ciint Main(const int argc, const char **argv)
1414514f5e3Sopenharmony_ci{
1424514f5e3Sopenharmony_ci    Option option;
1434514f5e3Sopenharmony_ci    if (!option.ParseCommand(argc, argv)) {
1444514f5e3Sopenharmony_ci        LOG_NO_TAG(ERROR) << option.GetHelper();
1454514f5e3Sopenharmony_ci        return  -1;
1464514f5e3Sopenharmony_ci    }
1474514f5e3Sopenharmony_ci    switch (option.GetMode()) {
1484514f5e3Sopenharmony_ci        case Option::Mode::VERSION_QUERY:
1494514f5e3Sopenharmony_ci            LOG_NO_TAG(ERROR) << "Ver: " << VERSION;
1504514f5e3Sopenharmony_ci            break;
1514514f5e3Sopenharmony_ci        case Option::Mode::TO_TEXT: {
1524514f5e3Sopenharmony_ci            if (PGOProfilerManager::GetInstance()->BinaryToText(option.GetProfInPath(),
1534514f5e3Sopenharmony_ci                option.GetProfOutPath(), option.GetHotnessThreshold())) {
1544514f5e3Sopenharmony_ci                LOG_NO_TAG(ERROR) << "profiler dump to text success!";
1554514f5e3Sopenharmony_ci            } else {
1564514f5e3Sopenharmony_ci                LOG_NO_TAG(ERROR) << "profiler dump to text failed!";
1574514f5e3Sopenharmony_ci            }
1584514f5e3Sopenharmony_ci            break;
1594514f5e3Sopenharmony_ci        }
1604514f5e3Sopenharmony_ci        case Option::Mode::TO_BINARY: {
1614514f5e3Sopenharmony_ci            if (PGOProfilerManager::GetInstance()->TextToBinary(option.GetProfInPath(), option.GetProfOutPath(),
1624514f5e3Sopenharmony_ci                                                                option.GetHotnessThreshold(), ApGenMode::OVERWRITE)) {
1634514f5e3Sopenharmony_ci                LOG_NO_TAG(ERROR) << "profiler dump to binary success!";
1644514f5e3Sopenharmony_ci            } else {
1654514f5e3Sopenharmony_ci                LOG_NO_TAG(ERROR) << "profiler dump to binary failed!";
1664514f5e3Sopenharmony_ci            }
1674514f5e3Sopenharmony_ci            break;
1684514f5e3Sopenharmony_ci        }
1694514f5e3Sopenharmony_ci        case Option::Mode::MERGE: {
1704514f5e3Sopenharmony_ci            // For CLI tools, do not merge with existed output file
1714514f5e3Sopenharmony_ci            if (PGOProfilerManager::MergeApFiles(option.GetProfInPath(), option.GetProfOutPath(),
1724514f5e3Sopenharmony_ci                                                 option.GetHotnessThreshold(), ApGenMode::OVERWRITE)) {
1734514f5e3Sopenharmony_ci                LOG_NO_TAG(ERROR) << "profiler merge success!";
1744514f5e3Sopenharmony_ci            }
1754514f5e3Sopenharmony_ci            break;
1764514f5e3Sopenharmony_ci        }
1774514f5e3Sopenharmony_ci        default:
1784514f5e3Sopenharmony_ci            break;
1794514f5e3Sopenharmony_ci    }
1804514f5e3Sopenharmony_ci    return 0;
1814514f5e3Sopenharmony_ci}
1824514f5e3Sopenharmony_ci} // namespace panda::ecmascript::pgo
1834514f5e3Sopenharmony_ci
1844514f5e3Sopenharmony_ciint main(int argc, const char **argv)
1854514f5e3Sopenharmony_ci{
1864514f5e3Sopenharmony_ci    return panda::ecmascript::pgo::Main(argc, argv);
1874514f5e3Sopenharmony_ci}
188