aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc
diff options
context:
space:
mode:
Diffstat (limited to 'backend/include/rcc')
-rw-r--r--backend/include/rcc/CodeGen/MachineConstantPool.h183
-rw-r--r--backend/include/rcc/CodeGen/MachineFunction.h20
-rw-r--r--backend/include/rcc/CodeGen/MachineIRBuilder.h2
-rw-r--r--backend/include/rcc/CodeGen/MachineIRTypes.h6
-rw-r--r--backend/include/rcc/CodeGen/MachineJumpTableInfo.h116
-rw-r--r--backend/include/rcc/CodeGen/TargetConstant.h259
6 files changed, 586 insertions, 0 deletions
diff --git a/backend/include/rcc/CodeGen/MachineConstantPool.h b/backend/include/rcc/CodeGen/MachineConstantPool.h
new file mode 100644
index 0000000..cc9ae04
--- /dev/null
+++ b/backend/include/rcc/CodeGen/MachineConstantPool.h
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_MACHINECONSTANTPOOL_H
+#define RCC_CODEGEN_MACHINECONSTANTPOOL_H
+
+#include "rcc/CodeGen/MachineIRTypes.h"
+#include "rcc/CodeGen/MachineMemOperand.h"
+#include "rcc/CodeGen/TargetConstant.h"
+#include "rcc/Support/Error.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include <span>
+#include <string>
+#include <utility>
+#include <variant>
+#include <vector>
+
+namespace rcc {
+
+enum class ConstantPoolEntryKind : std::uint8_t {
+ Generic,
+ Target,
+ SymbolDifference,
+ BlockAddress,
+ TargetExpression,
+};
+
+enum class ConstantPoolMergeKind : std::uint8_t {
+ Never,
+ Exact,
+};
+
+enum class ConstantPoolRelocationMode : std::uint8_t {
+ None,
+ Static,
+ PositionIndependent,
+ Target,
+};
+
+enum class ConstantPoolSectionKind : std::uint8_t {
+ TargetDefault,
+ ReadOnly,
+ MergeableReadOnly,
+ Data,
+ TextAdjacent,
+ Target,
+ Count,
+};
+
+struct ConstantPoolPlacement final {
+ ConstantPoolSectionKind Section = ConstantPoolSectionKind::TargetDefault;
+ bool UniqueSection = false;
+ std::optional<std::uint64_t> MaximumDistance;
+ std::uint64_t TargetFlags = 0;
+
+ friend bool operator==(const ConstantPoolPlacement &Left,
+ const ConstantPoolPlacement &Right) = default;
+};
+
+struct GenericConstantData final {
+ std::string TypeIdentity;
+ std::vector<std::byte> Bytes;
+
+ friend bool operator==(const GenericConstantData &Left,
+ const GenericConstantData &Right) = default;
+};
+
+struct SymbolDifferenceConstant final {
+ std::string Minuend;
+ std::string Subtrahend;
+ std::int64_t Addend = 0;
+
+ friend bool operator==(const SymbolDifferenceConstant &Left,
+ const SymbolDifferenceConstant &Right) = default;
+};
+
+struct BlockAddressConstant final {
+ std::string FunctionName;
+ std::string BlockName;
+ std::int64_t Addend = 0;
+
+ friend bool operator==(const BlockAddressConstant &Left,
+ const BlockAddressConstant &Right) = default;
+};
+
+struct TargetExpressionConstant final {
+ TargetConstant Expression;
+};
+
+using MachineConstantPoolValue =
+ std::variant<GenericConstantData, TargetConstant, SymbolDifferenceConstant,
+ BlockAddressConstant, TargetExpressionConstant>;
+
+struct MachineConstantPoolEntryDesc final {
+ MachineConstantPoolEntryDesc() = default;
+ MachineConstantPoolEntryDesc(const MachineConstantPoolEntryDesc &) = delete;
+ MachineConstantPoolEntryDesc &operator=(const MachineConstantPoolEntryDesc &) = delete;
+ MachineConstantPoolEntryDesc(MachineConstantPoolEntryDesc &&) noexcept = default;
+ MachineConstantPoolEntryDesc &operator=(MachineConstantPoolEntryDesc &&) noexcept = default;
+ ~MachineConstantPoolEntryDesc() = default;
+
+ MachineConstantPoolValue Value;
+ std::uint64_t Size = 0;
+ Alignment Align;
+ ConstantPoolMergeKind Merge = ConstantPoolMergeKind::Never;
+ ConstantPoolRelocationMode Relocation = ConstantPoolRelocationMode::None;
+ ConstantPoolPlacement Placement;
+
+ [[nodiscard]] ConstantPoolEntryKind kind() const noexcept;
+ [[nodiscard]] Expected<void> verify() const;
+ [[nodiscard]] Expected<MachineConstantPoolEntryDesc> clone() const;
+ [[nodiscard]] bool semanticallyEquals(const MachineConstantPoolEntryDesc &Other) const noexcept;
+};
+
+class MachineConstantPoolEntry final {
+public:
+ [[nodiscard]] ConstantPoolIndex index() const noexcept {
+ return Index;
+ }
+
+ [[nodiscard]] bool isTombstone() const noexcept {
+ return std::holds_alternative<std::monostate>(Description);
+ }
+
+ [[nodiscard]] const MachineConstantPoolEntryDesc *description() const noexcept {
+ return std::get_if<MachineConstantPoolEntryDesc>(&Description);
+ }
+
+ [[nodiscard]] Expected<MachineConstantPoolEntryDesc> cloneDescription() const;
+
+private:
+ MachineConstantPoolEntry(ConstantPoolIndex Index, MachineConstantPoolEntryDesc Description)
+ : Index(Index), Description(std::move(Description)) {}
+
+ ConstantPoolIndex Index;
+ std::variant<std::monostate, MachineConstantPoolEntryDesc> Description;
+
+ friend class MachineConstantPool;
+};
+
+class MachineConstantPool final {
+public:
+ MachineConstantPool() = default;
+ MachineConstantPool(const MachineConstantPool &) = delete;
+ MachineConstantPool &operator=(const MachineConstantPool &) = delete;
+ MachineConstantPool(MachineConstantPool &&) noexcept = default;
+ MachineConstantPool &operator=(MachineConstantPool &&) noexcept = default;
+ ~MachineConstantPool() = default;
+
+ [[nodiscard]] Expected<ConstantPoolIndex> addEntry(MachineConstantPoolEntryDesc Description);
+ [[nodiscard]] Expected<void> updateEntry(ConstantPoolIndex Index,
+ MachineConstantPoolEntryDesc Description);
+ [[nodiscard]] Expected<void> eraseEntry(ConstantPoolIndex Index);
+
+ [[nodiscard]] const MachineConstantPoolEntry *entry(ConstantPoolIndex Index) const noexcept;
+ [[nodiscard]] std::span<const MachineConstantPoolEntry> entries() const noexcept {
+ return Entries;
+ }
+
+ [[nodiscard]] std::size_t liveEntryCount() const noexcept;
+
+ [[nodiscard]] bool isFrozen() const noexcept {
+ return Frozen;
+ }
+
+ [[nodiscard]] Expected<void> freeze();
+ [[nodiscard]] Expected<void> verify() const;
+
+private:
+ [[nodiscard]] Expected<MachineConstantPoolEntry *> mutableEntry(ConstantPoolIndex Index);
+ [[nodiscard]] const MachineConstantPoolEntry *
+ findEquivalent(const MachineConstantPoolEntryDesc &Description,
+ std::optional<ConstantPoolIndex> Excluded = std::nullopt) const noexcept;
+
+ std::vector<MachineConstantPoolEntry> Entries;
+ bool Frozen = false;
+};
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_MACHINECONSTANTPOOL_H
diff --git a/backend/include/rcc/CodeGen/MachineFunction.h b/backend/include/rcc/CodeGen/MachineFunction.h
index 3e3fecb..38d88f9 100644
--- a/backend/include/rcc/CodeGen/MachineFunction.h
+++ b/backend/include/rcc/CodeGen/MachineFunction.h
@@ -3,8 +3,10 @@
#ifndef RCC_CODEGEN_MACHINEFUNCTION_H
#define RCC_CODEGEN_MACHINEFUNCTION_H
+#include "rcc/CodeGen/MachineConstantPool.h"
#include "rcc/CodeGen/MachineFrameInfo.h"
#include "rcc/CodeGen/MachineFunctionProperties.h"
+#include "rcc/CodeGen/MachineJumpTableInfo.h"
#include "rcc/CodeGen/MachineRegisterInfo.h"
#include "rcc/CodeGen/StableID.h"
#include "rcc/Support/Error.h"
@@ -61,6 +63,22 @@ public:
return FrameInfo;
}
+ [[nodiscard]] MachineConstantPool &constantPool() noexcept {
+ return ConstantPool;
+ }
+
+ [[nodiscard]] const MachineConstantPool &constantPool() const noexcept {
+ return ConstantPool;
+ }
+
+ [[nodiscard]] MachineJumpTableInfo &jumpTableInfo() noexcept {
+ return JumpTables;
+ }
+
+ [[nodiscard]] const MachineJumpTableInfo &jumpTableInfo() const noexcept {
+ return JumpTables;
+ }
+
[[nodiscard]] MachineFunctionProperties &properties() noexcept {
return Properties;
}
@@ -120,6 +138,8 @@ private:
MachineFunctionStableID StableID;
MachineRegisterInfo RegInfo;
MachineFrameInfo FrameInfo;
+ MachineConstantPool ConstantPool;
+ MachineJumpTableInfo JumpTables;
MachineFunctionProperties Properties;
MachineBasicBlock *FirstBlock = nullptr;
MachineBasicBlock *LastBlock = nullptr;
diff --git a/backend/include/rcc/CodeGen/MachineIRBuilder.h b/backend/include/rcc/CodeGen/MachineIRBuilder.h
index 3bd8d67..47fd63c 100644
--- a/backend/include/rcc/CodeGen/MachineIRBuilder.h
+++ b/backend/include/rcc/CodeGen/MachineIRBuilder.h
@@ -97,6 +97,8 @@ private:
[[nodiscard]] Expected<void> ensurePending() const;
[[nodiscard]] Expected<void> validateInsertionPoint() const;
[[nodiscard]] Expected<void> validateFrameReference(FrameIndex Index) const;
+ [[nodiscard]] Expected<void> validateConstantPoolReference(ConstantPoolIndex Index) const;
+ [[nodiscard]] Expected<void> validateJumpTableReference(JumpTableIndex Index) const;
[[nodiscard]] Expected<void> validateOperandOwnership(const MachineOperand &Operand) const;
[[nodiscard]] std::vector<MachineOperandTie> collectOperandTies() const;
[[nodiscard]] Expected<void> appendRegister(Register Reg, RegisterOperandFlags Flags,
diff --git a/backend/include/rcc/CodeGen/MachineIRTypes.h b/backend/include/rcc/CodeGen/MachineIRTypes.h
index de6be5a..058cacb 100644
--- a/backend/include/rcc/CodeGen/MachineIRTypes.h
+++ b/backend/include/rcc/CodeGen/MachineIRTypes.h
@@ -55,6 +55,9 @@ struct AssemblyFormatIDTag;
struct SyncScopeIDTag;
struct MemoryAliasSourceIDTag;
struct OriginIDTag;
+struct TargetConstantTypeIDTag;
+struct TargetFunctionStateTypeIDTag;
+struct TargetRelocationKindIDTag;
} // namespace detail
@@ -74,6 +77,9 @@ using AssemblyFormatID = MachineIndex<detail::AssemblyFormatIDTag>;
using SyncScopeID = MachineIndex<detail::SyncScopeIDTag>;
using MemoryAliasSourceID = MachineIndex<detail::MemoryAliasSourceIDTag, std::uint64_t>;
using OriginID = MachineIndex<detail::OriginIDTag, std::uint64_t>;
+using TargetConstantTypeID = MachineIndex<detail::TargetConstantTypeIDTag, std::uint64_t>;
+using TargetFunctionStateTypeID = MachineIndex<detail::TargetFunctionStateTypeIDTag, std::uint64_t>;
+using TargetRelocationKindID = MachineIndex<detail::TargetRelocationKindIDTag>;
class Opcode final {
public:
diff --git a/backend/include/rcc/CodeGen/MachineJumpTableInfo.h b/backend/include/rcc/CodeGen/MachineJumpTableInfo.h
new file mode 100644
index 0000000..6342281
--- /dev/null
+++ b/backend/include/rcc/CodeGen/MachineJumpTableInfo.h
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_MACHINEJUMPTABLEINFO_H
+#define RCC_CODEGEN_MACHINEJUMPTABLEINFO_H
+
+#include "rcc/CodeGen/MachineIRTypes.h"
+#include "rcc/CodeGen/MachineMemOperand.h"
+#include "rcc/Support/Error.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include <span>
+#include <utility>
+#include <variant>
+#include <vector>
+
+namespace rcc {
+
+class MachineBasicBlock;
+class MachineFunction;
+
+enum class JumpTableEntryEncoding : std::uint8_t {
+ AbsoluteAddress,
+ RelativeToTableBase,
+ RelativeToEntry,
+ CompressedOffset,
+ Target,
+ Count,
+};
+
+struct JumpTablePlacement final {
+ bool InTextSection = true;
+ bool UniqueSection = false;
+ std::optional<std::uint64_t> MaximumDistance;
+ std::uint64_t TargetFlags = 0;
+
+ friend bool operator==(const JumpTablePlacement &Left, const JumpTablePlacement &Right) = default;
+};
+
+struct MachineJumpTableDesc final {
+ JumpTableEntryEncoding Encoding = JumpTableEntryEncoding::AbsoluteAddress;
+ std::uint8_t EntrySize = 8;
+ Alignment Align;
+ std::vector<MachineBasicBlock *> Targets;
+ JumpTablePlacement Placement;
+ std::uint32_t TargetEncoding = 0;
+
+ friend bool operator==(const MachineJumpTableDesc &Left,
+ const MachineJumpTableDesc &Right) = default;
+};
+
+class MachineJumpTableEntry final {
+public:
+ [[nodiscard]] JumpTableIndex index() const noexcept {
+ return Index;
+ }
+
+ [[nodiscard]] bool isTombstone() const noexcept {
+ return std::holds_alternative<std::monostate>(Description);
+ }
+
+ [[nodiscard]] const MachineJumpTableDesc *description() const noexcept {
+ return std::get_if<MachineJumpTableDesc>(&Description);
+ }
+
+private:
+ MachineJumpTableEntry(JumpTableIndex Index, MachineJumpTableDesc Description)
+ : Index(Index), Description(std::move(Description)) {}
+
+ JumpTableIndex Index;
+ std::variant<std::monostate, MachineJumpTableDesc> Description;
+
+ friend class MachineJumpTableInfo;
+};
+
+class MachineJumpTableInfo final {
+public:
+ explicit MachineJumpTableInfo(MachineFunction &Owner) noexcept : Owner(&Owner) {}
+
+ MachineJumpTableInfo(const MachineJumpTableInfo &) = delete;
+ MachineJumpTableInfo &operator=(const MachineJumpTableInfo &) = delete;
+ MachineJumpTableInfo(MachineJumpTableInfo &&) = delete;
+ MachineJumpTableInfo &operator=(MachineJumpTableInfo &&) = delete;
+ ~MachineJumpTableInfo() = default;
+
+ [[nodiscard]] Expected<JumpTableIndex> createTable(MachineJumpTableDesc Description);
+ [[nodiscard]] Expected<void> updateTable(JumpTableIndex Index, MachineJumpTableDesc Description);
+ [[nodiscard]] Expected<void> eraseTable(JumpTableIndex Index);
+
+ [[nodiscard]] const MachineJumpTableEntry *table(JumpTableIndex Index) const noexcept;
+ [[nodiscard]] std::span<const MachineJumpTableEntry> tables() const noexcept {
+ return Tables;
+ }
+
+ [[nodiscard]] std::size_t liveTableCount() const noexcept;
+
+ [[nodiscard]] bool isFrozen() const noexcept {
+ return Frozen;
+ }
+
+ [[nodiscard]] Expected<void> freeze();
+ [[nodiscard]] Expected<void> verify() const;
+
+private:
+ [[nodiscard]] Expected<void> verifyDescription(const MachineJumpTableDesc &Description) const;
+ [[nodiscard]] Expected<MachineJumpTableEntry *> mutableTable(JumpTableIndex Index);
+
+ MachineFunction *Owner;
+ std::vector<MachineJumpTableEntry> Tables;
+ bool Frozen = false;
+};
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_MACHINEJUMPTABLEINFO_H
diff --git a/backend/include/rcc/CodeGen/TargetConstant.h b/backend/include/rcc/CodeGen/TargetConstant.h
new file mode 100644
index 0000000..37f352e
--- /dev/null
+++ b/backend/include/rcc/CodeGen/TargetConstant.h
@@ -0,0 +1,259 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_TARGETCONSTANT_H
+#define RCC_CODEGEN_TARGETCONSTANT_H
+
+#include "rcc/CodeGen/MachineIRTypes.h"
+#include "rcc/CodeGen/MachineMemOperand.h"
+#include "rcc/Support/Error.h"
+
+#include <concepts>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <span>
+#include <string>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace rcc {
+
+struct TargetConstantFixup final {
+ std::uint64_t Offset = 0;
+ TargetRelocationKindID Kind;
+ std::string Symbol;
+ std::int64_t Addend = 0;
+
+ friend bool operator==(const TargetConstantFixup &Left,
+ const TargetConstantFixup &Right) = default;
+};
+
+struct TargetConstantEmission final {
+ std::vector<std::byte> Bytes;
+ std::vector<TargetConstantFixup> Fixups;
+
+ [[nodiscard]] Expected<void> verify() const;
+
+ friend bool operator==(const TargetConstantEmission &Left,
+ const TargetConstantEmission &Right) = default;
+};
+
+struct EncodedTargetConstant final {
+ TargetConstantTypeID TypeID;
+ std::uint32_t Version = 0;
+ std::vector<std::byte> Payload;
+
+ friend bool operator==(const EncodedTargetConstant &Left,
+ const EncodedTargetConstant &Right) = default;
+};
+
+template <typename ValueT>
+concept TargetConstantValue =
+ std::move_constructible<ValueT> &&
+ requires(const ValueT &Value, const ValueT &Other, std::uint32_t Version,
+ std::span<const std::byte> Payload, std::string_view Text) {
+ { ValueT::stableTypeID() } -> std::same_as<TargetConstantTypeID>;
+ { ValueT::schemaVersion() } -> std::same_as<std::uint32_t>;
+ { Value.verify() } -> std::same_as<Expected<void>>;
+ { Value.clone() } -> std::same_as<Expected<ValueT>>;
+ { Value.stableHash() } -> std::same_as<std::uint64_t>;
+ { Value.print() } -> std::same_as<std::string>;
+ { Value.encode() } -> std::same_as<Expected<std::vector<std::byte>>>;
+ { Value.emit() } -> std::same_as<Expected<TargetConstantEmission>>;
+ { Value.requiredAlignment() } -> std::same_as<Alignment>;
+ { Value.relocationKind() } -> std::same_as<std::optional<TargetRelocationKindID>>;
+ { Value == Other } -> std::convertible_to<bool>;
+ { ValueT::parse(Text) } -> std::same_as<Expected<ValueT>>;
+ { ValueT::decode(Version, Payload) } -> std::same_as<Expected<ValueT>>;
+ };
+
+class TargetConstant final {
+public:
+ TargetConstant() = default;
+ TargetConstant(const TargetConstant &) = delete;
+ TargetConstant &operator=(const TargetConstant &) = delete;
+ TargetConstant(TargetConstant &&) noexcept;
+ TargetConstant &operator=(TargetConstant &&) noexcept;
+ ~TargetConstant();
+
+ template <TargetConstantValue ValueT>
+ [[nodiscard]] static Expected<TargetConstant> create(ValueT Value) {
+ if (ValueT::stableTypeID().value() == 0)
+ return makeUnexpected(ErrorCode::InvalidArgument, "target constant TypeID must be nonzero");
+ if (ValueT::schemaVersion() == 0) {
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "target constant schema version must be nonzero");
+ }
+ auto Verification = Value.verify();
+ if (!Verification)
+ return std::unexpected(Verification.error());
+
+ std::unique_ptr<Concept> NewStorage = std::make_unique<Model<ValueT>>(std::move(Value));
+ return TargetConstant(std::move(NewStorage));
+ }
+
+ template <TargetConstantValue ValueT>
+ [[nodiscard]] static Expected<TargetConstant> parse(std::string_view Text) {
+ auto Value = ValueT::parse(Text);
+ if (!Value)
+ return std::unexpected(Value.error());
+ return create<ValueT>(std::move(*Value));
+ }
+
+ template <TargetConstantValue ValueT>
+ [[nodiscard]] static Expected<TargetConstant> decode(const EncodedTargetConstant &Encoded) {
+ if (Encoded.TypeID != ValueT::stableTypeID()) {
+ return makeUnexpected(ErrorCode::ParseError,
+ "encoded target constant TypeID does not match its target schema");
+ }
+ if (Encoded.Version == 0)
+ return makeUnexpected(ErrorCode::ParseError, "target constant version must be nonzero");
+ auto Value = ValueT::decode(Encoded.Version, Encoded.Payload);
+ if (!Value)
+ return std::unexpected(Value.error());
+ return create<ValueT>(std::move(*Value));
+ }
+
+ [[nodiscard]] bool hasValue() const noexcept {
+ return Storage != nullptr;
+ }
+
+ [[nodiscard]] std::optional<TargetConstantTypeID> typeID() const noexcept;
+ [[nodiscard]] std::optional<std::uint32_t> schemaVersion() const noexcept;
+ [[nodiscard]] Expected<void> verify() const;
+ [[nodiscard]] Expected<TargetConstant> clone() const;
+ [[nodiscard]] Expected<std::uint64_t> stableHash() const;
+ [[nodiscard]] Expected<std::string> print() const;
+ [[nodiscard]] Expected<EncodedTargetConstant> encode() const;
+ [[nodiscard]] Expected<TargetConstantEmission> emit() const;
+ [[nodiscard]] Expected<Alignment> requiredAlignment() const;
+ [[nodiscard]] Expected<std::optional<TargetRelocationKindID>> relocationKind() const;
+
+ [[nodiscard]] bool equals(const TargetConstant &Other) const noexcept;
+
+ template <TargetConstantValue ValueT> [[nodiscard]] ValueT *getIf() noexcept {
+ if (!hasType<ValueT>())
+ return nullptr;
+ return &static_cast<Model<ValueT> *>(Storage.get())->value();
+ }
+
+ template <TargetConstantValue ValueT> [[nodiscard]] const ValueT *getIf() const noexcept {
+ if (!hasType<ValueT>())
+ return nullptr;
+ return &static_cast<const Model<ValueT> *>(Storage.get())->value();
+ }
+
+private:
+ class Concept {
+ public:
+ Concept() = default;
+ Concept(const Concept &) = delete;
+ Concept &operator=(const Concept &) = delete;
+ Concept(Concept &&) = delete;
+ Concept &operator=(Concept &&) = delete;
+ virtual ~Concept() = default;
+
+ [[nodiscard]] virtual TargetConstantTypeID typeID() const noexcept = 0;
+ [[nodiscard]] virtual std::uint32_t schemaVersion() const noexcept = 0;
+ [[nodiscard]] virtual const void *localTypeToken() const noexcept = 0;
+ [[nodiscard]] virtual Expected<void> verify() const = 0;
+ [[nodiscard]] virtual Expected<std::unique_ptr<Concept>> cloneStorage() const = 0;
+ [[nodiscard]] virtual std::uint64_t stableHash() const noexcept = 0;
+ [[nodiscard]] virtual std::string print() const = 0;
+ [[nodiscard]] virtual Expected<std::vector<std::byte>> encodePayload() const = 0;
+ [[nodiscard]] virtual Expected<TargetConstantEmission> emit() const = 0;
+ [[nodiscard]] virtual Alignment requiredAlignment() const noexcept = 0;
+ [[nodiscard]] virtual std::optional<TargetRelocationKindID> relocationKind() const noexcept = 0;
+ [[nodiscard]] virtual bool equals(const Concept &Other) const noexcept = 0;
+ };
+
+ template <typename ValueT> [[nodiscard]] static const void *typeToken() noexcept {
+ static const std::byte Token{};
+ return &Token;
+ }
+
+ template <TargetConstantValue ValueT> class Model final : public Concept {
+ public:
+ explicit Model(ValueT Value) : Value(std::move(Value)) {}
+
+ [[nodiscard]] TargetConstantTypeID typeID() const noexcept override {
+ return ValueT::stableTypeID();
+ }
+
+ [[nodiscard]] std::uint32_t schemaVersion() const noexcept override {
+ return ValueT::schemaVersion();
+ }
+
+ [[nodiscard]] const void *localTypeToken() const noexcept override {
+ return TargetConstant::typeToken<ValueT>();
+ }
+
+ [[nodiscard]] Expected<void> verify() const override {
+ return Value.verify();
+ }
+
+ [[nodiscard]] Expected<std::unique_ptr<Concept>> cloneStorage() const override {
+ auto Cloned = Value.clone();
+ if (!Cloned)
+ return std::unexpected(Cloned.error());
+ std::unique_ptr<Concept> Result = std::make_unique<Model<ValueT>>(std::move(*Cloned));
+ return Result;
+ }
+
+ [[nodiscard]] std::uint64_t stableHash() const noexcept override {
+ return Value.stableHash();
+ }
+
+ [[nodiscard]] std::string print() const override {
+ return Value.print();
+ }
+
+ [[nodiscard]] Expected<std::vector<std::byte>> encodePayload() const override {
+ return Value.encode();
+ }
+
+ [[nodiscard]] Expected<TargetConstantEmission> emit() const override {
+ return Value.emit();
+ }
+
+ [[nodiscard]] Alignment requiredAlignment() const noexcept override {
+ return Value.requiredAlignment();
+ }
+
+ [[nodiscard]] std::optional<TargetRelocationKindID> relocationKind() const noexcept override {
+ return Value.relocationKind();
+ }
+
+ [[nodiscard]] bool equals(const Concept &Other) const noexcept override {
+ if (Other.localTypeToken() != TargetConstant::typeToken<ValueT>())
+ return false;
+ return Value == static_cast<const Model<ValueT> &>(Other).Value;
+ }
+
+ [[nodiscard]] ValueT &value() noexcept {
+ return Value;
+ }
+
+ [[nodiscard]] const ValueT &value() const noexcept {
+ return Value;
+ }
+
+ private:
+ ValueT Value;
+ };
+
+ explicit TargetConstant(std::unique_ptr<Concept> Storage) : Storage(std::move(Storage)) {}
+
+ template <TargetConstantValue ValueT> [[nodiscard]] bool hasType() const noexcept {
+ return Storage != nullptr && Storage->typeID() == ValueT::stableTypeID() &&
+ Storage->localTypeToken() == typeToken<ValueT>();
+ }
+
+ std::unique_ptr<Concept> Storage;
+};
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_TARGETCONSTANT_H