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_annotation_processor.h"
17 #include "abc2program_log.h"
18 #include "abc_literal_array_processor.h"
19 #include "file-inl.h"
20 
21 namespace panda::abc2program {
22 
AbcAnnotationProcessor(panda_file::File::EntityId entity_id, Abc2ProgramEntityContainer &entity_container, pandasm::Function &function)23 AbcAnnotationProcessor::AbcAnnotationProcessor(panda_file::File::EntityId entity_id,
24                                                Abc2ProgramEntityContainer &entity_container,
25                                                pandasm::Function &function)
26     : AbcFileEntityProcessor(entity_id, entity_container), function_(function)
27 {
28     annotation_data_accessor_ = std::make_unique<panda_file::AnnotationDataAccessor>(*file_, entity_id_);
29     annotation_name_ = pandasm::Type::FromDescriptor(GetStringById(annotation_data_accessor_->GetClassId())).GetName();
30 }
31 
FillProgramData()32 void AbcAnnotationProcessor::FillProgramData()
33 {
34     if (annotation_name_.empty()) {
35         return;
36     }
37     FillAnnotation();
38 }
39 
FillAnnotation()40 void AbcAnnotationProcessor::FillAnnotation()
41 {
42     std::vector<pandasm::AnnotationElement> elements;
43     FillAnnotationElements(elements);
44     pandasm::AnnotationData annotation_data(annotation_name_, elements);
45     std::vector<pandasm::AnnotationData> annotations;
46     annotations.emplace_back(std::move(annotation_data));
47     function_.metadata->AddAnnotations(annotations);
48 }
49 
FillLiteralArrayAnnotation(std::vector<pandasm::AnnotationElement> &elements, const std::string &annotation_elem_name, uint32_t value)50 void AbcAnnotationProcessor::FillLiteralArrayAnnotation(std::vector<pandasm::AnnotationElement> &elements,
51                                                         const std::string &annotation_elem_name, uint32_t value)
52 {
53     panda_file::LiteralDataAccessor lit_data_accessor(*file_, file_->GetLiteralArraysId());
54     AbcLiteralArrayProcessor lit_array_proc(panda_file::File::EntityId{value}, entity_container_,
55                                             lit_data_accessor);
56     lit_array_proc.FillProgramData();
57     std::string name = entity_container_.GetLiteralArrayIdName(value);
58     pandasm::AnnotationElement annotation_element(
59         annotation_elem_name, std::make_unique<pandasm::ScalarValue>(
60         pandasm::ScalarValue::Create<pandasm::Value::Type::LITERALARRAY>(name)));
61     elements.emplace_back(annotation_element);
62 }
63 
FillAnnotationElements(std::vector<pandasm::AnnotationElement> &elements)64 void AbcAnnotationProcessor::FillAnnotationElements(std::vector<pandasm::AnnotationElement> &elements)
65 {
66     for (uint32_t i = 0; i < annotation_data_accessor_->GetCount(); ++i) {
67         auto annotation_data_accessor_elem = annotation_data_accessor_->GetElement(i);
68         auto annotation_elem_name = GetStringById(annotation_data_accessor_elem.GetNameId());
69         auto value_type = pandasm::Value::GetCharAsType(annotation_data_accessor_->GetTag(i).GetItem());
70         switch (value_type) {
71             case pandasm::Value::Type::U1: {
72                 auto value = annotation_data_accessor_elem.GetScalarValue().Get<bool>();
73                 pandasm::AnnotationElement annotation_element(
74                     annotation_elem_name, std::make_unique<pandasm::ScalarValue>(
75                     pandasm::ScalarValue::Create<pandasm::Value::Type::U1>(value)));
76                 elements.emplace_back(annotation_element);
77                 break;
78             }
79             case pandasm::Value::Type::U32: {
80                 auto value = annotation_data_accessor_elem.GetScalarValue().Get<uint32_t>();
81                 pandasm::AnnotationElement annotation_element(
82                     annotation_elem_name, std::make_unique<pandasm::ScalarValue>(
83                     pandasm::ScalarValue::Create<pandasm::Value::Type::U32>(value)));
84                 elements.emplace_back(annotation_element);
85                 break;
86             }
87             case pandasm::Value::Type::F64: {
88                 auto value = annotation_data_accessor_elem.GetScalarValue().Get<double>();
89                 pandasm::AnnotationElement annotation_element(
90                     annotation_elem_name, std::make_unique<pandasm::ScalarValue>(
91                     pandasm::ScalarValue::Create<pandasm::Value::Type::F64>(value)));
92                 elements.emplace_back(annotation_element);
93                 break;
94             }
95             case pandasm::Value::Type::STRING: {
96                 auto value = annotation_data_accessor_elem.GetScalarValue().Get<uint32_t>();
97                 std::string_view string_value {
98                     reinterpret_cast<const char *>(file_->GetStringData(panda_file::File::EntityId(value)).data)};
99                 pandasm::AnnotationElement annotation_element(
100                     annotation_elem_name, std::make_unique<pandasm::ScalarValue>(
101                     pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(string_value)));
102                 elements.emplace_back(annotation_element);
103                 break;
104             }
105             case pandasm::Value::Type::LITERALARRAY: {
106                 auto value = annotation_data_accessor_elem.GetScalarValue().Get<uint32_t>();
107                 FillLiteralArrayAnnotation(elements, annotation_elem_name, value);
108                 break;
109             }
110             default:
111                 UNREACHABLE();
112         }
113     }
114 }
115 
116 }  // namespace panda::abc2program
117