/** * 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_META_H #define ASSEMBLER_META_H #include #include #include #include #include #include #include #include "annotation.h" #include "modifiers.h" #include "assembly-type.h" namespace panda::pandasm { class Metadata { public: class Error { public: enum class Type { INVALID_VALUE, MISSING_ATTRIBUTE, MISSING_VALUE, MULTIPLE_ATTRIBUTE, UNEXPECTED_ATTRIBUTE, UNEXPECTED_VALUE, UNKNOWN_ATTRIBUTE }; Error(std::string msg, Type type) : msg_(std::move(msg)), type_(type) {} ~Error() = default; DEFAULT_MOVE_SEMANTIC(Error); DEFAULT_COPY_SEMANTIC(Error); std::string GetMessage() const { return msg_; } Type GetType() const { return type_; } private: std::string msg_; Type type_; }; Metadata() = default; virtual ~Metadata() = default; std::optional SetAttribute(const std::string_view &attribute) { auto err = Validate(attribute); if (err) { return err; } SetFlags(attribute); return Store(attribute); } void RemoveAttribute(const std::string &attribute) { RemoveFlags(attribute); set_attributes_.erase(attribute); } bool GetAttribute(const std::string &attribute) const { return set_attributes_.find(attribute) != set_attributes_.cend(); } std::optional SetAttributeValue(const std::string_view &attribute, const std::string_view &value) { auto err = Validate(attribute, value); if (err) { return err; } SetFlags(attribute, value); return StoreValue(attribute, value); } std::vector GetAttributeValues(const std::string &attribute) const { auto it = attributes_.find(attribute); if (it == attributes_.cend()) { return {}; } return it->second; } std::optional GetAttributeValue(const std::string &attribute) const { auto values = GetAttributeValues(attribute); if (!values.empty()) { return values.front(); } return {}; } const std::unordered_set &GetBoolAttributes() const { return set_attributes_; } const std::unordered_map> &GetAttributes() const { return attributes_; } virtual std::optional ValidateData() { return {}; } DEFAULT_COPY_SEMANTIC(Metadata); DEFAULT_MOVE_SEMANTIC(Metadata); protected: virtual std::optional Validate(const std::string_view &attribute) const = 0; virtual std::optional Validate(const std::string_view &attribute, const std::string_view &value) const = 0; virtual std::optional StoreValue(const std::string_view &attribute, const std::string_view &value) { std::string key(attribute); auto it = attributes_.find(key); if (it == attributes_.cend()) { std::tie(it, std::ignore) = attributes_.try_emplace(key); } it->second.emplace_back(value); return {}; } virtual std::optional Store(const std::string_view &attribute) { set_attributes_.emplace(attribute); return {}; } virtual void SetFlags(const std::string_view &attribute) = 0; virtual void SetFlags(const std::string_view &attribute, const std::string_view &value) = 0; virtual void RemoveFlags(const std::string_view &attribute) = 0; virtual void RemoveFlags(const std::string_view &attribute, const std::string_view &value) = 0; bool HasAttribute(const std::string_view &attribute) const { std::string key(attribute); return GetAttribute(key) || GetAttributeValue(key); } std::optional ValidateSize(const std::string_view &value) const; private: std::unordered_set set_attributes_; std::unordered_map> attributes_; }; class AnnotationMetadata : public Metadata { public: const std::vector &GetAnnotations() const { return annotations_; } void SetAnnotations(std::vector &&annotations) { annotations_ = std::forward>(annotations); } void AddAnnotations(const std::vector &annotations) { annotations_.insert(annotations_.end(), annotations.begin(), annotations.end()); } void DeleteAnnotationElementByName(std::string_view annotation_name, std::string_view annotation_elem_name) { auto annotation_iter = std::find_if(annotations_.begin(), annotations_.end(), [&](pandasm::AnnotationData &annotation) -> bool { return annotation.GetName() == annotation_name; }); if (annotation_iter != annotations_.end()) { annotation_iter->DeleteAnnotationElementByName(annotation_elem_name); } } void DeleteAnnotationByName(const std::string_view &annotation_name) { auto annotation_iter = std::find_if(annotations_.begin(), annotations_.end(), [&](pandasm::AnnotationData &annotation) -> bool { return annotation.GetName() == annotation_name; }); if (annotation_iter != annotations_.end()) { (void)annotations_.erase(annotation_iter); } } void AddAnnotationElementByName(const std::string_view &annotation_name, AnnotationElement &&element) { auto annotation_iter = std::find_if(annotations_.begin(), annotations_.end(), [&](pandasm::AnnotationData &annotation) -> bool { return annotation.GetName() == annotation_name; }); if (annotation_iter != annotations_.end()) { annotation_iter->AddElement(std::move(element)); } } void SetOrAddAnnotationElementByIndex(size_t anno_idx, size_t ele_idx, AnnotationElement &&element) { ASSERT(anno_idx < annotations_.size()); annotations_[anno_idx].SetOrAddElementByIndex(ele_idx, std::forward(element)); } std::optional ValidateData() override; protected: std::optional Store(const std::string_view &attribute) override; std::optional StoreValue(const std::string_view &attribute, const std::string_view &value) override; virtual bool IsAnnotationRecordAttribute([[maybe_unused]] const std::string_view &attribute) const { return false; } virtual bool IsAnnotationIdAttribute([[maybe_unused]] const std::string_view &attribute) const { return false; } virtual bool IsAnnotationElementTypeAttribute([[maybe_unused]] const std::string_view &attribute) const { return false; } virtual bool IsAnnotationElementArrayComponentTypeAttribute( [[maybe_unused]] const std::string_view &attribute) const { return false; } virtual bool IsAnnotationElementNameAttribute([[maybe_unused]] const std::string_view &attribute) const { return false; } virtual bool IsAnnotationElementValueAttribute([[maybe_unused]] const std::string_view &attribute) const { return false; } private: class AnnotationElementBuilder { public: void Initialize(const std::string_view &name) { name_ = name; is_initialized_ = true; } void Reset() { name_.clear(); values_.clear(); type_ = {}; component_type_ = {}; is_initialized_ = false; } void SetType(Value::Type type) { type_ = type; } void SetComponentType(Value::Type type) { ASSERT(type != Value::Type::ARRAY); component_type_ = type; } std::optional AddValue( const std::string_view &value, const std::unordered_map> &annotation_id_map); AnnotationElement CreateAnnotationElement() { if (IsArray()) { return AnnotationElement(name_, std::make_unique(component_type_.value(), std::move(values_))); } return AnnotationElement(name_, std::make_unique(values_.front())); } bool IsArray() const { return type_.value() == Value::Type::ARRAY; } bool IsTypeSet() const { return type_.has_value(); } bool IsComponentTypeSet() const { return component_type_.has_value(); } bool IsInitialized() const { return is_initialized_; } bool IsCompleted() const { if (!IsTypeSet()) { return false; } if (IsArray() && !IsComponentTypeSet()) { return false; } if (!IsArray() && values_.empty()) { return false; } return true; } private: bool is_initialized_ {false}; std::string name_; std::optional type_; std::optional component_type_; std::vector values_; }; class AnnotationBuilder { public: void Initialize(const std::string_view &name) { name_ = name; is_initialized_ = true; } void Reset() { name_.clear(); elements_.clear(); id_ = {}; is_initialized_ = false; } void SetId(const std::string_view &id) { id_ = id; } std::string GetId() const { ASSERT(HasId()); return id_.value(); } void AddElement(AnnotationElement &&element) { elements_.push_back(std::forward(element)); } std::unique_ptr CreateAnnotationData() { return std::make_unique(name_, std::move(elements_)); }; void AddAnnnotationDataToVector(std::vector *annotations) { annotations->emplace_back(name_, std::move(elements_)); } bool HasId() const { return id_.has_value(); } bool IsInitialized() const { return is_initialized_; } private: std::string name_; std::optional id_; std::vector elements_; bool is_initialized_ {false}; }; std::optional MeetExpRecordAttribute(const std::string_view &attribute, const std::string_view &value); std::optional MeetExpIdAttribute(const std::string_view &attribute, const std::string_view &value); std::optional MeetExpElementNameAttribute(const std::string_view &attribute, const std::string_view &value); std::optional MeetExpElementTypeAttribute(const std::string_view &attribute, const std::string_view &value); std::optional MeetExpElementArrayComponentTypeAttribute(const std::string_view &attribute, const std::string_view &value); std::optional MeetExpElementValueAttribute(const std::string_view &attribute, const std::string_view &value); void InitializeAnnotationBuilder(const std::string_view &name) { if (IsParseAnnotation()) { ResetAnnotationBuilder(); } annotation_builder_.Initialize(name); } void ResetAnnotationBuilder() { ASSERT(IsParseAnnotation()); if (IsParseAnnotationElement() && annotation_element_builder_.IsCompleted()) { ResetAnnotationElementBuilder(); } if (annotation_builder_.HasId()) { id_map_.insert({annotation_builder_.GetId(), annotation_builder_.CreateAnnotationData()}); } else { annotation_builder_.AddAnnnotationDataToVector(&annotations_); } annotation_builder_.Reset(); } bool IsParseAnnotation() const { return annotation_builder_.IsInitialized(); } void InitializeAnnotationElementBuilder(const std::string_view &name) { if (IsParseAnnotationElement() && annotation_element_builder_.IsCompleted()) { ResetAnnotationElementBuilder(); } annotation_element_builder_.Initialize(name); } void ResetAnnotationElementBuilder() { ASSERT(IsParseAnnotationElement()); ASSERT(annotation_element_builder_.IsCompleted()); annotation_builder_.AddElement(annotation_element_builder_.CreateAnnotationElement()); annotation_element_builder_.Reset(); } bool IsParseAnnotationElement() const { return annotation_element_builder_.IsInitialized(); } AnnotationBuilder annotation_builder_; AnnotationElementBuilder annotation_element_builder_; std::vector annotations_; std::unordered_map> id_map_; }; class ItemMetadata : public AnnotationMetadata { public: uint32_t GetAccessFlags() const { return access_flags_; } void SetAccessFlags(uint32_t access_flags) { access_flags_ = access_flags; } void AddAccessFlags(uint32_t access_flags) { access_flags_ = access_flags_ | access_flags; } bool IsForeign() const; private: uint32_t access_flags_ {0}; }; class RecordMetadata : public ItemMetadata { public: virtual std::string GetBase() const; virtual std::vector GetInterfaces() const; virtual bool IsAnnotation() const; virtual bool IsRuntimeAnnotation() const; virtual bool IsTypeAnnotation() const; virtual bool IsRuntimeTypeAnnotation() const; protected: std::optional Validate(const std::string_view &attribute) const override; std::optional Validate(const std::string_view &attribute, const std::string_view &value) const override; void SetFlags(const std::string_view &attribute) override; void SetFlags(const std::string_view &attribute, const std::string_view &value) override; void RemoveFlags(const std::string_view &attribute) override; void RemoveFlags(const std::string_view &attribute, const std::string_view &value) override; }; class FieldMetadata : public ItemMetadata { public: void SetFieldType(const Type &type) { field_type_ = type; } Type GetFieldType() const { return field_type_; } void SetValue(const ScalarValue &value) { value_ = value; } std::optional GetValue() const { return value_; } protected: std::optional StoreValue(const std::string_view &attribute, const std::string_view &value) override; std::optional Validate(const std::string_view &attribute) const override; std::optional Validate(const std::string_view &attribute, const std::string_view &value) const override; void SetFlags(const std::string_view &attribute) override; void SetFlags(const std::string_view &attribute, const std::string_view &value) override; void RemoveFlags(const std::string_view &attribute) override; void RemoveFlags(const std::string_view &attribute, const std::string_view &value) override; virtual bool IsValueAttribute(const std::string_view &attribute) { return attribute == "value"; } private: Type field_type_; std::optional value_; }; class FunctionMetadata : public ItemMetadata { public: virtual bool IsCtor() const; virtual bool IsCctor() const; protected: std::optional Validate(const std::string_view &attribute) const override; std::optional Validate(const std::string_view &attribute, const std::string_view &value) const override; void SetFlags(const std::string_view &attribute) override; void SetFlags(const std::string_view &attribute, const std::string_view &value) override; void RemoveFlags(const std::string_view &attribute) override; void RemoveFlags(const std::string_view &attribute, const std::string_view &value) override; }; class ParamMetadata : public AnnotationMetadata { protected: std::optional Validate(const std::string_view &attribute) const override; std::optional Validate(const std::string_view &attribute, const std::string_view &value) const override; void SetFlags(const std::string_view &attribute) override; void SetFlags(const std::string_view &attribute, const std::string_view &value) override; void RemoveFlags(const std::string_view &attribute) override; void RemoveFlags(const std::string_view &attribute, const std::string_view &value) override; }; } // namespace panda::pandasm #endif // ASSEMBLER_META_H