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 "abc_field_processor.h"
17 #include "abc2program_log.h"
18 #include "abc_literal_array_processor.h"
19 #include "file-inl.h"
20 #include "literal_data_accessor.h"
21
22 namespace panda::abc2program {
23
AbcFieldProcessor(panda_file::File::EntityId entity_id, Abc2ProgramEntityContainer &entity_container, pandasm::Record &record)24 AbcFieldProcessor::AbcFieldProcessor(panda_file::File::EntityId entity_id, Abc2ProgramEntityContainer &entity_container,
25 pandasm::Record &record)
26 : AbcFileEntityProcessor(entity_id, entity_container), record_(record),
27 type_converter_(entity_container),
28 field_(pandasm::Field(LANG_ECMA))
29 {
30 field_data_accessor_ = std::make_unique<panda_file::FieldDataAccessor>(*file_, entity_id_);
31 }
32
FillProgramData()33 void AbcFieldProcessor::FillProgramData()
34 {
35 FillFieldData();
36 record_.field_list.emplace_back(std::move(field_));
37 }
38
FillFieldData()39 void AbcFieldProcessor::FillFieldData()
40 {
41 FillFieldName();
42 FillFieldType();
43 FillFieldMetaData();
44 }
45
FillFieldName()46 void AbcFieldProcessor::FillFieldName()
47 {
48 panda_file::File::EntityId field_name_id = field_data_accessor_->GetNameId();
49 field_.name = GetStringById(field_name_id);
50 }
51
FillFieldType()52 void AbcFieldProcessor::FillFieldType()
53 {
54 uint32_t field_type = field_data_accessor_->GetType();
55 field_.type = type_converter_.FieldTypeToPandasmType(field_type);
56 }
57
FillFieldMetaData()58 void AbcFieldProcessor::FillFieldMetaData()
59 {
60 field_.metadata->SetFieldType(field_.type);
61 FillFieldAttributes();
62 FillMetaDataValue();
63 }
64
FillFieldAttributes()65 void AbcFieldProcessor::FillFieldAttributes()
66 {
67 if (field_data_accessor_->IsExternal()) {
68 field_.metadata->SetAttribute(ABC_ATTR_EXTERNAL);
69 }
70 if (field_data_accessor_->IsStatic()) {
71 field_.metadata->SetAttribute(ABC_ATTR_STATIC);
72 }
73 }
74
FillU32MetaData()75 void AbcFieldProcessor::FillU32MetaData()
76 {
77 uint32_t val = field_data_accessor_->GetValue<uint32_t>().value();
78 if (record_.name == ES_MODULE_RECORD || field_.name == MODULE_RECORD_IDX) {
79 entity_container_.AddModuleLiteralArrayId(val);
80 auto module_literal_array_id_name = entity_container_.GetLiteralArrayIdName(val);
81 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(
82 module_literal_array_id_name));
83 } else if (record_.name == ES_SCOPE_NAMES_RECORD || field_.name == SCOPE_NAMES) {
84 entity_container_.AddUnnestedLiteralArrayId(val);
85 auto literal_array_id_name = entity_container_.GetLiteralArrayIdName(val);
86 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(
87 literal_array_id_name));
88 } else if (field_.name == MODULE_REQUEST_PAHSE_IDX) {
89 entity_container_.AddModuleRequestPhaseId(val);
90 auto module_literal_array_id_name = entity_container_.GetLiteralArrayIdName(val);
91 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(
92 module_literal_array_id_name));
93 } else if (field_.name == JSON_FILE_CONTENT) {
94 auto json_string_id = panda_file::File::EntityId(val);
95 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(
96 entity_container_.GetStringById(json_string_id)));
97 } else {
98 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::U32>(val));
99 }
100 }
101
FillStringMetaData()102 void AbcFieldProcessor::FillStringMetaData()
103 {
104 std::optional<uint32_t> string_offset_val = field_data_accessor_->GetValue<uint32_t>();
105 if (string_offset_val.has_value()) {
106 std::string_view val {reinterpret_cast<const char *>(
107 file_->GetStringData(panda_file::File::EntityId(string_offset_val.value())).data)};
108 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(val));
109 }
110 }
111
FillLiteralArrayMetaData()112 void AbcFieldProcessor::FillLiteralArrayMetaData()
113 {
114 std::optional<uint32_t> litarray_offset_val = field_data_accessor_->GetValue<uint32_t>();
115 if (litarray_offset_val.has_value()) {
116 panda_file::LiteralDataAccessor literal_data_accessor(*file_, file_->GetLiteralArraysId());
117 AbcLiteralArrayProcessor abcLitarrayProcessor{panda_file::File::EntityId{litarray_offset_val.value()},
118 entity_container_, literal_data_accessor};
119 abcLitarrayProcessor.FillProgramData();
120 std::string name = entity_container_.GetLiteralArrayIdName(litarray_offset_val.value());
121 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(
122 std::string_view {name}));
123 }
124 }
125
FillMetaDataValue()126 void AbcFieldProcessor::FillMetaDataValue()
127 {
128 switch (field_.type.GetId()) {
129 case panda_file::Type::TypeId::U32: {
130 FillU32MetaData();
131 break;
132 }
133 case panda_file::Type::TypeId::U8: {
134 const uint8_t val = field_data_accessor_->GetValue<uint8_t>().value();
135 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::U8>(val));
136 break;
137 }
138 case panda_file::Type::TypeId::F64: {
139 std::optional<double> val = field_data_accessor_->GetValue<double>();
140 if (val.has_value()) {
141 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::F64>(val.value()));
142 }
143 break;
144 }
145 case panda_file::Type::TypeId::U1: {
146 std::optional<bool> val = field_data_accessor_->GetValue<bool>();
147 if (val.has_value()) {
148 field_.metadata->SetValue(pandasm::ScalarValue::Create<pandasm::Value::Type::U1>(val.value()));
149 }
150 break;
151 }
152 case panda_file::Type::TypeId::REFERENCE: {
153 if (field_.type.GetName() == "panda.String") {
154 FillStringMetaData();
155 }
156 if (field_.type.IsArray()) {
157 FillLiteralArrayMetaData();
158 }
159 break;
160 }
161 default:
162 UNREACHABLE();
163 }
164 }
165
FillFieldAnnotations()166 void AbcFieldProcessor::FillFieldAnnotations()
167 {
168 log::Unimplemented(__PRETTY_FUNCTION__);
169 }
170
171 } // namespace panda::abc2program
172