From cfdbcc469f9691bd9dce3b0b86982a63d86ca6b7 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sat, 1 Aug 2026 14:50:04 +0800 Subject: [CodeGen] Add target state and compilation status --- backend/include/rcc/CodeGen/TargetFunctionState.h | 210 ++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 backend/include/rcc/CodeGen/TargetFunctionState.h (limited to 'backend/include/rcc/CodeGen/TargetFunctionState.h') diff --git a/backend/include/rcc/CodeGen/TargetFunctionState.h b/backend/include/rcc/CodeGen/TargetFunctionState.h new file mode 100644 index 0000000..b11c91b --- /dev/null +++ b/backend/include/rcc/CodeGen/TargetFunctionState.h @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_TARGETFUNCTIONSTATE_H +#define RCC_CODEGEN_TARGETFUNCTIONSTATE_H + +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rcc { + +class MachineFunctionCloneContext; + +struct EncodedTargetFunctionState final { + TargetFunctionStateTypeID TypeID; + std::uint32_t Version = 0; + std::vector Payload; + + friend bool operator==(const EncodedTargetFunctionState &Left, + const EncodedTargetFunctionState &Right) = default; +}; + +template +concept TargetFunctionStateValue = + std::move_constructible && + requires(const ValueT &Value, const ValueT &Other, + const MachineFunctionCloneContext &CloneContext, std::uint32_t Version, + std::span Payload) { + { ValueT::stableTypeID() } -> std::same_as; + { ValueT::schemaVersion() } -> std::same_as; + { Value.verify() } -> std::same_as>; + { Value.clone(CloneContext) } -> std::same_as>; + { Value.print() } -> std::same_as; + { Value.encode() } -> std::same_as>>; + { Value == Other } -> std::convertible_to; + { ValueT::decode(Version, Payload) } -> std::same_as>; + }; + +class TargetFunctionState final { +public: + TargetFunctionState() = default; + TargetFunctionState(const TargetFunctionState &) = delete; + TargetFunctionState &operator=(const TargetFunctionState &) = delete; + TargetFunctionState(TargetFunctionState &&) noexcept; + TargetFunctionState &operator=(TargetFunctionState &&) noexcept; + ~TargetFunctionState(); + + template + [[nodiscard]] static Expected create(ValueT Value) { + if (ValueT::stableTypeID().value() == 0) { + return makeUnexpected(ErrorCode::InvalidArgument, + "target function state TypeID must be nonzero"); + } + if (ValueT::schemaVersion() == 0) { + return makeUnexpected(ErrorCode::InvalidArgument, + "target function state schema version must be nonzero"); + } + auto Verification = Value.verify(); + if (!Verification) + return std::unexpected(Verification.error()); + + std::unique_ptr NewStorage = std::make_unique>(std::move(Value)); + return TargetFunctionState(std::move(NewStorage)); + } + + template + [[nodiscard]] static Expected + decode(const EncodedTargetFunctionState &Encoded) { + if (Encoded.TypeID != ValueT::stableTypeID()) { + return makeUnexpected( + ErrorCode::ParseError, + "encoded target function state TypeID does not match its target schema"); + } + if (Encoded.Version == 0) { + return makeUnexpected(ErrorCode::ParseError, "target function state version must be nonzero"); + } + auto Value = ValueT::decode(Encoded.Version, Encoded.Payload); + if (!Value) + return std::unexpected(Value.error()); + return create(std::move(*Value)); + } + + [[nodiscard]] bool hasValue() const noexcept { + return Storage != nullptr; + } + + [[nodiscard]] std::optional typeID() const noexcept; + [[nodiscard]] std::optional schemaVersion() const noexcept; + [[nodiscard]] Expected verify() const; + [[nodiscard]] Expected + clone(const MachineFunctionCloneContext &CloneContext) const; + [[nodiscard]] Expected print() const; + [[nodiscard]] Expected encode() const; + [[nodiscard]] bool equals(const TargetFunctionState &Other) const noexcept; + + template [[nodiscard]] ValueT *getIf() noexcept { + if (!hasType()) + return nullptr; + return &static_cast *>(Storage.get())->value(); + } + + template [[nodiscard]] const ValueT *getIf() const noexcept { + if (!hasType()) + return nullptr; + return &static_cast *>(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 TargetFunctionStateTypeID typeID() const noexcept = 0; + [[nodiscard]] virtual std::uint32_t schemaVersion() const noexcept = 0; + [[nodiscard]] virtual const void *localTypeToken() const noexcept = 0; + [[nodiscard]] virtual Expected verify() const = 0; + [[nodiscard]] virtual Expected> + cloneStorage(const MachineFunctionCloneContext &CloneContext) const = 0; + [[nodiscard]] virtual std::string print() const = 0; + [[nodiscard]] virtual Expected> encodePayload() const = 0; + [[nodiscard]] virtual bool equals(const Concept &Other) const noexcept = 0; + }; + + template [[nodiscard]] static const void *typeToken() noexcept { + static const std::byte Token{}; + return &Token; + } + + template class Model final : public Concept { + public: + explicit Model(ValueT Value) : Value(std::move(Value)) {} + + [[nodiscard]] TargetFunctionStateTypeID 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 TargetFunctionState::typeToken(); + } + + [[nodiscard]] Expected verify() const override { + return Value.verify(); + } + + [[nodiscard]] Expected> + cloneStorage(const MachineFunctionCloneContext &CloneContext) const override { + auto Cloned = Value.clone(CloneContext); + if (!Cloned) + return std::unexpected(Cloned.error()); + std::unique_ptr Result = std::make_unique>(std::move(*Cloned)); + return Result; + } + + [[nodiscard]] std::string print() const override { + return Value.print(); + } + + [[nodiscard]] Expected> encodePayload() const override { + return Value.encode(); + } + + [[nodiscard]] bool equals(const Concept &Other) const noexcept override { + if (Other.localTypeToken() != TargetFunctionState::typeToken()) + return false; + return Value == static_cast &>(Other).Value; + } + + [[nodiscard]] ValueT &value() noexcept { + return Value; + } + + [[nodiscard]] const ValueT &value() const noexcept { + return Value; + } + + private: + ValueT Value; + }; + + explicit TargetFunctionState(std::unique_ptr Storage) : Storage(std::move(Storage)) {} + + template [[nodiscard]] bool hasType() const noexcept { + return Storage != nullptr && Storage->typeID() == ValueT::stableTypeID() && + Storage->localTypeToken() == typeToken(); + } + + std::unique_ptr Storage; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_TARGETFUNCTIONSTATE_H -- cgit v1.2.3