From d62f022c92fcc3ebe2269273628943a0089683fd Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Thu, 13 Aug 2026 06:19:30 +0800 Subject: [CodeGen] Align MIR parser and printer ownership --- backend/lib/MIR/MIRDocumentPrinter.cpp | 1499 -------------------------------- 1 file changed, 1499 deletions(-) delete mode 100644 backend/lib/MIR/MIRDocumentPrinter.cpp (limited to 'backend/lib/MIR/MIRDocumentPrinter.cpp') diff --git a/backend/lib/MIR/MIRDocumentPrinter.cpp b/backend/lib/MIR/MIRDocumentPrinter.cpp deleted file mode 100644 index 06998bb..0000000 --- a/backend/lib/MIR/MIRDocumentPrinter.cpp +++ /dev/null @@ -1,1499 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "MIRDocumentReferenceValidation.h" -#include "rcc/CodeGen/MachineBasicBlock.h" -#include "rcc/CodeGen/MachineCompilationStatus.h" -#include "rcc/CodeGen/MachineConstantPool.h" -#include "rcc/CodeGen/MachineFrameInfo.h" -#include "rcc/CodeGen/MachineFunction.h" -#include "rcc/CodeGen/MachineFunctionAttributes.h" -#include "rcc/CodeGen/MachineFunctionProperties.h" -#include "rcc/CodeGen/MachineFunctionRecords.h" -#include "rcc/CodeGen/MachineInstr.h" -#include "rcc/CodeGen/MachineJumpTableInfo.h" -#include "rcc/CodeGen/MachineMetadata.h" -#include "rcc/CodeGen/MachineRegisterInfo.h" -#include "rcc/CodeGen/TargetDescription.h" -#include "rcc/CodeGen/TargetMIRTextInfo.h" -#include "rcc/CodeGen/TargetRegisterInfo.h" -#include "rcc/MIR/LLVMConstantSyntax.h" -#include "rcc/MIR/MIDebugSyntax.h" -#include "rcc/MIR/MIRDocument.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace rcc::mir { -namespace { - -enum class YAMLQuoting : std::uint8_t { - None, - Single, - Double, -}; - -[[nodiscard]] bool isASCIIAlphanumeric(unsigned char Character) noexcept { - return (Character >= '0' && Character <= '9') || (Character >= 'A' && Character <= 'Z') || - (Character >= 'a' && Character <= 'z'); -} - -[[nodiscard]] bool isYAMLNumeric(std::string_view Value) noexcept { - if (Value.empty() || Value == "+" || Value == "-") - return false; - if (Value == ".nan" || Value == ".NaN" || Value == ".NAN") - return true; - - std::string_view Tail = Value; - if (Tail.front() == '+' || Tail.front() == '-') - Tail.remove_prefix(1); - if (Tail == ".inf" || Tail == ".Inf" || Tail == ".INF") - return true; - if (Value.starts_with("0o")) { - return Value.size() > 2U && - Value.substr(2).find_first_not_of("01234567") == std::string_view::npos; - } - if (Value.starts_with("0x")) { - return Value.size() > 2U && - Value.substr(2).find_first_not_of("0123456789abcdefABCDEF") == std::string_view::npos; - } - - if (Tail.empty() || Tail.front() == 'e' || Tail.front() == 'E') - return false; - std::size_t Position = 0; - if (Tail.front() == '.') { - ++Position; - if (Position == Tail.size() || Tail[Position] < '0' || Tail[Position] > '9') - return false; - while (Position < Tail.size() && Tail[Position] >= '0' && Tail[Position] <= '9') - ++Position; - } else { - while (Position < Tail.size() && Tail[Position] >= '0' && Tail[Position] <= '9') - ++Position; - if (Position == 0) - return false; - } - - if (Position < Tail.size() && Tail[Position] == '.') { - ++Position; - while (Position < Tail.size() && Tail[Position] >= '0' && Tail[Position] <= '9') - ++Position; - } - if (Position == Tail.size()) - return true; - if (Tail[Position] != 'e' && Tail[Position] != 'E') - return false; - ++Position; - if (Position < Tail.size() && (Tail[Position] == '+' || Tail[Position] == '-')) - ++Position; - const std::size_t ExponentBegin = Position; - while (Position < Tail.size() && Tail[Position] >= '0' && Tail[Position] <= '9') - ++Position; - return Position == Tail.size() && Position != ExponentBegin; -} - -[[nodiscard]] YAMLQuoting yamlQuoting(std::string_view Value) noexcept { - if (Value.empty()) - return YAMLQuoting::Single; - - YAMLQuoting Result = YAMLQuoting::None; - const auto IsSpace = [](unsigned char Character) { - return Character == ' ' || Character == '\t' || Character == '\r' || Character == '\n' || - Character == '\f' || Character == '\v'; - }; - if (IsSpace(static_cast(Value.front())) || - IsSpace(static_cast(Value.back())) || Value == "null" || Value == "Null" || - Value == "NULL" || Value == "~" || Value == "true" || Value == "True" || Value == "TRUE" || - Value == "false" || Value == "False" || Value == "FALSE" || isYAMLNumeric(Value)) { - Result = YAMLQuoting::Single; - } - - switch (Value.front()) { - case '-': - case '?': - case ':': - case '\\': - case ',': - case '[': - case ']': - case '{': - case '}': - case '#': - case '&': - case '*': - case '!': - case '|': - case '>': - case '\'': - case '"': - case '%': - case '@': - case '`': - Result = YAMLQuoting::Single; - break; - default: - break; - } - - for (const char RawCharacter : Value) { - const auto Character = static_cast(RawCharacter); - if (isASCIIAlphanumeric(Character)) - continue; - switch (Character) { - case '_': - case '-': - case '^': - case '.': - case ',': - case ' ': - case '\t': - continue; - case '\n': - case '\r': - case 0x7f: - return YAMLQuoting::Double; - default: - if (Character <= 0x1fU || (Character & 0x80U) != 0) - return YAMLQuoting::Double; - Result = YAMLQuoting::Single; - break; - } - } - return Result; -} - -[[nodiscard]] std::string yamlScalar(std::string_view Value) { - const YAMLQuoting Quoting = yamlQuoting(Value); - if (Quoting == YAMLQuoting::None) - return std::string(Value); - - std::string Result; - Result.reserve(Value.size() + 2U); - const char Quote = Quoting == YAMLQuoting::Single ? '\'' : '"'; - Result.push_back(Quote); - for (const char Character : Value) { - if (Quoting == YAMLQuoting::Single) { - Result.push_back(Character); - if (Character == '\'') - Result.push_back('\''); - continue; - } - switch (Character) { - case '\\': - Result.append("\\\\"); - break; - case '"': - Result.append("\\\""); - break; - case '\0': - Result.append("\\0"); - break; - case '\a': - Result.append("\\a"); - break; - case '\b': - Result.append("\\b"); - break; - case '\t': - Result.append("\\t"); - break; - case '\n': - Result.append("\\n"); - break; - case '\v': - Result.append("\\v"); - break; - case '\f': - Result.append("\\f"); - break; - case '\r': - Result.append("\\r"); - break; - case '\x1b': - Result.append("\\e"); - break; - default: { - const auto Byte = static_cast(Character); - if (Byte < 0x20U || Byte == 0x7fU) { - static constexpr std::string_view Hex = "0123456789ABCDEF"; - Result.append("\\x"); - Result.push_back(Hex[Byte >> 4U]); - Result.push_back(Hex[Byte & 0xfU]); - } else { - Result.push_back(Character); - } - break; - } - } - } - Result.push_back(Quote); - return Result; -} - -void appendBlockScalar(std::string &Output, std::string_view Text, std::size_t Indent) { - std::size_t Position = 0; - do { - Output.append(Indent, ' '); - const std::size_t End = Text.find('\n', Position); - if (End == std::string_view::npos) { - Output.append(Text.substr(Position)); - Output.push_back('\n'); - return; - } - Output.append(Text.substr(Position, End - Position)); - Output.push_back('\n'); - Position = End + 1U; - } while (Position < Text.size()); -} - -[[nodiscard]] std::optional parseDecimal32(std::string_view Text) noexcept { - std::uint32_t Value = 0; - if (Text.empty()) - return std::nullopt; - const auto [End, Error] = std::from_chars(Text.data(), Text.data() + Text.size(), Value, 10); - if (Error != std::errc{} || End != Text.data() + Text.size()) - return std::nullopt; - return Value; -} - -[[nodiscard]] bool isDefaultFrameState(const MachineFrameState &State) { - return State == MachineFrameState{}; -} - -class MIRDocumentPrinter final { -public: - MIRDocumentPrinter(const MIRDocument &Document, const TargetDescription &Target, - MIRDocumentPrinterOptions Options) - : Document(Document), Target(Target), Options(std::move(Options)) {} - - [[nodiscard]] Expected run(); - -private: - struct InstructionLocation final { - std::uint32_t Block = 0; - std::uint32_t Offset = 0; - }; - - [[nodiscard]] Expected printFunction(const MachineFunction &Function, - const MIRFunctionDocumentInfo *DocumentInfo); - [[nodiscard]] Expected createBodyContext(const MachineFunction &Function) const; - [[nodiscard]] Expected printRegisters(const MachineFunction &Function, - const MIParserContext &Context); - [[nodiscard]] Expected printFrameInfo(const MachineFunction &Function, - const MIParserContext &Context); - [[nodiscard]] Expected printStackObjects(const MachineFunction &Function, - const MIParserContext &Context, bool Fixed); - [[nodiscard]] Expected printConstants(const MachineFunction &Function, - const MIParserContext &Context); - [[nodiscard]] Expected printJumpTable(const MachineFunction &Function, - const MIParserContext &Context); - [[nodiscard]] Expected printMetadata(const MachineFunction &Function, - const MIParserContext &Context); - [[nodiscard]] Expected printTargetState(const MachineFunction &Function); - [[nodiscard]] Expected printFunctionRecords(const MachineFunction &Function, - const MIParserContext &Context); - [[nodiscard]] Expected verifyOmittedEmbeddedIRLayout(const MachineFunction &Function) const; - - [[nodiscard]] Expected physicalRegister(PhysicalRegister Register) const; - [[nodiscard]] Expected frameReference(FrameIndex Index, - const MIParserContext &Context) const; - [[nodiscard]] Expected metadataReference(MachineMetadataReference Reference, - const MIParserContext &Context) const; - [[nodiscard]] Expected metadataValue(const MachineMetadataValue &Value, - const MIParserContext &Context) const; - [[nodiscard]] Expected debugLocation(const MachineDebugLocation &Location, - const MIParserContext &Context) const; - [[nodiscard]] Expected diLocation(const MachineDILocation &Location, - std::size_t FrameIndex, - const MIParserContext &Context) const; - [[nodiscard]] Expected instructionLocation(const MachineFunction &Function, - MachineInstrStableID ID) const; - [[nodiscard]] Expected blockReference(const MachineFunction &Function, - MachineBlockStableID ID) const; - [[nodiscard]] Expected targetNode(const MIRTargetNode &Node) const; - [[nodiscard]] const MIRFunctionDocumentInfo * - documentInfo(const MachineFunction &Function) const noexcept; - - void printBoolean(std::string_view Key, bool Value, bool Always = false); - void printUnsigned(std::string_view Key, std::uint64_t Value, bool Always = false); - void printSigned(std::string_view Key, std::int64_t Value, bool Always = false); - - const MIRDocument &Document; - const TargetDescription &Target; - MIRDocumentPrinterOptions Options; - std::string Output; -}; - -void MIRDocumentPrinter::printBoolean(std::string_view Key, bool Value, bool Always) { - if (!Always && Options.Mode == MIPrintMode::Readable && !Value) - return; - Output.append(Key); - Output.append(Value ? ": true\n" : ": false\n"); -} - -void MIRDocumentPrinter::printUnsigned(std::string_view Key, std::uint64_t Value, bool Always) { - if (!Always && Options.Mode == MIPrintMode::Readable && Value == 0) - return; - Output.append(Key); - Output.append(": "); - Output.append(std::to_string(Value)); - Output.push_back('\n'); -} - -void MIRDocumentPrinter::printSigned(std::string_view Key, std::int64_t Value, bool Always) { - if (!Always && Options.Mode == MIPrintMode::Readable && Value == 0) - return; - Output.append(Key); - Output.append(": "); - Output.append(std::to_string(Value)); - Output.push_back('\n'); -} - -Expected MIRDocumentPrinter::physicalRegister(PhysicalRegister Register) const { - const auto Name = Target.registers().physicalRegisterMIRName(Register); - if (!Name) { - return makeUnexpected(ErrorCode::VerificationError, - "physical register has no canonical MIR name"); - } - return "$" + std::string(*Name); -} - -const MIRFunctionDocumentInfo * -MIRDocumentPrinter::documentInfo(const MachineFunction &Function) const noexcept { - const auto Infos = Document.functionDocumentInfo(); - const auto Found = std::ranges::find_if(Infos, [&Function](const MIRFunctionDocumentInfo &Info) { - return Info.Function == Function.stableID(); - }); - return Found == Infos.end() ? nullptr : &*Found; -} - -Expected -MIRDocumentPrinter::verifyOmittedEmbeddedIRLayout(const MachineFunction &Function) const { - if (Options.EmitEmbeddedIR) - return {}; - - const EmbeddedIRReferenceIndex *Embedded = Document.embeddedIR(); - if (Embedded == nullptr) - return {}; - - bool HasLayoutDependentContent = false; - for (const VirtualRegisterInfo &RegisterInfo : Function.registerInfo().virtualRegisters()) { - if (!RegisterInfo.IsTombstone && RegisterInfo.Type && - RegisterInfo.Type->isPointerOrPointerVector()) { - HasLayoutDependentContent = true; - break; - } - } - if (!HasLayoutDependentContent) { - for (const MachineConstantPoolEntry &Entry : Function.constantPool().entries()) { - const MachineConstantPoolEntryDesc *Description = Entry.description(); - if (Description != nullptr && - std::holds_alternative(Description->Value)) { - HasLayoutDependentContent = true; - break; - } - } - } - if (!HasLayoutDependentContent) - return {}; - - if (Options.DataLayout.empty()) { - return makeUnexpected( - ErrorCode::InvalidArgument, - "omitting embedded LLVM IR with layout-dependent MIR requires an explicit printer " - "DataLayout"); - } - - const LLVMConstantSyntaxOptions LayoutOptions{ - .DataLayout = Options.DataLayout, - .NamedTypes = {}, - }; - for (const VirtualRegisterInfo &RegisterInfo : Function.registerInfo().virtualRegisters()) { - if (RegisterInfo.IsTombstone || !RegisterInfo.Type || - !RegisterInfo.Type->isPointerOrPointerVector()) { - continue; - } - const auto AddressSpace = RegisterInfo.Type->addressSpace(); - if (!AddressSpace) { - return makeUnexpected(ErrorCode::VerificationError, - "pointer virtual register has no address space"); - } - auto PointerSize = llvmPointerSizeInBits(*AddressSpace, LayoutOptions); - if (!PointerSize) { - return makeUnexpected(ErrorCode::InvalidArgument, - "printer DataLayout cannot determine pointer width: " + - std::string(PointerSize.error().message())); - } - if (*PointerSize != RegisterInfo.Type->scalarBitWidth()) { - return makeUnexpected(ErrorCode::VerificationError, - "printer DataLayout does not match pointer virtual-register width"); - } - } - - for (const MachineConstantPoolEntry &Entry : Function.constantPool().entries()) { - const MachineConstantPoolEntryDesc *Description = Entry.description(); - if (Description == nullptr) - continue; - const auto *Generic = std::get_if(&Description->Value); - if (Generic == nullptr) - continue; - auto StorageSize = llvmConstantStorageSize(Generic->Type, LayoutOptions); - if (!StorageSize) { - return makeUnexpected(ErrorCode::InvalidArgument, - "printer DataLayout cannot lay out generic constant: " + - std::string(StorageSize.error().message())); - } - if (*StorageSize != Description->Size) { - return makeUnexpected(ErrorCode::VerificationError, - "printer DataLayout does not match generic constant storage size"); - } - } - return {}; -} - -Expected -MIRDocumentPrinter::createBodyContext(const MachineFunction &Function) const { - MIParserContext Context; - Context.SyncScopes.assign(Document.syncScopes().begin(), Document.syncScopes().end()); - const auto VirtualRegisters = Function.registerInfo().virtualRegisters(); - for (std::size_t Index = 0; Index < VirtualRegisters.size(); ++Index) { - if (VirtualRegisters[Index].IsTombstone) - continue; - auto Reg = Register::makeVirtual(Index); - if (!Reg) - return std::unexpected(Reg.error()); - if (Index > std::numeric_limits::max()) { - return makeUnexpected(ErrorCode::Unsupported, - "MIR cannot represent more than 2^32 virtual registers"); - } - Context.VirtualRegisters.push_back({.TextID = static_cast(Index), .Reg = *Reg}); - } - - std::uint32_t StackID = 0; - std::uint32_t FixedID = 0; - for (const StackObject &Object : Function.frameInfo().objects()) { - const StackObjectDesc *Description = Object.description(); - if (Description == nullptr) - continue; - MIFrameObjectSlot Slot{ - .TextID = Object.isFixed() ? FixedID++ : StackID++, - .Index = Object.index(), - .Name = Description->AllocaName, - }; - (Object.isFixed() ? Context.FixedStackObjects : Context.StackObjects) - .push_back(std::move(Slot)); - } - - std::uint32_t ConstantID = 0; - for (const MachineConstantPoolEntry &Entry : Function.constantPool().entries()) { - if (Entry.description() != nullptr) - Context.ConstantPoolItems.push_back({.TextID = ConstantID++, .Index = Entry.index()}); - } - std::uint32_t JumpTableID = 0; - for (const MachineJumpTableEntry &Entry : Function.jumpTableInfo().tables()) { - if (Entry.description() != nullptr) - Context.JumpTables.push_back({.TextID = JumpTableID++, .Index = Entry.index()}); - } - - std::unordered_set EmbeddedMetadataSlots; - if (const EmbeddedIRReferenceIndex *Embedded = Document.embeddedIR()) { - for (const EmbeddedIRMetadataDefinition &Definition : Embedded->metadataDefinitions()) { - const auto Slot = parseDecimal32(Definition.Name); - if (Slot) { - if (!EmbeddedMetadataSlots.insert(*Slot).second) { - return makeUnexpected(ErrorCode::VerificationError, - "embedded LLVM IR metadata slots are not unique"); - } - Context.Metadata.push_back( - {.TextID = *Slot, .Reference = MachineMetadataReference::embeddedIR(*Slot)}); - } - } - } - - std::unordered_set UsedMetadataSlots = EmbeddedMetadataSlots; - for (const MachineMetadataNode &Node : Function.metadata().nodes()) { - if (!EmbeddedMetadataSlots.contains(Node.Slot)) - UsedMetadataSlots.insert(Node.Slot); - } - std::uint64_t NextMetadataSlot = 0; - for (const MachineMetadataNode &Node : Function.metadata().nodes()) { - std::uint32_t TextID = Node.Slot; - if (EmbeddedMetadataSlots.contains(TextID)) { - while (NextMetadataSlot <= std::numeric_limits::max() && - UsedMetadataSlots.contains(static_cast(NextMetadataSlot))) { - ++NextMetadataSlot; - } - if (NextMetadataSlot > std::numeric_limits::max()) { - return makeUnexpected(ErrorCode::Unsupported, "MIR metadata text slot space is exhausted"); - } - TextID = static_cast(NextMetadataSlot); - UsedMetadataSlots.insert(TextID); - ++NextMetadataSlot; - } - Context.Metadata.push_back( - {.TextID = TextID, .Reference = MachineMetadataReference::machineFunction(Node.Slot)}); - } - return Context; -} - -Expected MIRDocumentPrinter::frameReference(FrameIndex Index, - const MIParserContext &Context) const { - const auto Stack = std::ranges::find_if( - Context.StackObjects, [Index](const MIFrameObjectSlot &Slot) { return Slot.Index == Index; }); - if (Stack != Context.StackObjects.end()) - return "%stack." + std::to_string(Stack->TextID); - const auto Fixed = - std::ranges::find_if(Context.FixedStackObjects, - [Index](const MIFrameObjectSlot &Slot) { return Slot.Index == Index; }); - if (Fixed != Context.FixedStackObjects.end()) - return "%fixed-stack." + std::to_string(Fixed->TextID); - return makeUnexpected(ErrorCode::VerificationError, - "frame state references an unknown stack object"); -} - -Expected MIRDocumentPrinter::metadataReference(MachineMetadataReference Reference, - const MIParserContext &Context) const { - if (!Reference.isValid()) - return makeUnexpected(ErrorCode::VerificationError, "invalid metadata reference"); - const auto Slot = - std::ranges::find_if(Context.Metadata, [Reference](const MIMetadataSlot &Candidate) { - return Candidate.Reference == Reference; - }); - if (Slot == Context.Metadata.end()) { - return makeUnexpected(ErrorCode::VerificationError, "metadata reference has no MIR text slot"); - } - return "!" + std::to_string(Slot->TextID); -} - -Expected MIRDocumentPrinter::metadataValue(const MachineMetadataValue &Value, - const MIParserContext &Context) const { - if (const MachineMetadataReference *Reference = Value.reference()) - return metadataReference(*Reference, Context); - const MachineDIExpression *Expression = Value.expression(); - if (Expression == nullptr) - return makeUnexpected(ErrorCode::VerificationError, "metadata value is not printable"); - return formatDIExpression(Expression->elements()); -} - -Expected MIRDocumentPrinter::diLocation(const MachineDILocation &Location, - std::size_t FrameIndex, - const MIParserContext &Context) const { - if (FrameIndex >= Location.inlineChain().size()) { - return makeUnexpected(ErrorCode::VerificationError, - "inline DILocation has an invalid frame chain"); - } - const MachineDILocationFrame &Frame = Location.inlineChain()[FrameIndex]; - auto Scope = metadataReference(Frame.Scope, Context); - if (!Scope) - return std::unexpected(Scope.error()); - std::string Text = "!DILocation(line: " + std::to_string(Frame.Line); - if (Options.Mode == MIPrintMode::Complete || Frame.Column != 0) - Text.append(", column: " + std::to_string(Frame.Column)); - Text.append(", scope: " + *Scope); - if (FrameIndex + 1U < Location.inlineChain().size()) { - auto Nested = diLocation(Location, FrameIndex + 1U, Context); - if (!Nested) - return std::unexpected(Nested.error()); - Text.append(", inlinedAt: " + *Nested); - } else if (Location.terminalInlinedAt()) { - auto Terminal = metadataReference(*Location.terminalInlinedAt(), Context); - if (!Terminal) - return std::unexpected(Terminal.error()); - Text.append(", inlinedAt: " + *Terminal); - } - if (Options.Mode == MIPrintMode::Complete || Frame.IsImplicitCode) - Text.append(Frame.IsImplicitCode ? ", isImplicitCode: true" : ", isImplicitCode: false"); - if (Options.Mode == MIPrintMode::Complete || Frame.AtomGroup != 0) - Text.append(", atomGroup: " + std::to_string(Frame.AtomGroup)); - if (Options.Mode == MIPrintMode::Complete || Frame.AtomRank != 0) - Text.append(", atomRank: " + std::to_string(Frame.AtomRank)); - Text.push_back(')'); - return Text; -} - -Expected MIRDocumentPrinter::debugLocation(const MachineDebugLocation &Location, - const MIParserContext &Context) const { - if (const MachineMetadataReference *Reference = Location.reference()) - return metadataReference(*Reference, Context); - if (const MachineDILocation *Inline = Location.inlineLocation()) - return diLocation(*Inline, 0, Context); - return makeUnexpected(ErrorCode::VerificationError, "debug location is not printable"); -} - -Expected -MIRDocumentPrinter::instructionLocation(const MachineFunction &Function, - MachineInstrStableID ID) const { - std::uint64_t BlockNumber = 0; - for (const MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; - Block = Block->next(), ++BlockNumber) { - if (BlockNumber > std::numeric_limits::max()) - break; - std::uint64_t Offset = 0; - for (const MachineInstr *Instruction = Block->firstInstruction(); Instruction != nullptr; - Instruction = Instruction->next(), ++Offset) { - if (Instruction->stableID() != ID) - continue; - if (Offset > std::numeric_limits::max()) { - return makeUnexpected(ErrorCode::Unsupported, "MIR instruction offset exceeds 32 bits"); - } - return InstructionLocation{static_cast(BlockNumber), - static_cast(Offset)}; - } - } - return makeUnexpected(ErrorCode::VerificationError, - "function record references an unlinked instruction"); -} - -Expected MIRDocumentPrinter::blockReference(const MachineFunction &Function, - MachineBlockStableID ID) const { - std::uint64_t Number = 0; - for (const MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; - Block = Block->next(), ++Number) { - if (Block->stableID() == ID) { - if (Number > std::numeric_limits::max()) - break; - return "%bb." + std::to_string(Number); - } - } - return makeUnexpected(ErrorCode::VerificationError, - "frame record references an unlinked basic block"); -} - -Expected MIRDocumentPrinter::targetNode(const MIRTargetNode &Node) const { - switch (Node.Kind) { - case MIRTargetNodeKind::Null: - return std::string("null"); - case MIRTargetNodeKind::Scalar: - return yamlScalar(Node.Scalar); - case MIRTargetNodeKind::Sequence: { - std::string Text = "[ "; - for (std::size_t Index = 0; Index < Node.Sequence.size(); ++Index) { - if (Index != 0) - Text.append(", "); - auto Element = targetNode(Node.Sequence[Index]); - if (!Element) - return std::unexpected(Element.error()); - Text.append(*Element); - } - Text.append(" ]"); - return Text; - } - case MIRTargetNodeKind::Mapping: { - std::string Text = "{ "; - for (std::size_t Index = 0; Index < Node.Mapping.size(); ++Index) { - if (Index != 0) - Text.append(", "); - Text.append(yamlScalar(Node.Mapping[Index].Key)); - Text.append(": "); - auto Value = targetNode(Node.Mapping[Index].Value); - if (!Value) - return std::unexpected(Value.error()); - Text.append(*Value); - } - Text.append(" }"); - return Text; - } - case MIRTargetNodeKind::Count: - break; - } - return makeUnexpected(ErrorCode::VerificationError, "target MIR node has an invalid kind"); -} - -Expected MIRDocumentPrinter::printRegisters(const MachineFunction &Function, - const MIParserContext &Context) { - if (Context.VirtualRegisters.empty()) { - if (Options.Mode == MIPrintMode::Complete) - Output.append("registers: []\n"); - } else { - Output.append("registers:\n"); - for (const MIVirtualRegisterSlot &Slot : Context.VirtualRegisters) { - auto InfoResult = Function.registerInfo().virtualRegisterInfo(Slot.Reg); - if (!InfoResult) - return std::unexpected(InfoResult.error()); - const VirtualRegisterInfo &Info = InfoResult->get(); - std::string Class = "_"; - if (Info.RegClass) { - const auto Name = Target.registers().registerClassMIRName(*Info.RegClass); - if (!Name) - return makeUnexpected(ErrorCode::VerificationError, - "virtual register class has no canonical MIR name"); - Class = *Name; - } else if (Info.Bank) { - const auto Name = Target.registers().registerBankMIRName(*Info.Bank); - if (!Name) - return makeUnexpected(ErrorCode::VerificationError, - "virtual register bank has no canonical MIR name"); - Class = *Name; - } - if (Info.AllocationHints.size() > 1) { - return makeUnexpected( - ErrorCode::Unsupported, - "fixed LLVM MIR can serialize only one simple preferred-register hint"); - } - - Output.append(" - { id: "); - Output.append(std::to_string(Slot.TextID)); - Output.append(", class: "); - Output.append(yamlScalar(Class)); - if (!Info.AllocationHints.empty()) { - auto Preferred = physicalRegister(Info.AllocationHints.front()); - if (!Preferred) - return std::unexpected(Preferred.error()); - Output.append(", preferred-register: "); - Output.append(yamlScalar(*Preferred)); - } - if (Info.TargetFlags != 0) { - auto Names = Target.mirText().virtualRegisterFlagNames(Info.TargetFlags); - if (!Names) - return std::unexpected(Names.error()); - Output.append(", flags: [ "); - for (std::size_t Index = 0; Index < Names->size(); ++Index) { - if (Index != 0) - Output.append(", "); - Output.append(yamlScalar((*Names)[Index])); - } - Output.append(" ]"); - } - Output.append(" }\n"); - } - } - - if (Function.registerInfo().liveIns().empty()) { - if (Options.Mode == MIPrintMode::Complete) - Output.append("liveins: []\n"); - } else { - Output.append("liveins:\n"); - for (const PhysicalRegisterLiveIn &LiveIn : Function.registerInfo().liveIns()) { - auto Name = physicalRegister(LiveIn.PhysReg); - if (!Name) - return std::unexpected(Name.error()); - Output.append(" - { reg: "); - Output.append(yamlScalar(*Name)); - if (LiveIn.InitialVirtualRegister) { - const auto Slot = std::ranges::find_if( - Context.VirtualRegisters, [&LiveIn](const MIVirtualRegisterSlot &Candidate) { - return Candidate.Reg == *LiveIn.InitialVirtualRegister; - }); - if (Slot == Context.VirtualRegisters.end()) { - return makeUnexpected(ErrorCode::VerificationError, - "live-in references an unknown virtual register"); - } - Output.append(", virtual-reg: "); - Output.append(yamlScalar("%" + std::to_string(Slot->TextID))); - } - Output.append(" }\n"); - } - } - - if (Function.records().hasCalleeSavedRegisters()) { - Output.append("calleeSavedRegisters: [ "); - const auto Registers = Function.records().calleeSavedRegisters(); - for (std::size_t Index = 0; Index < Registers.size(); ++Index) { - if (Index != 0) - Output.append(", "); - auto Name = physicalRegister(Registers[Index]); - if (!Name) - return std::unexpected(Name.error()); - Output.append(yamlScalar(*Name)); - } - Output.append(" ]\n"); - } - return {}; -} - -Expected MIRDocumentPrinter::printFrameInfo(const MachineFunction &Function, - const MIParserContext &Context) { - const MachineFrameState &State = Function.frameInfo().state(); - if (Options.Mode == MIPrintMode::Readable && isDefaultFrameState(State)) - return {}; - if (State.MaxCallFrameSize && - *State.MaxCallFrameSize > std::numeric_limits::max()) { - return makeUnexpected(ErrorCode::Unsupported, - "fixed LLVM MIR maxCallFrameSize is limited to 32 bits"); - } - Output.append("frameInfo:\n"); - const auto Bool = [this](std::string_view Key, bool Value) { - if (Options.Mode == MIPrintMode::Readable && !Value) - return; - Output.append(" "); - Output.append(Key); - Output.append(Value ? ": true\n" : ": false\n"); - }; - const auto Unsigned = [this](std::string_view Key, std::uint64_t Value) { - if (Options.Mode == MIPrintMode::Readable && Value == 0) - return; - Output.append(" "); - Output.append(Key); - Output.append(": "); - Output.append(std::to_string(Value)); - Output.push_back('\n'); - }; - - Bool("isFrameAddressTaken", State.IsFrameAddressTaken); - Bool("isReturnAddressTaken", State.IsReturnAddressTaken); - Bool("hasStackMap", State.HasStackMap); - Bool("hasPatchPoint", State.HasPatchPoint); - Unsigned("stackSize", State.StackSize); - if (Options.Mode == MIPrintMode::Complete || State.OffsetAdjustment != 0) { - Output.append(" offsetAdjustment: "); - Output.append(std::to_string(State.OffsetAdjustment)); - Output.push_back('\n'); - } - Unsigned("maxAlignment", State.MaxAlignment ? State.MaxAlignment->bytes() : 0); - Bool("adjustsStack", State.AdjustsStack); - Bool("hasCalls", State.HasCalls); - if (Options.Mode == MIPrintMode::Complete || - State.FramePointerPolicy != MachineFramePointerPolicy::None) { - Output.append(" framePointerPolicy: "); - Output.append(getMachineFramePointerPolicyName(State.FramePointerPolicy)); - Output.push_back('\n'); - } - if (Options.Mode == MIPrintMode::Complete || State.StackProtector) { - std::string Reference; - if (State.StackProtector) { - auto PrintedReference = frameReference(*State.StackProtector, Context); - if (!PrintedReference) - return std::unexpected(PrintedReference.error()); - Reference = std::move(*PrintedReference); - } - Output.append(" stackProtector: "); - Output.append(yamlScalar(Reference)); - Output.push_back('\n'); - } - if (Options.Mode == MIPrintMode::Complete || State.FunctionContext) { - std::string Reference; - if (State.FunctionContext) { - auto PrintedReference = frameReference(*State.FunctionContext, Context); - if (!PrintedReference) - return std::unexpected(PrintedReference.error()); - Reference = std::move(*PrintedReference); - } - Output.append(" functionContext: "); - Output.append(yamlScalar(Reference)); - Output.push_back('\n'); - } - if (Options.Mode == MIPrintMode::Complete || State.MaxCallFrameSize) { - Unsigned("maxCallFrameSize", - State.MaxCallFrameSize.value_or(std::numeric_limits::max())); - } - Unsigned("cvBytesOfCalleeSavedRegisters", State.CVBytesOfCalleeSavedRegisters); - Bool("hasOpaqueSPAdjustment", State.HasOpaqueSPAdjustment); - Bool("hasVAStart", State.HasVAStart); - Bool("hasMustTailInVarArgFunc", State.HasMustTailInVarArgFunc); - Bool("hasTailCall", State.HasTailCall); - Bool("isCalleeSavedInfoValid", State.IsCalleeSavedInfoValid); - Unsigned("localFrameSize", State.LocalFrameSize); - - const auto PrintPoints = - [this, &Function](std::string_view Key, - std::span Points) -> Expected { - if (Points.empty()) - return {}; - Output.append(" "); - Output.append(Key); - Output.append(":\n"); - for (const MachineFrameSaveRestorePoint &Point : Points) { - auto Block = blockReference(Function, Point.Block); - if (!Block) - return std::unexpected(Block.error()); - Output.append(" - { point: "); - Output.append(yamlScalar(*Block)); - if (!Point.Registers.empty()) { - Output.append(", registers: [ "); - for (std::size_t Index = 0; Index < Point.Registers.size(); ++Index) { - if (Index != 0) - Output.append(", "); - auto Name = physicalRegister(Point.Registers[Index]); - if (!Name) - return std::unexpected(Name.error()); - Output.append(yamlScalar(*Name)); - } - Output.append(" ]"); - } - Output.append(" }\n"); - } - return {}; - }; - if (auto Printed = PrintPoints("savePoint", State.SavePoints); !Printed) - return Printed; - return PrintPoints("restorePoint", State.RestorePoints); -} - -Expected MIRDocumentPrinter::printStackObjects(const MachineFunction &Function, - const MIParserContext &Context, bool Fixed) { - const auto &Slots = Fixed ? Context.FixedStackObjects : Context.StackObjects; - if (Slots.empty()) { - if (Options.Mode == MIPrintMode::Complete) - Output.append(Fixed ? "fixedStack: []\n" : "stack: []\n"); - return {}; - } - Output.append(Fixed ? "fixedStack:\n" : "stack:\n"); - for (const MIFrameObjectSlot &Slot : Slots) { - const StackObject *Object = Function.frameInfo().object(Slot.Index); - const StackObjectDesc *Description = Object == nullptr ? nullptr : Object->description(); - if (Description == nullptr) - return makeUnexpected(ErrorCode::VerificationError, "MIR stack slot is a tombstone"); - if (Description->IsDead || Description->AddressTaken || !Description->Lifetime.empty() || - Description->TargetFlags != 0) { - return makeUnexpected(ErrorCode::Unsupported, - "stack object contains state not represented by fixed LLVM MIR"); - } - - std::string_view Type; - switch (Description->Kind) { - case StackObjectKind::Default: - case StackObjectKind::FixedABI: - Type = "default"; - break; - case StackObjectKind::FixedSpillSlot: - case StackObjectKind::SpillSlot: - Type = "spill-slot"; - break; - case StackObjectKind::VariableSized: - Type = "variable-sized"; - break; - case StackObjectKind::DynamicAlloca: - case StackObjectKind::CalleeSaved: - case StackObjectKind::EmergencySpill: - case StackObjectKind::Target: - case StackObjectKind::Count: - return makeUnexpected(ErrorCode::Unsupported, - "stack object kind has no fixed LLVM MIR representation"); - } - - Output.append(" - { id: "); - Output.append(std::to_string(Slot.TextID)); - if (!Fixed && Description->AllocaName) { - Output.append(", name: "); - Output.append(yamlScalar(*Description->AllocaName)); - } - if (Options.Mode == MIPrintMode::Complete || Type != "default") { - Output.append(", type: "); - Output.append(Type); - } - if (Options.Mode == MIPrintMode::Complete || Description->Offset.value_or(0) != 0) { - Output.append(", offset: "); - Output.append(std::to_string(Description->Offset.value_or(0))); - } - if (Description->Kind != StackObjectKind::VariableSized) { - Output.append(", size: "); - Output.append(std::to_string(Description->Size.value_or(0))); - } - if (Options.Mode == MIPrintMode::Complete || Description->Align.bytes() != 1) { - Output.append(", alignment: "); - Output.append(std::to_string(Description->Align.bytes())); - } - if (Options.Mode == MIPrintMode::Complete || Description->Stack != StackID::defaultStack()) { - Output.append(", stack-id: "); - Output.append(getStackIDName(Description->Stack)); - } - if (Fixed && Description->Kind != StackObjectKind::FixedSpillSlot) { - if (Options.Mode == MIPrintMode::Complete || Description->IsImmutable) - Output.append(Description->IsImmutable ? ", isImmutable: true" : ", isImmutable: false"); - if (Options.Mode == MIPrintMode::Complete || Description->IsAliased) - Output.append(Description->IsAliased ? ", isAliased: true" : ", isAliased: false"); - } else if (!Fixed && (Description->IsImmutable || Description->IsAliased)) { - return makeUnexpected(ErrorCode::Unsupported, - "ordinary stack object immutable/aliased state is not serialized"); - } - if (Description->CalleeSavedRegister) { - auto Name = physicalRegister(*Description->CalleeSavedRegister); - if (!Name) - return std::unexpected(Name.error()); - Output.append(", callee-saved-register: "); - Output.append(yamlScalar(*Name)); - } - if (Options.Mode == MIPrintMode::Complete || !Description->CalleeSavedRestored) { - Output.append(Description->CalleeSavedRestored ? ", callee-saved-restored: true" - : ", callee-saved-restored: false"); - } - if (!Fixed && Description->LocalOffset) { - Output.append(", local-offset: "); - Output.append(std::to_string(*Description->LocalOffset)); - } - if (Description->DebugInfo) { - const MachineVariableDebugInfo &Debug = *Description->DebugInfo; - if (Debug.Variable) { - auto Value = metadataReference(*Debug.Variable, Context); - if (!Value) - return std::unexpected(Value.error()); - Output.append(", debug-info-variable: "); - Output.append(yamlScalar(*Value)); - } - if (Debug.Expression) { - auto Value = metadataValue(*Debug.Expression, Context); - if (!Value) - return std::unexpected(Value.error()); - Output.append(", debug-info-expression: "); - Output.append(yamlScalar(*Value)); - } - if (Debug.Location) { - auto Value = debugLocation(*Debug.Location, Context); - if (!Value) - return std::unexpected(Value.error()); - Output.append(", debug-info-location: "); - Output.append(yamlScalar(*Value)); - } - } - Output.append(" }\n"); - } - return {}; -} - -Expected MIRDocumentPrinter::printConstants(const MachineFunction &Function, - const MIParserContext &Context) { - if (Context.ConstantPoolItems.empty()) { - if (Options.Mode == MIPrintMode::Complete) - Output.append("constants: []\n"); - return {}; - } - Output.append("constants:\n"); - for (const MIConstantPoolSlot &Slot : Context.ConstantPoolItems) { - const MachineConstantPoolEntry *Entry = Function.constantPool().entry(Slot.Index); - const MachineConstantPoolEntryDesc *Description = - Entry == nullptr ? nullptr : Entry->description(); - if (Description == nullptr) - return makeUnexpected(ErrorCode::VerificationError, "constant-pool slot is a tombstone"); - if (Description->Merge != ConstantPoolMergeKind::Never || - Description->Relocation != ConstantPoolRelocationMode::None || - Description->Placement != ConstantPoolPlacement{}) { - return makeUnexpected(ErrorCode::Unsupported, - "constant-pool placement state is not represented by fixed LLVM MIR"); - } - - bool IsTargetSpecific = false; - Expected Value = - makeUnexpected(ErrorCode::Unsupported, "constant-pool kind is not MIR serializable"); - if (const auto *Generic = std::get_if(&Description->Value)) { - Value = printLLVMConstant(*Generic); - } else if (const auto *TargetConstantValue = std::get_if(&Description->Value)) { - IsTargetSpecific = true; - Value = Target.mirText().printTargetConstant(*TargetConstantValue); - } - if (!Value) - return std::unexpected(Value.error()); - - Output.append(" - id: "); - Output.append(std::to_string(Slot.TextID)); - Output.append("\n value: "); - Output.append(yamlScalar(*Value)); - Output.append("\n alignment: "); - Output.append(std::to_string(Description->Align.bytes())); - Output.push_back('\n'); - if (IsTargetSpecific) - Output.append(" isTargetSpecific: true\n"); - } - return {}; -} - -Expected MIRDocumentPrinter::printJumpTable(const MachineFunction &Function, - const MIParserContext &Context) { - if (Context.JumpTables.empty()) - return {}; - const MachineJumpTableEntry *FirstEntry = - Function.jumpTableInfo().table(Context.JumpTables.front().Index); - const MachineJumpTableDesc *First = FirstEntry == nullptr ? nullptr : FirstEntry->description(); - if (First == nullptr) - return makeUnexpected(ErrorCode::VerificationError, "jump-table slot is not defined"); - - std::string_view Kind; - std::uint8_t ExpectedSize = 8; - switch (First->Encoding) { - case JumpTableEntryEncoding::BlockAddress: - Kind = "block-address"; - break; - case JumpTableEntryEncoding::GPRelative64BlockAddress: - Kind = "gp-rel64-block-address"; - break; - case JumpTableEntryEncoding::GPRelative32BlockAddress: - Kind = "gp-rel32-block-address"; - ExpectedSize = 4; - break; - case JumpTableEntryEncoding::LabelDifference32: - Kind = "label-difference32"; - ExpectedSize = 4; - break; - case JumpTableEntryEncoding::LabelDifference64: - Kind = "label-difference64"; - break; - case JumpTableEntryEncoding::Inline: - Kind = "inline"; - ExpectedSize = 4; - break; - case JumpTableEntryEncoding::Custom32: - Kind = "custom32"; - ExpectedSize = 4; - break; - case JumpTableEntryEncoding::Target: - case JumpTableEntryEncoding::Count: - return makeUnexpected(ErrorCode::Unsupported, - "target jump-table encoding has no fixed LLVM MIR spelling"); - } - - Output.append("jumpTable:\n kind: "); - Output.append(Kind); - Output.append("\n entries:\n"); - for (const MIJumpTableSlot &Slot : Context.JumpTables) { - const MachineJumpTableEntry *Entry = Function.jumpTableInfo().table(Slot.Index); - const MachineJumpTableDesc *Description = Entry == nullptr ? nullptr : Entry->description(); - if (Description == nullptr) - return makeUnexpected(ErrorCode::VerificationError, "jump-table slot is not defined"); - if (Description->Encoding != First->Encoding || Description->EntrySize != ExpectedSize || - Description->Align.bytes() != ExpectedSize || - Description->Placement != JumpTablePlacement{} || Description->TargetEncoding != 0) { - return makeUnexpected(ErrorCode::Unsupported, - "jump-table entries cannot share one fixed LLVM MIR kind"); - } - Output.append(" - { id: "); - Output.append(std::to_string(Slot.TextID)); - Output.append(", blocks: [ "); - for (std::size_t Index = 0; Index < Description->Targets.size(); ++Index) { - if (Index != 0) - Output.append(", "); - if (Description->Targets[Index] == nullptr) - return makeUnexpected(ErrorCode::VerificationError, - "jump-table entry contains a null block"); - auto Block = blockReference(Function, Description->Targets[Index]->stableID()); - if (!Block) - return std::unexpected(Block.error()); - Output.append(yamlScalar(*Block)); - } - Output.append(" ] }\n"); - } - return {}; -} - -Expected MIRDocumentPrinter::printMetadata(const MachineFunction &Function, - const MIParserContext &Context) { - if (Function.metadata().nodes().empty()) - return {}; - Output.append("machineMetadataNodes:\n"); - for (const MachineMetadataNode &Node : Function.metadata().nodes()) { - auto NodeReference = - metadataReference(MachineMetadataReference::machineFunction(Node.Slot), Context); - if (!NodeReference) - return std::unexpected(NodeReference.error()); - std::string Text = *NodeReference + " = "; - if (Node.IsDistinct) - Text.append("distinct "); - Text.append("!{"); - for (std::size_t Index = 0; Index < Node.Elements.size(); ++Index) { - if (Index != 0) - Text.append(", "); - const MachineMetadataElement &Element = Node.Elements[Index]; - if (Element.isNull()) { - Text.append("null"); - } else if (const MachineMetadataReference *Reference = Element.reference()) { - auto Printed = metadataReference(*Reference, Context); - if (!Printed) - return std::unexpected(Printed.error()); - Text.append(*Printed); - } else if (const std::string *String = Element.string()) { - Text.append("!\""); - for (const char Character : *String) { - if (Character == '\\' || Character == '"') - Text.push_back('\\'); - Text.push_back(Character); - } - Text.push_back('"'); - } else { - return makeUnexpected(ErrorCode::VerificationError, - "machine metadata tuple contains an invalid element"); - } - } - Text.push_back('}'); - Output.append(" - "); - Output.append(yamlScalar(Text)); - Output.push_back('\n'); - } - return {}; -} - -Expected MIRDocumentPrinter::printTargetState(const MachineFunction &Function) { - if (!Function.targetState().hasValue()) - return {}; - auto Node = Target.mirText().printFunctionState(Function.targetState()); - if (!Node) - return std::unexpected(Node.error()); - auto Text = targetNode(*Node); - if (!Text) - return std::unexpected(Text.error()); - Output.append("machineFunctionInfo: "); - Output.append(*Text); - Output.push_back('\n'); - return {}; -} - -Expected MIRDocumentPrinter::printFunctionRecords(const MachineFunction &Function, - const MIParserContext &Context) { - const MachineFunctionRecords &Records = Function.records(); - if (!Records.entryValues().empty()) { - Output.append("entry_values:\n"); - for (const MachineEntryValueInfo &Entry : Records.entryValues()) { - auto RegisterName = physicalRegister(Entry.Reg); - if (!RegisterName) - return std::unexpected(RegisterName.error()); - if (!Entry.DebugInfo.Variable || !Entry.DebugInfo.Expression || !Entry.DebugInfo.Location) { - return makeUnexpected(ErrorCode::Unsupported, - "MIR entry value requires complete debug metadata"); - } - auto Variable = metadataReference(*Entry.DebugInfo.Variable, Context); - auto Expression = metadataValue(*Entry.DebugInfo.Expression, Context); - auto Location = debugLocation(*Entry.DebugInfo.Location, Context); - if (!Variable) - return std::unexpected(Variable.error()); - if (!Expression) - return std::unexpected(Expression.error()); - if (!Location) - return std::unexpected(Location.error()); - Output.append(" - { entry-value-register: "); - Output.append(yamlScalar(*RegisterName)); - Output.append(", debug-info-variable: "); - Output.append(yamlScalar(*Variable)); - Output.append(", debug-info-expression: "); - Output.append(yamlScalar(*Expression)); - Output.append(", debug-info-location: "); - Output.append(yamlScalar(*Location)); - Output.append(" }\n"); - } - } else if (Options.Mode == MIPrintMode::Complete) { - Output.append("entry_values: []\n"); - } - - if (!Records.callSites().empty()) { - Output.append("callSites:\n"); - for (const MachineCallSiteInfo &CallSite : Records.callSites()) { - auto Location = instructionLocation(Function, CallSite.CallInstruction); - if (!Location) - return std::unexpected(Location.error()); - Output.append(" - { bb: "); - Output.append(std::to_string(Location->Block)); - Output.append(", offset: "); - Output.append(std::to_string(Location->Offset)); - if (!CallSite.ForwardedArguments.empty()) { - Output.append(", fwdArgRegs: [ "); - for (std::size_t Index = 0; Index < CallSite.ForwardedArguments.size(); ++Index) { - if (Index != 0) - Output.append(", "); - const MachineCallSiteArgument &Argument = CallSite.ForwardedArguments[Index]; - auto RegisterName = physicalRegister(Argument.Reg); - if (!RegisterName) - return std::unexpected(RegisterName.error()); - Output.append("{ arg: "); - Output.append(std::to_string(Argument.ArgumentNumber)); - Output.append(", reg: "); - Output.append(yamlScalar(*RegisterName)); - Output.append(" }"); - } - Output.append(" ]"); - } - if (!CallSite.CalleeTypeIDs.empty()) { - Output.append(", calleeTypeIds: [ "); - for (std::size_t Index = 0; Index < CallSite.CalleeTypeIDs.size(); ++Index) { - if (Index != 0) - Output.append(", "); - Output.append(std::to_string(CallSite.CalleeTypeIDs[Index])); - } - Output.append(" ]"); - } - Output.append(" }\n"); - } - } else if (Options.Mode == MIPrintMode::Complete) { - Output.append("callSites: []\n"); - } - - if (!Records.debugValueSubstitutions().empty()) { - Output.append("debugValueSubstitutions:\n"); - for (const MachineDebugValueSubstitution &Substitution : Records.debugValueSubstitutions()) { - Output.append(" - { srcinst: "); - Output.append(std::to_string(Substitution.Source.InstructionNumber)); - Output.append(", srcop: "); - Output.append(std::to_string(Substitution.Source.OperandNumber)); - Output.append(", dstinst: "); - Output.append(std::to_string(Substitution.Destination.InstructionNumber)); - Output.append(", dstop: "); - Output.append(std::to_string(Substitution.Destination.OperandNumber)); - Output.append(", subreg: "); - Output.append(std::to_string(Substitution.Subregister.value())); - Output.append(" }\n"); - } - } else if (Options.Mode == MIPrintMode::Complete) { - Output.append("debugValueSubstitutions: []\n"); - } - - if (!Records.calledGlobals().empty()) { - Output.append("calledGlobals:\n"); - for (const MachineCalledGlobal &Called : Records.calledGlobals()) { - auto Location = instructionLocation(Function, Called.CallInstruction); - if (!Location) - return std::unexpected(Location.error()); - Output.append(" - { bb: "); - Output.append(std::to_string(Location->Block)); - Output.append(", offset: "); - Output.append(std::to_string(Location->Offset)); - Output.append(", callee: "); - Output.append(yamlScalar(Called.Callee)); - Output.append(", flags: "); - Output.append(std::to_string(Called.Flags)); - Output.append(" }\n"); - } - } - - if (!Records.prefetchTargets().empty()) { - Output.append("prefetch-targets: [ "); - const auto Targets = Records.prefetchTargets(); - for (std::size_t Index = 0; Index < Targets.size(); ++Index) { - if (Index != 0) - Output.append(", "); - const MachinePrefetchTarget &TargetValue = Targets[Index]; - std::string Text = "bb_id " + std::to_string(TargetValue.Block.BaseID) + ", " + - std::to_string(TargetValue.Block.CloneID) + ", " + - std::to_string(TargetValue.CallsiteIndex); - Output.append(yamlScalar(Text)); - } - Output.append(" ]\n"); - } - return {}; -} - -Expected MIRDocumentPrinter::printFunction(const MachineFunction &Function, - const MIRFunctionDocumentInfo *) { - if (Function.compilationStatus().state() != MachineCompilationState::Success) { - return makeUnexpected(ErrorCode::Unsupported, - "fixed LLVM MIR cannot serialize this compilation failure state"); - } - auto Context = createBodyContext(Function); - if (!Context) - return std::unexpected(Context.error()); - - Output.append("---\nname: "); - Output.append(yamlScalar(Function.name())); - Output.push_back('\n'); - const auto Alignment = Function.attributes().alignment(); - if (Options.Mode == MIPrintMode::Complete || Alignment) { - Output.append("alignment: "); - Output.append(std::to_string(Alignment ? Alignment->bytes() : 1U)); - Output.push_back('\n'); - } - - const MachineFunctionProperties &Properties = Function.properties(); - const MachineFunctionAttributes &Attributes = Function.attributes(); - printBoolean("exposesReturnsTwice", - Attributes.has(MachineFunctionAttribute::ExposesReturnsTwice)); - printBoolean("legalized", Properties.has(MachineFunctionProperty::Legalized)); - printBoolean("regBankSelected", Properties.has(MachineFunctionProperty::RegBankSelected)); - printBoolean("selected", Properties.has(MachineFunctionProperty::Selected)); - printBoolean("failedISel", Properties.has(MachineFunctionProperty::FailedISel)); - printBoolean("tracksRegLiveness", Properties.has(MachineFunctionProperty::TracksLiveness)); - printBoolean("hasWinCFI", Attributes.has(MachineFunctionAttribute::HasWinCFI)); - printBoolean("noPhis", Properties.has(MachineFunctionProperty::NoPHIs), true); - printBoolean("isSSA", Properties.has(MachineFunctionProperty::IsSSA), true); - printBoolean("noVRegs", Properties.has(MachineFunctionProperty::NoVRegs), true); - printBoolean("hasFakeUses", Attributes.has(MachineFunctionAttribute::HasFakeUses), true); - printBoolean("callsEHReturn", Attributes.has(MachineFunctionAttribute::CallsEHReturn)); - printBoolean("callsUnwindInit", Attributes.has(MachineFunctionAttribute::CallsUnwindInit)); - printBoolean("hasEHContTarget", Attributes.has(MachineFunctionAttribute::HasEHContTarget)); - printBoolean("hasEHScopes", Attributes.has(MachineFunctionAttribute::HasEHScopes)); - printBoolean("hasEHFunclets", Attributes.has(MachineFunctionAttribute::HasEHFunclets)); - printBoolean("isOutlined", Attributes.has(MachineFunctionAttribute::IsOutlined)); - printBoolean("debugInstrRef", Attributes.has(MachineFunctionAttribute::DebugInstrRef)); - printBoolean("failsVerification", Properties.has(MachineFunctionProperty::FailsVerification)); - printBoolean("tracksDebugUserValues", - Attributes.has(MachineFunctionAttribute::TracksDebugUserValues)); - - if (auto Printed = printRegisters(Function, *Context); !Printed) - return Printed; - if (auto Printed = printFrameInfo(Function, *Context); !Printed) - return Printed; - if (auto Printed = printStackObjects(Function, *Context, true); !Printed) - return Printed; - if (auto Printed = printStackObjects(Function, *Context, false); !Printed) - return Printed; - if (auto Printed = printFunctionRecords(Function, *Context); !Printed) - return Printed; - if (auto Printed = printConstants(Function, *Context); !Printed) - return Printed; - if (auto Printed = printTargetState(Function); !Printed) - return Printed; - if (auto Printed = printJumpTable(Function, *Context); !Printed) - return Printed; - if (auto Printed = printMetadata(Function, *Context); !Printed) - return Printed; - - auto Body = - printMachineFunctionBody(Function, Target, *Context, MIPrinterOptions{.Mode = Options.Mode}); - if (!Body) - return std::unexpected(Body.error()); - Output.append("body: |\n"); - appendBlockScalar(Output, *Body, 2); - Output.append("...\n"); - return {}; -} - -Expected MIRDocumentPrinter::run() { - auto UnitVerification = Document.unit().verify(); - if (!UnitVerification) - return std::unexpected(UnitVerification.error()); - if (Document.unit().functionCount() == 0) { - return makeUnexpected(ErrorCode::InvalidArgument, - "MIR document must contain at least one machine function"); - } - - for (const MIRFunctionDocumentInfo &Info : Document.functionDocumentInfo()) { - if (Document.unit().function(Info.Function) == nullptr) { - return makeUnexpected(ErrorCode::VerificationError, - "MIR document info references an unknown machine function"); - } - } - - for (std::size_t Index = 0; Index < Document.unit().functionCount(); ++Index) { - const MachineFunction *Function = Document.unit().functionAt(Index); - if (Function == nullptr) { - return makeUnexpected(ErrorCode::VerificationError, - "compilation unit contains a null machine function"); - } - auto ReferenceVerification = - verifyMIRDocumentReferences(Document, *Function, Options.EmitEmbeddedIR); - if (!ReferenceVerification) - return std::unexpected(ReferenceVerification.error()); - auto LayoutVerification = verifyOmittedEmbeddedIRLayout(*Function); - if (!LayoutVerification) - return std::unexpected(LayoutVerification.error()); - } - - if (Options.EmitEmbeddedIR && Document.embeddedIR() != nullptr) { - Output.append("--- |\n"); - appendBlockScalar(Output, Document.embeddedIR()->source().text(), 2); - Output.append("...\n"); - } - for (std::size_t Index = 0; Index < Document.unit().functionCount(); ++Index) { - const MachineFunction *Function = Document.unit().functionAt(Index); - if (Function == nullptr) - return makeUnexpected(ErrorCode::VerificationError, - "compilation unit contains a null machine function"); - if (auto Printed = printFunction(*Function, documentInfo(*Function)); !Printed) - return std::unexpected(Printed.error()); - } - return std::move(Output); -} - -} // namespace - -Expected printMIRDocument(const MIRDocument &Document, const TargetDescription &Target, - MIRDocumentPrinterOptions Options) { - return MIRDocumentPrinter(Document, Target, std::move(Options)).run(); -} - -} // namespace rcc::mir -- cgit v1.2.3