Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:33

0001 //===- MIRYamlMapping.h - Describe mapping between MIR and YAML--*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file implements the mapping between various MIR data structures and
0010 // their corresponding YAML representation.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CODEGEN_MIRYAMLMAPPING_H
0015 #define LLVM_CODEGEN_MIRYAMLMAPPING_H
0016 
0017 #include "llvm/ADT/StringRef.h"
0018 #include "llvm/CodeGen/MachineJumpTableInfo.h"
0019 #include "llvm/CodeGen/TargetFrameLowering.h"
0020 #include "llvm/Support/SMLoc.h"
0021 #include "llvm/Support/YAMLTraits.h"
0022 #include "llvm/Support/raw_ostream.h"
0023 #include <algorithm>
0024 #include <cstdint>
0025 #include <optional>
0026 #include <string>
0027 #include <vector>
0028 
0029 namespace llvm {
0030 namespace yaml {
0031 
0032 /// A wrapper around std::string which contains a source range that's being
0033 /// set during parsing.
0034 struct StringValue {
0035   std::string Value;
0036   SMRange SourceRange;
0037 
0038   StringValue() = default;
0039   StringValue(std::string Value) : Value(std::move(Value)) {}
0040   StringValue(const char Val[]) : Value(Val) {}
0041 
0042   bool operator==(const StringValue &Other) const {
0043     return Value == Other.Value;
0044   }
0045 };
0046 
0047 template <> struct ScalarTraits<StringValue> {
0048   static void output(const StringValue &S, void *, raw_ostream &OS) {
0049     OS << S.Value;
0050   }
0051 
0052   static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) {
0053     S.Value = Scalar.str();
0054     if (const auto *Node =
0055             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
0056       S.SourceRange = Node->getSourceRange();
0057     return "";
0058   }
0059 
0060   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
0061 };
0062 
0063 struct FlowStringValue : StringValue {
0064   FlowStringValue() = default;
0065   FlowStringValue(std::string Value) : StringValue(std::move(Value)) {}
0066 };
0067 
0068 template <> struct ScalarTraits<FlowStringValue> {
0069   static void output(const FlowStringValue &S, void *, raw_ostream &OS) {
0070     return ScalarTraits<StringValue>::output(S, nullptr, OS);
0071   }
0072 
0073   static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) {
0074     return ScalarTraits<StringValue>::input(Scalar, Ctx, S);
0075   }
0076 
0077   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
0078 };
0079 
0080 struct BlockStringValue {
0081   StringValue Value;
0082 
0083   bool operator==(const BlockStringValue &Other) const {
0084     return Value == Other.Value;
0085   }
0086 };
0087 
0088 template <> struct BlockScalarTraits<BlockStringValue> {
0089   static void output(const BlockStringValue &S, void *Ctx, raw_ostream &OS) {
0090     return ScalarTraits<StringValue>::output(S.Value, Ctx, OS);
0091   }
0092 
0093   static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) {
0094     return ScalarTraits<StringValue>::input(Scalar, Ctx, S.Value);
0095   }
0096 };
0097 
0098 /// A wrapper around unsigned which contains a source range that's being set
0099 /// during parsing.
0100 struct UnsignedValue {
0101   unsigned Value = 0;
0102   SMRange SourceRange;
0103 
0104   UnsignedValue() = default;
0105   UnsignedValue(unsigned Value) : Value(Value) {}
0106 
0107   bool operator==(const UnsignedValue &Other) const {
0108     return Value == Other.Value;
0109   }
0110 };
0111 
0112 template <> struct ScalarTraits<UnsignedValue> {
0113   static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) {
0114     return ScalarTraits<unsigned>::output(Value.Value, Ctx, OS);
0115   }
0116 
0117   static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) {
0118     if (const auto *Node =
0119             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
0120       Value.SourceRange = Node->getSourceRange();
0121     return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value);
0122   }
0123 
0124   static QuotingType mustQuote(StringRef Scalar) {
0125     return ScalarTraits<unsigned>::mustQuote(Scalar);
0126   }
0127 };
0128 
0129 template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> {
0130   static void enumeration(yaml::IO &IO,
0131                           MachineJumpTableInfo::JTEntryKind &EntryKind) {
0132     IO.enumCase(EntryKind, "block-address",
0133                 MachineJumpTableInfo::EK_BlockAddress);
0134     IO.enumCase(EntryKind, "gp-rel64-block-address",
0135                 MachineJumpTableInfo::EK_GPRel64BlockAddress);
0136     IO.enumCase(EntryKind, "gp-rel32-block-address",
0137                 MachineJumpTableInfo::EK_GPRel32BlockAddress);
0138     IO.enumCase(EntryKind, "label-difference32",
0139                 MachineJumpTableInfo::EK_LabelDifference32);
0140     IO.enumCase(EntryKind, "label-difference64",
0141                 MachineJumpTableInfo::EK_LabelDifference64);
0142     IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline);
0143     IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32);
0144   }
0145 };
0146 
0147 template <> struct ScalarTraits<MaybeAlign> {
0148   static void output(const MaybeAlign &Alignment, void *,
0149                      llvm::raw_ostream &out) {
0150     out << uint64_t(Alignment ? Alignment->value() : 0U);
0151   }
0152   static StringRef input(StringRef Scalar, void *, MaybeAlign &Alignment) {
0153     unsigned long long n;
0154     if (getAsUnsignedInteger(Scalar, 10, n))
0155       return "invalid number";
0156     if (n > 0 && !isPowerOf2_64(n))
0157       return "must be 0 or a power of two";
0158     Alignment = MaybeAlign(n);
0159     return StringRef();
0160   }
0161   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
0162 };
0163 
0164 template <> struct ScalarTraits<Align> {
0165   static void output(const Align &Alignment, void *, llvm::raw_ostream &OS) {
0166     OS << Alignment.value();
0167   }
0168   static StringRef input(StringRef Scalar, void *, Align &Alignment) {
0169     unsigned long long N;
0170     if (getAsUnsignedInteger(Scalar, 10, N))
0171       return "invalid number";
0172     if (!isPowerOf2_64(N))
0173       return "must be a power of two";
0174     Alignment = Align(N);
0175     return StringRef();
0176   }
0177   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
0178 };
0179 
0180 } // end namespace yaml
0181 } // end namespace llvm
0182 
0183 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
0184 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
0185 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
0186 
0187 namespace llvm {
0188 namespace yaml {
0189 
0190 struct VirtualRegisterDefinition {
0191   UnsignedValue ID;
0192   StringValue Class;
0193   StringValue PreferredRegister;
0194   std::vector<FlowStringValue> RegisterFlags;
0195 
0196   // TODO: Serialize the target specific register hints.
0197 
0198   bool operator==(const VirtualRegisterDefinition &Other) const {
0199     return ID == Other.ID && Class == Other.Class &&
0200            PreferredRegister == Other.PreferredRegister;
0201   }
0202 };
0203 
0204 template <> struct MappingTraits<VirtualRegisterDefinition> {
0205   static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
0206     YamlIO.mapRequired("id", Reg.ID);
0207     YamlIO.mapRequired("class", Reg.Class);
0208     YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
0209                        StringValue()); // Don't print out when it's empty.
0210     YamlIO.mapOptional("flags", Reg.RegisterFlags,
0211                        std::vector<FlowStringValue>());
0212   }
0213 
0214   static const bool flow = true;
0215 };
0216 
0217 struct MachineFunctionLiveIn {
0218   StringValue Register;
0219   StringValue VirtualRegister;
0220 
0221   bool operator==(const MachineFunctionLiveIn &Other) const {
0222     return Register == Other.Register &&
0223            VirtualRegister == Other.VirtualRegister;
0224   }
0225 };
0226 
0227 template <> struct MappingTraits<MachineFunctionLiveIn> {
0228   static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
0229     YamlIO.mapRequired("reg", LiveIn.Register);
0230     YamlIO.mapOptional(
0231         "virtual-reg", LiveIn.VirtualRegister,
0232         StringValue()); // Don't print the virtual register when it's empty.
0233   }
0234 
0235   static const bool flow = true;
0236 };
0237 
0238 /// Serializable representation of stack object from the MachineFrameInfo class.
0239 ///
0240 /// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
0241 /// determined by the object's type and frame information flags.
0242 /// Dead stack objects aren't serialized.
0243 ///
0244 /// The 'isPreallocated' flag is determined by the local offset.
0245 struct MachineStackObject {
0246   enum ObjectType { DefaultType, SpillSlot, VariableSized };
0247   UnsignedValue ID;
0248   StringValue Name;
0249   // TODO: Serialize unnamed LLVM alloca reference.
0250   ObjectType Type = DefaultType;
0251   int64_t Offset = 0;
0252   uint64_t Size = 0;
0253   MaybeAlign Alignment = std::nullopt;
0254   TargetStackID::Value StackID;
0255   StringValue CalleeSavedRegister;
0256   bool CalleeSavedRestored = true;
0257   std::optional<int64_t> LocalOffset;
0258   StringValue DebugVar;
0259   StringValue DebugExpr;
0260   StringValue DebugLoc;
0261 
0262   bool operator==(const MachineStackObject &Other) const {
0263     return ID == Other.ID && Name == Other.Name && Type == Other.Type &&
0264            Offset == Other.Offset && Size == Other.Size &&
0265            Alignment == Other.Alignment &&
0266            StackID == Other.StackID &&
0267            CalleeSavedRegister == Other.CalleeSavedRegister &&
0268            CalleeSavedRestored == Other.CalleeSavedRestored &&
0269            LocalOffset == Other.LocalOffset && DebugVar == Other.DebugVar &&
0270            DebugExpr == Other.DebugExpr && DebugLoc == Other.DebugLoc;
0271   }
0272 };
0273 
0274 template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
0275   static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
0276     IO.enumCase(Type, "default", MachineStackObject::DefaultType);
0277     IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
0278     IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
0279   }
0280 };
0281 
0282 template <> struct MappingTraits<MachineStackObject> {
0283   static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
0284     YamlIO.mapRequired("id", Object.ID);
0285     YamlIO.mapOptional("name", Object.Name,
0286                        StringValue()); // Don't print out an empty name.
0287     YamlIO.mapOptional(
0288         "type", Object.Type,
0289         MachineStackObject::DefaultType); // Don't print the default type.
0290     YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
0291     if (Object.Type != MachineStackObject::VariableSized)
0292       YamlIO.mapRequired("size", Object.Size);
0293     YamlIO.mapOptional("alignment", Object.Alignment, std::nullopt);
0294     YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
0295     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
0296                        StringValue()); // Don't print it out when it's empty.
0297     YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
0298                        true);
0299     YamlIO.mapOptional("local-offset", Object.LocalOffset,
0300                        std::optional<int64_t>());
0301     YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
0302                        StringValue()); // Don't print it out when it's empty.
0303     YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
0304                        StringValue()); // Don't print it out when it's empty.
0305     YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
0306                        StringValue()); // Don't print it out when it's empty.
0307   }
0308 
0309   static const bool flow = true;
0310 };
0311 
0312 /// Serializable representation of the MCRegister variant of
0313 /// MachineFunction::VariableDbgInfo.
0314 struct EntryValueObject {
0315   StringValue EntryValueRegister;
0316   StringValue DebugVar;
0317   StringValue DebugExpr;
0318   StringValue DebugLoc;
0319   bool operator==(const EntryValueObject &Other) const {
0320     return EntryValueRegister == Other.EntryValueRegister &&
0321            DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr &&
0322            DebugLoc == Other.DebugLoc;
0323   }
0324 };
0325 
0326 template <> struct MappingTraits<EntryValueObject> {
0327   static void mapping(yaml::IO &YamlIO, EntryValueObject &Object) {
0328     YamlIO.mapRequired("entry-value-register", Object.EntryValueRegister);
0329     YamlIO.mapRequired("debug-info-variable", Object.DebugVar);
0330     YamlIO.mapRequired("debug-info-expression", Object.DebugExpr);
0331     YamlIO.mapRequired("debug-info-location", Object.DebugLoc);
0332   }
0333   static const bool flow = true;
0334 };
0335 
0336 /// Serializable representation of the fixed stack object from the
0337 /// MachineFrameInfo class.
0338 struct FixedMachineStackObject {
0339   enum ObjectType { DefaultType, SpillSlot };
0340   UnsignedValue ID;
0341   ObjectType Type = DefaultType;
0342   int64_t Offset = 0;
0343   uint64_t Size = 0;
0344   MaybeAlign Alignment = std::nullopt;
0345   TargetStackID::Value StackID;
0346   bool IsImmutable = false;
0347   bool IsAliased = false;
0348   StringValue CalleeSavedRegister;
0349   bool CalleeSavedRestored = true;
0350   StringValue DebugVar;
0351   StringValue DebugExpr;
0352   StringValue DebugLoc;
0353 
0354   bool operator==(const FixedMachineStackObject &Other) const {
0355     return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
0356            Size == Other.Size && Alignment == Other.Alignment &&
0357            StackID == Other.StackID &&
0358            IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
0359            CalleeSavedRegister == Other.CalleeSavedRegister &&
0360            CalleeSavedRestored == Other.CalleeSavedRestored &&
0361            DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr
0362            && DebugLoc == Other.DebugLoc;
0363   }
0364 };
0365 
0366 template <>
0367 struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
0368   static void enumeration(yaml::IO &IO,
0369                           FixedMachineStackObject::ObjectType &Type) {
0370     IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
0371     IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
0372   }
0373 };
0374 
0375 template <>
0376 struct ScalarEnumerationTraits<TargetStackID::Value> {
0377   static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) {
0378     IO.enumCase(ID, "default", TargetStackID::Default);
0379     IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill);
0380     IO.enumCase(ID, "scalable-vector", TargetStackID::ScalableVector);
0381     IO.enumCase(ID, "wasm-local", TargetStackID::WasmLocal);
0382     IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc);
0383   }
0384 };
0385 
0386 template <> struct MappingTraits<FixedMachineStackObject> {
0387   static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
0388     YamlIO.mapRequired("id", Object.ID);
0389     YamlIO.mapOptional(
0390         "type", Object.Type,
0391         FixedMachineStackObject::DefaultType); // Don't print the default type.
0392     YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
0393     YamlIO.mapOptional("size", Object.Size, (uint64_t)0);
0394     YamlIO.mapOptional("alignment", Object.Alignment, std::nullopt);
0395     YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
0396     if (Object.Type != FixedMachineStackObject::SpillSlot) {
0397       YamlIO.mapOptional("isImmutable", Object.IsImmutable, false);
0398       YamlIO.mapOptional("isAliased", Object.IsAliased, false);
0399     }
0400     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
0401                        StringValue()); // Don't print it out when it's empty.
0402     YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
0403                      true);
0404     YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
0405                        StringValue()); // Don't print it out when it's empty.
0406     YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
0407                        StringValue()); // Don't print it out when it's empty.
0408     YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
0409                        StringValue()); // Don't print it out when it's empty.
0410   }
0411 
0412   static const bool flow = true;
0413 };
0414 
0415 /// A serializaable representation of a reference to a stack object or fixed
0416 /// stack object.
0417 struct FrameIndex {
0418   // The frame index as printed. This is always a positive number, even for
0419   // fixed objects. To obtain the real index,
0420   // MachineFrameInfo::getObjectIndexBegin has to be added.
0421   int FI;
0422   bool IsFixed;
0423   SMRange SourceRange;
0424 
0425   FrameIndex() = default;
0426   FrameIndex(int FI, const llvm::MachineFrameInfo &MFI);
0427 
0428   Expected<int> getFI(const llvm::MachineFrameInfo &MFI) const;
0429 };
0430 
0431 template <> struct ScalarTraits<FrameIndex> {
0432   static void output(const FrameIndex &FI, void *, raw_ostream &OS) {
0433     MachineOperand::printStackObjectReference(OS, FI.FI, FI.IsFixed, "");
0434   }
0435 
0436   static StringRef input(StringRef Scalar, void *Ctx, FrameIndex &FI) {
0437     FI.IsFixed = false;
0438     StringRef Num;
0439     if (Scalar.starts_with("%stack.")) {
0440       Num = Scalar.substr(7);
0441     } else if (Scalar.starts_with("%fixed-stack.")) {
0442       Num = Scalar.substr(13);
0443       FI.IsFixed = true;
0444     } else {
0445       return "Invalid frame index, needs to start with %stack. or "
0446              "%fixed-stack.";
0447     }
0448     if (Num.consumeInteger(10, FI.FI))
0449       return "Invalid frame index, not a valid number";
0450 
0451     if (const auto *Node =
0452             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
0453       FI.SourceRange = Node->getSourceRange();
0454     return StringRef();
0455   }
0456 
0457   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
0458 };
0459 
0460 /// Identifies call instruction location in machine function.
0461 struct MachineInstrLoc {
0462   unsigned BlockNum;
0463   unsigned Offset;
0464 
0465   bool operator==(const MachineInstrLoc &Other) const {
0466     return BlockNum == Other.BlockNum && Offset == Other.Offset;
0467   }
0468 };
0469 
0470 /// Serializable representation of CallSiteInfo.
0471 struct CallSiteInfo {
0472   // Representation of call argument and register which is used to
0473   // transfer it.
0474   struct ArgRegPair {
0475     StringValue Reg;
0476     uint16_t ArgNo;
0477 
0478     bool operator==(const ArgRegPair &Other) const {
0479       return Reg == Other.Reg && ArgNo == Other.ArgNo;
0480     }
0481   };
0482 
0483   MachineInstrLoc CallLocation;
0484   std::vector<ArgRegPair> ArgForwardingRegs;
0485 
0486   bool operator==(const CallSiteInfo &Other) const {
0487     return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
0488            CallLocation.Offset == Other.CallLocation.Offset;
0489   }
0490 };
0491 
0492 template <> struct MappingTraits<CallSiteInfo::ArgRegPair> {
0493   static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) {
0494     YamlIO.mapRequired("arg", ArgReg.ArgNo);
0495     YamlIO.mapRequired("reg", ArgReg.Reg);
0496   }
0497 
0498   static const bool flow = true;
0499 };
0500 }
0501 }
0502 
0503 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair)
0504 
0505 namespace llvm {
0506 namespace yaml {
0507 
0508 template <> struct MappingTraits<CallSiteInfo> {
0509   static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) {
0510     YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum);
0511     YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
0512     YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
0513                        std::vector<CallSiteInfo::ArgRegPair>());
0514   }
0515 
0516   static const bool flow = true;
0517 };
0518 
0519 /// Serializable representation of debug value substitutions.
0520 struct DebugValueSubstitution {
0521   unsigned SrcInst;
0522   unsigned SrcOp;
0523   unsigned DstInst;
0524   unsigned DstOp;
0525   unsigned Subreg;
0526 
0527   bool operator==(const DebugValueSubstitution &Other) const {
0528     return std::tie(SrcInst, SrcOp, DstInst, DstOp) ==
0529            std::tie(Other.SrcInst, Other.SrcOp, Other.DstInst, Other.DstOp);
0530   }
0531 };
0532 
0533 template <> struct MappingTraits<DebugValueSubstitution> {
0534   static void mapping(IO &YamlIO, DebugValueSubstitution &Sub) {
0535     YamlIO.mapRequired("srcinst", Sub.SrcInst);
0536     YamlIO.mapRequired("srcop", Sub.SrcOp);
0537     YamlIO.mapRequired("dstinst", Sub.DstInst);
0538     YamlIO.mapRequired("dstop", Sub.DstOp);
0539     YamlIO.mapRequired("subreg", Sub.Subreg);
0540   }
0541 
0542   static const bool flow = true;
0543 };
0544 } // namespace yaml
0545 } // namespace llvm
0546 
0547 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::DebugValueSubstitution)
0548 
0549 namespace llvm {
0550 namespace yaml {
0551 struct MachineConstantPoolValue {
0552   UnsignedValue ID;
0553   StringValue Value;
0554   MaybeAlign Alignment = std::nullopt;
0555   bool IsTargetSpecific = false;
0556 
0557   bool operator==(const MachineConstantPoolValue &Other) const {
0558     return ID == Other.ID && Value == Other.Value &&
0559            Alignment == Other.Alignment &&
0560            IsTargetSpecific == Other.IsTargetSpecific;
0561   }
0562 };
0563 
0564 template <> struct MappingTraits<MachineConstantPoolValue> {
0565   static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
0566     YamlIO.mapRequired("id", Constant.ID);
0567     YamlIO.mapOptional("value", Constant.Value, StringValue());
0568     YamlIO.mapOptional("alignment", Constant.Alignment, std::nullopt);
0569     YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false);
0570   }
0571 };
0572 
0573 struct MachineJumpTable {
0574   struct Entry {
0575     UnsignedValue ID;
0576     std::vector<FlowStringValue> Blocks;
0577 
0578     bool operator==(const Entry &Other) const {
0579       return ID == Other.ID && Blocks == Other.Blocks;
0580     }
0581   };
0582 
0583   MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
0584   std::vector<Entry> Entries;
0585 
0586   bool operator==(const MachineJumpTable &Other) const {
0587     return Kind == Other.Kind && Entries == Other.Entries;
0588   }
0589 };
0590 
0591 template <> struct MappingTraits<MachineJumpTable::Entry> {
0592   static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
0593     YamlIO.mapRequired("id", Entry.ID);
0594     YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>());
0595   }
0596 };
0597 
0598 struct CalledGlobal {
0599   MachineInstrLoc CallSite;
0600   StringValue Callee;
0601   unsigned Flags;
0602 
0603   bool operator==(const CalledGlobal &Other) const {
0604     return CallSite == Other.CallSite && Callee == Other.Callee &&
0605            Flags == Other.Flags;
0606   }
0607 };
0608 
0609 template <> struct MappingTraits<CalledGlobal> {
0610   static void mapping(IO &YamlIO, CalledGlobal &CG) {
0611     YamlIO.mapRequired("bb", CG.CallSite.BlockNum);
0612     YamlIO.mapRequired("offset", CG.CallSite.Offset);
0613     YamlIO.mapRequired("callee", CG.Callee);
0614     YamlIO.mapRequired("flags", CG.Flags);
0615   }
0616 };
0617 
0618 } // end namespace yaml
0619 } // end namespace llvm
0620 
0621 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
0622 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
0623 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
0624 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::EntryValueObject)
0625 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
0626 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo)
0627 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
0628 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
0629 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CalledGlobal)
0630 
0631 namespace llvm {
0632 namespace yaml {
0633 
0634 template <> struct MappingTraits<MachineJumpTable> {
0635   static void mapping(IO &YamlIO, MachineJumpTable &JT) {
0636     YamlIO.mapRequired("kind", JT.Kind);
0637     YamlIO.mapOptional("entries", JT.Entries,
0638                        std::vector<MachineJumpTable::Entry>());
0639   }
0640 };
0641 
0642 /// Serializable representation of MachineFrameInfo.
0643 ///
0644 /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
0645 /// 'RealignOption' as they are determined by the target and LLVM function
0646 /// attributes.
0647 /// It also doesn't serialize attributes like 'NumFixedObject' and
0648 /// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
0649 struct MachineFrameInfo {
0650   bool IsFrameAddressTaken = false;
0651   bool IsReturnAddressTaken = false;
0652   bool HasStackMap = false;
0653   bool HasPatchPoint = false;
0654   uint64_t StackSize = 0;
0655   int OffsetAdjustment = 0;
0656   unsigned MaxAlignment = 0;
0657   bool AdjustsStack = false;
0658   bool HasCalls = false;
0659   StringValue StackProtector;
0660   StringValue FunctionContext;
0661   unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
0662   unsigned CVBytesOfCalleeSavedRegisters = 0;
0663   bool HasOpaqueSPAdjustment = false;
0664   bool HasVAStart = false;
0665   bool HasMustTailInVarArgFunc = false;
0666   bool HasTailCall = false;
0667   bool IsCalleeSavedInfoValid = false;
0668   unsigned LocalFrameSize = 0;
0669   StringValue SavePoint;
0670   StringValue RestorePoint;
0671 
0672   bool operator==(const MachineFrameInfo &Other) const {
0673     return IsFrameAddressTaken == Other.IsFrameAddressTaken &&
0674            IsReturnAddressTaken == Other.IsReturnAddressTaken &&
0675            HasStackMap == Other.HasStackMap &&
0676            HasPatchPoint == Other.HasPatchPoint &&
0677            StackSize == Other.StackSize &&
0678            OffsetAdjustment == Other.OffsetAdjustment &&
0679            MaxAlignment == Other.MaxAlignment &&
0680            AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
0681            StackProtector == Other.StackProtector &&
0682            FunctionContext == Other.FunctionContext &&
0683            MaxCallFrameSize == Other.MaxCallFrameSize &&
0684            CVBytesOfCalleeSavedRegisters ==
0685                Other.CVBytesOfCalleeSavedRegisters &&
0686            HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
0687            HasVAStart == Other.HasVAStart &&
0688            HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
0689            HasTailCall == Other.HasTailCall &&
0690            LocalFrameSize == Other.LocalFrameSize &&
0691            SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint &&
0692            IsCalleeSavedInfoValid == Other.IsCalleeSavedInfoValid;
0693   }
0694 };
0695 
0696 template <> struct MappingTraits<MachineFrameInfo> {
0697   static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
0698     YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false);
0699     YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false);
0700     YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false);
0701     YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false);
0702     YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0);
0703     YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0);
0704     YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
0705     YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
0706     YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
0707     YamlIO.mapOptional("stackProtector", MFI.StackProtector,
0708                        StringValue()); // Don't print it out when it's empty.
0709     YamlIO.mapOptional("functionContext", MFI.FunctionContext,
0710                        StringValue()); // Don't print it out when it's empty.
0711     YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0);
0712     YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters",
0713                        MFI.CVBytesOfCalleeSavedRegisters, 0U);
0714     YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,
0715                        false);
0716     YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
0717     YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
0718                        false);
0719     YamlIO.mapOptional("hasTailCall", MFI.HasTailCall, false);
0720     YamlIO.mapOptional("isCalleeSavedInfoValid", MFI.IsCalleeSavedInfoValid,
0721                        false);
0722     YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0);
0723     YamlIO.mapOptional("savePoint", MFI.SavePoint,
0724                        StringValue()); // Don't print it out when it's empty.
0725     YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
0726                        StringValue()); // Don't print it out when it's empty.
0727   }
0728 };
0729 
0730 /// Targets should override this in a way that mirrors the implementation of
0731 /// llvm::MachineFunctionInfo.
0732 struct MachineFunctionInfo {
0733   virtual ~MachineFunctionInfo() = default;
0734   virtual void mappingImpl(IO &YamlIO) {}
0735 };
0736 
0737 template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
0738   static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
0739     if (MFI)
0740       MFI->mappingImpl(YamlIO);
0741   }
0742 };
0743 
0744 struct MachineFunction {
0745   StringRef Name;
0746   MaybeAlign Alignment = std::nullopt;
0747   bool ExposesReturnsTwice = false;
0748   // GISel MachineFunctionProperties.
0749   bool Legalized = false;
0750   bool RegBankSelected = false;
0751   bool Selected = false;
0752   bool FailedISel = false;
0753   // Register information
0754   bool TracksRegLiveness = false;
0755   bool HasWinCFI = false;
0756 
0757   // Computed properties that should be overridable
0758   std::optional<bool> NoPHIs;
0759   std::optional<bool> IsSSA;
0760   std::optional<bool> NoVRegs;
0761   std::optional<bool> HasFakeUses;
0762 
0763   bool CallsEHReturn = false;
0764   bool CallsUnwindInit = false;
0765   bool HasEHCatchret = false;
0766   bool HasEHScopes = false;
0767   bool HasEHFunclets = false;
0768   bool IsOutlined = false;
0769 
0770   bool FailsVerification = false;
0771   bool TracksDebugUserValues = false;
0772   bool UseDebugInstrRef = false;
0773   std::vector<VirtualRegisterDefinition> VirtualRegisters;
0774   std::vector<MachineFunctionLiveIn> LiveIns;
0775   std::optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
0776   // TODO: Serialize the various register masks.
0777   // Frame information
0778   MachineFrameInfo FrameInfo;
0779   std::vector<FixedMachineStackObject> FixedStackObjects;
0780   std::vector<EntryValueObject> EntryValueObjects;
0781   std::vector<MachineStackObject> StackObjects;
0782   std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
0783   std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
0784   std::vector<CallSiteInfo> CallSitesInfo;
0785   std::vector<DebugValueSubstitution> DebugValueSubstitutions;
0786   MachineJumpTable JumpTableInfo;
0787   std::vector<StringValue> MachineMetadataNodes;
0788   std::vector<CalledGlobal> CalledGlobals;
0789   BlockStringValue Body;
0790 };
0791 
0792 template <> struct MappingTraits<MachineFunction> {
0793   static void mapping(IO &YamlIO, MachineFunction &MF) {
0794     YamlIO.mapRequired("name", MF.Name);
0795     YamlIO.mapOptional("alignment", MF.Alignment, std::nullopt);
0796     YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false);
0797     YamlIO.mapOptional("legalized", MF.Legalized, false);
0798     YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
0799     YamlIO.mapOptional("selected", MF.Selected, false);
0800     YamlIO.mapOptional("failedISel", MF.FailedISel, false);
0801     YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
0802     YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false);
0803 
0804     // PHIs must be not be capitalized, since it will clash with the MIR opcode
0805     // leading to false-positive FileCheck hits with CHECK-NOT
0806     YamlIO.mapOptional("noPhis", MF.NoPHIs, std::optional<bool>());
0807     YamlIO.mapOptional("isSSA", MF.IsSSA, std::optional<bool>());
0808     YamlIO.mapOptional("noVRegs", MF.NoVRegs, std::optional<bool>());
0809     YamlIO.mapOptional("hasFakeUses", MF.HasFakeUses, std::optional<bool>());
0810 
0811     YamlIO.mapOptional("callsEHReturn", MF.CallsEHReturn, false);
0812     YamlIO.mapOptional("callsUnwindInit", MF.CallsUnwindInit, false);
0813     YamlIO.mapOptional("hasEHCatchret", MF.HasEHCatchret, false);
0814     YamlIO.mapOptional("hasEHScopes", MF.HasEHScopes, false);
0815     YamlIO.mapOptional("hasEHFunclets", MF.HasEHFunclets, false);
0816     YamlIO.mapOptional("isOutlined", MF.IsOutlined, false);
0817     YamlIO.mapOptional("debugInstrRef", MF.UseDebugInstrRef, false);
0818 
0819     YamlIO.mapOptional("failsVerification", MF.FailsVerification, false);
0820     YamlIO.mapOptional("tracksDebugUserValues", MF.TracksDebugUserValues,
0821                        false);
0822     YamlIO.mapOptional("registers", MF.VirtualRegisters,
0823                        std::vector<VirtualRegisterDefinition>());
0824     YamlIO.mapOptional("liveins", MF.LiveIns,
0825                        std::vector<MachineFunctionLiveIn>());
0826     YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters,
0827                        std::optional<std::vector<FlowStringValue>>());
0828     YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo());
0829     YamlIO.mapOptional("fixedStack", MF.FixedStackObjects,
0830                        std::vector<FixedMachineStackObject>());
0831     YamlIO.mapOptional("stack", MF.StackObjects,
0832                        std::vector<MachineStackObject>());
0833     YamlIO.mapOptional("entry_values", MF.EntryValueObjects,
0834                        std::vector<EntryValueObject>());
0835     YamlIO.mapOptional("callSites", MF.CallSitesInfo,
0836                        std::vector<CallSiteInfo>());
0837     YamlIO.mapOptional("debugValueSubstitutions", MF.DebugValueSubstitutions,
0838                        std::vector<DebugValueSubstitution>());
0839     YamlIO.mapOptional("constants", MF.Constants,
0840                        std::vector<MachineConstantPoolValue>());
0841     YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
0842     if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
0843       YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
0844     if (!YamlIO.outputting() || !MF.MachineMetadataNodes.empty())
0845       YamlIO.mapOptional("machineMetadataNodes", MF.MachineMetadataNodes,
0846                          std::vector<StringValue>());
0847     if (!YamlIO.outputting() || !MF.CalledGlobals.empty())
0848       YamlIO.mapOptional("calledGlobals", MF.CalledGlobals,
0849                          std::vector<CalledGlobal>());
0850     YamlIO.mapOptional("body", MF.Body, BlockStringValue());
0851   }
0852 };
0853 
0854 } // end namespace yaml
0855 } // end namespace llvm
0856 
0857 #endif // LLVM_CODEGEN_MIRYAMLMAPPING_H