From c9634fa9f529afbdf622a9cd96741bd09d14ef86 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sat, 1 Aug 2026 13:55:21 +0800 Subject: [CodeGen] Add MachineFrameInfo Model stable frame indices, stack object kinds, tombstones, lifetimes, and frozen layouts. Validate owned frame references in the builder and verifier, and remap complete frame state during MachineFunction cloning. --- backend/include/rcc/CodeGen/MachineFrameInfo.h | 186 +++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 backend/include/rcc/CodeGen/MachineFrameInfo.h (limited to 'backend/include/rcc/CodeGen/MachineFrameInfo.h') diff --git a/backend/include/rcc/CodeGen/MachineFrameInfo.h b/backend/include/rcc/CodeGen/MachineFrameInfo.h new file mode 100644 index 0000000..ad1de53 --- /dev/null +++ b/backend/include/rcc/CodeGen/MachineFrameInfo.h @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACHINEFRAMEINFO_H +#define RCC_CODEGEN_MACHINEFRAMEINFO_H + +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/CodeGen/MachineMemOperand.h" +#include "rcc/CodeGen/StableID.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include +#include + +namespace rcc { + +enum class StackObjectKind : std::uint8_t { + Default, + FixedABI, + SpillSlot, + VariableSized, + DynamicAlloca, + CalleeSaved, + EmergencySpill, + Target, + Count, +}; + +class StackID final { +public: + constexpr StackID() noexcept = default; + + [[nodiscard]] static constexpr StackID defaultStack() noexcept { + return StackID(DefaultStackValue); + } + + [[nodiscard]] static constexpr StackID safeStack() noexcept { + return StackID(SafeStackValue); + } + + [[nodiscard]] static constexpr StackID shadowCallStack() noexcept { + return StackID(ShadowCallStackValue); + } + + [[nodiscard]] static constexpr StackID scalableVectorStack() noexcept { + return StackID(ScalableVectorStackValue); + } + + [[nodiscard]] static Expected targetStack(std::uint32_t Value); + + [[nodiscard]] constexpr std::uint32_t value() const noexcept { + return Value; + } + + [[nodiscard]] constexpr bool isTargetStack() const noexcept { + return Value >= FirstTargetStackValue; + } + + [[nodiscard]] constexpr bool isValid() const noexcept { + return Value <= ScalableVectorStackValue || isTargetStack(); + } + + friend constexpr bool operator==(StackID Left, StackID Right) noexcept = default; + +private: + static constexpr std::uint32_t DefaultStackValue = 0; + static constexpr std::uint32_t SafeStackValue = 1; + static constexpr std::uint32_t ShadowCallStackValue = 2; + static constexpr std::uint32_t ScalableVectorStackValue = 3; + static constexpr std::uint32_t FirstTargetStackValue = 256; + + explicit constexpr StackID(std::uint32_t Value) noexcept : Value(Value) {} + + std::uint32_t Value = DefaultStackValue; +}; + +struct StackObjectLifetimeRange final { + MachineInstrStableID Begin; + MachineInstrStableID End; + + friend constexpr bool operator==(StackObjectLifetimeRange Left, + StackObjectLifetimeRange Right) noexcept = default; +}; + +struct StackObjectDesc final { + StackObjectKind Kind = StackObjectKind::Default; + std::optional Size; + Alignment Align; + std::optional Offset; + StackID Stack; + bool IsDead = false; + bool IsAliased = false; + bool AddressTaken = false; + std::vector Lifetime; + std::uint64_t TargetFlags = 0; + + friend bool operator==(const StackObjectDesc &Left, const StackObjectDesc &Right) = default; +}; + +class StackObject final { +public: + [[nodiscard]] FrameIndex index() const noexcept { + return Index; + } + + [[nodiscard]] bool isTombstone() const noexcept { + return std::holds_alternative(Description); + } + + [[nodiscard]] const StackObjectDesc *description() const noexcept { + return std::get_if(&Description); + } + + [[nodiscard]] bool isSpill() const noexcept; + [[nodiscard]] bool isFixed() const noexcept; + [[nodiscard]] bool isVariableSized() const noexcept; + +private: + StackObject(FrameIndex Index, StackObjectDesc Description) + : Index(Index), Description(std::move(Description)) {} + + FrameIndex Index; + std::variant Description; + + friend class MachineFrameInfo; +}; + +class MachineFrameInfo final { +public: + MachineFrameInfo() = default; + MachineFrameInfo(const MachineFrameInfo &) = delete; + MachineFrameInfo &operator=(const MachineFrameInfo &) = delete; + MachineFrameInfo(MachineFrameInfo &&) noexcept = default; + MachineFrameInfo &operator=(MachineFrameInfo &&) noexcept = default; + ~MachineFrameInfo() = default; + + [[nodiscard]] Expected createObject(StackObjectDesc Description); + [[nodiscard]] Expected updateObject(FrameIndex Index, StackObjectDesc Description); + [[nodiscard]] Expected setObjectOffset(FrameIndex Index, std::int64_t Offset); + [[nodiscard]] Expected markObjectDead(FrameIndex Index); + [[nodiscard]] Expected eraseObject(FrameIndex Index); + + [[nodiscard]] const StackObject *object(FrameIndex Index) const noexcept; + [[nodiscard]] std::span objects() const noexcept { + return Objects; + } + + [[nodiscard]] std::size_t liveObjectCount() const noexcept; + + [[nodiscard]] bool isFrozen() const noexcept { + return Frozen; + } + + [[nodiscard]] std::optional staticStackSize() const noexcept { + return StaticStackSize; + } + + [[nodiscard]] Alignment stackAlignment() const noexcept { + return StackAlign; + } + + [[nodiscard]] std::uint64_t maxCallFrameSize() const noexcept { + return MaxCallFrameSize; + } + + [[nodiscard]] Expected setMaxCallFrameSize(std::uint64_t Size); + [[nodiscard]] Expected freeze(std::uint64_t Size, Alignment Align); + [[nodiscard]] Expected verify() const; + +private: + [[nodiscard]] static Expected verifyDescription(const StackObjectDesc &Description); + [[nodiscard]] Expected mutableObject(FrameIndex Index); + + std::vector Objects; + bool Frozen = false; + std::optional StaticStackSize; + Alignment StackAlign; + std::uint64_t MaxCallFrameSize = 0; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINEFRAMEINFO_H -- cgit v1.2.3