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_method_processor.h"
17 #include "abc_code_processor.h"
18
19 namespace panda::abc2program {
20
AbcMethodProcessor(panda_file::File::EntityId entity_id,Abc2ProgramEntityContainer & entity_container)21 AbcMethodProcessor::AbcMethodProcessor(panda_file::File::EntityId entity_id,
22 Abc2ProgramEntityContainer &entity_container)
23 : AbcFileEntityProcessor(entity_id, entity_container),
24 type_converter_(entity_container),
25 function_(pandasm::Function(entity_container_.GetFullMethodNameById(entity_id_), DEFUALT_SOURCE_LANG)),
26 debug_info_extractor_(entity_container.GetDebugInfoExtractor())
27 {
28 method_data_accessor_ = std::make_unique<panda_file::MethodDataAccessor>(*file_, entity_id_);
29 function_.language = method_data_accessor_->GetSourceLang().value_or(DEFUALT_SOURCE_LANG);
30 }
31
FillProgramData()32 void AbcMethodProcessor::FillProgramData()
33 {
34 FillFunctionData();
35 program_->function_table.emplace(function_.name, std::move(function_));
36 }
37
FillFunctionData()38 void AbcMethodProcessor::FillFunctionData()
39 {
40 FillProto();
41 FillFunctionKind();
42 FillFunctionMetaData();
43 FillCodeData();
44 FillDebugInfo();
45 FillFuncAnnotation();
46 FillAnnotationData();
47 }
48
FillProto()49 void AbcMethodProcessor::FillProto()
50 {
51 uint32_t params_num = GetNumArgs();
52 pandasm::Type any_type = pandasm::Type(ANY_TYPE_NAME, 0);
53 function_.return_type = any_type;
54 for (uint8_t i = 0; i < params_num; i++) {
55 function_.params.emplace_back(
56 pandasm::Function::Parameter(any_type, function_.language)
57 );
58 }
59 }
60
GetNumArgs() const61 uint32_t AbcMethodProcessor::GetNumArgs() const
62 {
63 std::optional<panda_file::File::EntityId> code_id = method_data_accessor_->GetCodeId();
64 if (!code_id.has_value()) {
65 return 0;
66 }
67 panda_file::File::EntityId code_id_value = code_id.value();
68 panda_file::CodeDataAccessor code_data_accessor(*file_, code_id_value);
69 return code_data_accessor.GetNumArgs();
70 }
71
FillFunctionKind()72 void AbcMethodProcessor::FillFunctionKind()
73 {
74 uint32_t method_acc_flags = method_data_accessor_->GetAccessFlags();
75 uint32_t func_kind_u32 = ((method_acc_flags & panda_file::FUNCTION_KIND_MASK) >> panda_file::FLAG_WIDTH);
76 panda_file::FunctionKind func_kind = static_cast<panda_file::FunctionKind>(func_kind_u32);
77 function_.SetFunctionKind(func_kind);
78 }
79
FillFunctionMetaData()80 void AbcMethodProcessor::FillFunctionMetaData()
81 {
82 FillFunctionAttributes();
83 FillAccessFlags();
84 }
85
FillFunctionAttributes()86 void AbcMethodProcessor::FillFunctionAttributes()
87 {
88 if (method_data_accessor_->IsStatic()) {
89 function_.metadata->SetAttribute(ABC_ATTR_STATIC);
90 }
91 if (file_->IsExternal(method_data_accessor_->GetMethodId())) {
92 function_.metadata->SetAttribute(ABC_ATTR_EXTERNAL);
93 }
94 }
95
FillAccessFlags()96 void AbcMethodProcessor::FillAccessFlags()
97 {
98 uint32_t access_flags = method_data_accessor_->GetAccessFlags();
99 access_flags = (access_flags & panda_file::FLAG_MASK);
100 function_.metadata->SetAccessFlags(access_flags);
101 }
102
FillCodeData()103 void AbcMethodProcessor::FillCodeData()
104 {
105 std::optional<panda_file::File::EntityId> code_id = method_data_accessor_->GetCodeId();
106 if (code_id.has_value()) {
107 AbcCodeProcessor code_processor(code_id.value(), entity_container_, entity_id_, function_);
108 code_processor.FillProgramData();
109 }
110 }
111
FillDebugInfo()112 void AbcMethodProcessor::FillDebugInfo()
113 {
114 FillSourceFile();
115 FillSourceCode();
116 }
117
FillSourceFile()118 void AbcMethodProcessor::FillSourceFile()
119 {
120 function_.source_file = debug_info_extractor_.GetSourceFile(entity_id_);
121 }
122
FillSourceCode()123 void AbcMethodProcessor::FillSourceCode()
124 {
125 function_.source_code = debug_info_extractor_.GetSourceCode(entity_id_);
126 }
127
FillFuncAnnotation()128 void AbcMethodProcessor::FillFuncAnnotation()
129 {
130 method_data_accessor_->EnumerateAnnotations([&](panda_file::File::EntityId annotation_id) {
131 AbcAnnotationProcessor annotation_processor(annotation_id, entity_container_, function_);
132 annotation_processor.FillProgramData();
133 });
134 }
135
FillAnnotationData()136 void AbcMethodProcessor::FillAnnotationData()
137 {
138 for (auto annotation : function_.metadata->GetAnnotations()) {
139 const auto& name = annotation.GetName();
140 const auto& elements = annotation.GetElements();
141
142 if (name == SLOT_NUMBER_RECORD_NAME && !elements.empty()) {
143 uint32_t slots_num = elements[0].GetValue()->GetAsScalar()->GetValue<uint32_t>();
144 function_.SetSlotsNum(static_cast<size_t>(slots_num));
145 } else if (name == CONCURRENT_MODULE_REQUEST_RECORD_NAME) {
146 for (auto &elem : elements) {
147 function_.concurrent_module_requests.emplace_back(
148 elem.GetValue()->GetAsScalar()->GetValue<uint32_t>());
149 }
150 } else if (name == EXPECTED_PROPERTY_COUNT_RECORD_NAME && !elements.empty()) {
151 uint32_t expected_property = elements[0].GetValue()->GetAsScalar()->GetValue<uint32_t>();
152 function_.SetExpectedPropertyCount(static_cast<size_t>(expected_property));
153 }
154 }
155 }
156 } // namespace panda::abc2program