Nazarov Konstantin 97385e96aa Support add/delete annotation elements
Issue: #IAS8XN

Signed-off-by: Nazarov Konstantin <nazarov.konstantin@huawei.com>
Change-Id: I27fad211bc40a469505b19bbea60df1861f6cca6
2024-09-20 20:39:58 +08:00

573 lines
16 KiB
C++

/**
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ASSEMBLER_ANNOTATION_H
#define ASSEMBLER_ANNOTATION_H
#include <cstddef>
#include <memory>
#include <string>
#include <string_view>
#include <type_traits>
#include <variant>
#include <vector>
#include "assembly-type.h"
#include "macros.h"
namespace panda::pandasm {
class AnnotationElement;
class AnnotationData {
public:
AnnotationData(const std::string_view &record_name, std::vector<AnnotationElement> elements)
: record_name_(record_name), elements_(std::move(elements))
{
}
explicit AnnotationData(const std::string_view &record_name) : record_name_(record_name) {}
DEFAULT_MOVE_SEMANTIC(AnnotationData);
DEFAULT_COPY_SEMANTIC(AnnotationData);
~AnnotationData() = default;
std::string GetName() const
{
return record_name_;
}
const std::vector<AnnotationElement> &GetElements() const
{
return elements_;
}
void AddElement(AnnotationElement &&element)
{
elements_.push_back(std::forward<AnnotationElement>(element));
}
void DeleteAnnotationElementByName(const std::string_view &annotation_elem_name);
void SetOrAddElementByIndex(size_t ele_idx, AnnotationElement &&element);
private:
std::string record_name_;
std::vector<AnnotationElement> elements_;
};
class ScalarValue;
class ArrayValue;
class Value {
public:
enum class Type {
U1,
I8,
U8,
I16,
U16,
I32,
U32,
I64,
U64,
F32,
F64,
STRING,
STRING_NULLPTR,
RECORD,
METHOD,
ENUM,
ANNOTATION,
ARRAY,
VOID,
METHOD_HANDLE,
LITERALARRAY,
UNKNOWN
};
static constexpr char GetTypeAsChar(Type t)
{
char type = '0';
switch (t) {
case Type::U1:
type = '1';
break;
case Type::I8:
type = '2';
break;
case Type::U8:
type = '3';
break;
case Type::I16:
type = '4';
break;
case Type::U16:
type = '5';
break;
case Type::I32:
type = '6';
break;
case Type::U32:
type = '7';
break;
case Type::I64:
type = '8';
break;
case Type::U64:
type = '9';
break;
case Type::F32:
type = 'A';
break;
case Type::F64:
type = 'B';
break;
case Type::STRING:
type = 'C';
break;
case Type::RECORD:
type = 'D';
break;
case Type::METHOD:
type = 'E';
break;
case Type::ENUM:
type = 'F';
break;
case Type::ANNOTATION:
type = 'G';
break;
case Type::ARRAY:
type = 'H';
break;
case Type::VOID:
type = 'I';
break;
case Type::METHOD_HANDLE:
type = 'J';
break;
case Type::STRING_NULLPTR:
type = '*';
break;
case Type::LITERALARRAY:
type = '#';
break;
case Type::UNKNOWN:
default:
type = '0';
}
return type;
}
static constexpr char GetArrayTypeAsChar(Type t)
{
char type = '0';
switch (t) {
case Type::U1:
type = 'K';
break;
case Type::I8:
type = 'L';
break;
case Type::U8:
type = 'M';
break;
case Type::I16:
type = 'N';
break;
case Type::U16:
type = 'O';
break;
case Type::I32:
type = 'P';
break;
case Type::U32:
type = 'Q';
break;
case Type::I64:
type = 'R';
break;
case Type::U64:
type = 'S';
break;
case Type::F32:
type = 'T';
break;
case Type::F64:
type = 'U';
break;
case Type::STRING:
type = 'V';
break;
case Type::RECORD:
type = 'W';
break;
case Type::METHOD:
type = 'X';
break;
case Type::ENUM:
type = 'Y';
break;
case Type::ANNOTATION:
type = 'Z';
break;
case Type::METHOD_HANDLE:
type = '@';
break;
case Type::UNKNOWN:
default:
type = '0';
}
return type;
}
static constexpr Type GetCharAsType(char c)
{
Type type = Type::UNKNOWN;
switch (c) {
case '1':
type = Type::U1;
break;
case '2':
type = Type::I8;
break;
case '3':
type = Type::U8;
break;
case '4':
type = Type::I16;
break;
case '5':
type = Type::U16;
break;
case '6':
type = Type::I32;
break;
case '7':
type = Type::U32;
break;
case '8':
type = Type::I64;
break;
case '9':
type = Type::U64;
break;
case 'A':
type = Type::F32;
break;
case 'B':
type = Type::F64;
break;
case 'C':
type = Type::STRING;
break;
case 'D':
type = Type::RECORD;
break;
case 'E':
type = Type::METHOD;
break;
case 'F':
type = Type::ENUM;
break;
case 'G':
type = Type::ANNOTATION;
break;
case 'H':
type = Type::ARRAY;
break;
case 'I':
type = Type::VOID;
break;
case 'J':
type = Type::METHOD_HANDLE;
break;
case '*':
type = Type::STRING_NULLPTR;
break;
case '#':
type = Type::LITERALARRAY;
break;
case '0':
default:
type = Type::UNKNOWN;
}
return type;
}
static constexpr Type GetCharAsArrayType(char c)
{
Type type = Type::UNKNOWN;
switch (c) {
case 'K':
type = Type::U1;
break;
case 'L':
type = Type::I8;
break;
case 'M':
type = Type::U8;
break;
case 'N':
type = Type::I16;
break;
case 'O':
type = Type::U16;
break;
case 'P':
type = Type::I32;
break;
case 'Q':
type = Type::U32;
break;
case 'R':
type = Type::I64;
break;
case 'S':
type = Type::U64;
break;
case 'T':
type = Type::F32;
break;
case 'U':
type = Type::F64;
break;
case 'V':
type = Type::STRING;
break;
case 'W':
type = Type::RECORD;
break;
case 'X':
type = Type::METHOD;
break;
case 'Y':
type = Type::ENUM;
break;
case 'Z':
type = Type::ANNOTATION;
break;
case '@':
type = Type::METHOD_HANDLE;
break;
case '#':
type = Type::LITERALARRAY;
break;
case '0':
default:
type = Type::UNKNOWN;
}
return type;
}
Type GetType() const
{
return type_;
}
bool IsArray() const
{
return type_ == Type::ARRAY;
}
ScalarValue *GetAsScalar();
const ScalarValue *GetAsScalar() const;
ArrayValue *GetAsArray();
const ArrayValue *GetAsArray() const;
virtual ~Value() = default;
DEFAULT_COPY_SEMANTIC(Value);
DEFAULT_MOVE_SEMANTIC(Value);
protected:
explicit Value(Type type) : type_(type) {}
private:
Type type_;
};
// clang-format off
template <Value::Type value_type>
struct ValueTypeHelper {
// Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=40640
// NOLINTNEXTLINE(readability-magic-numbers)
using type = std::conditional_t<value_type == Value::Type::U1, uint8_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::I8, int8_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::U8, uint8_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::I16, int16_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::U16, uint16_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::I32, int32_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::U32, uint32_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::I64, int64_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::U64, uint64_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::F32, float,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::F64, double,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::STRING, std::string_view,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::STRING_NULLPTR, uint32_t,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::RECORD, pandasm::Type,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::METHOD, std::string_view,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::ENUM, std::string_view,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::ANNOTATION, AnnotationData,
// NOLINTNEXTLINE(readability-magic-numbers)
std::conditional_t<value_type == Value::Type::LITERALARRAY, std::string_view,
void>>>>>>>>>>>>>>>>>>;
};
// clang-format on
template <Value::Type type>
using ValueTypeHelperT = typename ValueTypeHelper<type>::type;
class ScalarValue : public Value {
public:
template <Value::Type type>
// Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=40640
// NOLINTNEXTLINE(readability-magic-numbers)
static ScalarValue Create(ValueTypeHelperT<type> value)
{
// NOLINTNEXTLINE(readability-magic-numbers)
using T = ValueTypeHelperT<type>;
// Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
// NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
if constexpr (std::is_integral_v<T>) { // NOLINT(bugprone-suspicious-semicolon)
// NOLINTNEXTLINE(readability-magic-numbers)
return ScalarValue(type, static_cast<uint64_t>(value));
}
// NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
if constexpr (!std::is_integral_v<T>) { // NOLINT(bugprone-suspicious-semicolon)
// NOLINTNEXTLINE(readability-magic-numbers)
return ScalarValue(type, value);
}
}
template <class T>
T GetValue() const
{
// Disable checks due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
// NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
if constexpr (std::is_integral_v<T>) { // NOLINT(bugprone-suspicious-semicolon)
return static_cast<T>(std::get<uint64_t>(value_));
}
// NOLINTNEXTLINE(readability-braces-around-statements, hicpp-braces-around-statements)
if constexpr (!std::is_integral_v<T>) { // NOLINT(bugprone-suspicious-semicolon)
return std::get<T>(value_);
}
}
DEFAULT_MOVE_SEMANTIC(ScalarValue);
DEFAULT_COPY_SEMANTIC(ScalarValue);
~ScalarValue() override = default;
private:
ScalarValue(Type type, uint64_t value) : Value(type), value_(value) {}
ScalarValue(Type type, float value) : Value(type), value_(value) {}
ScalarValue(Type type, double value) : Value(type), value_(value) {}
ScalarValue(Type type, const std::string_view &value) : Value(type), value_(std::string(value)) {}
ScalarValue(Type type, pandasm::Type value) : Value(type), value_(std::move(value)) {}
ScalarValue(Type type, AnnotationData &value) : Value(type), value_(value) {}
std::variant<uint64_t, float, double, std::string, pandasm::Type, AnnotationData> value_;
};
class ArrayValue : public Value {
public:
ArrayValue(Type component_type, std::vector<ScalarValue> values)
: Value(Type::ARRAY), component_type_(component_type), values_(std::move(values))
{
}
DEFAULT_MOVE_SEMANTIC(ArrayValue);
DEFAULT_COPY_SEMANTIC(ArrayValue);
~ArrayValue() override = default;
const std::vector<ScalarValue> &GetValues() const
{
return values_;
}
Type GetComponentType() const
{
return component_type_;
}
private:
Type component_type_;
std::vector<ScalarValue> values_;
};
class AnnotationElement {
public:
AnnotationElement(const std::string_view &name, std::unique_ptr<Value> value)
: name_(name), value_(std::move(value)) {}
AnnotationElement(const AnnotationElement &ann_elem);
AnnotationElement &operator=(const AnnotationElement &ann_elem);
DEFAULT_MOVE_SEMANTIC(AnnotationElement);
~AnnotationElement() = default;
std::string GetName() const
{
return name_;
}
Value *GetValue() const
{
return value_.get();
}
static std::string TypeToString(Value::Type type);
private:
std::string name_;
std::unique_ptr<Value> value_;
};
} // namespace panda::pandasm
#endif // ASSEMBLER_ANNOTATION_H