1 /*
2 * Copyright (c) 2021 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 "meta.h"
17
18 #include <stdlib.h>
19
20 #include <algorithm>
21 #include <limits>
22
23 #include "utils/expected.h"
24
25 namespace panda::pandasm {
26
ValidateSize(std::string_view value) const27 std::optional<Metadata::Error> Metadata::ValidateSize(std::string_view value) const
28 {
29 constexpr size_t SIZE = 10;
30
31 if (!std::all_of(value.cbegin(), value.cend(), ::isdigit)) {
32 return Error("Unsigned interger value expected", Error::Type::INVALID_VALUE);
33 }
34
35 strtoul(value.data(), nullptr, SIZE);
36 if (errno == ERANGE) {
37 return Error("Value is out of range", Error::Type::INVALID_VALUE);
38 }
39
40 return {};
41 }
42
IsForeign() const43 bool ItemMetadata::IsForeign() const
44 {
45 return GetAttribute("external");
46 }
47
GetType(std::string_view value)48 static panda::pandasm::Value::Type GetType(std::string_view value)
49 {
50 using VType = panda::pandasm::Value::Type;
51 static std::unordered_map<std::string_view, VType> types {
52 {"u1", VType::U1}, {"i8", VType::I8}, {"u8", VType::U8},
53 {"i16", VType::I16}, {"u16", VType::U16}, {"i32", VType::I32},
54 {"u32", VType::U32}, {"i64", VType::I64}, {"u64", VType::U64},
55 {"f32", VType::F32}, {"f64", VType::F64}, {"string", VType::STRING},
56 {"class", VType::RECORD}, {"enum", VType::ENUM}, {"annotation", VType::ANNOTATION},
57 {"array", VType::ARRAY}, {"method", VType::METHOD}};
58
59 return types[value];
60 }
61
62 template <class T>
ConvertFromString(std::string_view value,char ** end)63 static T ConvertFromString(std::string_view value, char **end)
64 {
65 static_assert(std::is_integral_v<T>, "T must be integral type");
66
67 constexpr T MIN = std::numeric_limits<T>::min();
68 constexpr T MAX = std::numeric_limits<T>::max();
69
70 if constexpr (std::is_signed_v<T>) {
71 auto v = ConvertFromString<int64_t>(value, end);
72 if (v < MIN || v > MAX) {
73 errno = ERANGE;
74 }
75 return static_cast<T>(v);
76 }
77
78 if constexpr (!std::is_signed_v<T>) {
79 auto v = ConvertFromString<uint64_t>(value, end);
80 if (v < MIN || v > MAX) {
81 errno = ERANGE;
82 }
83 return static_cast<T>(v);
84 }
85 }
86
87 template <>
ConvertFromString(std::string_view value,char ** end)88 int64_t ConvertFromString(std::string_view value, char **end)
89 {
90 return static_cast<int64_t>(strtoll(value.data(), end, 0));
91 }
92
93 template <>
ConvertFromString(std::string_view value,char ** end)94 uint64_t ConvertFromString(std::string_view value, char **end)
95 {
96 return static_cast<uint64_t>(strtoull(value.data(), end, 0));
97 }
98
99 template <>
ConvertFromString(std::string_view value,char ** end)100 float ConvertFromString(std::string_view value, char **end)
101 {
102 return strtof(value.data(), end);
103 }
104
105 template <>
ConvertFromString(std::string_view value,char ** end)106 double ConvertFromString(std::string_view value, char **end)
107 {
108 return strtod(value.data(), end);
109 }
110
111 template <class T>
ConvertFromString(std::string_view value)112 static Expected<T, Metadata::Error> ConvertFromString(std::string_view value)
113 {
114 static_assert(std::is_arithmetic_v<T>, "T must be arithmetic type");
115
116 char *end = nullptr;
117 auto v = ConvertFromString<T>(value, &end);
118
119 if (end != value.data() + value.length()) {
120 return Unexpected(Metadata::Error("Excepted integer literal", Metadata::Error::Type::INVALID_VALUE));
121 }
122
123 if (errno == ERANGE) {
124 errno = 0;
125 return Unexpected(Metadata::Error("Value is out of range", Metadata::Error::Type::INVALID_VALUE));
126 }
127
128 return static_cast<T>(v);
129 }
130
131 template <Value::Type type, class T = ValueTypeHelperT<type>>
CreatePrimitiveValue(std::string_view value,T max_value=std::numeric_limits<T>::max ())132 static Expected<ScalarValue, Metadata::Error> CreatePrimitiveValue(std::string_view value,
133 T max_value = std::numeric_limits<T>::max())
134 {
135 auto res = ConvertFromString<T>(value);
136 if (!res) {
137 return Unexpected(res.Error());
138 }
139
140 auto converted = res.Value();
141 if (converted > max_value) {
142 return Unexpected(Metadata::Error("Value is out of range", Metadata::Error::Type::INVALID_VALUE));
143 }
144
145 return ScalarValue::Create<type>(converted);
146 }
147
148 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE)
CreateValue(Value::Type type,std::string_view value,const std::unordered_map<std::string,std::unique_ptr<AnnotationData>> & annotation_id_map={})149 static Expected<ScalarValue, Metadata::Error> CreateValue(
150 Value::Type type, std::string_view value,
151 const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map = {})
152 {
153 switch (type) {
154 case Value::Type::U1: {
155 return CreatePrimitiveValue<Value::Type::U1>(value, 1);
156 }
157 case Value::Type::I8: {
158 return CreatePrimitiveValue<Value::Type::I8>(value);
159 }
160 case Value::Type::U8: {
161 return CreatePrimitiveValue<Value::Type::U8>(value);
162 }
163 case Value::Type::I16: {
164 return CreatePrimitiveValue<Value::Type::I16>(value);
165 }
166 case Value::Type::U16: {
167 return CreatePrimitiveValue<Value::Type::U16>(value);
168 }
169 case Value::Type::I32: {
170 return CreatePrimitiveValue<Value::Type::I32>(value);
171 }
172 case Value::Type::U32: {
173 return CreatePrimitiveValue<Value::Type::U32>(value);
174 }
175 case Value::Type::I64: {
176 return CreatePrimitiveValue<Value::Type::I64>(value);
177 }
178 case Value::Type::U64: {
179 return CreatePrimitiveValue<Value::Type::U64>(value);
180 }
181 case Value::Type::F32: {
182 return CreatePrimitiveValue<Value::Type::F32>(value);
183 }
184 case Value::Type::F64: {
185 return CreatePrimitiveValue<Value::Type::F64>(value);
186 }
187 case Value::Type::STRING: {
188 return ScalarValue::Create<Value::Type::STRING>(value);
189 }
190 case Value::Type::RECORD: {
191 return ScalarValue::Create<Value::Type::RECORD>(Type::FromName(value));
192 }
193 case Value::Type::METHOD: {
194 return ScalarValue::Create<Value::Type::METHOD>(value);
195 }
196 case Value::Type::ENUM: {
197 return ScalarValue::Create<Value::Type::ENUM>(value);
198 }
199 case Value::Type::ANNOTATION: {
200 auto it = annotation_id_map.find(std::string(value));
201 if (it == annotation_id_map.cend()) {
202 return Unexpected(Metadata::Error("Unknown annotation id", Metadata::Error::Type::INVALID_VALUE));
203 }
204
205 auto annotation_value = it->second.get();
206 return ScalarValue::Create<Value::Type::ANNOTATION>(*annotation_value);
207 }
208 default: {
209 break;
210 }
211 }
212
213 UNREACHABLE();
214 }
215
AddValue(std::string_view value,const std::unordered_map<std::string,std::unique_ptr<AnnotationData>> & annotation_id_map)216 std::optional<Metadata::Error> AnnotationMetadata::AnnotationElementBuilder::AddValue(
217 std::string_view value, const std::unordered_map<std::string, std::unique_ptr<AnnotationData>> &annotation_id_map)
218 {
219 ASSERT(type_.has_value());
220
221 auto type = type_.value();
222 if (type == Value::Type::ARRAY) {
223 ASSERT(component_type_.has_value());
224 type = component_type_.value();
225 }
226
227 auto res = CreateValue(type, value, annotation_id_map);
228 if (!res) {
229 return res.Error();
230 }
231
232 values_.push_back(res.Value());
233
234 return {};
235 }
236
Store(std::string_view attribute)237 std::optional<Metadata::Error> AnnotationMetadata::Store(std::string_view attribute)
238 {
239 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
240 return Error(std::string("Unexpected attribute '").append(attribute) +
241 "'. Annotation element isn't completely defined",
242 Error::Type::UNEXPECTED_ATTRIBUTE);
243 }
244
245 if (IsParseAnnotation()) {
246 ResetAnnotationBuilder();
247 }
248
249 return Metadata::Store(attribute);
250 }
251
MeetExpRecordAttribute(std::string_view attribute,std::string_view value)252 std::optional<Metadata::Error> AnnotationMetadata::MeetExpRecordAttribute(std::string_view attribute,
253 std::string_view value)
254 {
255 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
256 return Error(std::string("Unexpected attribute '").append(attribute) +
257 "'. Annotation element isn't completely defined",
258 Error::Type::UNEXPECTED_ATTRIBUTE);
259 }
260
261 InitializeAnnotationBuilder(value);
262
263 return {};
264 }
265
MeetExpIdAttribute(std::string_view attribute,std::string_view value)266 std::optional<Metadata::Error> AnnotationMetadata::MeetExpIdAttribute(std::string_view attribute,
267 std::string_view value)
268 {
269 if (!IsParseAnnotation() || IsParseAnnotationElement()) {
270 return Error(std::string("Unexpected attribute '").append(attribute) +
271 "'. Annotation record attribute must be defined first",
272 Error::Type::UNEXPECTED_ATTRIBUTE);
273 }
274
275 if (annotation_builder_.HasId()) {
276 return Error(std::string("Unexpected attribute '").append(attribute) +
277 "'. Annotation id attribute already defined",
278 Error::Type::UNEXPECTED_ATTRIBUTE);
279 }
280
281 annotation_builder_.SetId(value);
282
283 return {};
284 }
285
MeetExpElementNameAttribute(std::string_view attribute,std::string_view value)286 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementNameAttribute(std::string_view attribute,
287 std::string_view value)
288 {
289 if (!IsParseAnnotation()) {
290 return Error(std::string("Unexpected attribute '").append(attribute) +
291 "'. Annotation record attribute must be defined first",
292 Error::Type::UNEXPECTED_ATTRIBUTE);
293 }
294
295 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
296 return Error(std::string("Unexpected attribute '").append(attribute) +
297 "'. Previous annotation element isn't defined completely",
298 Error::Type::UNEXPECTED_ATTRIBUTE);
299 }
300
301 InitializeAnnotationElementBuilder(value);
302
303 return {};
304 }
305
MeetExpElementTypeAttribute(std::string_view attribute,std::string_view value)306 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementTypeAttribute(std::string_view attribute,
307 std::string_view value)
308 {
309 if (!IsParseAnnotationElement()) {
310 return Error(std::string("Unexpected attribute '").append(attribute) +
311 "'. Annotation element name attribute must be defined first",
312 Error::Type::UNEXPECTED_ATTRIBUTE);
313 }
314
315 if (annotation_element_builder_.IsTypeSet()) {
316 return Error(std::string("Unexpected attribute '").append(attribute) +
317 "'. Annotation element type attribute already defined",
318 Error::Type::UNEXPECTED_ATTRIBUTE);
319 }
320
321 annotation_element_builder_.SetType(GetType(value));
322
323 return {};
324 }
325
MeetExpElementArrayComponentTypeAttribute(std::string_view attribute,std::string_view value)326 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementArrayComponentTypeAttribute(std::string_view attribute,
327 std::string_view value)
328 {
329 if (!IsParseAnnotationElement()) {
330 return Error(std::string("Unexpected attribute '").append(attribute) +
331 "'. Annotation element name attribute must be defined first",
332 Error::Type::UNEXPECTED_ATTRIBUTE);
333 }
334
335 if (!annotation_element_builder_.IsArray()) {
336 return Error(std::string("Unexpected attribute '").append(attribute) + "'. Annotation element type isn't array",
337 Error::Type::UNEXPECTED_ATTRIBUTE);
338 }
339
340 if (annotation_element_builder_.IsComponentTypeSet()) {
341 return Error(std::string("Unexpected attribute '").append(attribute) +
342 "'. Annotation element array component type attribute already defined",
343 Error::Type::UNEXPECTED_ATTRIBUTE);
344 }
345
346 annotation_element_builder_.SetComponentType(GetType(value));
347
348 return {};
349 }
350
MeetExpElementValueAttribute(std::string_view attribute,std::string_view value)351 std::optional<Metadata::Error> AnnotationMetadata::MeetExpElementValueAttribute(std::string_view attribute,
352 std::string_view value)
353 {
354 if (!IsParseAnnotationElement()) {
355 return Error(std::string("Unexpected attribute '").append(attribute) +
356 "'. Annotation element name attribute must be defined first",
357 Error::Type::UNEXPECTED_ATTRIBUTE);
358 }
359
360 if (!annotation_element_builder_.IsTypeSet()) {
361 return Error(std::string("Unexpected attribute '").append(attribute) +
362 "'. Annotation element type attribute isn't defined",
363 Error::Type::UNEXPECTED_ATTRIBUTE);
364 }
365
366 if (annotation_element_builder_.IsArray() && !annotation_element_builder_.IsComponentTypeSet()) {
367 return Error(std::string("Unexpected attribute '").append(attribute) +
368 "'. Annotation element array component type attribute isn't defined",
369 Error::Type::UNEXPECTED_ATTRIBUTE);
370 }
371
372 if (!annotation_element_builder_.IsArray() && annotation_element_builder_.IsCompleted()) {
373 return Error(std::string("Unexpected attribute '").append(attribute) +
374 "'. Annotation element is completely defined",
375 Error::Type::UNEXPECTED_ATTRIBUTE);
376 }
377
378 return annotation_element_builder_.AddValue(value, id_map_);
379 }
380
StoreValue(std::string_view attribute,std::string_view value)381 std::optional<Metadata::Error> AnnotationMetadata::StoreValue(std::string_view attribute, std::string_view value)
382 {
383 auto err = Metadata::StoreValue(attribute, value);
384 if (err) {
385 return err;
386 }
387
388 if (IsAnnotationRecordAttribute(attribute)) {
389 return MeetExpRecordAttribute(attribute, value);
390 }
391
392 if (IsAnnotationIdAttribute(attribute)) {
393 return MeetExpIdAttribute(attribute, value);
394 }
395
396 if (IsAnnotationElementNameAttribute(attribute)) {
397 return MeetExpElementNameAttribute(attribute, value);
398 }
399
400 if (IsAnnotationElementTypeAttribute(attribute)) {
401 return MeetExpElementTypeAttribute(attribute, value);
402 }
403
404 if (IsAnnotationElementArrayComponentTypeAttribute(attribute)) {
405 return MeetExpElementArrayComponentTypeAttribute(attribute, value);
406 }
407
408 if (IsAnnotationElementValueAttribute(attribute)) {
409 return MeetExpElementValueAttribute(attribute, value);
410 }
411
412 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
413 return Error(std::string("Unexpected attribute '").append(attribute) +
414 "'. Annotation element isn't completely defined",
415 Error::Type::UNEXPECTED_ATTRIBUTE);
416 }
417
418 if (IsParseAnnotation()) {
419 ResetAnnotationBuilder();
420 }
421
422 return {};
423 }
424
ValidateData()425 std::optional<Metadata::Error> AnnotationMetadata::ValidateData()
426 {
427 if (IsParseAnnotationElement() && !annotation_element_builder_.IsCompleted()) {
428 return Error("Annotation element isn't completely defined", Error::Type::MISSING_ATTRIBUTE);
429 }
430
431 if (IsParseAnnotation()) {
432 ResetAnnotationBuilder();
433 }
434
435 return Metadata::ValidateData();
436 }
437
GetBase() const438 std::string RecordMetadata::GetBase() const
439 {
440 return "";
441 }
442
GetInterfaces() const443 std::vector<std::string> RecordMetadata::GetInterfaces() const
444 {
445 return {};
446 }
447
IsAnnotation() const448 bool RecordMetadata::IsAnnotation() const
449 {
450 return false;
451 }
452
IsRuntimeAnnotation() const453 bool RecordMetadata::IsRuntimeAnnotation() const
454 {
455 return false;
456 }
457
IsTypeAnnotation() const458 bool RecordMetadata::IsTypeAnnotation() const
459 {
460 return false;
461 }
462
IsRuntimeTypeAnnotation() const463 bool RecordMetadata::IsRuntimeTypeAnnotation() const
464 {
465 return false;
466 }
467
HasImplementation() const468 bool FunctionMetadata::HasImplementation() const
469 {
470 return !(ACC_ABSTRACT & GetAccessFlags()) && !(ACC_NATIVE & GetAccessFlags());
471 }
472
IsCtor() const473 bool FunctionMetadata::IsCtor() const
474 {
475 return GetAttribute("ctor");
476 }
477
IsCctor() const478 bool FunctionMetadata::IsCctor() const
479 {
480 return GetAttribute("cctor");
481 }
482
StoreValue(std::string_view attribute,std::string_view value)483 std::optional<Metadata::Error> FieldMetadata::StoreValue(std::string_view attribute, std::string_view value)
484 {
485 auto err = ItemMetadata::StoreValue(attribute, value);
486 if (err) {
487 return err;
488 }
489
490 if (IsValueAttribute(attribute)) {
491 Value::Type value_type;
492 if (!field_type_.IsObject()) {
493 value_type = GetType(field_type_.GetName());
494 } else {
495 value_type = Value::Type::STRING;
496 }
497
498 auto res = CreateValue(value_type, value);
499 if (!res) {
500 return res.Error();
501 }
502
503 value_ = res.Value();
504 }
505
506 return {};
507 }
508
509 #include <meta_gen.h>
510
511 } // namespace panda::pandasm
512