1 //===- MIRYamlMapping.h - Describe mapping between MIR and YAML--*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the mapping between various MIR data structures and 10 // their corresponding YAML representation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CODEGEN_MIRYAMLMAPPING_H 15 #define LLVM_CODEGEN_MIRYAMLMAPPING_H 16 17 #include "llvm/ADT/Optional.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/CodeGen/MachineJumpTableInfo.h" 20 #include "llvm/CodeGen/TargetFrameLowering.h" 21 #include "llvm/Support/SMLoc.h" 22 #include "llvm/Support/YAMLTraits.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include <algorithm> 25 #include <cstdint> 26 #include <string> 27 #include <vector> 28 29 namespace llvm { 30 namespace yaml { 31 32 /// A wrapper around std::string which contains a source range that's being 33 /// set during parsing. 34 struct StringValue { 35 std::string Value; 36 SMRange SourceRange; 37 38 StringValue() = default; StringValueStringValue39 StringValue(std::string Value) : Value(std::move(Value)) {} StringValueStringValue40 StringValue(const char Val[]) : Value(Val) {} 41 42 bool operator==(const StringValue &Other) const { 43 return Value == Other.Value; 44 } 45 }; 46 47 template <> struct ScalarTraits<StringValue> { 48 static void output(const StringValue &S, void *, raw_ostream &OS) { 49 OS << S.Value; 50 } 51 52 static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) { 53 S.Value = Scalar.str(); 54 if (const auto *Node = 55 reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode()) 56 S.SourceRange = Node->getSourceRange(); 57 return ""; 58 } 59 60 static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } 61 }; 62 63 struct FlowStringValue : StringValue { 64 FlowStringValue() = default; 65 FlowStringValue(std::string Value) : StringValue(std::move(Value)) {} 66 }; 67 68 template <> struct ScalarTraits<FlowStringValue> { 69 static void output(const FlowStringValue &S, void *, raw_ostream &OS) { 70 return ScalarTraits<StringValue>::output(S, nullptr, OS); 71 } 72 73 static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) { 74 return ScalarTraits<StringValue>::input(Scalar, Ctx, S); 75 } 76 77 static QuotingType mustQuote(StringRef S) { return needsQuotes(S); } 78 }; 79 80 struct BlockStringValue { 81 StringValue Value; 82 83 bool operator==(const BlockStringValue &Other) const { 84 return Value == Other.Value; 85 } 86 }; 87 88 template <> struct BlockScalarTraits<BlockStringValue> { 89 static void output(const BlockStringValue &S, void *Ctx, raw_ostream &OS) { 90 return ScalarTraits<StringValue>::output(S.Value, Ctx, OS); 91 } 92 93 static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) { 94 return ScalarTraits<StringValue>::input(Scalar, Ctx, S.Value); 95 } 96 }; 97 98 /// A wrapper around unsigned which contains a source range that's being set 99 /// during parsing. 100 struct UnsignedValue { 101 unsigned Value = 0; 102 SMRange SourceRange; 103 104 UnsignedValue() = default; 105 UnsignedValue(unsigned Value) : Value(Value) {} 106 107 bool operator==(const UnsignedValue &Other) const { 108 return Value == Other.Value; 109 } 110 }; 111 112 template <> struct ScalarTraits<UnsignedValue> { 113 static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) { 114 return ScalarTraits<unsigned>::output(Value.Value, Ctx, OS); 115 } 116 117 static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) { 118 if (const auto *Node = 119 reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode()) 120 Value.SourceRange = Node->getSourceRange(); 121 return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value); 122 } 123 124 static QuotingType mustQuote(StringRef Scalar) { 125 return ScalarTraits<unsigned>::mustQuote(Scalar); 126 } 127 }; 128 129 template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> { 130 static void enumeration(yaml::IO &IO, 131 MachineJumpTableInfo::JTEntryKind &EntryKind) { 132 IO.enumCase(EntryKind, "block-address", 133 MachineJumpTableInfo::EK_BlockAddress); 134 IO.enumCase(EntryKind, "gp-rel64-block-address", 135 MachineJumpTableInfo::EK_GPRel64BlockAddress); 136 IO.enumCase(EntryKind, "gp-rel32-block-address", 137 MachineJumpTableInfo::EK_GPRel32BlockAddress); 138 IO.enumCase(EntryKind, "label-difference32", 139 MachineJumpTableInfo::EK_LabelDifference32); 140 IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline); 141 IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32); 142 } 143 }; 144 145 template <> struct ScalarTraits<MaybeAlign> { 146 static void output(const MaybeAlign &Alignment, void *, 147 llvm::raw_ostream &out) { 148 out << uint64_t(Alignment ? Alignment->value() : 0U); 149 } 150 static StringRef input(StringRef Scalar, void *, MaybeAlign &Alignment) { 151 unsigned long long n; 152 if (getAsUnsignedInteger(Scalar, 10, n)) 153 return "invalid number"; 154 if (n > 0 && !isPowerOf2_64(n)) 155 return "must be 0 or a power of two"; 156 Alignment = MaybeAlign(n); 157 return StringRef(); 158 } 159 static QuotingType mustQuote(StringRef) { return QuotingType::None; } 160 }; 161 162 } // end namespace yaml 163 } // end namespace llvm 164 165 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue) 166 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue) 167 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue) 168 169 namespace llvm { 170 namespace yaml { 171 172 struct VirtualRegisterDefinition { 173 UnsignedValue ID; 174 StringValue Class; 175 StringValue PreferredRegister; 176 177 // TODO: Serialize the target specific register hints. 178 179 bool operator==(const VirtualRegisterDefinition &Other) const { 180 return ID == Other.ID && Class == Other.Class && 181 PreferredRegister == Other.PreferredRegister; 182 } 183 }; 184 185 template <> struct MappingTraits<VirtualRegisterDefinition> { 186 static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) { 187 YamlIO.mapRequired("id", Reg.ID); 188 YamlIO.mapRequired("class", Reg.Class); 189 YamlIO.mapOptional("preferred-register", Reg.PreferredRegister, 190 StringValue()); // Don't print out when it's empty. 191 } 192 193 static const bool flow = true; 194 }; 195 196 struct MachineFunctionLiveIn { 197 StringValue Register; 198 StringValue VirtualRegister; 199 200 bool operator==(const MachineFunctionLiveIn &Other) const { 201 return Register == Other.Register && 202 VirtualRegister == Other.VirtualRegister; 203 } 204 }; 205 206 template <> struct MappingTraits<MachineFunctionLiveIn> { 207 static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) { 208 YamlIO.mapRequired("reg", LiveIn.Register); 209 YamlIO.mapOptional( 210 "virtual-reg", LiveIn.VirtualRegister, 211 StringValue()); // Don't print the virtual register when it's empty. 212 } 213 214 static const bool flow = true; 215 }; 216 217 /// Serializable representation of stack object from the MachineFrameInfo class. 218 /// 219 /// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are 220 /// determined by the object's type and frame information flags. 221 /// Dead stack objects aren't serialized. 222 /// 223 /// The 'isPreallocated' flag is determined by the local offset. 224 struct MachineStackObject { 225 enum ObjectType { DefaultType, SpillSlot, VariableSized }; 226 UnsignedValue ID; 227 StringValue Name; 228 // TODO: Serialize unnamed LLVM alloca reference. 229 ObjectType Type = DefaultType; 230 int64_t Offset = 0; 231 uint64_t Size = 0; 232 MaybeAlign Alignment = None; 233 TargetStackID::Value StackID; 234 StringValue CalleeSavedRegister; 235 bool CalleeSavedRestored = true; 236 Optional<int64_t> LocalOffset; 237 StringValue DebugVar; 238 StringValue DebugExpr; 239 StringValue DebugLoc; 240 241 bool operator==(const MachineStackObject &Other) const { 242 return ID == Other.ID && Name == Other.Name && Type == Other.Type && 243 Offset == Other.Offset && Size == Other.Size && 244 Alignment == Other.Alignment && 245 StackID == Other.StackID && 246 CalleeSavedRegister == Other.CalleeSavedRegister && 247 CalleeSavedRestored == Other.CalleeSavedRestored && 248 LocalOffset == Other.LocalOffset && DebugVar == Other.DebugVar && 249 DebugExpr == Other.DebugExpr && DebugLoc == Other.DebugLoc; 250 } 251 }; 252 253 template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> { 254 static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) { 255 IO.enumCase(Type, "default", MachineStackObject::DefaultType); 256 IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot); 257 IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized); 258 } 259 }; 260 261 template <> struct MappingTraits<MachineStackObject> { 262 static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) { 263 YamlIO.mapRequired("id", Object.ID); 264 YamlIO.mapOptional("name", Object.Name, 265 StringValue()); // Don't print out an empty name. 266 YamlIO.mapOptional( 267 "type", Object.Type, 268 MachineStackObject::DefaultType); // Don't print the default type. 269 YamlIO.mapOptional("offset", Object.Offset, (int64_t)0); 270 if (Object.Type != MachineStackObject::VariableSized) 271 YamlIO.mapRequired("size", Object.Size); 272 YamlIO.mapOptional("alignment", Object.Alignment, None); 273 YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); 274 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, 275 StringValue()); // Don't print it out when it's empty. 276 YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, 277 true); 278 YamlIO.mapOptional("local-offset", Object.LocalOffset, Optional<int64_t>()); 279 YamlIO.mapOptional("debug-info-variable", Object.DebugVar, 280 StringValue()); // Don't print it out when it's empty. 281 YamlIO.mapOptional("debug-info-expression", Object.DebugExpr, 282 StringValue()); // Don't print it out when it's empty. 283 YamlIO.mapOptional("debug-info-location", Object.DebugLoc, 284 StringValue()); // Don't print it out when it's empty. 285 } 286 287 static const bool flow = true; 288 }; 289 290 /// Serializable representation of the fixed stack object from the 291 /// MachineFrameInfo class. 292 struct FixedMachineStackObject { 293 enum ObjectType { DefaultType, SpillSlot }; 294 UnsignedValue ID; 295 ObjectType Type = DefaultType; 296 int64_t Offset = 0; 297 uint64_t Size = 0; 298 MaybeAlign Alignment = None; 299 TargetStackID::Value StackID; 300 bool IsImmutable = false; 301 bool IsAliased = false; 302 StringValue CalleeSavedRegister; 303 bool CalleeSavedRestored = true; 304 StringValue DebugVar; 305 StringValue DebugExpr; 306 StringValue DebugLoc; 307 308 bool operator==(const FixedMachineStackObject &Other) const { 309 return ID == Other.ID && Type == Other.Type && Offset == Other.Offset && 310 Size == Other.Size && Alignment == Other.Alignment && 311 StackID == Other.StackID && 312 IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased && 313 CalleeSavedRegister == Other.CalleeSavedRegister && 314 CalleeSavedRestored == Other.CalleeSavedRestored && 315 DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr 316 && DebugLoc == Other.DebugLoc; 317 } 318 }; 319 320 template <> 321 struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> { 322 static void enumeration(yaml::IO &IO, 323 FixedMachineStackObject::ObjectType &Type) { 324 IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType); 325 IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot); 326 } 327 }; 328 329 template <> 330 struct ScalarEnumerationTraits<TargetStackID::Value> { 331 static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) { 332 IO.enumCase(ID, "default", TargetStackID::Default); 333 IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill); 334 IO.enumCase(ID, "sve-vec", TargetStackID::SVEVector); 335 IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc); 336 } 337 }; 338 339 template <> struct MappingTraits<FixedMachineStackObject> { 340 static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) { 341 YamlIO.mapRequired("id", Object.ID); 342 YamlIO.mapOptional( 343 "type", Object.Type, 344 FixedMachineStackObject::DefaultType); // Don't print the default type. 345 YamlIO.mapOptional("offset", Object.Offset, (int64_t)0); 346 YamlIO.mapOptional("size", Object.Size, (uint64_t)0); 347 YamlIO.mapOptional("alignment", Object.Alignment, None); 348 YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); 349 if (Object.Type != FixedMachineStackObject::SpillSlot) { 350 YamlIO.mapOptional("isImmutable", Object.IsImmutable, false); 351 YamlIO.mapOptional("isAliased", Object.IsAliased, false); 352 } 353 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, 354 StringValue()); // Don't print it out when it's empty. 355 YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, 356 true); 357 YamlIO.mapOptional("debug-info-variable", Object.DebugVar, 358 StringValue()); // Don't print it out when it's empty. 359 YamlIO.mapOptional("debug-info-expression", Object.DebugExpr, 360 StringValue()); // Don't print it out when it's empty. 361 YamlIO.mapOptional("debug-info-location", Object.DebugLoc, 362 StringValue()); // Don't print it out when it's empty. 363 } 364 365 static const bool flow = true; 366 }; 367 368 369 /// Serializable representation of CallSiteInfo. 370 struct CallSiteInfo { 371 // Representation of call argument and register which is used to 372 // transfer it. 373 struct ArgRegPair { 374 StringValue Reg; 375 uint16_t ArgNo; 376 377 bool operator==(const ArgRegPair &Other) const { 378 return Reg == Other.Reg && ArgNo == Other.ArgNo; 379 } 380 }; 381 382 /// Identifies call instruction location in machine function. 383 struct MachineInstrLoc { 384 unsigned BlockNum; 385 unsigned Offset; 386 387 bool operator==(const MachineInstrLoc &Other) const { 388 return BlockNum == Other.BlockNum && Offset == Other.Offset; 389 } 390 }; 391 392 MachineInstrLoc CallLocation; 393 std::vector<ArgRegPair> ArgForwardingRegs; 394 395 bool operator==(const CallSiteInfo &Other) const { 396 return CallLocation.BlockNum == Other.CallLocation.BlockNum && 397 CallLocation.Offset == Other.CallLocation.Offset; 398 } 399 }; 400 401 template <> struct MappingTraits<CallSiteInfo::ArgRegPair> { 402 static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) { 403 YamlIO.mapRequired("arg", ArgReg.ArgNo); 404 YamlIO.mapRequired("reg", ArgReg.Reg); 405 } 406 407 static const bool flow = true; 408 }; 409 } 410 } 411 412 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair) 413 414 namespace llvm { 415 namespace yaml { 416 417 template <> struct MappingTraits<CallSiteInfo> { 418 static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) { 419 YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum); 420 YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset); 421 YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs, 422 std::vector<CallSiteInfo::ArgRegPair>()); 423 } 424 425 static const bool flow = true; 426 }; 427 428 struct MachineConstantPoolValue { 429 UnsignedValue ID; 430 StringValue Value; 431 MaybeAlign Alignment = None; 432 bool IsTargetSpecific = false; 433 434 bool operator==(const MachineConstantPoolValue &Other) const { 435 return ID == Other.ID && Value == Other.Value && 436 Alignment == Other.Alignment && 437 IsTargetSpecific == Other.IsTargetSpecific; 438 } 439 }; 440 441 template <> struct MappingTraits<MachineConstantPoolValue> { 442 static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) { 443 YamlIO.mapRequired("id", Constant.ID); 444 YamlIO.mapOptional("value", Constant.Value, StringValue()); 445 YamlIO.mapOptional("alignment", Constant.Alignment, None); 446 YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false); 447 } 448 }; 449 450 struct MachineJumpTable { 451 struct Entry { 452 UnsignedValue ID; 453 std::vector<FlowStringValue> Blocks; 454 455 bool operator==(const Entry &Other) const { 456 return ID == Other.ID && Blocks == Other.Blocks; 457 } 458 }; 459 460 MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32; 461 std::vector<Entry> Entries; 462 463 bool operator==(const MachineJumpTable &Other) const { 464 return Kind == Other.Kind && Entries == Other.Entries; 465 } 466 }; 467 468 template <> struct MappingTraits<MachineJumpTable::Entry> { 469 static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) { 470 YamlIO.mapRequired("id", Entry.ID); 471 YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>()); 472 } 473 }; 474 475 } // end namespace yaml 476 } // end namespace llvm 477 478 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn) 479 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) 480 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) 481 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) 482 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo) 483 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue) 484 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry) 485 486 namespace llvm { 487 namespace yaml { 488 489 template <> struct MappingTraits<MachineJumpTable> { 490 static void mapping(IO &YamlIO, MachineJumpTable &JT) { 491 YamlIO.mapRequired("kind", JT.Kind); 492 YamlIO.mapOptional("entries", JT.Entries, 493 std::vector<MachineJumpTable::Entry>()); 494 } 495 }; 496 497 /// Serializable representation of MachineFrameInfo. 498 /// 499 /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and 500 /// 'RealignOption' as they are determined by the target and LLVM function 501 /// attributes. 502 /// It also doesn't serialize attributes like 'NumFixedObject' and 503 /// 'HasVarSizedObjects' as they are determined by the frame objects themselves. 504 struct MachineFrameInfo { 505 bool IsFrameAddressTaken = false; 506 bool IsReturnAddressTaken = false; 507 bool HasStackMap = false; 508 bool HasPatchPoint = false; 509 uint64_t StackSize = 0; 510 int OffsetAdjustment = 0; 511 unsigned MaxAlignment = 0; 512 bool AdjustsStack = false; 513 bool HasCalls = false; 514 StringValue StackProtector; 515 // TODO: Serialize FunctionContextIdx 516 unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet. 517 unsigned CVBytesOfCalleeSavedRegisters = 0; 518 bool HasOpaqueSPAdjustment = false; 519 bool HasVAStart = false; 520 bool HasMustTailInVarArgFunc = false; 521 unsigned LocalFrameSize = 0; 522 StringValue SavePoint; 523 StringValue RestorePoint; 524 525 bool operator==(const MachineFrameInfo &Other) const { 526 return IsFrameAddressTaken == Other.IsFrameAddressTaken && 527 IsReturnAddressTaken == Other.IsReturnAddressTaken && 528 HasStackMap == Other.HasStackMap && 529 HasPatchPoint == Other.HasPatchPoint && 530 StackSize == Other.StackSize && 531 OffsetAdjustment == Other.OffsetAdjustment && 532 MaxAlignment == Other.MaxAlignment && 533 AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls && 534 StackProtector == Other.StackProtector && 535 MaxCallFrameSize == Other.MaxCallFrameSize && 536 CVBytesOfCalleeSavedRegisters == 537 Other.CVBytesOfCalleeSavedRegisters && 538 HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment && 539 HasVAStart == Other.HasVAStart && 540 HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc && 541 LocalFrameSize == Other.LocalFrameSize && 542 SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint; 543 } 544 }; 545 546 template <> struct MappingTraits<MachineFrameInfo> { 547 static void mapping(IO &YamlIO, MachineFrameInfo &MFI) { 548 YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false); 549 YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false); 550 YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false); 551 YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false); 552 YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0); 553 YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0); 554 YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0); 555 YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false); 556 YamlIO.mapOptional("hasCalls", MFI.HasCalls, false); 557 YamlIO.mapOptional("stackProtector", MFI.StackProtector, 558 StringValue()); // Don't print it out when it's empty. 559 YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0); 560 YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters", 561 MFI.CVBytesOfCalleeSavedRegisters, 0U); 562 YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment, 563 false); 564 YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false); 565 YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc, 566 false); 567 YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0); 568 YamlIO.mapOptional("savePoint", MFI.SavePoint, 569 StringValue()); // Don't print it out when it's empty. 570 YamlIO.mapOptional("restorePoint", MFI.RestorePoint, 571 StringValue()); // Don't print it out when it's empty. 572 } 573 }; 574 575 /// Targets should override this in a way that mirrors the implementation of 576 /// llvm::MachineFunctionInfo. 577 struct MachineFunctionInfo { 578 virtual ~MachineFunctionInfo() {} 579 virtual void mappingImpl(IO &YamlIO) {} 580 }; 581 582 template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> { 583 static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) { 584 if (MFI) 585 MFI->mappingImpl(YamlIO); 586 } 587 }; 588 589 struct MachineFunction { 590 StringRef Name; 591 MaybeAlign Alignment = None; 592 bool ExposesReturnsTwice = false; 593 // GISel MachineFunctionProperties. 594 bool Legalized = false; 595 bool RegBankSelected = false; 596 bool Selected = false; 597 bool FailedISel = false; 598 // Register information 599 bool TracksRegLiveness = false; 600 bool HasWinCFI = false; 601 std::vector<VirtualRegisterDefinition> VirtualRegisters; 602 std::vector<MachineFunctionLiveIn> LiveIns; 603 Optional<std::vector<FlowStringValue>> CalleeSavedRegisters; 604 // TODO: Serialize the various register masks. 605 // Frame information 606 MachineFrameInfo FrameInfo; 607 std::vector<FixedMachineStackObject> FixedStackObjects; 608 std::vector<MachineStackObject> StackObjects; 609 std::vector<MachineConstantPoolValue> Constants; /// Constant pool. 610 std::unique_ptr<MachineFunctionInfo> MachineFuncInfo; 611 std::vector<CallSiteInfo> CallSitesInfo; 612 MachineJumpTable JumpTableInfo; 613 BlockStringValue Body; 614 }; 615 616 template <> struct MappingTraits<MachineFunction> { 617 static void mapping(IO &YamlIO, MachineFunction &MF) { 618 YamlIO.mapRequired("name", MF.Name); 619 YamlIO.mapOptional("alignment", MF.Alignment, None); 620 YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false); 621 YamlIO.mapOptional("legalized", MF.Legalized, false); 622 YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false); 623 YamlIO.mapOptional("selected", MF.Selected, false); 624 YamlIO.mapOptional("failedISel", MF.FailedISel, false); 625 YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false); 626 YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false); 627 YamlIO.mapOptional("registers", MF.VirtualRegisters, 628 std::vector<VirtualRegisterDefinition>()); 629 YamlIO.mapOptional("liveins", MF.LiveIns, 630 std::vector<MachineFunctionLiveIn>()); 631 YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters, 632 Optional<std::vector<FlowStringValue>>()); 633 YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo()); 634 YamlIO.mapOptional("fixedStack", MF.FixedStackObjects, 635 std::vector<FixedMachineStackObject>()); 636 YamlIO.mapOptional("stack", MF.StackObjects, 637 std::vector<MachineStackObject>()); 638 YamlIO.mapOptional("callSites", MF.CallSitesInfo, 639 std::vector<CallSiteInfo>()); 640 YamlIO.mapOptional("constants", MF.Constants, 641 std::vector<MachineConstantPoolValue>()); 642 YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo); 643 if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty()) 644 YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable()); 645 YamlIO.mapOptional("body", MF.Body, BlockStringValue()); 646 } 647 }; 648 649 } // end namespace yaml 650 } // end namespace llvm 651 652 #endif // LLVM_CODEGEN_MIRYAMLMAPPING_H 653