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;
StringValueStringValue39   StringValue(std::string Value) : Value(std::move(Value)) {}
StringValueStringValue40   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 } // end namespace yaml
163 } // end namespace llvm
164 
165 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
166 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
167 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
168 
169 namespace llvm {
170 namespace yaml {
171 
172 struct VirtualRegisterDefinition {
173   UnsignedValue ID;
174   StringValue Class;
175   StringValue PreferredRegister;
176 
177   // TODO: Serialize the target specific register hints.
178 
179   bool operator==(const VirtualRegisterDefinition &Other) const {
180     return ID == Other.ID && Class == Other.Class &&
181            PreferredRegister == Other.PreferredRegister;
182   }
183 };
184 
185 template <> struct MappingTraits<VirtualRegisterDefinition> {
186   static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
187     YamlIO.mapRequired("id", Reg.ID);
188     YamlIO.mapRequired("class", Reg.Class);
189     YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
190                        StringValue()); // Don't print out when it's empty.
191   }
192 
193   static const bool flow = true;
194 };
195 
196 struct MachineFunctionLiveIn {
197   StringValue Register;
198   StringValue VirtualRegister;
199 
200   bool operator==(const MachineFunctionLiveIn &Other) const {
201     return Register == Other.Register &&
202            VirtualRegister == Other.VirtualRegister;
203   }
204 };
205 
206 template <> struct MappingTraits<MachineFunctionLiveIn> {
207   static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
208     YamlIO.mapRequired("reg", LiveIn.Register);
209     YamlIO.mapOptional(
210         "virtual-reg", LiveIn.VirtualRegister,
211         StringValue()); // Don't print the virtual register when it's empty.
212   }
213 
214   static const bool flow = true;
215 };
216 
217 /// Serializable representation of stack object from the MachineFrameInfo class.
218 ///
219 /// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
220 /// determined by the object's type and frame information flags.
221 /// Dead stack objects aren't serialized.
222 ///
223 /// The 'isPreallocated' flag is determined by the local offset.
224 struct MachineStackObject {
225   enum ObjectType { DefaultType, SpillSlot, VariableSized };
226   UnsignedValue ID;
227   StringValue Name;
228   // TODO: Serialize unnamed LLVM alloca reference.
229   ObjectType Type = DefaultType;
230   int64_t Offset = 0;
231   uint64_t Size = 0;
232   MaybeAlign Alignment = None;
233   TargetStackID::Value StackID;
234   StringValue CalleeSavedRegister;
235   bool CalleeSavedRestored = true;
236   Optional<int64_t> LocalOffset;
237   StringValue DebugVar;
238   StringValue DebugExpr;
239   StringValue DebugLoc;
240 
241   bool operator==(const MachineStackObject &Other) const {
242     return ID == Other.ID && Name == Other.Name && Type == Other.Type &&
243            Offset == Other.Offset && Size == Other.Size &&
244            Alignment == Other.Alignment &&
245            StackID == Other.StackID &&
246            CalleeSavedRegister == Other.CalleeSavedRegister &&
247            CalleeSavedRestored == Other.CalleeSavedRestored &&
248            LocalOffset == Other.LocalOffset && DebugVar == Other.DebugVar &&
249            DebugExpr == Other.DebugExpr && DebugLoc == Other.DebugLoc;
250   }
251 };
252 
253 template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
254   static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
255     IO.enumCase(Type, "default", MachineStackObject::DefaultType);
256     IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
257     IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
258   }
259 };
260 
261 template <> struct MappingTraits<MachineStackObject> {
262   static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
263     YamlIO.mapRequired("id", Object.ID);
264     YamlIO.mapOptional("name", Object.Name,
265                        StringValue()); // Don't print out an empty name.
266     YamlIO.mapOptional(
267         "type", Object.Type,
268         MachineStackObject::DefaultType); // Don't print the default type.
269     YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
270     if (Object.Type != MachineStackObject::VariableSized)
271       YamlIO.mapRequired("size", Object.Size);
272     YamlIO.mapOptional("alignment", Object.Alignment, None);
273     YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
274     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
275                        StringValue()); // Don't print it out when it's empty.
276     YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
277                        true);
278     YamlIO.mapOptional("local-offset", Object.LocalOffset, Optional<int64_t>());
279     YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
280                        StringValue()); // Don't print it out when it's empty.
281     YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
282                        StringValue()); // Don't print it out when it's empty.
283     YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
284                        StringValue()); // Don't print it out when it's empty.
285   }
286 
287   static const bool flow = true;
288 };
289 
290 /// Serializable representation of the fixed stack object from the
291 /// MachineFrameInfo class.
292 struct FixedMachineStackObject {
293   enum ObjectType { DefaultType, SpillSlot };
294   UnsignedValue ID;
295   ObjectType Type = DefaultType;
296   int64_t Offset = 0;
297   uint64_t Size = 0;
298   MaybeAlign Alignment = None;
299   TargetStackID::Value StackID;
300   bool IsImmutable = false;
301   bool IsAliased = false;
302   StringValue CalleeSavedRegister;
303   bool CalleeSavedRestored = true;
304   StringValue DebugVar;
305   StringValue DebugExpr;
306   StringValue DebugLoc;
307 
308   bool operator==(const FixedMachineStackObject &Other) const {
309     return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
310            Size == Other.Size && Alignment == Other.Alignment &&
311            StackID == Other.StackID &&
312            IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
313            CalleeSavedRegister == Other.CalleeSavedRegister &&
314            CalleeSavedRestored == Other.CalleeSavedRestored &&
315            DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr
316            && DebugLoc == Other.DebugLoc;
317   }
318 };
319 
320 template <>
321 struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
322   static void enumeration(yaml::IO &IO,
323                           FixedMachineStackObject::ObjectType &Type) {
324     IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
325     IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
326   }
327 };
328 
329 template <>
330 struct ScalarEnumerationTraits<TargetStackID::Value> {
331   static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) {
332     IO.enumCase(ID, "default", TargetStackID::Default);
333     IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill);
334     IO.enumCase(ID, "sve-vec", TargetStackID::SVEVector);
335     IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc);
336   }
337 };
338 
339 template <> struct MappingTraits<FixedMachineStackObject> {
340   static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
341     YamlIO.mapRequired("id", Object.ID);
342     YamlIO.mapOptional(
343         "type", Object.Type,
344         FixedMachineStackObject::DefaultType); // Don't print the default type.
345     YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
346     YamlIO.mapOptional("size", Object.Size, (uint64_t)0);
347     YamlIO.mapOptional("alignment", Object.Alignment, None);
348     YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
349     if (Object.Type != FixedMachineStackObject::SpillSlot) {
350       YamlIO.mapOptional("isImmutable", Object.IsImmutable, false);
351       YamlIO.mapOptional("isAliased", Object.IsAliased, false);
352     }
353     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
354                        StringValue()); // Don't print it out when it's empty.
355     YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
356                      true);
357     YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
358                        StringValue()); // Don't print it out when it's empty.
359     YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
360                        StringValue()); // Don't print it out when it's empty.
361     YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
362                        StringValue()); // Don't print it out when it's empty.
363   }
364 
365   static const bool flow = true;
366 };
367 
368 
369 /// Serializable representation of CallSiteInfo.
370 struct CallSiteInfo {
371   // Representation of call argument and register which is used to
372   // transfer it.
373   struct ArgRegPair {
374     StringValue Reg;
375     uint16_t ArgNo;
376 
377     bool operator==(const ArgRegPair &Other) const {
378       return Reg == Other.Reg && ArgNo == Other.ArgNo;
379     }
380   };
381 
382   /// Identifies call instruction location in machine function.
383   struct MachineInstrLoc {
384     unsigned BlockNum;
385     unsigned Offset;
386 
387     bool operator==(const MachineInstrLoc &Other) const {
388       return BlockNum == Other.BlockNum && Offset == Other.Offset;
389     }
390   };
391 
392   MachineInstrLoc CallLocation;
393   std::vector<ArgRegPair> ArgForwardingRegs;
394 
395   bool operator==(const CallSiteInfo &Other) const {
396     return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
397            CallLocation.Offset == Other.CallLocation.Offset;
398   }
399 };
400 
401 template <> struct MappingTraits<CallSiteInfo::ArgRegPair> {
402   static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) {
403     YamlIO.mapRequired("arg", ArgReg.ArgNo);
404     YamlIO.mapRequired("reg", ArgReg.Reg);
405   }
406 
407   static const bool flow = true;
408 };
409 }
410 }
411 
412 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair)
413 
414 namespace llvm {
415 namespace yaml {
416 
417 template <> struct MappingTraits<CallSiteInfo> {
418   static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) {
419     YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum);
420     YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
421     YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
422                        std::vector<CallSiteInfo::ArgRegPair>());
423   }
424 
425   static const bool flow = true;
426 };
427 
428 struct MachineConstantPoolValue {
429   UnsignedValue ID;
430   StringValue Value;
431   MaybeAlign Alignment = None;
432   bool IsTargetSpecific = false;
433 
434   bool operator==(const MachineConstantPoolValue &Other) const {
435     return ID == Other.ID && Value == Other.Value &&
436            Alignment == Other.Alignment &&
437            IsTargetSpecific == Other.IsTargetSpecific;
438   }
439 };
440 
441 template <> struct MappingTraits<MachineConstantPoolValue> {
442   static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
443     YamlIO.mapRequired("id", Constant.ID);
444     YamlIO.mapOptional("value", Constant.Value, StringValue());
445     YamlIO.mapOptional("alignment", Constant.Alignment, None);
446     YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false);
447   }
448 };
449 
450 struct MachineJumpTable {
451   struct Entry {
452     UnsignedValue ID;
453     std::vector<FlowStringValue> Blocks;
454 
455     bool operator==(const Entry &Other) const {
456       return ID == Other.ID && Blocks == Other.Blocks;
457     }
458   };
459 
460   MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
461   std::vector<Entry> Entries;
462 
463   bool operator==(const MachineJumpTable &Other) const {
464     return Kind == Other.Kind && Entries == Other.Entries;
465   }
466 };
467 
468 template <> struct MappingTraits<MachineJumpTable::Entry> {
469   static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
470     YamlIO.mapRequired("id", Entry.ID);
471     YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>());
472   }
473 };
474 
475 } // end namespace yaml
476 } // end namespace llvm
477 
478 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
479 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
480 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
481 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
482 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo)
483 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
484 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
485 
486 namespace llvm {
487 namespace yaml {
488 
489 template <> struct MappingTraits<MachineJumpTable> {
490   static void mapping(IO &YamlIO, MachineJumpTable &JT) {
491     YamlIO.mapRequired("kind", JT.Kind);
492     YamlIO.mapOptional("entries", JT.Entries,
493                        std::vector<MachineJumpTable::Entry>());
494   }
495 };
496 
497 /// Serializable representation of MachineFrameInfo.
498 ///
499 /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
500 /// 'RealignOption' as they are determined by the target and LLVM function
501 /// attributes.
502 /// It also doesn't serialize attributes like 'NumFixedObject' and
503 /// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
504 struct MachineFrameInfo {
505   bool IsFrameAddressTaken = false;
506   bool IsReturnAddressTaken = false;
507   bool HasStackMap = false;
508   bool HasPatchPoint = false;
509   uint64_t StackSize = 0;
510   int OffsetAdjustment = 0;
511   unsigned MaxAlignment = 0;
512   bool AdjustsStack = false;
513   bool HasCalls = false;
514   StringValue StackProtector;
515   // TODO: Serialize FunctionContextIdx
516   unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
517   unsigned CVBytesOfCalleeSavedRegisters = 0;
518   bool HasOpaqueSPAdjustment = false;
519   bool HasVAStart = false;
520   bool HasMustTailInVarArgFunc = false;
521   unsigned LocalFrameSize = 0;
522   StringValue SavePoint;
523   StringValue RestorePoint;
524 
525   bool operator==(const MachineFrameInfo &Other) const {
526     return IsFrameAddressTaken == Other.IsFrameAddressTaken &&
527            IsReturnAddressTaken == Other.IsReturnAddressTaken &&
528            HasStackMap == Other.HasStackMap &&
529            HasPatchPoint == Other.HasPatchPoint &&
530            StackSize == Other.StackSize &&
531            OffsetAdjustment == Other.OffsetAdjustment &&
532            MaxAlignment == Other.MaxAlignment &&
533            AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
534            StackProtector == Other.StackProtector &&
535            MaxCallFrameSize == Other.MaxCallFrameSize &&
536            CVBytesOfCalleeSavedRegisters ==
537                Other.CVBytesOfCalleeSavedRegisters &&
538            HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
539            HasVAStart == Other.HasVAStart &&
540            HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
541            LocalFrameSize == Other.LocalFrameSize &&
542            SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint;
543   }
544 };
545 
546 template <> struct MappingTraits<MachineFrameInfo> {
547   static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
548     YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false);
549     YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false);
550     YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false);
551     YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false);
552     YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0);
553     YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0);
554     YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
555     YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
556     YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
557     YamlIO.mapOptional("stackProtector", MFI.StackProtector,
558                        StringValue()); // Don't print it out when it's empty.
559     YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0);
560     YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters",
561                        MFI.CVBytesOfCalleeSavedRegisters, 0U);
562     YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,
563                        false);
564     YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
565     YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
566                        false);
567     YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0);
568     YamlIO.mapOptional("savePoint", MFI.SavePoint,
569                        StringValue()); // Don't print it out when it's empty.
570     YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
571                        StringValue()); // Don't print it out when it's empty.
572   }
573 };
574 
575 /// Targets should override this in a way that mirrors the implementation of
576 /// llvm::MachineFunctionInfo.
577 struct MachineFunctionInfo {
578   virtual ~MachineFunctionInfo() {}
579   virtual void mappingImpl(IO &YamlIO) {}
580 };
581 
582 template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
583   static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
584     if (MFI)
585       MFI->mappingImpl(YamlIO);
586   }
587 };
588 
589 struct MachineFunction {
590   StringRef Name;
591   MaybeAlign Alignment = None;
592   bool ExposesReturnsTwice = false;
593   // GISel MachineFunctionProperties.
594   bool Legalized = false;
595   bool RegBankSelected = false;
596   bool Selected = false;
597   bool FailedISel = false;
598   // Register information
599   bool TracksRegLiveness = false;
600   bool HasWinCFI = false;
601   std::vector<VirtualRegisterDefinition> VirtualRegisters;
602   std::vector<MachineFunctionLiveIn> LiveIns;
603   Optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
604   // TODO: Serialize the various register masks.
605   // Frame information
606   MachineFrameInfo FrameInfo;
607   std::vector<FixedMachineStackObject> FixedStackObjects;
608   std::vector<MachineStackObject> StackObjects;
609   std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
610   std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
611   std::vector<CallSiteInfo> CallSitesInfo;
612   MachineJumpTable JumpTableInfo;
613   BlockStringValue Body;
614 };
615 
616 template <> struct MappingTraits<MachineFunction> {
617   static void mapping(IO &YamlIO, MachineFunction &MF) {
618     YamlIO.mapRequired("name", MF.Name);
619     YamlIO.mapOptional("alignment", MF.Alignment, None);
620     YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false);
621     YamlIO.mapOptional("legalized", MF.Legalized, false);
622     YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
623     YamlIO.mapOptional("selected", MF.Selected, false);
624     YamlIO.mapOptional("failedISel", MF.FailedISel, false);
625     YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
626     YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false);
627     YamlIO.mapOptional("registers", MF.VirtualRegisters,
628                        std::vector<VirtualRegisterDefinition>());
629     YamlIO.mapOptional("liveins", MF.LiveIns,
630                        std::vector<MachineFunctionLiveIn>());
631     YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters,
632                        Optional<std::vector<FlowStringValue>>());
633     YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo());
634     YamlIO.mapOptional("fixedStack", MF.FixedStackObjects,
635                        std::vector<FixedMachineStackObject>());
636     YamlIO.mapOptional("stack", MF.StackObjects,
637                        std::vector<MachineStackObject>());
638     YamlIO.mapOptional("callSites", MF.CallSitesInfo,
639                        std::vector<CallSiteInfo>());
640     YamlIO.mapOptional("constants", MF.Constants,
641                        std::vector<MachineConstantPoolValue>());
642     YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
643     if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
644       YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
645     YamlIO.mapOptional("body", MF.Body, BlockStringValue());
646   }
647 };
648 
649 } // end namespace yaml
650 } // end namespace llvm
651 
652 #endif // LLVM_CODEGEN_MIRYAMLMAPPING_H
653