1 //===- MIRYAMLMapping.h - Describes the mapping between MIR and YAML ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the mapping between various MIR data structures and
11 // their corresponding YAML representation.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
16 #define LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/CodeGen/MachineJumpTableInfo.h"
20 #include "llvm/Support/YAMLTraits.h"
26 /// A wrapper around std::string which contains a source range that's being
27 /// set during parsing.
33 StringValue(std::string Value) : Value(std::move(Value)) {}
35 bool operator==(const StringValue &Other) const {
36 return Value == Other.Value;
40 template <> struct ScalarTraits<StringValue> {
41 static void output(const StringValue &S, void *, llvm::raw_ostream &OS) {
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();
53 static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
56 struct FlowStringValue : StringValue {
58 FlowStringValue(std::string Value) : StringValue(std::move(Value)) {}
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);
66 static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) {
67 return ScalarTraits<StringValue>::input(Scalar, Ctx, S);
70 static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
73 struct BlockStringValue {
75 bool operator==(const BlockStringValue &Other) const {
76 return Value == Other.Value;
80 template <> struct BlockScalarTraits<BlockStringValue> {
81 static void output(const BlockStringValue &S, void *Ctx, raw_ostream &OS) {
82 return ScalarTraits<StringValue>::output(S.Value, Ctx, OS);
85 static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) {
86 return ScalarTraits<StringValue>::input(Scalar, Ctx, S.Value);
90 /// A wrapper around unsigned which contains a source range that's being set
92 struct UnsignedValue {
96 UnsignedValue() : Value(0) {}
97 UnsignedValue(unsigned Value) : Value(Value) {}
99 bool operator==(const UnsignedValue &Other) const {
100 return Value == Other.Value;
104 template <> struct ScalarTraits<UnsignedValue> {
105 static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) {
106 return ScalarTraits<unsigned>::output(Value.Value, Ctx, OS);
109 static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) {
110 if (const auto *Node =
111 reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
112 Value.SourceRange = Node->getSourceRange();
113 return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value);
116 static bool mustQuote(StringRef Scalar) {
117 return ScalarTraits<unsigned>::mustQuote(Scalar);
121 template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> {
122 static void enumeration(yaml::IO &IO,
123 MachineJumpTableInfo::JTEntryKind &EntryKind) {
124 IO.enumCase(EntryKind, "block-address",
125 MachineJumpTableInfo::EK_BlockAddress);
126 IO.enumCase(EntryKind, "gp-rel64-block-address",
127 MachineJumpTableInfo::EK_GPRel64BlockAddress);
128 IO.enumCase(EntryKind, "gp-rel32-block-address",
129 MachineJumpTableInfo::EK_GPRel32BlockAddress);
130 IO.enumCase(EntryKind, "label-difference32",
131 MachineJumpTableInfo::EK_LabelDifference32);
132 IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline);
133 IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32);
137 } // end namespace yaml
138 } // end namespace llvm
140 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
141 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
142 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
147 struct VirtualRegisterDefinition {
150 StringValue PreferredRegister;
151 // TODO: Serialize the target specific register hints.
152 bool operator==(const VirtualRegisterDefinition &Other) const {
153 return ID == Other.ID && Class == Other.Class &&
154 PreferredRegister == Other.PreferredRegister;
158 template <> struct MappingTraits<VirtualRegisterDefinition> {
159 static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
160 YamlIO.mapRequired("id", Reg.ID);
161 YamlIO.mapRequired("class", Reg.Class);
162 YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
163 StringValue()); // Don't print out when it's empty.
166 static const bool flow = true;
169 struct MachineFunctionLiveIn {
170 StringValue Register;
171 StringValue VirtualRegister;
172 bool operator==(const MachineFunctionLiveIn &Other) const {
173 return Register == Other.Register &&
174 VirtualRegister == Other.VirtualRegister;
178 template <> struct MappingTraits<MachineFunctionLiveIn> {
179 static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
180 YamlIO.mapRequired("reg", LiveIn.Register);
182 "virtual-reg", LiveIn.VirtualRegister,
183 StringValue()); // Don't print the virtual register when it's empty.
186 static const bool flow = true;
189 /// Serializable representation of stack object from the MachineFrameInfo class.
191 /// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
192 /// determined by the object's type and frame information flags.
193 /// Dead stack objects aren't serialized.
195 /// The 'isPreallocated' flag is determined by the local offset.
196 struct MachineStackObject {
197 enum ObjectType { DefaultType, SpillSlot, VariableSized };
200 // TODO: Serialize unnamed LLVM alloca reference.
201 ObjectType Type = DefaultType;
204 unsigned Alignment = 0;
205 StringValue CalleeSavedRegister;
206 Optional<int64_t> LocalOffset;
207 StringValue DebugVar;
208 StringValue DebugExpr;
209 StringValue DebugLoc;
210 bool operator==(const MachineStackObject &Other) const {
211 return ID == Other.ID && Name == Other.Name && Type == Other.Type &&
212 Offset == Other.Offset && Size == Other.Size &&
213 Alignment == Other.Alignment &&
214 CalleeSavedRegister == Other.CalleeSavedRegister &&
215 LocalOffset == Other.LocalOffset && DebugVar == Other.DebugVar &&
216 DebugExpr == Other.DebugExpr && DebugLoc == Other.DebugLoc;
220 template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
221 static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
222 IO.enumCase(Type, "default", MachineStackObject::DefaultType);
223 IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
224 IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
228 template <> struct MappingTraits<MachineStackObject> {
229 static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
230 YamlIO.mapRequired("id", Object.ID);
231 YamlIO.mapOptional("name", Object.Name,
232 StringValue()); // Don't print out an empty name.
235 MachineStackObject::DefaultType); // Don't print the default type.
236 YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
237 if (Object.Type != MachineStackObject::VariableSized)
238 YamlIO.mapRequired("size", Object.Size);
239 YamlIO.mapOptional("alignment", Object.Alignment, (unsigned)0);
240 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
241 StringValue()); // Don't print it out when it's empty.
242 YamlIO.mapOptional("local-offset", Object.LocalOffset, Optional<int64_t>());
243 YamlIO.mapOptional("di-variable", Object.DebugVar,
244 StringValue()); // Don't print it out when it's empty.
245 YamlIO.mapOptional("di-expression", Object.DebugExpr,
246 StringValue()); // Don't print it out when it's empty.
247 YamlIO.mapOptional("di-location", Object.DebugLoc,
248 StringValue()); // Don't print it out when it's empty.
251 static const bool flow = true;
254 /// Serializable representation of the fixed stack object from the
255 /// MachineFrameInfo class.
256 struct FixedMachineStackObject {
257 enum ObjectType { DefaultType, SpillSlot };
259 ObjectType Type = DefaultType;
262 unsigned Alignment = 0;
263 bool IsImmutable = false;
264 bool IsAliased = false;
265 StringValue CalleeSavedRegister;
266 bool operator==(const FixedMachineStackObject &Other) const {
267 return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
268 Size == Other.Size && Alignment == Other.Alignment &&
269 IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
270 CalleeSavedRegister == Other.CalleeSavedRegister;
275 struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
276 static void enumeration(yaml::IO &IO,
277 FixedMachineStackObject::ObjectType &Type) {
278 IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
279 IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
283 template <> struct MappingTraits<FixedMachineStackObject> {
284 static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
285 YamlIO.mapRequired("id", Object.ID);
288 FixedMachineStackObject::DefaultType); // Don't print the default type.
289 YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
290 YamlIO.mapOptional("size", Object.Size, (uint64_t)0);
291 YamlIO.mapOptional("alignment", Object.Alignment, (unsigned)0);
292 if (Object.Type != FixedMachineStackObject::SpillSlot) {
293 YamlIO.mapOptional("isImmutable", Object.IsImmutable, false);
294 YamlIO.mapOptional("isAliased", Object.IsAliased, false);
296 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
297 StringValue()); // Don't print it out when it's empty.
300 static const bool flow = true;
303 struct MachineConstantPoolValue {
306 unsigned Alignment = 0;
307 bool operator==(const MachineConstantPoolValue &Other) const {
308 return ID == Other.ID && Value == Other.Value &&
309 Alignment == Other.Alignment;
313 template <> struct MappingTraits<MachineConstantPoolValue> {
314 static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
315 YamlIO.mapRequired("id", Constant.ID);
316 YamlIO.mapOptional("value", Constant.Value, StringValue());
317 YamlIO.mapOptional("alignment", Constant.Alignment, (unsigned)0);
321 struct MachineJumpTable {
324 std::vector<FlowStringValue> Blocks;
325 bool operator==(const Entry &Other) const {
326 return ID == Other.ID && Blocks == Other.Blocks;
330 MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
331 std::vector<Entry> Entries;
332 bool operator==(const MachineJumpTable &Other) const {
333 return Kind == Other.Kind && Entries == Other.Entries;
337 template <> struct MappingTraits<MachineJumpTable::Entry> {
338 static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
339 YamlIO.mapRequired("id", Entry.ID);
340 YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>());
344 } // end namespace yaml
345 } // end namespace llvm
347 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
348 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
349 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
350 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
351 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
352 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
357 template <> struct MappingTraits<MachineJumpTable> {
358 static void mapping(IO &YamlIO, MachineJumpTable &JT) {
359 YamlIO.mapRequired("kind", JT.Kind);
360 YamlIO.mapOptional("entries", JT.Entries,
361 std::vector<MachineJumpTable::Entry>());
365 /// Serializable representation of MachineFrameInfo.
367 /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
368 /// 'RealignOption' as they are determined by the target and LLVM function
370 /// It also doesn't serialize attributes like 'NumFixedObject' and
371 /// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
372 struct MachineFrameInfo {
373 bool IsFrameAddressTaken = false;
374 bool IsReturnAddressTaken = false;
375 bool HasStackMap = false;
376 bool HasPatchPoint = false;
377 uint64_t StackSize = 0;
378 int OffsetAdjustment = 0;
379 unsigned MaxAlignment = 0;
380 bool AdjustsStack = false;
381 bool HasCalls = false;
382 StringValue StackProtector;
383 // TODO: Serialize FunctionContextIdx
384 unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
385 bool HasOpaqueSPAdjustment = false;
386 bool HasVAStart = false;
387 bool HasMustTailInVarArgFunc = false;
388 StringValue SavePoint;
389 StringValue RestorePoint;
390 bool operator==(const MachineFrameInfo &Other) const {
391 return IsFrameAddressTaken == Other.IsFrameAddressTaken &&
392 IsReturnAddressTaken == Other.IsReturnAddressTaken &&
393 HasStackMap == Other.HasStackMap &&
394 HasPatchPoint == Other.HasPatchPoint &&
395 StackSize == Other.StackSize &&
396 OffsetAdjustment == Other.OffsetAdjustment &&
397 MaxAlignment == Other.MaxAlignment &&
398 AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
399 StackProtector == Other.StackProtector &&
400 MaxCallFrameSize == Other.MaxCallFrameSize &&
401 HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
402 HasVAStart == Other.HasVAStart &&
403 HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
404 SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint;
408 template <> struct MappingTraits<MachineFrameInfo> {
409 static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
410 YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false);
411 YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false);
412 YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false);
413 YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false);
414 YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0);
415 YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0);
416 YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
417 YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
418 YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
419 YamlIO.mapOptional("stackProtector", MFI.StackProtector,
420 StringValue()); // Don't print it out when it's empty.
421 YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0);
422 YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,
424 YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
425 YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
427 YamlIO.mapOptional("savePoint", MFI.SavePoint,
428 StringValue()); // Don't print it out when it's empty.
429 YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
430 StringValue()); // Don't print it out when it's empty.
434 struct MachineFunction {
436 unsigned Alignment = 0;
437 bool ExposesReturnsTwice = false;
438 // GISel MachineFunctionProperties.
439 bool Legalized = false;
440 bool RegBankSelected = false;
441 bool Selected = false;
442 // Register information
443 bool TracksRegLiveness = false;
444 std::vector<VirtualRegisterDefinition> VirtualRegisters;
445 std::vector<MachineFunctionLiveIn> LiveIns;
446 Optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
447 // TODO: Serialize the various register masks.
449 MachineFrameInfo FrameInfo;
450 std::vector<FixedMachineStackObject> FixedStackObjects;
451 std::vector<MachineStackObject> StackObjects;
452 std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
453 MachineJumpTable JumpTableInfo;
454 BlockStringValue Body;
457 template <> struct MappingTraits<MachineFunction> {
458 static void mapping(IO &YamlIO, MachineFunction &MF) {
459 YamlIO.mapRequired("name", MF.Name);
460 YamlIO.mapOptional("alignment", MF.Alignment, (unsigned)0);
461 YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false);
462 YamlIO.mapOptional("legalized", MF.Legalized, false);
463 YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
464 YamlIO.mapOptional("selected", MF.Selected, false);
465 YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
466 YamlIO.mapOptional("registers", MF.VirtualRegisters,
467 std::vector<VirtualRegisterDefinition>());
468 YamlIO.mapOptional("liveins", MF.LiveIns,
469 std::vector<MachineFunctionLiveIn>());
470 YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters,
471 Optional<std::vector<FlowStringValue>>());
472 YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo());
473 YamlIO.mapOptional("fixedStack", MF.FixedStackObjects,
474 std::vector<FixedMachineStackObject>());
475 YamlIO.mapOptional("stack", MF.StackObjects,
476 std::vector<MachineStackObject>());
477 YamlIO.mapOptional("constants", MF.Constants,
478 std::vector<MachineConstantPoolValue>());
479 if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
480 YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
481 YamlIO.mapOptional("body", MF.Body, BlockStringValue());
485 } // end namespace yaml
486 } // end namespace llvm