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