aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'backend/include/rcc/CodeGen')
-rw-r--r--backend/include/rcc/CodeGen/MachineCompilationStatus.h107
-rw-r--r--backend/include/rcc/CodeGen/MachineFunction.h27
-rw-r--r--backend/include/rcc/CodeGen/MachineFunctionCloner.h45
-rw-r--r--backend/include/rcc/CodeGen/TargetFunctionState.h210
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