From fde3e045d4dcc5c404cb4216389e18b0e720b8e0 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Thu, 13 Aug 2026 12:55:12 +0800 Subject: [IR] Split LL parsing, assembly writing, and data layout --- backend/include/rcc/AsmParser/LLParser.h | 36 +++++ backend/include/rcc/CodeGen/GenericConstant.h | 176 --------------------- backend/include/rcc/CodeGen/GlobalObject.h | 2 +- backend/include/rcc/CodeGen/MIRYamlMapping.h | 4 +- backend/include/rcc/CodeGen/MachineConstantPool.h | 2 +- backend/include/rcc/CodeGen/MachineMemOperand.h | 2 +- backend/include/rcc/IR/Constants.h | 177 ++++++++++++++++++++++ backend/include/rcc/IR/DataLayout.h | 82 ++++++++++ backend/include/rcc/MIR/LLVMConstantSyntax.h | 52 ------- 9 files changed, 300 insertions(+), 233 deletions(-) create mode 100644 backend/include/rcc/AsmParser/LLParser.h delete mode 100644 backend/include/rcc/CodeGen/GenericConstant.h create mode 100644 backend/include/rcc/IR/Constants.h create mode 100644 backend/include/rcc/IR/DataLayout.h delete mode 100644 backend/include/rcc/MIR/LLVMConstantSyntax.h (limited to 'backend/include') diff --git a/backend/include/rcc/AsmParser/LLParser.h b/backend/include/rcc/AsmParser/LLParser.h new file mode 100644 index 0000000..e15a006 --- /dev/null +++ b/backend/include/rcc/AsmParser/LLParser.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_ASMPARSER_LLPARSER_H +#define RCC_ASMPARSER_LLPARSER_H + +#include "rcc/IR/Constants.h" +#include "rcc/Support/Error.h" + +#include +#include +#include + +namespace rcc { + +struct LLNamedTypeDefinition final { + std::string_view Name; + std::string_view Definition; + bool NumericName = false; +}; + +struct LLParserOptions final { + std::span NamedTypes; + std::size_t MaximumDepth = 1024; + std::size_t MaximumNodes = std::size_t{1} << 24U; + std::size_t MaximumTokenLength = std::size_t{1} << 24U; +}; + +[[nodiscard]] Expected parseLLVMConstant(std::string_view Text, + LLParserOptions Options = {}); + +[[nodiscard]] Expected parseLLVMType(std::string_view Text, + LLParserOptions Options = {}); + +} // namespace rcc + +#endif // RCC_ASMPARSER_LLPARSER_H diff --git a/backend/include/rcc/CodeGen/GenericConstant.h b/backend/include/rcc/CodeGen/GenericConstant.h deleted file mode 100644 index 4219c24..0000000 --- a/backend/include/rcc/CodeGen/GenericConstant.h +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef RCC_CODEGEN_GENERICCONSTANT_H -#define RCC_CODEGEN_GENERICCONSTANT_H - -#include "rcc/ADT/APFloat.h" -#include "rcc/ADT/APInt.h" -#include "rcc/CodeGen/LowLevelType.h" -#include "rcc/Support/Error.h" - -#include -#include -#include -#include -#include - -namespace rcc { - -enum class GenericConstantTypeKind : std::uint8_t { - Invalid, - Void, - Label, - Token, - Metadata, - Integer, - Byte, - Floating, - Pointer, - Array, - Vector, - Struct, - Function, - Named, -}; - -struct GenericConstantType final { - GenericConstantTypeKind Kind = GenericConstantTypeKind::Invalid; - std::uint32_t BitWidth = 0; - FloatSemantics Semantics = FloatSemantics::IEEEHalf; - std::uint32_t AddressSpace = 0; - std::uint64_t ElementCount = 0; - bool Scalable = false; - bool Packed = false; - bool VarArg = false; - bool NumericName = false; - std::string Name; - std::vector Elements; - - [[nodiscard]] static Expected integer(std::uint32_t BitWidth); - [[nodiscard]] static GenericConstantType primitive(GenericConstantTypeKind Kind) noexcept; - [[nodiscard]] static GenericConstantType byte() noexcept; - [[nodiscard]] static Expected floating(FloatSemantics Semantics); - [[nodiscard]] static GenericConstantType pointer(std::uint32_t AddressSpace = 0) noexcept; - [[nodiscard]] static Expected array(std::uint64_t ElementCount, - GenericConstantType Element); - [[nodiscard]] static Expected - vector(std::uint64_t ElementCount, GenericConstantType Element, bool Scalable = false); - [[nodiscard]] static Expected - structure(std::vector Elements, bool Packed = false); - [[nodiscard]] static Expected - function(GenericConstantType Return, std::vector Parameters, - bool VarArg = false); - [[nodiscard]] static Expected named(std::string Name, - bool NumericName = false); - - [[nodiscard]] Expected verify() const; - - friend bool operator==(const GenericConstantType &Left, - const GenericConstantType &Right) = default; -}; - -enum class GenericConstantKind : std::uint8_t { - Invalid, - Integer, - Floating, - NullPointer, - ZeroInitializer, - Undef, - Poison, - Aggregate, - ByteString, - GlobalAddress, - BlockAddress, - DSOLocalEquivalent, - NoCFI, - PointerAuth, - Expression, -}; - -enum class GenericConstantExpressionOpcode : std::uint8_t { - Invalid, - Trunc, - BitCast, - AddressSpaceCast, - IntToPtr, - PtrToAddr, - PtrToInt, - Add, - Sub, - Xor, - GetElementPtr, - ShuffleVector, - InsertElement, - ExtractElement, - Splat, -}; - -enum class GenericConstantExpressionFlag : std::uint8_t { - NoUnsignedWrap, - NoSignedWrap, - InBounds, - NoUnsignedSignedWrap, - GEPNoUnsignedWrap, - Count, -}; - -class GenericConstantExpressionFlags final { -public: - constexpr GenericConstantExpressionFlags() noexcept = default; - - [[nodiscard]] constexpr bool has(GenericConstantExpressionFlag Flag) const noexcept { - const auto Index = static_cast(Flag); - if (Index >= static_cast(GenericConstantExpressionFlag::Count)) - return false; - return (Mask & (std::uint8_t{1} << Index)) != 0; - } - - constexpr void set(GenericConstantExpressionFlag Flag) noexcept { - const auto Index = static_cast(Flag); - if (Index < static_cast(GenericConstantExpressionFlag::Count)) - Mask |= std::uint8_t{1} << Index; - } - - [[nodiscard]] constexpr std::uint8_t rawValue() const noexcept { - return Mask; - } - - friend constexpr bool operator==(GenericConstantExpressionFlags Left, - GenericConstantExpressionFlags Right) noexcept = default; - -private: - std::uint8_t Mask = 0; -}; - -struct GenericConstantData final { - GenericConstantType Type; - GenericConstantKind Kind = GenericConstantKind::Invalid; - std::optional IntegerValue; - std::optional FloatingValue; - std::vector ByteValue; - std::vector Elements; - std::string Symbol; - std::string Block; - bool NumericSymbol = false; - bool NumericBlock = false; - GenericConstantExpressionOpcode ExpressionOpcode = GenericConstantExpressionOpcode::Invalid; - GenericConstantExpressionFlags ExpressionFlags; - std::optional SourceElementType; - std::optional InRangeStart; - std::optional InRangeEnd; - - [[nodiscard]] static Expected integer(APInt Value); - [[nodiscard]] static Expected floating(APFloat Value); - [[nodiscard]] static Expected byteString(GenericConstantType Type, - std::vector Bytes); - - [[nodiscard]] Expected verify() const; - [[nodiscard]] bool referencesSymbol() const noexcept; - - friend bool operator==(const GenericConstantData &Left, - const GenericConstantData &Right) = default; -}; - -} // namespace rcc - -#endif // RCC_CODEGEN_GENERICCONSTANT_H diff --git a/backend/include/rcc/CodeGen/GlobalObject.h b/backend/include/rcc/CodeGen/GlobalObject.h index 798dcd8..1ddc34a 100644 --- a/backend/include/rcc/CodeGen/GlobalObject.h +++ b/backend/include/rcc/CodeGen/GlobalObject.h @@ -3,9 +3,9 @@ #ifndef RCC_CODEGEN_GLOBALOBJECT_H #define RCC_CODEGEN_GLOBALOBJECT_H -#include "rcc/CodeGen/GenericConstant.h" #include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/CodeGen/TargetConstant.h" +#include "rcc/IR/Constants.h" #include "rcc/Support/Error.h" #include diff --git a/backend/include/rcc/CodeGen/MIRYamlMapping.h b/backend/include/rcc/CodeGen/MIRYamlMapping.h index 82880ca..c25559b 100644 --- a/backend/include/rcc/CodeGen/MIRYamlMapping.h +++ b/backend/include/rcc/CodeGen/MIRYamlMapping.h @@ -9,7 +9,7 @@ #include "rcc/CodeGen/MachineJumpTableInfo.h" #include "rcc/CodeGen/MachineMetadata.h" #include "rcc/CodeGen/TargetMIRTextInfo.h" -#include "rcc/MIR/LLVMConstantSyntax.h" +#include "rcc/IR/DataLayout.h" #include "rcc/Support/Error.h" #include @@ -106,7 +106,7 @@ private: [[nodiscard]] bool convertTargetNode(const yaml::Node &Source, MIRTargetNode &Destination); [[nodiscard]] bool validateDocumentReferences(const MachineFunction &Function); [[nodiscard]] std::string_view effectiveDataLayout() const noexcept; - [[nodiscard]] LLVMConstantSyntaxOptions pointerLayoutOptions() const noexcept; + [[nodiscard]] Expected dataLayout() const; [[nodiscard]] MachineBasicBlock *blockAt(MachineFunction &Function, std::uint32_t Number) const noexcept; diff --git a/backend/include/rcc/CodeGen/MachineConstantPool.h b/backend/include/rcc/CodeGen/MachineConstantPool.h index a0c269b..104e559 100644 --- a/backend/include/rcc/CodeGen/MachineConstantPool.h +++ b/backend/include/rcc/CodeGen/MachineConstantPool.h @@ -3,10 +3,10 @@ #ifndef RCC_CODEGEN_MACHINECONSTANTPOOL_H #define RCC_CODEGEN_MACHINECONSTANTPOOL_H -#include "rcc/CodeGen/GenericConstant.h" #include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/CodeGen/MachineMemOperand.h" #include "rcc/CodeGen/TargetConstant.h" +#include "rcc/IR/Constants.h" #include "rcc/Support/Error.h" #include diff --git a/backend/include/rcc/CodeGen/MachineMemOperand.h b/backend/include/rcc/CodeGen/MachineMemOperand.h index c5c1357..d236fd3 100644 --- a/backend/include/rcc/CodeGen/MachineMemOperand.h +++ b/backend/include/rcc/CodeGen/MachineMemOperand.h @@ -3,10 +3,10 @@ #ifndef RCC_CODEGEN_MACHINEMEMOPERAND_H #define RCC_CODEGEN_MACHINEMEMOPERAND_H -#include "rcc/CodeGen/GenericConstant.h" #include "rcc/CodeGen/LowLevelType.h" #include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/CodeGen/MachineMetadata.h" +#include "rcc/IR/Constants.h" #include #include diff --git a/backend/include/rcc/IR/Constants.h b/backend/include/rcc/IR/Constants.h new file mode 100644 index 0000000..9f894f2 --- /dev/null +++ b/backend/include/rcc/IR/Constants.h @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_IR_CONSTANTS_H +#define RCC_IR_CONSTANTS_H + +#include "rcc/ADT/APFloat.h" +#include "rcc/ADT/APInt.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include + +namespace rcc { + +enum class GenericConstantTypeKind : std::uint8_t { + Invalid, + Void, + Label, + Token, + Metadata, + Integer, + Byte, + Floating, + Pointer, + Array, + Vector, + Struct, + Function, + Named, +}; + +struct GenericConstantType final { + GenericConstantTypeKind Kind = GenericConstantTypeKind::Invalid; + std::uint32_t BitWidth = 0; + FloatSemantics Semantics = FloatSemantics::IEEEHalf; + std::uint32_t AddressSpace = 0; + std::uint64_t ElementCount = 0; + bool Scalable = false; + bool Packed = false; + bool VarArg = false; + bool NumericName = false; + std::string Name; + std::vector Elements; + + [[nodiscard]] static Expected integer(std::uint32_t BitWidth); + [[nodiscard]] static GenericConstantType primitive(GenericConstantTypeKind Kind) noexcept; + [[nodiscard]] static GenericConstantType byte() noexcept; + [[nodiscard]] static Expected floating(FloatSemantics Semantics); + [[nodiscard]] static GenericConstantType pointer(std::uint32_t AddressSpace = 0) noexcept; + [[nodiscard]] static Expected array(std::uint64_t ElementCount, + GenericConstantType Element); + [[nodiscard]] static Expected + vector(std::uint64_t ElementCount, GenericConstantType Element, bool Scalable = false); + [[nodiscard]] static Expected + structure(std::vector Elements, bool Packed = false); + [[nodiscard]] static Expected + function(GenericConstantType Return, std::vector Parameters, + bool VarArg = false); + [[nodiscard]] static Expected named(std::string Name, + bool NumericName = false); + + [[nodiscard]] const GenericConstantType &resolved() const noexcept; + [[nodiscard]] Expected verify() const; + + friend bool operator==(const GenericConstantType &Left, + const GenericConstantType &Right) = default; +}; + +enum class GenericConstantKind : std::uint8_t { + Invalid, + Integer, + Floating, + NullPointer, + ZeroInitializer, + Undef, + Poison, + Aggregate, + ByteString, + GlobalAddress, + BlockAddress, + DSOLocalEquivalent, + NoCFI, + PointerAuth, + Expression, +}; + +enum class GenericConstantExpressionOpcode : std::uint8_t { + Invalid, + Trunc, + BitCast, + AddressSpaceCast, + IntToPtr, + PtrToAddr, + PtrToInt, + Add, + Sub, + Xor, + GetElementPtr, + ShuffleVector, + InsertElement, + ExtractElement, + Splat, +}; + +enum class GenericConstantExpressionFlag : std::uint8_t { + NoUnsignedWrap, + NoSignedWrap, + InBounds, + NoUnsignedSignedWrap, + GEPNoUnsignedWrap, + Count, +}; + +class GenericConstantExpressionFlags final { +public: + constexpr GenericConstantExpressionFlags() noexcept = default; + + [[nodiscard]] constexpr bool has(GenericConstantExpressionFlag Flag) const noexcept { + const auto Index = static_cast(Flag); + if (Index >= static_cast(GenericConstantExpressionFlag::Count)) + return false; + return (Mask & (std::uint8_t{1} << Index)) != 0; + } + + constexpr void set(GenericConstantExpressionFlag Flag) noexcept { + const auto Index = static_cast(Flag); + if (Index < static_cast(GenericConstantExpressionFlag::Count)) + Mask |= std::uint8_t{1} << Index; + } + + [[nodiscard]] constexpr std::uint8_t rawValue() const noexcept { + return Mask; + } + + friend constexpr bool operator==(GenericConstantExpressionFlags Left, + GenericConstantExpressionFlags Right) noexcept = default; + +private: + std::uint8_t Mask = 0; +}; + +struct GenericConstantData final { + GenericConstantType Type; + GenericConstantKind Kind = GenericConstantKind::Invalid; + std::optional IntegerValue; + std::optional FloatingValue; + std::vector ByteValue; + std::vector Elements; + std::string Symbol; + std::string Block; + bool NumericSymbol = false; + bool NumericBlock = false; + GenericConstantExpressionOpcode ExpressionOpcode = GenericConstantExpressionOpcode::Invalid; + GenericConstantExpressionFlags ExpressionFlags; + std::optional SourceElementType; + std::optional InRangeStart; + std::optional InRangeEnd; + + [[nodiscard]] static Expected integer(APInt Value); + [[nodiscard]] static Expected floating(APFloat Value); + [[nodiscard]] static Expected byteString(GenericConstantType Type, + std::vector Bytes); + + [[nodiscard]] Expected toLLVMString() const; + [[nodiscard]] Expected verify() const; + [[nodiscard]] bool referencesSymbol() const noexcept; + + friend bool operator==(const GenericConstantData &Left, + const GenericConstantData &Right) = default; +}; + +} // namespace rcc + +#endif // RCC_IR_CONSTANTS_H diff --git a/backend/include/rcc/IR/DataLayout.h b/backend/include/rcc/IR/DataLayout.h new file mode 100644 index 0000000..0ca3f07 --- /dev/null +++ b/backend/include/rcc/IR/DataLayout.h @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_IR_DATALAYOUT_H +#define RCC_IR_DATALAYOUT_H + +#include "rcc/IR/Constants.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include + +namespace rcc { + +class DataLayout final { +public: + [[nodiscard]] static Expected parse(std::string_view LayoutString); + + [[nodiscard]] Expected getTypeAllocSize(const GenericConstantType &Type) const; + [[nodiscard]] Expected getABITypeAlign(const GenericConstantType &Type) const; + [[nodiscard]] Expected getPrefTypeAlign(const GenericConstantType &Type) const; + [[nodiscard]] Expected getPointerSizeInBits(std::uint32_t AddressSpace = 0) const; + +private: + struct AlignmentSpec final { + std::uint64_t ABI = 1; + std::uint64_t Preferred = 1; + }; + + struct PrimitiveSpec final { + char Kind = '\0'; + std::uint32_t BitWidth = 0; + AlignmentSpec Alignment; + }; + + struct PointerSpec final { + std::uint32_t AddressSpace = 0; + std::uint32_t SizeInBits = 0; + AlignmentSpec Alignment; + std::string AddressSpaceName; + }; + + struct TypeLayout final { + std::uint64_t StoreSize = 0; + std::uint64_t AllocationSize = 0; + std::uint64_t ABIAlignment = 1; + std::uint64_t PreferredAlignment = 1; + }; + + [[nodiscard]] static Expected parseUnsignedField(std::string_view Text, + std::string_view Description); + [[nodiscard]] static Expected alignmentBytes(std::string_view Text, bool AllowZero, + std::string_view Description); + [[nodiscard]] static std::vector split(std::string_view Text, char Separator); + + void setPrimitiveSpec(PrimitiveSpec Entry); + void setPointerSpec(PointerSpec Entry); + [[nodiscard]] AlignmentSpec naturalAlignment(std::uint64_t StoreSize) const noexcept; + [[nodiscard]] AlignmentSpec scalarAlignment(char Kind, std::uint32_t BitWidth, + std::uint64_t StoreSize) const noexcept; + [[nodiscard]] AlignmentSpec integerAlignment(std::uint32_t BitWidth, + std::uint64_t StoreSize) const noexcept; + [[nodiscard]] AlignmentSpec floatingAlignment(std::uint32_t BitWidth, + std::uint64_t StoreSize) const noexcept; + [[nodiscard]] AlignmentSpec vectorAlignment(std::uint32_t BitWidth, + std::uint64_t StoreSize) const noexcept; + [[nodiscard]] Expected getPointerSpec(std::uint32_t AddressSpace) const; + [[nodiscard]] Expected getTypeLayout(const GenericConstantType &Type, + std::vector &NamedTypeStack, + std::size_t Depth) const; + + bool Explicit = false; + std::vector PrimitiveSpecs; + std::vector PointerSpecs; + AlignmentSpec AggregateAlignment{1, 8}; +}; + +} // namespace rcc + +#endif // RCC_IR_DATALAYOUT_H diff --git a/backend/include/rcc/MIR/LLVMConstantSyntax.h b/backend/include/rcc/MIR/LLVMConstantSyntax.h deleted file mode 100644 index 7e18d60..0000000 --- a/backend/include/rcc/MIR/LLVMConstantSyntax.h +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef RCC_MIR_LLVMCONSTANTSYNTAX_H -#define RCC_MIR_LLVMCONSTANTSYNTAX_H - -#include "rcc/CodeGen/GenericConstant.h" -#include "rcc/CodeGen/MachineIRTypes.h" -#include "rcc/Support/Error.h" - -#include -#include -#include -#include -#include - -namespace rcc::mir { - -struct LLVMNamedTypeDefinition final { - std::string_view Name; - std::string_view Definition; - bool NumericName = false; -}; - -struct LLVMConstantSyntaxOptions final { - std::string_view DataLayout; - std::span NamedTypes; - std::size_t MaximumDepth = 1024; - std::size_t MaximumNodes = std::size_t{1} << 24U; - std::size_t MaximumTokenLength = std::size_t{1} << 24U; -}; - -[[nodiscard]] Expected -parseLLVMConstant(std::string_view Text, LLVMConstantSyntaxOptions Options = {}); - -[[nodiscard]] Expected parseLLVMType(std::string_view Text, - LLVMConstantSyntaxOptions Options = {}); - -[[nodiscard]] Expected printLLVMConstant(const GenericConstantData &Constant); - -[[nodiscard]] Expected -llvmConstantStorageSize(const GenericConstantType &Type, LLVMConstantSyntaxOptions Options = {}); - -[[nodiscard]] Expected -llvmConstantPreferredAlignment(const GenericConstantType &Type, - LLVMConstantSyntaxOptions Options = {}); - -[[nodiscard]] Expected llvmPointerSizeInBits(std::uint32_t AddressSpace, - LLVMConstantSyntaxOptions Options = {}); - -} // namespace rcc::mir - -#endif // RCC_MIR_LLVMCONSTANTSYNTAX_H -- cgit v1.2.3