Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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/StringRef.h"
  18. #include "llvm/CodeGen/MachineJumpTableInfo.h"
  19. #include "llvm/CodeGen/TargetFrameLowering.h"
  20. #include "llvm/Support/SMLoc.h"
  21. #include "llvm/Support/YAMLTraits.h"
  22. #include "llvm/Support/raw_ostream.h"
  23. #include <algorithm>
  24. #include <cstdint>
  25. #include <optional>
  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 = std::nullopt;
  249.   TargetStackID::Value StackID;
  250.   StringValue CalleeSavedRegister;
  251.   bool CalleeSavedRestored = true;
  252.   std::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, std::nullopt);
  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,
  295.                        std::optional<int64_t>());
  296.     YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
  297.                        StringValue()); // Don't print it out when it's empty.
  298.     YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
  299.                        StringValue()); // Don't print it out when it's empty.
  300.     YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
  301.                        StringValue()); // Don't print it out when it's empty.
  302.   }
  303.  
  304.   static const bool flow = true;
  305. };
  306.  
  307. /// Serializable representation of the fixed stack object from the
  308. /// MachineFrameInfo class.
  309. struct FixedMachineStackObject {
  310.   enum ObjectType { DefaultType, SpillSlot };
  311.   UnsignedValue ID;
  312.   ObjectType Type = DefaultType;
  313.   int64_t Offset = 0;
  314.   uint64_t Size = 0;
  315.   MaybeAlign Alignment = std::nullopt;
  316.   TargetStackID::Value StackID;
  317.   bool IsImmutable = false;
  318.   bool IsAliased = false;
  319.   StringValue CalleeSavedRegister;
  320.   bool CalleeSavedRestored = true;
  321.   StringValue DebugVar;
  322.   StringValue DebugExpr;
  323.   StringValue DebugLoc;
  324.  
  325.   bool operator==(const FixedMachineStackObject &Other) const {
  326.     return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
  327.            Size == Other.Size && Alignment == Other.Alignment &&
  328.            StackID == Other.StackID &&
  329.            IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
  330.            CalleeSavedRegister == Other.CalleeSavedRegister &&
  331.            CalleeSavedRestored == Other.CalleeSavedRestored &&
  332.            DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr
  333.            && DebugLoc == Other.DebugLoc;
  334.   }
  335. };
  336.  
  337. template <>
  338. struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
  339.   static void enumeration(yaml::IO &IO,
  340.                           FixedMachineStackObject::ObjectType &Type) {
  341.     IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
  342.     IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
  343.   }
  344. };
  345.  
  346. template <>
  347. struct ScalarEnumerationTraits<TargetStackID::Value> {
  348.   static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) {
  349.     IO.enumCase(ID, "default", TargetStackID::Default);
  350.     IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill);
  351.     IO.enumCase(ID, "scalable-vector", TargetStackID::ScalableVector);
  352.     IO.enumCase(ID, "wasm-local", TargetStackID::WasmLocal);
  353.     IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc);
  354.   }
  355. };
  356.  
  357. template <> struct MappingTraits<FixedMachineStackObject> {
  358.   static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
  359.     YamlIO.mapRequired("id", Object.ID);
  360.     YamlIO.mapOptional(
  361.         "type", Object.Type,
  362.         FixedMachineStackObject::DefaultType); // Don't print the default type.
  363.     YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
  364.     YamlIO.mapOptional("size", Object.Size, (uint64_t)0);
  365.     YamlIO.mapOptional("alignment", Object.Alignment, std::nullopt);
  366.     YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
  367.     if (Object.Type != FixedMachineStackObject::SpillSlot) {
  368.       YamlIO.mapOptional("isImmutable", Object.IsImmutable, false);
  369.       YamlIO.mapOptional("isAliased", Object.IsAliased, false);
  370.     }
  371.     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
  372.                        StringValue()); // Don't print it out when it's empty.
  373.     YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
  374.                      true);
  375.     YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
  376.                        StringValue()); // Don't print it out when it's empty.
  377.     YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
  378.                        StringValue()); // Don't print it out when it's empty.
  379.     YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
  380.                        StringValue()); // Don't print it out when it's empty.
  381.   }
  382.  
  383.   static const bool flow = true;
  384. };
  385.  
  386. /// A serializaable representation of a reference to a stack object or fixed
  387. /// stack object.
  388. struct FrameIndex {
  389.   // The frame index as printed. This is always a positive number, even for
  390.   // fixed objects. To obtain the real index,
  391.   // MachineFrameInfo::getObjectIndexBegin has to be added.
  392.   int FI;
  393.   bool IsFixed;
  394.   SMRange SourceRange;
  395.  
  396.   FrameIndex() = default;
  397.   FrameIndex(int FI, const llvm::MachineFrameInfo &MFI);
  398.  
  399.   Expected<int> getFI(const llvm::MachineFrameInfo &MFI) const;
  400. };
  401.  
  402. template <> struct ScalarTraits<FrameIndex> {
  403.   static void output(const FrameIndex &FI, void *, raw_ostream &OS) {
  404.     MachineOperand::printStackObjectReference(OS, FI.FI, FI.IsFixed, "");
  405.   }
  406.  
  407.   static StringRef input(StringRef Scalar, void *Ctx, FrameIndex &FI) {
  408.     FI.IsFixed = false;
  409.     StringRef Num;
  410.     if (Scalar.startswith("%stack.")) {
  411.       Num = Scalar.substr(7);
  412.     } else if (Scalar.startswith("%fixed-stack.")) {
  413.       Num = Scalar.substr(13);
  414.       FI.IsFixed = true;
  415.     } else {
  416.       return "Invalid frame index, needs to start with %stack. or "
  417.              "%fixed-stack.";
  418.     }
  419.     if (Num.consumeInteger(10, FI.FI))
  420.       return "Invalid frame index, not a valid number";
  421.  
  422.     if (const auto *Node =
  423.             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
  424.       FI.SourceRange = Node->getSourceRange();
  425.     return StringRef();
  426.   }
  427.  
  428.   static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  429. };
  430.  
  431. /// Serializable representation of CallSiteInfo.
  432. struct CallSiteInfo {
  433.   // Representation of call argument and register which is used to
  434.   // transfer it.
  435.   struct ArgRegPair {
  436.     StringValue Reg;
  437.     uint16_t ArgNo;
  438.  
  439.     bool operator==(const ArgRegPair &Other) const {
  440.       return Reg == Other.Reg && ArgNo == Other.ArgNo;
  441.     }
  442.   };
  443.  
  444.   /// Identifies call instruction location in machine function.
  445.   struct MachineInstrLoc {
  446.     unsigned BlockNum;
  447.     unsigned Offset;
  448.  
  449.     bool operator==(const MachineInstrLoc &Other) const {
  450.       return BlockNum == Other.BlockNum && Offset == Other.Offset;
  451.     }
  452.   };
  453.  
  454.   MachineInstrLoc CallLocation;
  455.   std::vector<ArgRegPair> ArgForwardingRegs;
  456.  
  457.   bool operator==(const CallSiteInfo &Other) const {
  458.     return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
  459.            CallLocation.Offset == Other.CallLocation.Offset;
  460.   }
  461. };
  462.  
  463. template <> struct MappingTraits<CallSiteInfo::ArgRegPair> {
  464.   static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) {
  465.     YamlIO.mapRequired("arg", ArgReg.ArgNo);
  466.     YamlIO.mapRequired("reg", ArgReg.Reg);
  467.   }
  468.  
  469.   static const bool flow = true;
  470. };
  471. }
  472. }
  473.  
  474. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair)
  475.  
  476. namespace llvm {
  477. namespace yaml {
  478.  
  479. template <> struct MappingTraits<CallSiteInfo> {
  480.   static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) {
  481.     YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum);
  482.     YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
  483.     YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
  484.                        std::vector<CallSiteInfo::ArgRegPair>());
  485.   }
  486.  
  487.   static const bool flow = true;
  488. };
  489.  
  490. /// Serializable representation of debug value substitutions.
  491. struct DebugValueSubstitution {
  492.   unsigned SrcInst;
  493.   unsigned SrcOp;
  494.   unsigned DstInst;
  495.   unsigned DstOp;
  496.   unsigned Subreg;
  497.  
  498.   bool operator==(const DebugValueSubstitution &Other) const {
  499.     return std::tie(SrcInst, SrcOp, DstInst, DstOp) ==
  500.            std::tie(Other.SrcInst, Other.SrcOp, Other.DstInst, Other.DstOp);
  501.   }
  502. };
  503.  
  504. template <> struct MappingTraits<DebugValueSubstitution> {
  505.   static void mapping(IO &YamlIO, DebugValueSubstitution &Sub) {
  506.     YamlIO.mapRequired("srcinst", Sub.SrcInst);
  507.     YamlIO.mapRequired("srcop", Sub.SrcOp);
  508.     YamlIO.mapRequired("dstinst", Sub.DstInst);
  509.     YamlIO.mapRequired("dstop", Sub.DstOp);
  510.     YamlIO.mapRequired("subreg", Sub.Subreg);
  511.   }
  512.  
  513.   static const bool flow = true;
  514. };
  515. } // namespace yaml
  516. } // namespace llvm
  517.  
  518. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::DebugValueSubstitution)
  519.  
  520. namespace llvm {
  521. namespace yaml {
  522. struct MachineConstantPoolValue {
  523.   UnsignedValue ID;
  524.   StringValue Value;
  525.   MaybeAlign Alignment = std::nullopt;
  526.   bool IsTargetSpecific = false;
  527.  
  528.   bool operator==(const MachineConstantPoolValue &Other) const {
  529.     return ID == Other.ID && Value == Other.Value &&
  530.            Alignment == Other.Alignment &&
  531.            IsTargetSpecific == Other.IsTargetSpecific;
  532.   }
  533. };
  534.  
  535. template <> struct MappingTraits<MachineConstantPoolValue> {
  536.   static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
  537.     YamlIO.mapRequired("id", Constant.ID);
  538.     YamlIO.mapOptional("value", Constant.Value, StringValue());
  539.     YamlIO.mapOptional("alignment", Constant.Alignment, std::nullopt);
  540.     YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false);
  541.   }
  542. };
  543.  
  544. struct MachineJumpTable {
  545.   struct Entry {
  546.     UnsignedValue ID;
  547.     std::vector<FlowStringValue> Blocks;
  548.  
  549.     bool operator==(const Entry &Other) const {
  550.       return ID == Other.ID && Blocks == Other.Blocks;
  551.     }
  552.   };
  553.  
  554.   MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
  555.   std::vector<Entry> Entries;
  556.  
  557.   bool operator==(const MachineJumpTable &Other) const {
  558.     return Kind == Other.Kind && Entries == Other.Entries;
  559.   }
  560. };
  561.  
  562. template <> struct MappingTraits<MachineJumpTable::Entry> {
  563.   static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
  564.     YamlIO.mapRequired("id", Entry.ID);
  565.     YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>());
  566.   }
  567. };
  568.  
  569. } // end namespace yaml
  570. } // end namespace llvm
  571.  
  572. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
  573. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
  574. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
  575. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
  576. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo)
  577. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
  578. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
  579.  
  580. namespace llvm {
  581. namespace yaml {
  582.  
  583. template <> struct MappingTraits<MachineJumpTable> {
  584.   static void mapping(IO &YamlIO, MachineJumpTable &JT) {
  585.     YamlIO.mapRequired("kind", JT.Kind);
  586.     YamlIO.mapOptional("entries", JT.Entries,
  587.                        std::vector<MachineJumpTable::Entry>());
  588.   }
  589. };
  590.  
  591. /// Serializable representation of MachineFrameInfo.
  592. ///
  593. /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
  594. /// 'RealignOption' as they are determined by the target and LLVM function
  595. /// attributes.
  596. /// It also doesn't serialize attributes like 'NumFixedObject' and
  597. /// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
  598. struct MachineFrameInfo {
  599.   bool IsFrameAddressTaken = false;
  600.   bool IsReturnAddressTaken = false;
  601.   bool HasStackMap = false;
  602.   bool HasPatchPoint = false;
  603.   uint64_t StackSize = 0;
  604.   int OffsetAdjustment = 0;
  605.   unsigned MaxAlignment = 0;
  606.   bool AdjustsStack = false;
  607.   bool HasCalls = false;
  608.   StringValue StackProtector;
  609.   StringValue FunctionContext;
  610.   unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
  611.   unsigned CVBytesOfCalleeSavedRegisters = 0;
  612.   bool HasOpaqueSPAdjustment = false;
  613.   bool HasVAStart = false;
  614.   bool HasMustTailInVarArgFunc = false;
  615.   bool HasTailCall = false;
  616.   unsigned LocalFrameSize = 0;
  617.   StringValue SavePoint;
  618.   StringValue RestorePoint;
  619.  
  620.   bool operator==(const MachineFrameInfo &Other) const {
  621.     return IsFrameAddressTaken == Other.IsFrameAddressTaken &&
  622.            IsReturnAddressTaken == Other.IsReturnAddressTaken &&
  623.            HasStackMap == Other.HasStackMap &&
  624.            HasPatchPoint == Other.HasPatchPoint &&
  625.            StackSize == Other.StackSize &&
  626.            OffsetAdjustment == Other.OffsetAdjustment &&
  627.            MaxAlignment == Other.MaxAlignment &&
  628.            AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
  629.            StackProtector == Other.StackProtector &&
  630.            FunctionContext == Other.FunctionContext &&
  631.            MaxCallFrameSize == Other.MaxCallFrameSize &&
  632.            CVBytesOfCalleeSavedRegisters ==
  633.                Other.CVBytesOfCalleeSavedRegisters &&
  634.            HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
  635.            HasVAStart == Other.HasVAStart &&
  636.            HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
  637.            HasTailCall == Other.HasTailCall &&
  638.            LocalFrameSize == Other.LocalFrameSize &&
  639.            SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint;
  640.   }
  641. };
  642.  
  643. template <> struct MappingTraits<MachineFrameInfo> {
  644.   static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
  645.     YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false);
  646.     YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false);
  647.     YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false);
  648.     YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false);
  649.     YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0);
  650.     YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0);
  651.     YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
  652.     YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
  653.     YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
  654.     YamlIO.mapOptional("stackProtector", MFI.StackProtector,
  655.                        StringValue()); // Don't print it out when it's empty.
  656.     YamlIO.mapOptional("functionContext", MFI.FunctionContext,
  657.                        StringValue()); // Don't print it out when it's empty.
  658.     YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0);
  659.     YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters",
  660.                        MFI.CVBytesOfCalleeSavedRegisters, 0U);
  661.     YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,
  662.                        false);
  663.     YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
  664.     YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
  665.                        false);
  666.     YamlIO.mapOptional("hasTailCall", MFI.HasTailCall, false);
  667.     YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0);
  668.     YamlIO.mapOptional("savePoint", MFI.SavePoint,
  669.                        StringValue()); // Don't print it out when it's empty.
  670.     YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
  671.                        StringValue()); // Don't print it out when it's empty.
  672.   }
  673. };
  674.  
  675. /// Targets should override this in a way that mirrors the implementation of
  676. /// llvm::MachineFunctionInfo.
  677. struct MachineFunctionInfo {
  678.   virtual ~MachineFunctionInfo() = default;
  679.   virtual void mappingImpl(IO &YamlIO) {}
  680. };
  681.  
  682. template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
  683.   static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
  684.     if (MFI)
  685.       MFI->mappingImpl(YamlIO);
  686.   }
  687. };
  688.  
  689. struct MachineFunction {
  690.   StringRef Name;
  691.   MaybeAlign Alignment = std::nullopt;
  692.   bool ExposesReturnsTwice = false;
  693.   // GISel MachineFunctionProperties.
  694.   bool Legalized = false;
  695.   bool RegBankSelected = false;
  696.   bool Selected = false;
  697.   bool FailedISel = false;
  698.   // Register information
  699.   bool TracksRegLiveness = false;
  700.   bool HasWinCFI = false;
  701.  
  702.   bool CallsEHReturn = false;
  703.   bool CallsUnwindInit = false;
  704.   bool HasEHCatchret = false;
  705.   bool HasEHScopes = false;
  706.   bool HasEHFunclets = false;
  707.  
  708.   bool FailsVerification = false;
  709.   bool TracksDebugUserValues = false;
  710.   bool UseDebugInstrRef = false;
  711.   std::vector<VirtualRegisterDefinition> VirtualRegisters;
  712.   std::vector<MachineFunctionLiveIn> LiveIns;
  713.   std::optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
  714.   // TODO: Serialize the various register masks.
  715.   // Frame information
  716.   MachineFrameInfo FrameInfo;
  717.   std::vector<FixedMachineStackObject> FixedStackObjects;
  718.   std::vector<MachineStackObject> StackObjects;
  719.   std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
  720.   std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
  721.   std::vector<CallSiteInfo> CallSitesInfo;
  722.   std::vector<DebugValueSubstitution> DebugValueSubstitutions;
  723.   MachineJumpTable JumpTableInfo;
  724.   std::vector<StringValue> MachineMetadataNodes;
  725.   BlockStringValue Body;
  726. };
  727.  
  728. template <> struct MappingTraits<MachineFunction> {
  729.   static void mapping(IO &YamlIO, MachineFunction &MF) {
  730.     YamlIO.mapRequired("name", MF.Name);
  731.     YamlIO.mapOptional("alignment", MF.Alignment, std::nullopt);
  732.     YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false);
  733.     YamlIO.mapOptional("legalized", MF.Legalized, false);
  734.     YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
  735.     YamlIO.mapOptional("selected", MF.Selected, false);
  736.     YamlIO.mapOptional("failedISel", MF.FailedISel, false);
  737.     YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
  738.     YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false);
  739.  
  740.     YamlIO.mapOptional("callsEHReturn", MF.CallsEHReturn, false);
  741.     YamlIO.mapOptional("callsUnwindInit", MF.CallsUnwindInit, false);
  742.     YamlIO.mapOptional("hasEHCatchret", MF.HasEHCatchret, false);
  743.     YamlIO.mapOptional("hasEHScopes", MF.HasEHScopes, false);
  744.     YamlIO.mapOptional("hasEHFunclets", MF.HasEHFunclets, false);
  745.     YamlIO.mapOptional("debugInstrRef", MF.UseDebugInstrRef, false);
  746.  
  747.     YamlIO.mapOptional("failsVerification", MF.FailsVerification, false);
  748.     YamlIO.mapOptional("tracksDebugUserValues", MF.TracksDebugUserValues,
  749.                        false);
  750.     YamlIO.mapOptional("registers", MF.VirtualRegisters,
  751.                        std::vector<VirtualRegisterDefinition>());
  752.     YamlIO.mapOptional("liveins", MF.LiveIns,
  753.                        std::vector<MachineFunctionLiveIn>());
  754.     YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters,
  755.                        std::optional<std::vector<FlowStringValue>>());
  756.     YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo());
  757.     YamlIO.mapOptional("fixedStack", MF.FixedStackObjects,
  758.                        std::vector<FixedMachineStackObject>());
  759.     YamlIO.mapOptional("stack", MF.StackObjects,
  760.                        std::vector<MachineStackObject>());
  761.     YamlIO.mapOptional("callSites", MF.CallSitesInfo,
  762.                        std::vector<CallSiteInfo>());
  763.     YamlIO.mapOptional("debugValueSubstitutions", MF.DebugValueSubstitutions,
  764.                        std::vector<DebugValueSubstitution>());
  765.     YamlIO.mapOptional("constants", MF.Constants,
  766.                        std::vector<MachineConstantPoolValue>());
  767.     YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
  768.     if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
  769.       YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
  770.     if (!YamlIO.outputting() || !MF.MachineMetadataNodes.empty())
  771.       YamlIO.mapOptional("machineMetadataNodes", MF.MachineMetadataNodes,
  772.                          std::vector<StringValue>());
  773.     YamlIO.mapOptional("body", MF.Body, BlockStringValue());
  774.   }
  775. };
  776.  
  777. } // end namespace yaml
  778. } // end namespace llvm
  779.  
  780. #endif // LLVM_CODEGEN_MIRYAMLMAPPING_H
  781.