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 23namespace llvm { 24namespace yaml { 25 26/// A wrapper around std::string which contains a source range that's being 27/// set during parsing. 28struct StringValue { 29 std::string Value; 30 SMRange SourceRange; 31 32 StringValue() {} 33 StringValue(std::string Value) : Value(std::move(Value)) {} 34 35 bool operator==(const StringValue &Other) const { 36 return Value == Other.Value; 37 } 38}; 39 40template <> 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 56struct FlowStringValue : StringValue { 57 FlowStringValue() {} 58 FlowStringValue(std::string Value) : StringValue(std::move(Value)) {} 59}; 60 61template <> 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 73struct BlockStringValue { 74 StringValue Value; 75 bool operator==(const BlockStringValue &Other) const { 76 return Value == Other.Value; 77 } 78}; 79 80template <> struct BlockScalarTraits<BlockStringValue> { 81 static void output(const BlockStringValue &S, void *Ctx, raw_ostream &OS) { 82 return ScalarTraits<StringValue>::output(S.Value, Ctx, OS); 83 } 84 85 static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) { 86 return ScalarTraits<StringValue>::input(Scalar, Ctx, S.Value); 87 } 88}; 89 90/// A wrapper around unsigned which contains a source range that's being set 91/// during parsing. 92struct UnsignedValue { 93 unsigned Value; 94 SMRange SourceRange; 95 96 UnsignedValue() : Value(0) {} 97 UnsignedValue(unsigned Value) : Value(Value) {} 98 99 bool operator==(const UnsignedValue &Other) const { 100 return Value == Other.Value; 101 } 102}; 103 104template <> struct ScalarTraits<UnsignedValue> { 105 static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) { 106 return ScalarTraits<unsigned>::output(Value.Value, Ctx, OS); 107 } 108 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); 114 } 115 116 static bool mustQuote(StringRef Scalar) { 117 return ScalarTraits<unsigned>::mustQuote(Scalar); 118 } 119}; 120 121template <> 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); 134 } 135}; 136 137} // end namespace yaml 138} // end namespace llvm 139 140LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue) 141LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue) 142LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue) 143 144namespace llvm { 145namespace yaml { 146 147struct VirtualRegisterDefinition { 148 UnsignedValue ID; 149 StringValue Class; 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; 155 } 156}; 157 158template <> 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. 164 } 165 166 static const bool flow = true; 167}; 168 169struct MachineFunctionLiveIn { 170 StringValue Register; 171 StringValue VirtualRegister; 172 bool operator==(const MachineFunctionLiveIn &Other) const { 173 return Register == Other.Register && 174 VirtualRegister == Other.VirtualRegister; 175 } 176}; 177 178template <> struct MappingTraits<MachineFunctionLiveIn> { 179 static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) { 180 YamlIO.mapRequired("reg", LiveIn.Register); 181 YamlIO.mapOptional( 182 "virtual-reg", LiveIn.VirtualRegister, 183 StringValue()); // Don't print the virtual register when it's empty. 184 } 185 186 static const bool flow = true; 187}; 188 189/// Serializable representation of stack object from the MachineFrameInfo class. 190/// 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. 194/// 195/// The 'isPreallocated' flag is determined by the local offset. 196struct MachineStackObject { 197 enum ObjectType { DefaultType, SpillSlot, VariableSized }; 198 UnsignedValue ID; 199 StringValue Name; 200 // TODO: Serialize unnamed LLVM alloca reference. 201 ObjectType Type = DefaultType; 202 int64_t Offset = 0; 203 uint64_t Size = 0; 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; 217 } 218}; 219 220template <> 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); 225 } 226}; 227 228template <> 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. 233 YamlIO.mapOptional( 234 "type", Object.Type, 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. 249 } 250 251 static const bool flow = true; 252}; 253 254/// Serializable representation of the fixed stack object from the 255/// MachineFrameInfo class. 256struct FixedMachineStackObject { 257 enum ObjectType { DefaultType, SpillSlot }; 258 UnsignedValue ID; 259 ObjectType Type = DefaultType; 260 int64_t Offset = 0; 261 uint64_t Size = 0; 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; 271 } 272}; 273 274template <> 275struct 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); 280 } 281}; 282 283template <> struct MappingTraits<FixedMachineStackObject> { 284 static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) { 285 YamlIO.mapRequired("id", Object.ID); 286 YamlIO.mapOptional( 287 "type", Object.Type, 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); 295 } 296 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, 297 StringValue()); // Don't print it out when it's empty. 298 } 299 300 static const bool flow = true; 301}; 302 303struct MachineConstantPoolValue { 304 UnsignedValue ID; 305 StringValue Value; 306 unsigned Alignment = 0; 307 bool operator==(const MachineConstantPoolValue &Other) const { 308 return ID == Other.ID && Value == Other.Value && 309 Alignment == Other.Alignment; 310 } 311}; 312 313template <> 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); 318 } 319}; 320 321struct MachineJumpTable { 322 struct Entry { 323 UnsignedValue ID; 324 std::vector<FlowStringValue> Blocks; 325 bool operator==(const Entry &Other) const { 326 return ID == Other.ID && Blocks == Other.Blocks; 327 } 328 }; 329 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; 334 } 335}; 336 337template <> 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>()); 341 } 342}; 343 344} // end namespace yaml 345} // end namespace llvm 346 347LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn) 348LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) 349LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) 350LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) 351LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue) 352LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry) 353 354namespace llvm { 355namespace yaml { 356 357template <> 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>()); 362 } 363}; 364 365/// Serializable representation of MachineFrameInfo. 366/// 367/// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and 368/// 'RealignOption' as they are determined by the target and LLVM function 369/// attributes. 370/// It also doesn't serialize attributes like 'NumFixedObject' and 371/// 'HasVarSizedObjects' as they are determined by the frame objects themselves. 372struct 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; 405 } 406}; 407 408template <> 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, 423 false); 424 YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false); 425 YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc, 426 false); 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. 431 } 432}; 433 434struct MachineFunction { 435 StringRef Name; 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. 448 // Frame information 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; 455}; 456 457template <> 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()); 482 } 483}; 484 485} // end namespace yaml 486} // end namespace llvm 487 488#endif 489