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