MIRYamlMapping.h revision 286684
1218885Sdim//===- MIRYAMLMapping.h - Describes the mapping between MIR and YAML ------===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// The MIR serialization library is currently a work in progress. It can't
11218885Sdim// serialize machine functions at this time.
12218885Sdim//
13218885Sdim// This file implements the mapping between various MIR data structures and
14218885Sdim// their corresponding YAML representation.
15221345Sdim//
16218885Sdim//===----------------------------------------------------------------------===//
17218885Sdim
18218885Sdim#ifndef LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
19218885Sdim#define LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
20218885Sdim
21218885Sdim#include "llvm/ADT/StringRef.h"
22218885Sdim#include "llvm/Support/YAMLTraits.h"
23218885Sdim#include <vector>
24218885Sdim
25218885Sdimnamespace llvm {
26218885Sdimnamespace yaml {
27218885Sdim
28218885Sdim/// A wrapper around std::string which contains a source range that's being
29218885Sdim/// set during parsing.
30218885Sdimstruct StringValue {
31218885Sdim  std::string Value;
32218885Sdim  SMRange SourceRange;
33218885Sdim
34218885Sdim  StringValue() {}
35218885Sdim  StringValue(std::string Value) : Value(std::move(Value)) {}
36218885Sdim
37218885Sdim  bool operator==(const StringValue &Other) const {
38218885Sdim    return Value == Other.Value;
39218885Sdim  }
40218885Sdim};
41218885Sdim
42218885Sdimtemplate <> struct ScalarTraits<StringValue> {
43218885Sdim  static void output(const StringValue &S, void *, llvm::raw_ostream &OS) {
44218885Sdim    OS << S.Value;
45218885Sdim  }
46218885Sdim
47218885Sdim  static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) {
48249423Sdim    S.Value = Scalar.str();
49249423Sdim    if (const auto *Node =
50249423Sdim            reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
51249423Sdim      S.SourceRange = Node->getSourceRange();
52218885Sdim    return "";
53218885Sdim  }
54218885Sdim
55218885Sdim  static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
56218885Sdim};
57
58struct FlowStringValue : StringValue {
59  FlowStringValue() {}
60  FlowStringValue(std::string Value) : StringValue(Value) {}
61};
62
63template <> struct ScalarTraits<FlowStringValue> {
64  static void output(const FlowStringValue &S, void *, llvm::raw_ostream &OS) {
65    return ScalarTraits<StringValue>::output(S, nullptr, OS);
66  }
67
68  static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) {
69    return ScalarTraits<StringValue>::input(Scalar, Ctx, S);
70  }
71
72  static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
73};
74
75} // end namespace yaml
76} // end namespace llvm
77
78LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
79LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
80
81namespace llvm {
82namespace yaml {
83
84struct VirtualRegisterDefinition {
85  unsigned ID;
86  StringValue Class;
87  // TODO: Serialize the virtual register hints.
88};
89
90template <> struct MappingTraits<VirtualRegisterDefinition> {
91  static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
92    YamlIO.mapRequired("id", Reg.ID);
93    YamlIO.mapRequired("class", Reg.Class);
94  }
95
96  static const bool flow = true;
97};
98
99struct MachineBasicBlock {
100  unsigned ID;
101  StringValue Name;
102  unsigned Alignment = 0;
103  bool IsLandingPad = false;
104  bool AddressTaken = false;
105  // TODO: Serialize the successor weights.
106  std::vector<FlowStringValue> Successors;
107  std::vector<FlowStringValue> LiveIns;
108  std::vector<StringValue> Instructions;
109};
110
111template <> struct MappingTraits<MachineBasicBlock> {
112  static void mapping(IO &YamlIO, MachineBasicBlock &MBB) {
113    YamlIO.mapRequired("id", MBB.ID);
114    YamlIO.mapOptional("name", MBB.Name,
115                       StringValue()); // Don't print out an empty name.
116    YamlIO.mapOptional("alignment", MBB.Alignment);
117    YamlIO.mapOptional("isLandingPad", MBB.IsLandingPad);
118    YamlIO.mapOptional("addressTaken", MBB.AddressTaken);
119    YamlIO.mapOptional("successors", MBB.Successors);
120    YamlIO.mapOptional("liveins", MBB.LiveIns);
121    YamlIO.mapOptional("instructions", MBB.Instructions);
122  }
123};
124
125/// Serializable representation of stack object from the MachineFrameInfo class.
126///
127/// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
128/// determined by the object's type and frame information flags.
129/// Dead stack objects aren't serialized.
130///
131/// TODO: Determine isPreallocated flag by mapping between objects and local
132/// objects (Serialize local objects).
133struct MachineStackObject {
134  enum ObjectType { DefaultType, SpillSlot, VariableSized };
135  // TODO: Serialize LLVM alloca reference.
136  unsigned ID;
137  ObjectType Type = DefaultType;
138  int64_t Offset = 0;
139  uint64_t Size = 0;
140  unsigned Alignment = 0;
141};
142
143template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
144  static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
145    IO.enumCase(Type, "default", MachineStackObject::DefaultType);
146    IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
147    IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
148  }
149};
150
151template <> struct MappingTraits<MachineStackObject> {
152  static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
153    YamlIO.mapRequired("id", Object.ID);
154    YamlIO.mapOptional(
155        "type", Object.Type,
156        MachineStackObject::DefaultType); // Don't print the default type.
157    YamlIO.mapOptional("offset", Object.Offset);
158    if (Object.Type != MachineStackObject::VariableSized)
159      YamlIO.mapRequired("size", Object.Size);
160    YamlIO.mapOptional("alignment", Object.Alignment);
161  }
162
163  static const bool flow = true;
164};
165
166/// Serializable representation of the fixed stack object from the
167/// MachineFrameInfo class.
168struct FixedMachineStackObject {
169  enum ObjectType { DefaultType, SpillSlot };
170  unsigned ID;
171  ObjectType Type = DefaultType;
172  int64_t Offset = 0;
173  uint64_t Size = 0;
174  unsigned Alignment = 0;
175  bool IsImmutable = false;
176  bool IsAliased = false;
177};
178
179template <>
180struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
181  static void enumeration(yaml::IO &IO,
182                          FixedMachineStackObject::ObjectType &Type) {
183    IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
184    IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
185  }
186};
187
188template <> struct MappingTraits<FixedMachineStackObject> {
189  static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
190    YamlIO.mapRequired("id", Object.ID);
191    YamlIO.mapOptional(
192        "type", Object.Type,
193        FixedMachineStackObject::DefaultType); // Don't print the default type.
194    YamlIO.mapOptional("offset", Object.Offset);
195    YamlIO.mapOptional("size", Object.Size);
196    YamlIO.mapOptional("alignment", Object.Alignment);
197    if (Object.Type != FixedMachineStackObject::SpillSlot) {
198      YamlIO.mapOptional("isImmutable", Object.IsImmutable);
199      YamlIO.mapOptional("isAliased", Object.IsAliased);
200    }
201  }
202
203  static const bool flow = true;
204};
205
206} // end namespace yaml
207} // end namespace llvm
208
209LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
210LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineBasicBlock)
211LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
212LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
213
214namespace llvm {
215namespace yaml {
216
217/// Serializable representation of MachineFrameInfo.
218///
219/// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
220/// 'RealignOption' as they are determined by the target and LLVM function
221/// attributes.
222/// It also doesn't serialize attributes like 'NumFixedObject' and
223/// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
224struct MachineFrameInfo {
225  bool IsFrameAddressTaken = false;
226  bool IsReturnAddressTaken = false;
227  bool HasStackMap = false;
228  bool HasPatchPoint = false;
229  uint64_t StackSize = 0;
230  int OffsetAdjustment = 0;
231  unsigned MaxAlignment = 0;
232  bool AdjustsStack = false;
233  bool HasCalls = false;
234  // TODO: Serialize StackProtectorIdx and FunctionContextIdx
235  unsigned MaxCallFrameSize = 0;
236  // TODO: Serialize callee saved info.
237  // TODO: Serialize local frame objects.
238  bool HasOpaqueSPAdjustment = false;
239  bool HasVAStart = false;
240  bool HasMustTailInVarArgFunc = false;
241  // TODO: Serialize save and restore MBB references.
242};
243
244template <> struct MappingTraits<MachineFrameInfo> {
245  static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
246    YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken);
247    YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken);
248    YamlIO.mapOptional("hasStackMap", MFI.HasStackMap);
249    YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint);
250    YamlIO.mapOptional("stackSize", MFI.StackSize);
251    YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment);
252    YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment);
253    YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack);
254    YamlIO.mapOptional("hasCalls", MFI.HasCalls);
255    YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize);
256    YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment);
257    YamlIO.mapOptional("hasVAStart", MFI.HasVAStart);
258    YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc);
259  }
260};
261
262struct MachineFunction {
263  StringRef Name;
264  unsigned Alignment = 0;
265  bool ExposesReturnsTwice = false;
266  bool HasInlineAsm = false;
267  // Register information
268  bool IsSSA = false;
269  bool TracksRegLiveness = false;
270  bool TracksSubRegLiveness = false;
271  std::vector<VirtualRegisterDefinition> VirtualRegisters;
272  // TODO: Serialize the various register masks.
273  // TODO: Serialize live in registers.
274  // Frame information
275  MachineFrameInfo FrameInfo;
276  std::vector<FixedMachineStackObject> FixedStackObjects;
277  std::vector<MachineStackObject> StackObjects;
278
279  std::vector<MachineBasicBlock> BasicBlocks;
280};
281
282template <> struct MappingTraits<MachineFunction> {
283  static void mapping(IO &YamlIO, MachineFunction &MF) {
284    YamlIO.mapRequired("name", MF.Name);
285    YamlIO.mapOptional("alignment", MF.Alignment);
286    YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
287    YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm);
288    YamlIO.mapOptional("isSSA", MF.IsSSA);
289    YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness);
290    YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
291    YamlIO.mapOptional("registers", MF.VirtualRegisters);
292    YamlIO.mapOptional("frameInfo", MF.FrameInfo);
293    YamlIO.mapOptional("fixedStack", MF.FixedStackObjects);
294    YamlIO.mapOptional("stack", MF.StackObjects);
295    YamlIO.mapOptional("body", MF.BasicBlocks);
296  }
297};
298
299} // end namespace yaml
300} // end namespace llvm
301
302#endif
303