MIR Parser: Report an error when a jump table entry is redefined.
[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 /// A wrapper around unsigned which contains a source range that's being set
77 /// during parsing.
78 struct UnsignedValue {
79   unsigned Value;
80   SMRange SourceRange;
81
82   UnsignedValue() : Value(0) {}
83   UnsignedValue(unsigned Value) : Value(Value) {}
84
85   bool operator==(const UnsignedValue &Other) const {
86     return Value == Other.Value;
87   }
88 };
89
90 template <> struct ScalarTraits<UnsignedValue> {
91   static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) {
92     return ScalarTraits<unsigned>::output(Value.Value, Ctx, OS);
93   }
94
95   static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) {
96     if (const auto *Node =
97             reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
98       Value.SourceRange = Node->getSourceRange();
99     return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value);
100   }
101
102   static bool mustQuote(StringRef Scalar) {
103     return ScalarTraits<unsigned>::mustQuote(Scalar);
104   }
105 };
106
107 template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> {
108   static void enumeration(yaml::IO &IO,
109                           MachineJumpTableInfo::JTEntryKind &EntryKind) {
110     IO.enumCase(EntryKind, "block-address",
111                 MachineJumpTableInfo::EK_BlockAddress);
112     IO.enumCase(EntryKind, "gp-rel64-block-address",
113                 MachineJumpTableInfo::EK_GPRel64BlockAddress);
114     IO.enumCase(EntryKind, "gp-rel32-block-address",
115                 MachineJumpTableInfo::EK_GPRel32BlockAddress);
116     IO.enumCase(EntryKind, "label-difference32",
117                 MachineJumpTableInfo::EK_LabelDifference32);
118     IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline);
119     IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32);
120   }
121 };
122
123 } // end namespace yaml
124 } // end namespace llvm
125
126 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
127 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
128 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
129
130 namespace llvm {
131 namespace yaml {
132
133 struct VirtualRegisterDefinition {
134   UnsignedValue ID;
135   StringValue Class;
136   StringValue PreferredRegister;
137   // TODO: Serialize the target specific register hints.
138 };
139
140 template <> struct MappingTraits<VirtualRegisterDefinition> {
141   static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
142     YamlIO.mapRequired("id", Reg.ID);
143     YamlIO.mapRequired("class", Reg.Class);
144     YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
145                        StringValue()); // Don't print out when it's empty.
146   }
147
148   static const bool flow = true;
149 };
150
151 struct MachineFunctionLiveIn {
152   StringValue Register;
153   StringValue VirtualRegister;
154 };
155
156 template <> struct MappingTraits<MachineFunctionLiveIn> {
157   static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
158     YamlIO.mapRequired("reg", LiveIn.Register);
159     YamlIO.mapOptional(
160         "virtual-reg", LiveIn.VirtualRegister,
161         StringValue()); // Don't print the virtual register when it's empty.
162   }
163
164   static const bool flow = true;
165 };
166
167 struct MachineBasicBlock {
168   unsigned ID;
169   StringValue Name;
170   StringValue IRBlock;
171   unsigned Alignment = 0;
172   bool IsLandingPad = false;
173   bool AddressTaken = false;
174   std::vector<FlowStringValue> Successors;
175   std::vector<UnsignedValue> SuccessorWeights;
176   std::vector<FlowStringValue> LiveIns;
177   std::vector<StringValue> Instructions;
178 };
179
180 template <> struct MappingTraits<MachineBasicBlock> {
181   static void mapping(IO &YamlIO, MachineBasicBlock &MBB) {
182     YamlIO.mapRequired("id", MBB.ID);
183     YamlIO.mapOptional("name", MBB.Name,
184                        StringValue()); // Don't print out an empty name.
185     YamlIO.mapOptional("ir-block", MBB.IRBlock,
186                        StringValue()); // Don't print out an empty BB reference.
187     YamlIO.mapOptional("alignment", MBB.Alignment);
188     YamlIO.mapOptional("isLandingPad", MBB.IsLandingPad);
189     YamlIO.mapOptional("addressTaken", MBB.AddressTaken);
190     YamlIO.mapOptional("successors", MBB.Successors);
191     YamlIO.mapOptional("weights", MBB.SuccessorWeights);
192     YamlIO.mapOptional("liveins", MBB.LiveIns);
193     YamlIO.mapOptional("instructions", MBB.Instructions);
194   }
195 };
196
197 /// Serializable representation of stack object from the MachineFrameInfo class.
198 ///
199 /// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
200 /// determined by the object's type and frame information flags.
201 /// Dead stack objects aren't serialized.
202 ///
203 /// TODO: Determine isPreallocated flag by mapping between objects and local
204 /// objects (Serialize local objects).
205 struct MachineStackObject {
206   enum ObjectType { DefaultType, SpillSlot, VariableSized };
207   unsigned ID;
208   StringValue Name;
209   // TODO: Serialize unnamed LLVM alloca reference.
210   ObjectType Type = DefaultType;
211   int64_t Offset = 0;
212   uint64_t Size = 0;
213   unsigned Alignment = 0;
214   StringValue CalleeSavedRegister;
215 };
216
217 template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
218   static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
219     IO.enumCase(Type, "default", MachineStackObject::DefaultType);
220     IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
221     IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
222   }
223 };
224
225 template <> struct MappingTraits<MachineStackObject> {
226   static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
227     YamlIO.mapRequired("id", Object.ID);
228     YamlIO.mapOptional("name", Object.Name,
229                        StringValue()); // Don't print out an empty name.
230     YamlIO.mapOptional(
231         "type", Object.Type,
232         MachineStackObject::DefaultType); // Don't print the default type.
233     YamlIO.mapOptional("offset", Object.Offset);
234     if (Object.Type != MachineStackObject::VariableSized)
235       YamlIO.mapRequired("size", Object.Size);
236     YamlIO.mapOptional("alignment", Object.Alignment);
237     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
238                        StringValue()); // Don't print it out when it's empty.
239   }
240
241   static const bool flow = true;
242 };
243
244 /// Serializable representation of the fixed stack object from the
245 /// MachineFrameInfo class.
246 struct FixedMachineStackObject {
247   enum ObjectType { DefaultType, SpillSlot };
248   unsigned ID;
249   ObjectType Type = DefaultType;
250   int64_t Offset = 0;
251   uint64_t Size = 0;
252   unsigned Alignment = 0;
253   bool IsImmutable = false;
254   bool IsAliased = false;
255   StringValue CalleeSavedRegister;
256 };
257
258 template <>
259 struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
260   static void enumeration(yaml::IO &IO,
261                           FixedMachineStackObject::ObjectType &Type) {
262     IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
263     IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
264   }
265 };
266
267 template <> struct MappingTraits<FixedMachineStackObject> {
268   static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
269     YamlIO.mapRequired("id", Object.ID);
270     YamlIO.mapOptional(
271         "type", Object.Type,
272         FixedMachineStackObject::DefaultType); // Don't print the default type.
273     YamlIO.mapOptional("offset", Object.Offset);
274     YamlIO.mapOptional("size", Object.Size);
275     YamlIO.mapOptional("alignment", Object.Alignment);
276     if (Object.Type != FixedMachineStackObject::SpillSlot) {
277       YamlIO.mapOptional("isImmutable", Object.IsImmutable);
278       YamlIO.mapOptional("isAliased", Object.IsAliased);
279     }
280     YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
281                        StringValue()); // Don't print it out when it's empty.
282   }
283
284   static const bool flow = true;
285 };
286
287 struct MachineConstantPoolValue {
288   UnsignedValue ID;
289   StringValue Value;
290   unsigned Alignment = 0;
291 };
292
293 template <> struct MappingTraits<MachineConstantPoolValue> {
294   static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
295     YamlIO.mapRequired("id", Constant.ID);
296     YamlIO.mapOptional("value", Constant.Value);
297     YamlIO.mapOptional("alignment", Constant.Alignment);
298   }
299 };
300
301 struct MachineJumpTable {
302   struct Entry {
303     UnsignedValue ID;
304     std::vector<FlowStringValue> Blocks;
305   };
306
307   MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
308   std::vector<Entry> Entries;
309 };
310
311 template <> struct MappingTraits<MachineJumpTable::Entry> {
312   static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
313     YamlIO.mapRequired("id", Entry.ID);
314     YamlIO.mapOptional("blocks", Entry.Blocks);
315   }
316 };
317
318 } // end namespace yaml
319 } // end namespace llvm
320
321 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
322 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
323 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineBasicBlock)
324 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
325 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
326 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
327 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
328
329 namespace llvm {
330 namespace yaml {
331
332 template <> struct MappingTraits<MachineJumpTable> {
333   static void mapping(IO &YamlIO, MachineJumpTable &JT) {
334     YamlIO.mapRequired("kind", JT.Kind);
335     YamlIO.mapOptional("entries", JT.Entries);
336   }
337 };
338
339 /// Serializable representation of MachineFrameInfo.
340 ///
341 /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
342 /// 'RealignOption' as they are determined by the target and LLVM function
343 /// attributes.
344 /// It also doesn't serialize attributes like 'NumFixedObject' and
345 /// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
346 struct MachineFrameInfo {
347   bool IsFrameAddressTaken = false;
348   bool IsReturnAddressTaken = false;
349   bool HasStackMap = false;
350   bool HasPatchPoint = false;
351   uint64_t StackSize = 0;
352   int OffsetAdjustment = 0;
353   unsigned MaxAlignment = 0;
354   bool AdjustsStack = false;
355   bool HasCalls = false;
356   // TODO: Serialize StackProtectorIdx and FunctionContextIdx
357   unsigned MaxCallFrameSize = 0;
358   // TODO: Serialize local frame objects.
359   bool HasOpaqueSPAdjustment = false;
360   bool HasVAStart = false;
361   bool HasMustTailInVarArgFunc = false;
362   StringValue SavePoint;
363   StringValue RestorePoint;
364 };
365
366 template <> struct MappingTraits<MachineFrameInfo> {
367   static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
368     YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken);
369     YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken);
370     YamlIO.mapOptional("hasStackMap", MFI.HasStackMap);
371     YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint);
372     YamlIO.mapOptional("stackSize", MFI.StackSize);
373     YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment);
374     YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment);
375     YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack);
376     YamlIO.mapOptional("hasCalls", MFI.HasCalls);
377     YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize);
378     YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment);
379     YamlIO.mapOptional("hasVAStart", MFI.HasVAStart);
380     YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc);
381     YamlIO.mapOptional("savePoint", MFI.SavePoint,
382                        StringValue()); // Don't print it out when it's empty.
383     YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
384                        StringValue()); // Don't print it out when it's empty.
385   }
386 };
387
388 struct MachineFunction {
389   StringRef Name;
390   unsigned Alignment = 0;
391   bool ExposesReturnsTwice = false;
392   bool HasInlineAsm = false;
393   // Register information
394   bool IsSSA = false;
395   bool TracksRegLiveness = false;
396   bool TracksSubRegLiveness = false;
397   std::vector<VirtualRegisterDefinition> VirtualRegisters;
398   std::vector<MachineFunctionLiveIn> LiveIns;
399   // TODO: Serialize the various register masks.
400   // Frame information
401   MachineFrameInfo FrameInfo;
402   std::vector<FixedMachineStackObject> FixedStackObjects;
403   std::vector<MachineStackObject> StackObjects;
404   std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
405   MachineJumpTable JumpTableInfo;
406
407   std::vector<MachineBasicBlock> BasicBlocks;
408 };
409
410 template <> struct MappingTraits<MachineFunction> {
411   static void mapping(IO &YamlIO, MachineFunction &MF) {
412     YamlIO.mapRequired("name", MF.Name);
413     YamlIO.mapOptional("alignment", MF.Alignment);
414     YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
415     YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm);
416     YamlIO.mapOptional("isSSA", MF.IsSSA);
417     YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness);
418     YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
419     YamlIO.mapOptional("registers", MF.VirtualRegisters);
420     YamlIO.mapOptional("liveins", MF.LiveIns);
421     YamlIO.mapOptional("frameInfo", MF.FrameInfo);
422     YamlIO.mapOptional("fixedStack", MF.FixedStackObjects);
423     YamlIO.mapOptional("stack", MF.StackObjects);
424     YamlIO.mapOptional("constants", MF.Constants);
425     if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
426       YamlIO.mapOptional("jumpTable", MF.JumpTableInfo);
427     YamlIO.mapOptional("body", MF.BasicBlocks);
428   }
429 };
430
431 } // end namespace yaml
432 } // end namespace llvm
433
434 #endif