MIRYamlMapping.h revision 309124
1//===- MIRYAMLMapping.h - Describes the mapping between MIR and YAML ------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the mapping between various MIR data structures and
11// their corresponding YAML representation.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
16#define LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
17
18#include "llvm/ADT/StringRef.h"
19#include "llvm/CodeGen/MachineJumpTableInfo.h"
20#include "llvm/Support/YAMLTraits.h"
21#include <vector>
22
23namespace llvm {
24namespace yaml {
25
26/// A wrapper around std::string which contains a source range that's being
27/// set during parsing.
28struct StringValue {
29  std::string Value;
30  SMRange SourceRange;
31
32  StringValue() {}
33  StringValue(std::string Value) : Value(std::move(Value)) {}
34
35  bool operator==(const StringValue &Other) const {
36    return Value == Other.Value;
37  }
38};
39
40template <> struct ScalarTraits<StringValue> {
41  static void output(const StringValue &S, void *, llvm::raw_ostream &OS) {
42    OS << S.Value;
43  }
44
45  static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) {
46    S.Value = Scalar.str();
47    if (const auto *Node =
48            reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
49      S.SourceRange = Node->getSourceRange();
50    return "";
51  }
52
53  static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
54};
55
56struct FlowStringValue : StringValue {
57  FlowStringValue() {}
58  FlowStringValue(std::string Value) : StringValue(Value) {}
59};
60
61template <> struct ScalarTraits<FlowStringValue> {
62  static void output(const FlowStringValue &S, void *, llvm::raw_ostream &OS) {
63    return ScalarTraits<StringValue>::output(S, nullptr, OS);
64  }
65
66  static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) {
67    return ScalarTraits<StringValue>::input(Scalar, Ctx, S);
68  }
69
70  static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
71};
72
73struct BlockStringValue {
74  StringValue Value;
75};
76
77template <> struct BlockScalarTraits<BlockStringValue> {
78  static void output(const BlockStringValue &S, void *Ctx, raw_ostream &OS) {
79    return ScalarTraits<StringValue>::output(S.Value, Ctx, OS);
80  }
81
82  static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) {
83    return ScalarTraits<StringValue>::input(Scalar, Ctx, S.Value);
84  }
85};
86
87/// A wrapper around unsigned which contains a source range that's being set
88/// during parsing.
89struct UnsignedValue {
90  unsigned Value;
91  SMRange SourceRange;
92
93  UnsignedValue() : Value(0) {}
94  UnsignedValue(unsigned Value) : Value(Value) {}
95
96  bool operator==(const UnsignedValue &Other) const {
97    return Value == Other.Value;
98  }
99};
100
101template <> struct ScalarTraits<UnsignedValue> {
102  static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) {
103    return ScalarTraits<unsigned>::output(Value.Value, Ctx, OS);
104  }
105
106  static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) {
107    if (const auto *Node =
108            reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
109      Value.SourceRange = Node->getSourceRange();
110    return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value);
111  }
112
113  static bool mustQuote(StringRef Scalar) {
114    return ScalarTraits<unsigned>::mustQuote(Scalar);
115  }
116};
117
118template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> {
119  static void enumeration(yaml::IO &IO,
120                          MachineJumpTableInfo::JTEntryKind &EntryKind) {
121    IO.enumCase(EntryKind, "block-address",
122                MachineJumpTableInfo::EK_BlockAddress);
123    IO.enumCase(EntryKind, "gp-rel64-block-address",
124                MachineJumpTableInfo::EK_GPRel64BlockAddress);
125    IO.enumCase(EntryKind, "gp-rel32-block-address",
126                MachineJumpTableInfo::EK_GPRel32BlockAddress);
127    IO.enumCase(EntryKind, "label-difference32",
128                MachineJumpTableInfo::EK_LabelDifference32);
129    IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline);
130    IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32);
131  }
132};
133
134} // end namespace yaml
135} // end namespace llvm
136
137LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
138LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
139LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
140
141namespace llvm {
142namespace yaml {
143
144struct VirtualRegisterDefinition {
145  UnsignedValue ID;
146  StringValue Class;
147  StringValue PreferredRegister;
148  // TODO: Serialize the target specific register hints.
149};
150
151template <> struct MappingTraits<VirtualRegisterDefinition> {
152  static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
153    YamlIO.mapRequired("id", Reg.ID);
154    YamlIO.mapRequired("class", Reg.Class);
155    YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
156                       StringValue()); // Don't print out when it's empty.
157  }
158
159  static const bool flow = true;
160};
161
162struct MachineFunctionLiveIn {
163  StringValue Register;
164  StringValue VirtualRegister;
165};
166
167template <> struct MappingTraits<MachineFunctionLiveIn> {
168  static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
169    YamlIO.mapRequired("reg", LiveIn.Register);
170    YamlIO.mapOptional(
171        "virtual-reg", LiveIn.VirtualRegister,
172        StringValue()); // Don't print the virtual register when it's empty.
173  }
174
175  static const bool flow = true;
176};
177
178/// Serializable representation of stack object from the MachineFrameInfo class.
179///
180/// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
181/// determined by the object's type and frame information flags.
182/// Dead stack objects aren't serialized.
183///
184/// The 'isPreallocated' flag is determined by the local offset.
185struct MachineStackObject {
186  enum ObjectType { DefaultType, SpillSlot, VariableSized };
187  UnsignedValue ID;
188  StringValue Name;
189  // TODO: Serialize unnamed LLVM alloca reference.
190  ObjectType Type = DefaultType;
191  int64_t Offset = 0;
192  uint64_t Size = 0;
193  unsigned Alignment = 0;
194  StringValue CalleeSavedRegister;
195  Optional<int64_t> LocalOffset;
196  StringValue DebugVar;
197  StringValue DebugExpr;
198  StringValue DebugLoc;
199};
200
201template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
202  static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
203    IO.enumCase(Type, "default", MachineStackObject::DefaultType);
204    IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
205    IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
206  }
207};
208
209template <> struct MappingTraits<MachineStackObject> {
210  static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
211    YamlIO.mapRequired("id", Object.ID);
212    YamlIO.mapOptional("name", Object.Name,
213                       StringValue()); // Don't print out an empty name.
214    YamlIO.mapOptional(
215        "type", Object.Type,
216        MachineStackObject::DefaultType); // Don't print the default type.
217    YamlIO.mapOptional("offset", Object.Offset);
218    if (Object.Type != MachineStackObject::VariableSized)
219      YamlIO.mapRequired("size", Object.Size);
220    YamlIO.mapOptional("alignment", Object.Alignment);
221    YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
222                       StringValue()); // Don't print it out when it's empty.
223    YamlIO.mapOptional("local-offset", Object.LocalOffset);
224    YamlIO.mapOptional("di-variable", Object.DebugVar,
225                       StringValue()); // Don't print it out when it's empty.
226    YamlIO.mapOptional("di-expression", Object.DebugExpr,
227                       StringValue()); // Don't print it out when it's empty.
228    YamlIO.mapOptional("di-location", Object.DebugLoc,
229                       StringValue()); // Don't print it out when it's empty.
230  }
231
232  static const bool flow = true;
233};
234
235/// Serializable representation of the fixed stack object from the
236/// MachineFrameInfo class.
237struct FixedMachineStackObject {
238  enum ObjectType { DefaultType, SpillSlot };
239  UnsignedValue ID;
240  ObjectType Type = DefaultType;
241  int64_t Offset = 0;
242  uint64_t Size = 0;
243  unsigned Alignment = 0;
244  bool IsImmutable = false;
245  bool IsAliased = false;
246  StringValue CalleeSavedRegister;
247};
248
249template <>
250struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
251  static void enumeration(yaml::IO &IO,
252                          FixedMachineStackObject::ObjectType &Type) {
253    IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
254    IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
255  }
256};
257
258template <> struct MappingTraits<FixedMachineStackObject> {
259  static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
260    YamlIO.mapRequired("id", Object.ID);
261    YamlIO.mapOptional(
262        "type", Object.Type,
263        FixedMachineStackObject::DefaultType); // Don't print the default type.
264    YamlIO.mapOptional("offset", Object.Offset);
265    YamlIO.mapOptional("size", Object.Size);
266    YamlIO.mapOptional("alignment", Object.Alignment);
267    if (Object.Type != FixedMachineStackObject::SpillSlot) {
268      YamlIO.mapOptional("isImmutable", Object.IsImmutable);
269      YamlIO.mapOptional("isAliased", Object.IsAliased);
270    }
271    YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
272                       StringValue()); // Don't print it out when it's empty.
273  }
274
275  static const bool flow = true;
276};
277
278struct MachineConstantPoolValue {
279  UnsignedValue ID;
280  StringValue Value;
281  unsigned Alignment = 0;
282};
283
284template <> struct MappingTraits<MachineConstantPoolValue> {
285  static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
286    YamlIO.mapRequired("id", Constant.ID);
287    YamlIO.mapOptional("value", Constant.Value);
288    YamlIO.mapOptional("alignment", Constant.Alignment);
289  }
290};
291
292struct MachineJumpTable {
293  struct Entry {
294    UnsignedValue ID;
295    std::vector<FlowStringValue> Blocks;
296  };
297
298  MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
299  std::vector<Entry> Entries;
300};
301
302template <> struct MappingTraits<MachineJumpTable::Entry> {
303  static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
304    YamlIO.mapRequired("id", Entry.ID);
305    YamlIO.mapOptional("blocks", Entry.Blocks);
306  }
307};
308
309} // end namespace yaml
310} // end namespace llvm
311
312LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
313LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
314LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
315LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
316LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
317LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
318
319namespace llvm {
320namespace yaml {
321
322template <> struct MappingTraits<MachineJumpTable> {
323  static void mapping(IO &YamlIO, MachineJumpTable &JT) {
324    YamlIO.mapRequired("kind", JT.Kind);
325    YamlIO.mapOptional("entries", JT.Entries);
326  }
327};
328
329/// Serializable representation of MachineFrameInfo.
330///
331/// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
332/// 'RealignOption' as they are determined by the target and LLVM function
333/// attributes.
334/// It also doesn't serialize attributes like 'NumFixedObject' and
335/// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
336struct MachineFrameInfo {
337  bool IsFrameAddressTaken = false;
338  bool IsReturnAddressTaken = false;
339  bool HasStackMap = false;
340  bool HasPatchPoint = false;
341  uint64_t StackSize = 0;
342  int OffsetAdjustment = 0;
343  unsigned MaxAlignment = 0;
344  bool AdjustsStack = false;
345  bool HasCalls = false;
346  StringValue StackProtector;
347  // TODO: Serialize FunctionContextIdx
348  unsigned MaxCallFrameSize = 0;
349  bool HasOpaqueSPAdjustment = false;
350  bool HasVAStart = false;
351  bool HasMustTailInVarArgFunc = false;
352  StringValue SavePoint;
353  StringValue RestorePoint;
354};
355
356template <> struct MappingTraits<MachineFrameInfo> {
357  static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
358    YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken);
359    YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken);
360    YamlIO.mapOptional("hasStackMap", MFI.HasStackMap);
361    YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint);
362    YamlIO.mapOptional("stackSize", MFI.StackSize);
363    YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment);
364    YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment);
365    YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack);
366    YamlIO.mapOptional("hasCalls", MFI.HasCalls);
367    YamlIO.mapOptional("stackProtector", MFI.StackProtector,
368                       StringValue()); // Don't print it out when it's empty.
369    YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize);
370    YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment);
371    YamlIO.mapOptional("hasVAStart", MFI.HasVAStart);
372    YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc);
373    YamlIO.mapOptional("savePoint", MFI.SavePoint,
374                       StringValue()); // Don't print it out when it's empty.
375    YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
376                       StringValue()); // Don't print it out when it's empty.
377  }
378};
379
380struct MachineFunction {
381  StringRef Name;
382  unsigned Alignment = 0;
383  bool ExposesReturnsTwice = false;
384  bool HasInlineAsm = false;
385  // MachineFunctionProperties
386  bool AllVRegsAllocated = false;
387  // Register information
388  bool IsSSA = false;
389  bool TracksRegLiveness = false;
390  bool TracksSubRegLiveness = false;
391  std::vector<VirtualRegisterDefinition> VirtualRegisters;
392  std::vector<MachineFunctionLiveIn> LiveIns;
393  Optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
394  // TODO: Serialize the various register masks.
395  // Frame information
396  MachineFrameInfo FrameInfo;
397  std::vector<FixedMachineStackObject> FixedStackObjects;
398  std::vector<MachineStackObject> StackObjects;
399  std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
400  MachineJumpTable JumpTableInfo;
401  BlockStringValue Body;
402};
403
404template <> struct MappingTraits<MachineFunction> {
405  static void mapping(IO &YamlIO, MachineFunction &MF) {
406    YamlIO.mapRequired("name", MF.Name);
407    YamlIO.mapOptional("alignment", MF.Alignment);
408    YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
409    YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm);
410    YamlIO.mapOptional("allVRegsAllocated", MF.AllVRegsAllocated);
411    YamlIO.mapOptional("isSSA", MF.IsSSA);
412    YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness);
413    YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
414    YamlIO.mapOptional("registers", MF.VirtualRegisters);
415    YamlIO.mapOptional("liveins", MF.LiveIns);
416    YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters);
417    YamlIO.mapOptional("frameInfo", MF.FrameInfo);
418    YamlIO.mapOptional("fixedStack", MF.FixedStackObjects);
419    YamlIO.mapOptional("stack", MF.StackObjects);
420    YamlIO.mapOptional("constants", MF.Constants);
421    if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
422      YamlIO.mapOptional("jumpTable", MF.JumpTableInfo);
423    YamlIO.mapOptional("body", MF.Body);
424  }
425};
426
427} // end namespace yaml
428} // end namespace llvm
429
430#endif
431