diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-01 14:50:04 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-01 14:50:04 +0800 |
| commit | cfdbcc469f9691bd9dce3b0b86982a63d86ca6b7 (patch) | |
| tree | 19f4ad856c3e4900a0501ab2cad41981b49569b5 /backend/include | |
| parent | a69d14b8ebc028dddc689658b08d42d3e83f5e38 (diff) | |
| download | rcc-project-cfdbcc469f9691bd9dce3b0b86982a63d86ca6b7.tar.gz rcc-project-cfdbcc469f9691bd9dce3b0b86982a63d86ca6b7.tar.xz | |
[CodeGen] Add target state and compilation status
Diffstat (limited to 'backend/include')
| -rw-r--r-- | backend/include/rcc/CodeGen/MachineCompilationStatus.h | 107 | ||||
| -rw-r--r-- | backend/include/rcc/CodeGen/MachineFunction.h | 27 | ||||
| -rw-r--r-- | backend/include/rcc/CodeGen/MachineFunctionCloner.h | 45 | ||||
| -rw-r--r-- | backend/include/rcc/CodeGen/TargetFunctionState.h | 210 |
4 files changed, 389 insertions, 0 deletions
diff --git a/backend/include/rcc/CodeGen/MachineCompilationStatus.h b/backend/include/rcc/CodeGen/MachineCompilationStatus.h new file mode 100644 index 0000000..f889574 --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineCompilationStatus.h @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACHINECOMPILATIONSTATUS_H +#define RCC_CODEGEN_MACHINECOMPILATIONSTATUS_H + +#include "rcc/CodeGen/InstructionDescriptor.h" +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/CodeGen/StableID.h" +#include "rcc/Support/Error.h" + +#include <cstdint> +#include <optional> +#include <string> +#include <string_view> + +namespace rcc { + +class MachineFunctionCloneContext; + +enum class MachineCompilationState : std::uint8_t { + Success, + Unsupported, + MIRParseFailed, + LegalizationFailed, + SelectionFailed, + RegisterAllocationFailed, + CallLoweringFailed, + FrameLayoutFailed, + FinalizationFailed, + AssemblyLoweringFailed, + InternalError, + Count, +}; + +[[nodiscard]] bool isKnownMachineCompilationState(MachineCompilationState State) noexcept; +[[nodiscard]] std::string_view +getMachineCompilationStateName(MachineCompilationState State) noexcept; + +enum class MachineCompilationDiagnosticSeverity : std::uint8_t { + Error, + Fatal, + Count, +}; + +struct MachineCompilationDiagnostic final { + MachineCompilationDiagnosticSeverity Severity = MachineCompilationDiagnosticSeverity::Error; + ErrorCode Code = ErrorCode::InternalError; + std::string Message; + std::optional<SourceLocation> Location; + + friend bool operator==(const MachineCompilationDiagnostic &Left, + const MachineCompilationDiagnostic &Right) = default; +}; + +struct MachineCompilationFailure final { + MachineCompilationDiagnostic Diagnostic; + std::optional<std::string> FailurePass; + std::optional<MachineInstrStableID> FailureInstruction; + std::optional<PipelineStage> FailureStage; + std::optional<std::string> FailureRule; + std::optional<std::string> Target; + std::optional<std::string> Subtarget; + + friend bool operator==(const MachineCompilationFailure &Left, + const MachineCompilationFailure &Right) = default; +}; + +class MachineCompilationStatus final { +public: + MachineCompilationStatus() = default; + MachineCompilationStatus(const MachineCompilationStatus &) = delete; + MachineCompilationStatus &operator=(const MachineCompilationStatus &) = delete; + MachineCompilationStatus(MachineCompilationStatus &&) noexcept = default; + MachineCompilationStatus &operator=(MachineCompilationStatus &&) noexcept = default; + ~MachineCompilationStatus() = default; + + [[nodiscard]] MachineCompilationState state() const noexcept { + return State; + } + + [[nodiscard]] bool succeeded() const noexcept { + return State == MachineCompilationState::Success; + } + + [[nodiscard]] const MachineCompilationFailure *failure() const noexcept { + if (!Failure) + return nullptr; + return &*Failure; + } + + [[nodiscard]] Expected<void> fail(MachineCompilationState NewState, + MachineCompilationFailure NewFailure); + [[nodiscard]] Expected<void> verify() const; + [[nodiscard]] Expected<MachineCompilationStatus> + clone(const MachineFunctionCloneContext &CloneContext) const; + + friend bool operator==(const MachineCompilationStatus &Left, + const MachineCompilationStatus &Right) = default; + +private: + MachineCompilationState State = MachineCompilationState::Success; + std::optional<MachineCompilationFailure> Failure; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINECOMPILATIONSTATUS_H diff --git a/backend/include/rcc/CodeGen/MachineFunction.h b/backend/include/rcc/CodeGen/MachineFunction.h index 38d88f9..b687573 100644 --- a/backend/include/rcc/CodeGen/MachineFunction.h +++ b/backend/include/rcc/CodeGen/MachineFunction.h @@ -3,12 +3,14 @@ #ifndef RCC_CODEGEN_MACHINEFUNCTION_H #define RCC_CODEGEN_MACHINEFUNCTION_H +#include "rcc/CodeGen/MachineCompilationStatus.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/CodeGen/TargetFunctionState.h" #include "rcc/Support/Error.h" #include <cstddef> @@ -87,6 +89,29 @@ public: return Properties; } + [[nodiscard]] const TargetFunctionState &targetState() const noexcept { + return TargetState; + } + + [[nodiscard]] Expected<void> setTargetState(TargetFunctionState State); + + template <TargetFunctionStateValue ValueT> [[nodiscard]] ValueT *getTargetInfo() noexcept { + return TargetState.getIf<ValueT>(); + } + + template <TargetFunctionStateValue ValueT> + [[nodiscard]] const ValueT *getTargetInfo() const noexcept { + return TargetState.getIf<ValueT>(); + } + + [[nodiscard]] MachineCompilationStatus &compilationStatus() noexcept { + return CompilationStatus; + } + + [[nodiscard]] const MachineCompilationStatus &compilationStatus() const noexcept { + return CompilationStatus; + } + [[nodiscard]] Expected<MachineBasicBlock *> createBasicBlock(); [[nodiscard]] Expected<MachineInstr *> createInstruction(Opcode InstructionOpcode); [[nodiscard]] Expected<const MachineMemOperand *> @@ -141,6 +166,8 @@ private: MachineConstantPool ConstantPool; MachineJumpTableInfo JumpTables; MachineFunctionProperties Properties; + TargetFunctionState TargetState; + MachineCompilationStatus CompilationStatus; MachineBasicBlock *FirstBlock = nullptr; MachineBasicBlock *LastBlock = nullptr; std::vector<MachineBasicBlock *> AllBlocks; diff --git a/backend/include/rcc/CodeGen/MachineFunctionCloner.h b/backend/include/rcc/CodeGen/MachineFunctionCloner.h index 3abdf78..658614f 100644 --- a/backend/include/rcc/CodeGen/MachineFunctionCloner.h +++ b/backend/include/rcc/CodeGen/MachineFunctionCloner.h @@ -16,7 +16,9 @@ namespace rcc { class InstructionSet; +class MachineBasicBlock; class MachineFunction; +class MachineInstr; struct MachineFunctionCloneOptions final { MachineFunctionStableID NewStableID; @@ -40,6 +42,49 @@ struct MachineFunctionCloneResult final { std::unordered_map<JumpTableIndex, JumpTableIndex> JumpTableIndices; }; +class MachineFunctionCloneContext final { +public: + [[nodiscard]] const MachineFunction &sourceFunction() const noexcept { + return Source; + } + + [[nodiscard]] MachineFunction &destinationFunction() const noexcept { + return Destination; + } + + [[nodiscard]] Expected<MachineBasicBlock *> mapBlock(const MachineBasicBlock &SourceBlock) const; + [[nodiscard]] Expected<MachineInstr *> + mapInstruction(const MachineInstr &SourceInstruction) const; + [[nodiscard]] Expected<MachineBlockStableID> + mapBlockStableID(MachineBlockStableID SourceID) const; + [[nodiscard]] Expected<MachineInstrStableID> + mapInstructionStableID(MachineInstrStableID SourceID) const; + [[nodiscard]] Expected<Register> mapRegister(Register SourceRegister) const; + [[nodiscard]] Expected<FrameIndex> mapFrameIndex(FrameIndex SourceIndex) const; + [[nodiscard]] Expected<ConstantPoolIndex> + mapConstantPoolIndex(ConstantPoolIndex SourceIndex) const; + [[nodiscard]] Expected<JumpTableIndex> mapJumpTableIndex(JumpTableIndex SourceIndex) const; + +private: + MachineFunctionCloneContext( + const MachineFunction &Source, MachineFunction &Destination, + const MachineFunctionCloneResult &Result, + const std::unordered_map<const MachineBasicBlock *, MachineBasicBlock *> &Blocks, + const std::unordered_map<const MachineInstr *, MachineInstr *> &Instructions) noexcept + : Source(Source), Destination(Destination), Result(Result), Blocks(Blocks), + Instructions(Instructions) {} + + const MachineFunction &Source; + MachineFunction &Destination; + const MachineFunctionCloneResult &Result; + const std::unordered_map<const MachineBasicBlock *, MachineBasicBlock *> &Blocks; + const std::unordered_map<const MachineInstr *, MachineInstr *> &Instructions; + + friend Expected<MachineFunctionCloneResult> + cloneMachineFunction(const MachineFunction &Source, const InstructionSet &Instructions, + MachineFunctionCloneOptions Options); +}; + [[nodiscard]] Expected<MachineFunctionCloneResult> cloneMachineFunction(const MachineFunction &Source, const InstructionSet &Instructions, MachineFunctionCloneOptions Options); 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 <concepts> +#include <cstddef> +#include <cstdint> +#include <memory> +#include <optional> +#include <span> +#include <string> +#include <utility> +#include <vector> + +namespace rcc { + +class MachineFunctionCloneContext; + +struct EncodedTargetFunctionState final { + TargetFunctionStateTypeID TypeID; + std::uint32_t Version = 0; + std::vector<std::byte> Payload; + + friend bool operator==(const EncodedTargetFunctionState &Left, + const EncodedTargetFunctionState &Right) = default; +}; + +template <typename ValueT> +concept TargetFunctionStateValue = + std::move_constructible<ValueT> && + requires(const ValueT &Value, const ValueT &Other, + const MachineFunctionCloneContext &CloneContext, std::uint32_t Version, + std::span<const std::byte> Payload) { + { ValueT::stableTypeID() } -> std::same_as<TargetFunctionStateTypeID>; + { ValueT::schemaVersion() } -> std::same_as<std::uint32_t>; + { Value.verify() } -> std::same_as<Expected<void>>; + { Value.clone(CloneContext) } -> std::same_as<Expected<ValueT>>; + { Value.print() } -> std::same_as<std::string>; + { Value.encode() } -> std::same_as<Expected<std::vector<std::byte>>>; + { Value == Other } -> std::convertible_to<bool>; + { ValueT::decode(Version, Payload) } -> std::same_as<Expected<ValueT>>; + }; + +class TargetFunctionState final { +public: + TargetFunctionState() = default; + TargetFunctionState(const TargetFunctionState &) = delete; + TargetFunctionState &operator=(const TargetFunctionState &) = delete; + TargetFunctionState(TargetFunctionState &&) noexcept; + TargetFunctionState &operator=(TargetFunctionState &&) noexcept; + ~TargetFunctionState(); + + template <TargetFunctionStateValue ValueT> + [[nodiscard]] static Expected<TargetFunctionState> 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<Concept> NewStorage = std::make_unique<Model<ValueT>>(std::move(Value)); + return TargetFunctionState(std::move(NewStorage)); + } + + template <TargetFunctionStateValue ValueT> + [[nodiscard]] static Expected<TargetFunctionState> + 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<ValueT>(std::move(*Value)); + } + + [[nodiscard]] bool hasValue() const noexcept { + return Storage != nullptr; + } + + [[nodiscard]] std::optional<TargetFunctionStateTypeID> typeID() const noexcept; + [[nodiscard]] std::optional<std::uint32_t> schemaVersion() const noexcept; + [[nodiscard]] Expected<void> verify() const; + [[nodiscard]] Expected<TargetFunctionState> + clone(const MachineFunctionCloneContext &CloneContext) const; + [[nodiscard]] Expected<std::string> print() const; + [[nodiscard]] Expected<EncodedTargetFunctionState> encode() const; + [[nodiscard]] bool equals(const TargetFunctionState &Other) const noexcept; + + template <TargetFunctionStateValue ValueT> [[nodiscard]] ValueT *getIf() noexcept { + if (!hasType<ValueT>()) + return nullptr; + return &static_cast<Model<ValueT> *>(Storage.get())->value(); + } + + template <TargetFunctionStateValue 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 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<void> verify() const = 0; + [[nodiscard]] virtual Expected<std::unique_ptr<Concept>> + cloneStorage(const MachineFunctionCloneContext &CloneContext) const = 0; + [[nodiscard]] virtual std::string print() const = 0; + [[nodiscard]] virtual Expected<std::vector<std::byte>> encodePayload() const = 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 <TargetFunctionStateValue ValueT> 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<ValueT>(); + } + + [[nodiscard]] Expected<void> verify() const override { + return Value.verify(); + } + + [[nodiscard]] Expected<std::unique_ptr<Concept>> + cloneStorage(const MachineFunctionCloneContext &CloneContext) const override { + auto Cloned = Value.clone(CloneContext); + if (!Cloned) + return std::unexpected(Cloned.error()); + std::unique_ptr<Concept> Result = std::make_unique<Model<ValueT>>(std::move(*Cloned)); + return Result; + } + + [[nodiscard]] std::string print() const override { + return Value.print(); + } + + [[nodiscard]] Expected<std::vector<std::byte>> encodePayload() const override { + return Value.encode(); + } + + [[nodiscard]] bool equals(const Concept &Other) const noexcept override { + if (Other.localTypeToken() != TargetFunctionState::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 TargetFunctionState(std::unique_ptr<Concept> Storage) : Storage(std::move(Storage)) {} + + template <TargetFunctionStateValue 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_TARGETFUNCTIONSTATE_H |
