From 76d89700953ddd81cf31ab8f260eddf67e93aa85 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Fri, 7 Aug 2026 01:27:41 +0800 Subject: [MIR] Complete document parsing and printing Implement the single LLVM-compatible MIR document path with structured\nembedded-IR references, YAML mappings, constants, and deterministic printing.\n\nKeep pointer LLT widths DataLayout-derived, reject layout-dependent output\nwhen embedded IR is omitted, and record the fixed-baseline compatibility\ncontract and regression coverage. --- backend/lib/MIR/MIPrinter.cpp | 122 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 4 deletions(-) (limited to 'backend/lib/MIR/MIPrinter.cpp') diff --git a/backend/lib/MIR/MIPrinter.cpp b/backend/lib/MIR/MIPrinter.cpp index e3f504b..83fce40 100644 --- a/backend/lib/MIR/MIPrinter.cpp +++ b/backend/lib/MIR/MIPrinter.cpp @@ -61,6 +61,15 @@ namespace { return Result; } +[[nodiscard]] std::string quoteString(std::string_view Value) { + std::string Result = quoteName(Value); + if (!Result.empty() && Result.front() == '"') + return Result; + Result.insert(Result.begin(), '"'); + Result.push_back('"'); + return Result; +} + [[nodiscard]] std::string hexadecimalWords(std::span Words, std::uint32_t BitWidth) { constexpr std::string_view Hex = "0123456789ABCDEF"; @@ -208,6 +217,91 @@ namespace { return {}; } +[[nodiscard]] Expected llvmMIRScalarLowLevelType(LLT Type) { + if (Type.isToken()) + return "s0"; + if (Type.isAnyScalar()) + return "s" + std::to_string(Type.scalarBitWidth()); + if (Type.isInteger()) + return "i" + std::to_string(Type.scalarBitWidth()); + if (Type.isPointer()) { + const auto AddressSpace = Type.addressSpace(); + if (!AddressSpace) { + return makeUnexpected(ErrorCode::VerificationError, + "pointer low-level type has no address space"); + } + return "p" + std::to_string(*AddressSpace); + } + if (!Type.isFloat()) { + return makeUnexpected(ErrorCode::VerificationError, + "invalid scalar low-level type cannot be printed as LLVM MIR"); + } + + const auto Semantics = Type.floatSemantics(); + if (!Semantics) { + return makeUnexpected(ErrorCode::VerificationError, + "floating low-level type has no floating-point semantics"); + } + switch (*Semantics) { + case FloatSemantics::IEEEHalf: + return "f16"; + case FloatSemantics::BFloat: + return "bf16"; + case FloatSemantics::IEEESingle: + return "f32"; + case FloatSemantics::IEEEDouble: + return "f64"; + case FloatSemantics::IEEEQuad: + return "f128"; + case FloatSemantics::PPCDoubleDouble: + case FloatSemantics::PPCDoubleDoubleLegacy: + case FloatSemantics::Float8E5M2: + case FloatSemantics::Float8E5M2FNUZ: + case FloatSemantics::Float8E4M3: + case FloatSemantics::Float8E4M3FN: + case FloatSemantics::Float8E4M3FNUZ: + case FloatSemantics::Float8E4M3B11FNUZ: + case FloatSemantics::Float8E3M4: + case FloatSemantics::FloatTF32: + case FloatSemantics::Float8E8M0FNU: + case FloatSemantics::Float6E3M2FN: + case FloatSemantics::Float6E2M3FN: + case FloatSemantics::Float4E2M1FN: + case FloatSemantics::X87DoubleExtended: + case FloatSemantics::Count: + return makeUnexpected(ErrorCode::Unsupported, + "fixed LLVM MIR cannot spell this floating low-level type"); + } + return makeUnexpected(ErrorCode::InternalError, "floating low-level type is unhandled"); +} + +[[nodiscard]] Expected llvmMIRLowLevelType(LLT Type) { + if (!Type.isValid()) { + return makeUnexpected(ErrorCode::VerificationError, + "invalid low-level type cannot be printed as LLVM MIR"); + } + if (!Type.isVector()) + return llvmMIRScalarLowLevelType(Type); + + const auto ElementType = Type.scalarElementType(); + if (!ElementType) { + return makeUnexpected(ErrorCode::VerificationError, + "vector low-level type has no scalar element type"); + } + auto Scalar = llvmMIRScalarLowLevelType(*ElementType); + if (!Scalar) + return std::unexpected(Scalar.error()); + + std::string Result = "<"; + if (Type.isScalableVector()) + Result.append("vscale x "); + Result.append(std::to_string(Type.minimumElementCount())); + Result.append(" x "); + Result.append(*Scalar); + Result.push_back('>'); + return Result; +} + class BodyPrinter final { public: BodyPrinter(const MachineFunction &Function, const TargetDescription &Target, @@ -232,6 +326,7 @@ private: [[nodiscard]] Expected printMemoryBase(const MemoryBase &Base, std::int64_t Offset); [[nodiscard]] Expected blockID(const MachineBasicBlock &Block) const; + [[nodiscard]] Expected virtualRegisterID(Register Reg) const; [[nodiscard]] Expected frameID(FrameIndex Index) const; [[nodiscard]] Expected constantPoolID(ConstantPoolIndex Index) const; [[nodiscard]] Expected jumpTableID(JumpTableIndex Index) const; @@ -270,6 +365,22 @@ Expected BodyPrinter::blockID(const MachineBasicBlock &Block) con return Found->second; } +Expected BodyPrinter::virtualRegisterID(Register Reg) const { + if (!Context.VirtualRegisters.empty()) { + const auto Found = + std::ranges::find_if(Context.VirtualRegisters, + [Reg](const MIVirtualRegisterSlot &Slot) { return Slot.Reg == Reg; }); + if (Found == Context.VirtualRegisters.end()) { + return makeUnexpected(ErrorCode::VerificationError, "virtual register has no MIR text slot"); + } + return Found->TextID; + } + const auto VirtualIndex = Reg.virtualIndex(); + if (!VirtualIndex) + return makeUnexpected(ErrorCode::VerificationError, "virtual register has no numeric index"); + return *VirtualIndex; +} + Expected BodyPrinter::frameID(FrameIndex Index) const { const auto InStack = std::ranges::find_if( Context.StackObjects, [Index](const MIFrameObjectSlot &Slot) { return Slot.Index == Index; }); @@ -459,9 +570,9 @@ Expected BodyPrinter::printRegisterOperand(const MachineOperand &Operand, if (!Printed) return Printed; } else { - const auto VirtualIndex = Reg.virtualIndex(); + auto VirtualIndex = virtualRegisterID(Reg); if (!VirtualIndex) - return makeUnexpected(ErrorCode::VerificationError, "virtual register has no numeric index"); + return std::unexpected(VirtualIndex.error()); Output.push_back('%'); Output.append(std::to_string(*VirtualIndex)); if (Operand.subReg().value() != 0) { @@ -495,8 +606,11 @@ Expected BodyPrinter::printRegisterOperand(const MachineOperand &Operand, Output.append(":_"); } if (RegisterInfo.Type) { + auto Type = llvmMIRLowLevelType(*RegisterInfo.Type); + if (!Type) + return std::unexpected(Type.error()); Output.push_back('('); - Output.append(RegisterInfo.Type->toString()); + Output.append(*Type); Output.push_back(')'); } } @@ -1092,7 +1206,7 @@ Expected BodyPrinter::printMemoryOperand(const MachineMemOperand &Operand) return makeUnexpected(ErrorCode::VerificationError, "synchronization scope has no MIR name"); } Output.append(" syncscope("); - Output.append(quoteName(Scope->Name)); + Output.append(quoteString(Scope->Name)); Output.push_back(')'); } if (Description.SuccessOrdering != AtomicOrdering::NotAtomic) { -- cgit v1.2.3