mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
138 lines
4.7 KiB
C++
138 lines
4.7 KiB
C++
#pragma once
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "revng/ADT/ConstexprString.h"
|
|
#include "revng/ADT/STLExtras.h"
|
|
|
|
namespace ptml {
|
|
|
|
/// Attribute in this context is a revng-specific macro that gets unrolled into
|
|
/// an `__attribute__(($something))` for the compiler.
|
|
struct Attribute {
|
|
std::string_view Macro;
|
|
std::string_view Value;
|
|
};
|
|
|
|
/// Annotation is an attribute that can also encode a value
|
|
/// (for example an abi name).
|
|
struct Annotation {
|
|
std::string_view Macro;
|
|
std::string_view Prefix;
|
|
};
|
|
|
|
struct AttributeRegistry {
|
|
static constexpr std::array<Attribute, 5> StaticAttributes{
|
|
Attribute{ .Macro = "_PACKED", .Value = "packed" },
|
|
Attribute{ .Macro = "_ALWAYS_INLINE", .Value = "always_inline" },
|
|
Attribute{ .Macro = "_NORETURN", .Value = "noreturn" },
|
|
|
|
Attribute{ .Macro = "_STACK", .Value = "stack" },
|
|
Attribute{ .Macro = "_CAN_CONTAIN_CODE", .Value = "can_contain_code" }
|
|
};
|
|
static constexpr std::array<Annotation, 5> StaticAnnotations{
|
|
Annotation{ .Macro = "_REG", .Prefix = "reg:" },
|
|
Annotation{ .Macro = "_ABI", .Prefix = "abi:" },
|
|
Annotation{ .Macro = "_STARTS_AT", .Prefix = "field_start_offset:" },
|
|
Annotation{ .Macro = "_SIZE", .Prefix = "struct_size:" },
|
|
Annotation{ .Macro = "_ENUM_UNDERLYING", .Prefix = "enum_underlying_type:" }
|
|
};
|
|
|
|
// TODO: add dynamic containers if the need ever arises.
|
|
|
|
public:
|
|
template<ConstexprString Macro>
|
|
static consteval std::optional<Attribute> getAttribute() {
|
|
constexpr auto Result = std::ranges::find_if(StaticAttributes,
|
|
[](auto &&A) {
|
|
return *Macro == A.Macro;
|
|
});
|
|
if (Result == StaticAttributes.end())
|
|
return std::nullopt;
|
|
return *Result;
|
|
}
|
|
|
|
template<ConstexprString Macro>
|
|
static consteval std::optional<Annotation> getAnnotation() {
|
|
constexpr auto Result = std::ranges::find_if(StaticAnnotations,
|
|
[](auto &&A) {
|
|
return *Macro == A.Macro;
|
|
});
|
|
if (Result == StaticAnnotations.end())
|
|
return std::nullopt;
|
|
return *Result;
|
|
}
|
|
|
|
template<ConstexprString Macro>
|
|
static consteval void assertAttributeName() {
|
|
constexpr auto Result = std::ranges::find_if(StaticAttributes,
|
|
[](auto &&A) {
|
|
return *Macro == A.Macro;
|
|
});
|
|
static_assert(Result != StaticAttributes.end());
|
|
}
|
|
|
|
template<ConstexprString Macro>
|
|
static consteval void assertAnnotationName() {
|
|
constexpr auto Result = std::ranges::find_if(StaticAnnotations,
|
|
[](auto &&A) {
|
|
return *Macro == A.Macro;
|
|
});
|
|
static_assert(Result != StaticAnnotations.end());
|
|
}
|
|
|
|
template<ConstexprString Macro>
|
|
static std::string getAttributeString() {
|
|
constexpr std::optional Attribute = getAttribute<Macro>();
|
|
if constexpr (Attribute) {
|
|
return std::string(Attribute->Macro);
|
|
} else {
|
|
static_assert(value_always_false_v<Macro>, "Unknown attribute.");
|
|
}
|
|
}
|
|
template<ConstexprString Macro>
|
|
static std::string getAnnotationString(std::string_view Value) {
|
|
constexpr std::optional Annotation = getAnnotation<Macro>();
|
|
if constexpr (Annotation) {
|
|
return std::string(Annotation->Macro) + "(" + std::string(Value) + ")";
|
|
} else {
|
|
static_assert(value_always_false_v<Macro>, "Unknown annotation.");
|
|
}
|
|
}
|
|
template<ConstexprString Macro>
|
|
static std::string getAnnotationString(uint64_t Value) {
|
|
return getAnnotationString<Macro>(std::to_string(Value));
|
|
}
|
|
|
|
template<ConstexprString Macro>
|
|
static consteval std::string_view getPrefix() {
|
|
constexpr std::optional Annotation = getAnnotation<Macro>();
|
|
if constexpr (Annotation) {
|
|
return Annotation->Prefix;
|
|
} else {
|
|
constexpr std::optional Attribute = getAttribute<Macro>();
|
|
if constexpr (Attribute) {
|
|
return Attribute->Value;
|
|
} else {
|
|
static_assert(value_always_false_v<Macro>,
|
|
"Unknown attribute or annotation.");
|
|
}
|
|
}
|
|
}
|
|
|
|
public:
|
|
constexpr bool isMacro(llvm::StringRef String) const {
|
|
auto Comparator = [String](const auto &A) {
|
|
return std::string_view(String) == A.Macro;
|
|
};
|
|
|
|
return revng::any_of(StaticAttributes, Comparator)
|
|
|| revng::any_of(StaticAnnotations, Comparator);
|
|
}
|
|
};
|
|
inline constexpr AttributeRegistry Attributes;
|
|
|
|
} // namespace ptml
|