Home | History | Annotate | Line # | Download | only in CodeGen
      1 //===- MIRYamlMapping.h - Describe mapping between MIR and YAML--*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file implements the mapping between various MIR data structures and
     10 // their corresponding YAML representation.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_CODEGEN_MIRYAMLMAPPING_H
     15 #define LLVM_CODEGEN_MIRYAMLMAPPING_H
     16 
     17 #include "llvm/ADT/Optional.h"
     18 #include "llvm/ADT/StringRef.h"
     19 #include "llvm/CodeGen/MachineJumpTableInfo.h"
     20 #include "llvm/CodeGen/TargetFrameLowering.h"
     21 #include "llvm/Support/SMLoc.h"
     22 #include "llvm/Support/YAMLTraits.h"
     23 #include "llvm/Support/raw_ostream.h"
     24 #include <algorithm>
     25 #include <cstdint>
     26 #include <string>
     27 #include <vector>
     28 
     29 namespace llvm {
     30 namespace yaml {
     31 
     32 /// A wrapper around std::string which contains a source range that's being
     33 /// set during parsing.
     34 struct StringValue {
     35   std::string Value;
     36   SMRange SourceRange;
     37 
     38   StringValue() = default;
     39   StringValue(std::string Value) : Value(std::move(Value)) {}
     40   StringValue(const char Val[]) : Value(Val) {}
     41 
     42   bool operator==(const StringValue &Other) const {
     43     return Value == Other.Value;
     44   }
     45 };
     46 
     47 template <> struct ScalarTraits<StringValue> {
     48   static void output(const StringValue &S, void *, raw_ostream &OS) {
     49     OS << S.Value;
     50   }
     51 
     52   static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) {
     53     S.Value = Scalar.str();
     54     if (const auto *Node =
     55             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
     56       S.SourceRange = Node->getSourceRange();
     57     return "";
     58   }
     59 
     60   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
     61 };
     62 
     63 struct FlowStringValue : StringValue {
     64   FlowStringValue() = default;
     65   FlowStringValue(std::string Value) : StringValue(std::move(Value)) {}
     66 };
     67 
     68 template <> struct ScalarTraits<FlowStringValue> {
     69   static void output(const FlowStringValue &S, void *, raw_ostream &OS) {
     70     return ScalarTraits<StringValue>::output(S, nullptr, OS);
     71   }
     72 
     73   static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) {
     74     return ScalarTraits<StringValue>::input(Scalar, Ctx, S);
     75   }
     76 
     77   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
     78 };
     79 
     80 struct BlockStringValue {
     81   StringValue Value;
     82 
     83   bool operator==(const BlockStringValue &Other) const {
     84     return Value == Other.Value;
     85   }
     86 };
     87 
     88 template <> struct BlockScalarTraits<BlockStringValue> {
     89   static void output(const BlockStringValue &S, void *Ctx, raw_ostream &OS) {
     90     return ScalarTraits<StringValue>::output(S.Value, Ctx, OS);
     91   }
     92 
     93   static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) {
     94     return ScalarTraits<StringValue>::input(Scalar, Ctx, S.Value);
     95   }
     96 };
     97 
     98 /// A wrapper around unsigned which contains a source range that's being set
     99 /// during parsing.
    100 struct UnsignedValue {
    101   unsigned Value = 0;
    102   SMRange SourceRange;
    103 
    104   UnsignedValue() = default;
    105   UnsignedValue(unsigned Value) : Value(Value) {}
    106 
    107   bool operator==(const UnsignedValue &Other) const {
    108     return Value == Other.Value;
    109   }
    110 };
    111 
    112 template <> struct ScalarTraits<UnsignedValue> {
    113   static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) {
    114     return ScalarTraits<unsigned>::output(Value.Value, Ctx, OS);
    115   }
    116 
    117   static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) {
    118     if (const auto *Node =
    119             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
    120       Value.SourceRange = Node->getSourceRange();
    121     return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value);
    122   }
    123 
    124   static QuotingType mustQuote(StringRef Scalar) {
    125     return ScalarTraits<unsigned>::mustQuote(Scalar);
    126   }
    127 };
    128 
    129 template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> {
    130   static void enumeration(yaml::IO &IO,
    131                           MachineJumpTableInfo::JTEntryKind &EntryKind) {
    132     IO.enumCase(EntryKind, "block-address",
    133                 MachineJumpTableInfo::EK_BlockAddress);
    134     IO.enumCase(EntryKind, "gp-rel64-block-address",
    135                 MachineJumpTableInfo::EK_GPRel64BlockAddress);
    136     IO.enumCase(EntryKind, "gp-rel32-block-address",
    137                 MachineJumpTableInfo::EK_GPRel32BlockAddress);
    138     IO.enumCase(EntryKind, "label-difference32",
    139                 MachineJumpTableInfo::EK_LabelDifference32);
    140     IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline);
    141     IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32);
    142   }
    143 };
    144 
    145 template <> struct ScalarTraits<MaybeAlign> {
    146   static void output(const MaybeAlign &Alignment, void *,
    147                      llvm::raw_ostream &out) {
    148     out << uint64_t(Alignment ? Alignment->value() : 0U);
    149   }
    150   static StringRef input(StringRef Scalar, void *, MaybeAlign &Alignment) {
    151     unsigned long long n;
    152     if (getAsUnsignedInteger(Scalar, 10, n))
    153       return "invalid number";
    154     if (n > 0 && !isPowerOf2_64(n))
    155       return "must be 0 or a power of two";
    156     Alignment = MaybeAlign(n);
    157     return StringRef();
    158   }
    159   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    160 };
    161 
    162 template <> struct ScalarTraits<Align> {
    163   static void output(const Align &Alignment, void *, llvm::raw_ostream &OS) {
    164     OS << Alignment.value();
    165   }
    166   static StringRef input(StringRef Scalar, void *, Align &Alignment) {
    167     unsigned long long N;
    168     if (getAsUnsignedInteger(Scalar, 10, N))
    169       return "invalid number";
    170     if (!isPowerOf2_64(N))
    171       return "must be a power of two";
    172     Alignment = Align(N);
    173     return StringRef();
    174   }
    175   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
    176 };
    177 
    178 } // end namespace yaml
    179 } // end namespace llvm
    180 
    181 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
    182 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
    183 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
    184 
    185 namespace llvm {
    186 namespace yaml {
    187 
    188 struct VirtualRegisterDefinition {
    189   UnsignedValue ID;
    190   StringValue Class;
    191   StringValue PreferredRegister;
    192 
    193   // TODO: Serialize the target specific register hints.
    194 
    195   bool operator==(const VirtualRegisterDefinition &Other) const {
    196     return ID == Other.ID && Class == Other.Class &&
    197            PreferredRegister == Other.PreferredRegister;
    198   }
    199 };
    200 
    201 template <> struct MappingTraits<VirtualRegisterDefinition> {
    202   static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
    203     YamlIO.mapRequired("id", Reg.ID);
    204     YamlIO.mapRequired("class", Reg.Class);
    205     YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
    206                        StringValue()); // Don't print out when it's empty.
    207   }
    208 
    209   static const bool flow = true;
    210 };
    211 
    212 struct MachineFunctionLiveIn {
    213   StringValue Register;
    214   StringValue VirtualRegister;
    215 
    216   bool operator==(const MachineFunctionLiveIn &Other) const {
    217     return Register == Other.Register &&
    218            VirtualRegister == Other.VirtualRegister;
    219   }
    220 };
    221 
    222 template <> struct MappingTraits<MachineFunctionLiveIn> {
    223   static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
    224     YamlIO.mapRequired("reg", LiveIn.Register);
    225     YamlIO.mapOptional(
    226         "virtual-reg", LiveIn.VirtualRegister,
    227         StringValue()); // Don't print the virtual register when it's empty.
    228   }
    229 
    230   static const bool flow = true;
    231 };
    232 
    233 /// Serializable representation of stack object from the MachineFrameInfo class.
    234 ///
    235 /// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
    236 /// determined by the object's type and frame information flags.
    237 /// Dead stack objects aren't serialized.
    238 ///
    239 /// The 'isPreallocated' flag is determined by the local offset.
    240 struct MachineStackObject {
    241   enum ObjectType { DefaultType, SpillSlot, VariableSized };
    242   UnsignedValue ID;
    243   StringValue Name;
    244   // TODO: Serialize unnamed LLVM alloca reference.
    245   ObjectType Type = DefaultType;
    246   int64_t Offset = 0;
    247   uint64_t Size = 0;
    248   MaybeAlign Alignment = None;
    249   TargetStackID::Value StackID;
    250   StringValue CalleeSavedRegister;
    251   bool CalleeSavedRestored = true;
    252   Optional<int64_t> LocalOffset;
    253   StringValue DebugVar;
    254   StringValue DebugExpr;
    255   StringValue DebugLoc;
    256 
    257   bool operator==(const MachineStackObject &Other) const {
    258     return ID == Other.ID && Name == Other.Name && Type == Other.Type &&
    259            Offset == Other.Offset && Size == Other.Size &&
    260            Alignment == Other.Alignment &&
    261            StackID == Other.StackID &&
    262            CalleeSavedRegister == Other.CalleeSavedRegister &&
    263            CalleeSavedRestored == Other.CalleeSavedRestored &&
    264            LocalOffset == Other.LocalOffset && DebugVar == Other.DebugVar &&
    265            DebugExpr == Other.DebugExpr && DebugLoc == Other.DebugLoc;
    266   }
    267 };
    268 
    269 template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
    270   static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
    271     IO.enumCase(Type, "default", MachineStackObject::DefaultType);
    272     IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
    273     IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
    274   }
    275 };
    276 
    277 template <> struct MappingTraits<MachineStackObject> {
    278   static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
    279     YamlIO.mapRequired("id", Object.ID);
    280     YamlIO.mapOptional("name", Object.Name,
    281                        StringValue()); // Don't print out an empty name.
    282     YamlIO.mapOptional(
    283         "type", Object.Type,
    284         MachineStackObject::DefaultType); // Don't print the default type.
    285     YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
    286     if (Object.Type != MachineStackObject::VariableSized)
    287       YamlIO.mapRequired("size", Object.Size);
    288     YamlIO.mapOptional("alignment", Object.Alignment, None);
    289     YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
    290     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
    291                        StringValue()); // Don't print it out when it's empty.
    292     YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
    293                        true);
    294     YamlIO.mapOptional("local-offset", Object.LocalOffset, Optional<int64_t>());
    295     YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
    296                        StringValue()); // Don't print it out when it's empty.
    297     YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
    298                        StringValue()); // Don't print it out when it's empty.
    299     YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
    300                        StringValue()); // Don't print it out when it's empty.
    301   }
    302 
    303   static const bool flow = true;
    304 };
    305 
    306 /// Serializable representation of the fixed stack object from the
    307 /// MachineFrameInfo class.
    308 struct FixedMachineStackObject {
    309   enum ObjectType { DefaultType, SpillSlot };
    310   UnsignedValue ID;
    311   ObjectType Type = DefaultType;
    312   int64_t Offset = 0;
    313   uint64_t Size = 0;
    314   MaybeAlign Alignment = None;
    315   TargetStackID::Value StackID;
    316   bool IsImmutable = false;
    317   bool IsAliased = false;
    318   StringValue CalleeSavedRegister;
    319   bool CalleeSavedRestored = true;
    320   StringValue DebugVar;
    321   StringValue DebugExpr;
    322   StringValue DebugLoc;
    323 
    324   bool operator==(const FixedMachineStackObject &Other) const {
    325     return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
    326            Size == Other.Size && Alignment == Other.Alignment &&
    327            StackID == Other.StackID &&
    328            IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
    329            CalleeSavedRegister == Other.CalleeSavedRegister &&
    330            CalleeSavedRestored == Other.CalleeSavedRestored &&
    331            DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr
    332            && DebugLoc == Other.DebugLoc;
    333   }
    334 };
    335 
    336 template <>
    337 struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
    338   static void enumeration(yaml::IO &IO,
    339                           FixedMachineStackObject::ObjectType &Type) {
    340     IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
    341     IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
    342   }
    343 };
    344 
    345 template <>
    346 struct ScalarEnumerationTraits<TargetStackID::Value> {
    347   static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) {
    348     IO.enumCase(ID, "default", TargetStackID::Default);
    349     IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill);
    350     IO.enumCase(ID, "scalable-vector", TargetStackID::ScalableVector);
    351     IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc);
    352   }
    353 };
    354 
    355 template <> struct MappingTraits<FixedMachineStackObject> {
    356   static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
    357     YamlIO.mapRequired("id", Object.ID);
    358     YamlIO.mapOptional(
    359         "type", Object.Type,
    360         FixedMachineStackObject::DefaultType); // Don't print the default type.
    361     YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
    362     YamlIO.mapOptional("size", Object.Size, (uint64_t)0);
    363     YamlIO.mapOptional("alignment", Object.Alignment, None);
    364     YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
    365     if (Object.Type != FixedMachineStackObject::SpillSlot) {
    366       YamlIO.mapOptional("isImmutable", Object.IsImmutable, false);
    367       YamlIO.mapOptional("isAliased", Object.IsAliased, false);
    368     }
    369     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
    370                        StringValue()); // Don't print it out when it's empty.
    371     YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
    372                      true);
    373     YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
    374                        StringValue()); // Don't print it out when it's empty.
    375     YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
    376                        StringValue()); // Don't print it out when it's empty.
    377     YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
    378                        StringValue()); // Don't print it out when it's empty.
    379   }
    380 
    381   static const bool flow = true;
    382 };
    383 
    384 /// A serializaable representation of a reference to a stack object or fixed
    385 /// stack object.
    386 struct FrameIndex {
    387   // The frame index as printed. This is always a positive number, even for
    388   // fixed objects. To obtain the real index,
    389   // MachineFrameInfo::getObjectIndexBegin has to be added.
    390   int FI;
    391   bool IsFixed;
    392   SMRange SourceRange;
    393 
    394   FrameIndex() {}
    395   FrameIndex(int FI, const llvm::MachineFrameInfo &MFI);
    396 
    397   Expected<int> getFI(const llvm::MachineFrameInfo &MFI) const;
    398 };
    399 
    400 template <> struct ScalarTraits<FrameIndex> {
    401   static void output(const FrameIndex &FI, void *, raw_ostream &OS) {
    402     MachineOperand::printStackObjectReference(OS, FI.FI, FI.IsFixed, "");
    403   }
    404 
    405   static StringRef input(StringRef Scalar, void *Ctx, FrameIndex &FI) {
    406     FI.IsFixed = false;
    407     StringRef Num;
    408     if (Scalar.startswith("%stack.")) {
    409       Num = Scalar.substr(7);
    410     } else if (Scalar.startswith("%fixed-stack.")) {
    411       Num = Scalar.substr(13);
    412       FI.IsFixed = true;
    413     } else {
    414       return "Invalid frame index, needs to start with %stack. or "
    415              "%fixed-stack.";
    416     }
    417     if (Num.consumeInteger(10, FI.FI))
    418       return "Invalid frame index, not a valid number";
    419 
    420     if (const auto *Node =
    421             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
    422       FI.SourceRange = Node->getSourceRange();
    423     return StringRef();
    424   }
    425 
    426   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
    427 };
    428 
    429 /// Serializable representation of CallSiteInfo.
    430 struct CallSiteInfo {
    431   // Representation of call argument and register which is used to
    432   // transfer it.
    433   struct ArgRegPair {
    434     StringValue Reg;
    435     uint16_t ArgNo;
    436 
    437     bool operator==(const ArgRegPair &Other) const {
    438       return Reg == Other.Reg && ArgNo == Other.ArgNo;
    439     }
    440   };
    441 
    442   /// Identifies call instruction location in machine function.
    443   struct MachineInstrLoc {
    444     unsigned BlockNum;
    445     unsigned Offset;
    446 
    447     bool operator==(const MachineInstrLoc &Other) const {
    448       return BlockNum == Other.BlockNum && Offset == Other.Offset;
    449     }
    450   };
    451 
    452   MachineInstrLoc CallLocation;
    453   std::vector<ArgRegPair> ArgForwardingRegs;
    454 
    455   bool operator==(const CallSiteInfo &Other) const {
    456     return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
    457            CallLocation.Offset == Other.CallLocation.Offset;
    458   }
    459 };
    460 
    461 template <> struct MappingTraits<CallSiteInfo::ArgRegPair> {
    462   static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) {
    463     YamlIO.mapRequired("arg", ArgReg.ArgNo);
    464     YamlIO.mapRequired("reg", ArgReg.Reg);
    465   }
    466 
    467   static const bool flow = true;
    468 };
    469 }
    470 }
    471 
    472 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair)
    473 
    474 namespace llvm {
    475 namespace yaml {
    476 
    477 template <> struct MappingTraits<CallSiteInfo> {
    478   static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) {
    479     YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum);
    480     YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
    481     YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
    482                        std::vector<CallSiteInfo::ArgRegPair>());
    483   }
    484 
    485   static const bool flow = true;
    486 };
    487 
    488 /// Serializable representation of debug value substitutions.
    489 struct DebugValueSubstitution {
    490   unsigned SrcInst;
    491   unsigned SrcOp;
    492   unsigned DstInst;
    493   unsigned DstOp;
    494 
    495   bool operator==(const DebugValueSubstitution &Other) const {
    496     return std::tie(SrcInst, SrcOp, DstInst, DstOp) ==
    497            std::tie(Other.SrcInst, Other.SrcOp, Other.DstInst, Other.DstOp);
    498   }
    499 };
    500 
    501 template <> struct MappingTraits<DebugValueSubstitution> {
    502   static void mapping(IO &YamlIO, DebugValueSubstitution &Sub) {
    503     YamlIO.mapRequired("srcinst", Sub.SrcInst);
    504     YamlIO.mapRequired("srcop", Sub.SrcOp);
    505     YamlIO.mapRequired("dstinst", Sub.DstInst);
    506     YamlIO.mapRequired("dstop", Sub.DstOp);
    507   }
    508 
    509   static const bool flow = true;
    510 };
    511 } // namespace yaml
    512 } // namespace llvm
    513 
    514 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::DebugValueSubstitution)
    515 
    516 namespace llvm {
    517 namespace yaml {
    518 struct MachineConstantPoolValue {
    519   UnsignedValue ID;
    520   StringValue Value;
    521   MaybeAlign Alignment = None;
    522   bool IsTargetSpecific = false;
    523 
    524   bool operator==(const MachineConstantPoolValue &Other) const {
    525     return ID == Other.ID && Value == Other.Value &&
    526            Alignment == Other.Alignment &&
    527            IsTargetSpecific == Other.IsTargetSpecific;
    528   }
    529 };
    530 
    531 template <> struct MappingTraits<MachineConstantPoolValue> {
    532   static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
    533     YamlIO.mapRequired("id", Constant.ID);
    534     YamlIO.mapOptional("value", Constant.Value, StringValue());
    535     YamlIO.mapOptional("alignment", Constant.Alignment, None);
    536     YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false);
    537   }
    538 };
    539 
    540 struct MachineJumpTable {
    541   struct Entry {
    542     UnsignedValue ID;
    543     std::vector<FlowStringValue> Blocks;
    544 
    545     bool operator==(const Entry &Other) const {
    546       return ID == Other.ID && Blocks == Other.Blocks;
    547     }
    548   };
    549 
    550   MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
    551   std::vector<Entry> Entries;
    552 
    553   bool operator==(const MachineJumpTable &Other) const {
    554     return Kind == Other.Kind && Entries == Other.Entries;
    555   }
    556 };
    557 
    558 template <> struct MappingTraits<MachineJumpTable::Entry> {
    559   static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
    560     YamlIO.mapRequired("id", Entry.ID);
    561     YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>());
    562   }
    563 };
    564 
    565 } // end namespace yaml
    566 } // end namespace llvm
    567 
    568 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
    569 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
    570 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
    571 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
    572 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo)
    573 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
    574 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
    575 
    576 namespace llvm {
    577 namespace yaml {
    578 
    579 template <> struct MappingTraits<MachineJumpTable> {
    580   static void mapping(IO &YamlIO, MachineJumpTable &JT) {
    581     YamlIO.mapRequired("kind", JT.Kind);
    582     YamlIO.mapOptional("entries", JT.Entries,
    583                        std::vector<MachineJumpTable::Entry>());
    584   }
    585 };
    586 
    587 /// Serializable representation of MachineFrameInfo.
    588 ///
    589 /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
    590 /// 'RealignOption' as they are determined by the target and LLVM function
    591 /// attributes.
    592 /// It also doesn't serialize attributes like 'NumFixedObject' and
    593 /// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
    594 struct MachineFrameInfo {
    595   bool IsFrameAddressTaken = false;
    596   bool IsReturnAddressTaken = false;
    597   bool HasStackMap = false;
    598   bool HasPatchPoint = false;
    599   uint64_t StackSize = 0;
    600   int OffsetAdjustment = 0;
    601   unsigned MaxAlignment = 0;
    602   bool AdjustsStack = false;
    603   bool HasCalls = false;
    604   StringValue StackProtector;
    605   // TODO: Serialize FunctionContextIdx
    606   unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
    607   unsigned CVBytesOfCalleeSavedRegisters = 0;
    608   bool HasOpaqueSPAdjustment = false;
    609   bool HasVAStart = false;
    610   bool HasMustTailInVarArgFunc = false;
    611   bool HasTailCall = false;
    612   unsigned LocalFrameSize = 0;
    613   StringValue SavePoint;
    614   StringValue RestorePoint;
    615 
    616   bool operator==(const MachineFrameInfo &Other) const {
    617     return IsFrameAddressTaken == Other.IsFrameAddressTaken &&
    618            IsReturnAddressTaken == Other.IsReturnAddressTaken &&
    619            HasStackMap == Other.HasStackMap &&
    620            HasPatchPoint == Other.HasPatchPoint &&
    621            StackSize == Other.StackSize &&
    622            OffsetAdjustment == Other.OffsetAdjustment &&
    623            MaxAlignment == Other.MaxAlignment &&
    624            AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
    625            StackProtector == Other.StackProtector &&
    626            MaxCallFrameSize == Other.MaxCallFrameSize &&
    627            CVBytesOfCalleeSavedRegisters ==
    628                Other.CVBytesOfCalleeSavedRegisters &&
    629            HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
    630            HasVAStart == Other.HasVAStart &&
    631            HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
    632            HasTailCall == Other.HasTailCall &&
    633            LocalFrameSize == Other.LocalFrameSize &&
    634            SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint;
    635   }
    636 };
    637 
    638 template <> struct MappingTraits<MachineFrameInfo> {
    639   static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
    640     YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false);
    641     YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false);
    642     YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false);
    643     YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false);
    644     YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0);
    645     YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0);
    646     YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
    647     YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
    648     YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
    649     YamlIO.mapOptional("stackProtector", MFI.StackProtector,
    650                        StringValue()); // Don't print it out when it's empty.
    651     YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0);
    652     YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters",
    653                        MFI.CVBytesOfCalleeSavedRegisters, 0U);
    654     YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,
    655                        false);
    656     YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
    657     YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
    658                        false);
    659     YamlIO.mapOptional("hasTailCall", MFI.HasTailCall, false);
    660     YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0);
    661     YamlIO.mapOptional("savePoint", MFI.SavePoint,
    662                        StringValue()); // Don't print it out when it's empty.
    663     YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
    664                        StringValue()); // Don't print it out when it's empty.
    665   }
    666 };
    667 
    668 /// Targets should override this in a way that mirrors the implementation of
    669 /// llvm::MachineFunctionInfo.
    670 struct MachineFunctionInfo {
    671   virtual ~MachineFunctionInfo() {}
    672   virtual void mappingImpl(IO &YamlIO) {}
    673 };
    674 
    675 template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
    676   static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
    677     if (MFI)
    678       MFI->mappingImpl(YamlIO);
    679   }
    680 };
    681 
    682 struct MachineFunction {
    683   StringRef Name;
    684   MaybeAlign Alignment = None;
    685   bool ExposesReturnsTwice = false;
    686   // GISel MachineFunctionProperties.
    687   bool Legalized = false;
    688   bool RegBankSelected = false;
    689   bool Selected = false;
    690   bool FailedISel = false;
    691   // Register information
    692   bool TracksRegLiveness = false;
    693   bool HasWinCFI = false;
    694   std::vector<VirtualRegisterDefinition> VirtualRegisters;
    695   std::vector<MachineFunctionLiveIn> LiveIns;
    696   Optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
    697   // TODO: Serialize the various register masks.
    698   // Frame information
    699   MachineFrameInfo FrameInfo;
    700   std::vector<FixedMachineStackObject> FixedStackObjects;
    701   std::vector<MachineStackObject> StackObjects;
    702   std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
    703   std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
    704   std::vector<CallSiteInfo> CallSitesInfo;
    705   std::vector<DebugValueSubstitution> DebugValueSubstitutions;
    706   MachineJumpTable JumpTableInfo;
    707   BlockStringValue Body;
    708 };
    709 
    710 template <> struct MappingTraits<MachineFunction> {
    711   static void mapping(IO &YamlIO, MachineFunction &MF) {
    712     YamlIO.mapRequired("name", MF.Name);
    713     YamlIO.mapOptional("alignment", MF.Alignment, None);
    714     YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false);
    715     YamlIO.mapOptional("legalized", MF.Legalized, false);
    716     YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
    717     YamlIO.mapOptional("selected", MF.Selected, false);
    718     YamlIO.mapOptional("failedISel", MF.FailedISel, false);
    719     YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
    720     YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false);
    721     YamlIO.mapOptional("registers", MF.VirtualRegisters,
    722                        std::vector<VirtualRegisterDefinition>());
    723     YamlIO.mapOptional("liveins", MF.LiveIns,
    724                        std::vector<MachineFunctionLiveIn>());
    725     YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters,
    726                        Optional<std::vector<FlowStringValue>>());
    727     YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo());
    728     YamlIO.mapOptional("fixedStack", MF.FixedStackObjects,
    729                        std::vector<FixedMachineStackObject>());
    730     YamlIO.mapOptional("stack", MF.StackObjects,
    731                        std::vector<MachineStackObject>());
    732     YamlIO.mapOptional("callSites", MF.CallSitesInfo,
    733                        std::vector<CallSiteInfo>());
    734     YamlIO.mapOptional("debugValueSubstitutions", MF.DebugValueSubstitutions,
    735                        std::vector<DebugValueSubstitution>());
    736     YamlIO.mapOptional("constants", MF.Constants,
    737                        std::vector<MachineConstantPoolValue>());
    738     YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
    739     if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
    740       YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
    741     YamlIO.mapOptional("body", MF.Body, BlockStringValue());
    742   }
    743 };
    744 
    745 } // end namespace yaml
    746 } // end namespace llvm
    747 
    748 #endif // LLVM_CODEGEN_MIRYAMLMAPPING_H
    749