1/*
2 * Copyright (c) 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 "abc2program_compiler.h"
17#include "abc_class_processor.h"
18#include "file_format_version.h"
19#include "utils/timers.h"
20
21namespace panda::abc2program {
22
23Abc2ProgramCompiler::~Abc2ProgramCompiler()
24{
25    if (prog_ != nullptr) {
26        delete prog_;
27        prog_ = nullptr;
28    }
29}
30
31bool Abc2ProgramCompiler::OpenAbcFile(const std::string &file_path)
32{
33    file_ = panda_file::File::Open(file_path);
34    if (file_ == nullptr) {
35        return false;
36    }
37    debug_info_extractor_ = std::make_unique<panda_file::DebugInfoExtractor>(file_.get());
38    return true;
39}
40
41bool Abc2ProgramCompiler::CheckFileVersionIsSupported(std::array<uint8_t, panda_file::File::VERSION_SIZE> min_version,
42                                                      uint8_t target_api_version,
43                                                      std::string target_api_sub_version) const
44{
45    auto target_version = panda_file::GetVersionByApi(target_api_version, target_api_sub_version);
46    if (!target_version.has_value()) {
47        return false;
48    }
49    const auto &file_version = file_->GetHeader()->version;
50    return panda::panda_file::IsVersionLessOrEqual(min_version, file_version) &&
51        panda::panda_file::IsVersionLessOrEqual(file_version, target_version.value());
52}
53
54const panda_file::File &Abc2ProgramCompiler::GetAbcFile() const
55{
56    return *file_;
57}
58
59const panda_file::DebugInfoExtractor &Abc2ProgramCompiler::GetDebugInfoExtractor() const
60{
61    return *debug_info_extractor_;
62}
63
64pandasm::Program *Abc2ProgramCompiler::CompileAbcFile()
65{
66    prog_ = new pandasm::Program();
67    prog_->lang = LANG_ECMA;
68    auto classes = file_->GetClasses();
69    std::string record_name = "";
70    for (size_t i = 0; i < classes.size(); i++) {
71        panda_file::File::EntityId record_id(classes[i]);
72        CompileAbcClass(record_id, *prog_, record_name);
73    }
74    return prog_;
75}
76
77void Abc2ProgramCompiler::CompileAbcClass(const panda_file::File::EntityId &record_id,
78                                          pandasm::Program &program, std::string &record_name)
79{
80    Abc2ProgramEntityContainer entity_container(*file_, program, *debug_info_extractor_, record_id.GetOffset());
81    record_name = entity_container.GetFullRecordNameById(record_id);
82    panda::Timer::timerStart(EVENT_COMPILE_ABC_FILE_RECORD, record_name);
83    AbcClassProcessor class_processor(record_id, entity_container);
84    class_processor.FillProgramData();
85    panda::Timer::timerEnd(EVENT_COMPILE_ABC_FILE_RECORD, record_name);
86}
87
88bool Abc2ProgramCompiler::CheckClassId(uint32_t class_id, size_t offset) const
89{
90    auto *header = file_->GetHeader();
91    auto class_off = header->class_idx_off + sizeof(uint32_t) * offset;
92    if (class_id > header->file_size) {
93        LOG(FATAL, ABC2PROGRAM) << "> error encountered in record at " << class_off << " (0x" << std::hex
94                                << class_off << "). binary file corrupted. record offset (0x" << class_id
95                                << ") out of bounds (0x" << header->file_size << ")!";
96    }
97    return !file_->IsExternal(panda_file::File::EntityId(class_id));
98}
99
100} // namespace panda::abc2program
101