• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 namespace llvm {
24 namespace yaml {
25 
26 /// A wrapper around std::string which contains a source range that's being
27 /// set during parsing.
28 struct StringValue {
29   std::string Value;
30   SMRange SourceRange;
31 
StringValueStringValue32   StringValue() {}
StringValueStringValue33   StringValue(std::string Value) : Value(std::move(Value)) {}
34 
35   bool operator==(const StringValue &Other) const {
36     return Value == Other.Value;
37   }
38 };
39 
40 template <> 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 
56 struct FlowStringValue : StringValue {
57   FlowStringValue() {}
58   FlowStringValue(std::string Value) : StringValue(Value) {}
59 };
60 
61 template <> 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 
73 struct BlockStringValue {
74   StringValue Value;
75 };
76 
77 template <> 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.
89 struct 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 
101 template <> 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 
118 template <> 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 
137 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
138 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
139 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
140 
141 namespace llvm {
142 namespace yaml {
143 
144 struct VirtualRegisterDefinition {
145   UnsignedValue ID;
146   StringValue Class;
147   StringValue PreferredRegister;
148   // TODO: Serialize the target specific register hints.
149 };
150 
151 template <> 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 
162 struct MachineFunctionLiveIn {
163   StringValue Register;
164   StringValue VirtualRegister;
165 };
166 
167 template <> 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.
185 struct 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 
201 template <> 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 
209 template <> 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.
237 struct 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 
249 template <>
250 struct 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 
258 template <> 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 
278 struct MachineConstantPoolValue {
279   UnsignedValue ID;
280   StringValue Value;
281   unsigned Alignment = 0;
282 };
283 
284 template <> 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 
292 struct 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 
302 template <> 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 
312 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
313 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
314 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
315 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
316 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
317 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
318 
319 namespace llvm {
320 namespace yaml {
321 
322 template <> 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.
336 struct 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 
356 template <> 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 
380 struct 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 
404 template <> 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