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 29namespace llvm { 30namespace yaml { 31 32/// A wrapper around std::string which contains a source range that's being 33/// set during parsing. 34struct StringValue { 35 std::string Value; 36 SMRange SourceRange; 37 38 StringValue() = default; 39 StringValue(std::string Value) : Value(std::move(Value)) {} 40 StringValue(const char Val[]) : Value(Val) {} 41 42 bool operator==(const StringValue &Other) const { 43 return Value == Other.Value; 44 } 45}; 46 47template <> 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 63struct FlowStringValue : StringValue { 64 FlowStringValue() = default; 65 FlowStringValue(std::string Value) : StringValue(std::move(Value)) {} 66}; 67 68template <> 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 80struct BlockStringValue { 81 StringValue Value; 82 83 bool operator==(const BlockStringValue &Other) const { 84 return Value == Other.Value; 85 } 86}; 87 88template <> 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. 100struct 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 112template <> 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 129template <> 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} // end namespace yaml 146} // end namespace llvm 147 148LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue) 149LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue) 150LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue) 151 152namespace llvm { 153namespace yaml { 154 155struct VirtualRegisterDefinition { 156 UnsignedValue ID; 157 StringValue Class; 158 StringValue PreferredRegister; 159 160 // TODO: Serialize the target specific register hints. 161 162 bool operator==(const VirtualRegisterDefinition &Other) const { 163 return ID == Other.ID && Class == Other.Class && 164 PreferredRegister == Other.PreferredRegister; 165 } 166}; 167 168template <> struct MappingTraits<VirtualRegisterDefinition> { 169 static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) { 170 YamlIO.mapRequired("id", Reg.ID); 171 YamlIO.mapRequired("class", Reg.Class); 172 YamlIO.mapOptional("preferred-register", Reg.PreferredRegister, 173 StringValue()); // Don't print out when it's empty. 174 } 175 176 static const bool flow = true; 177}; 178 179struct MachineFunctionLiveIn { 180 StringValue Register; 181 StringValue VirtualRegister; 182 183 bool operator==(const MachineFunctionLiveIn &Other) const { 184 return Register == Other.Register && 185 VirtualRegister == Other.VirtualRegister; 186 } 187}; 188 189template <> struct MappingTraits<MachineFunctionLiveIn> { 190 static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) { 191 YamlIO.mapRequired("reg", LiveIn.Register); 192 YamlIO.mapOptional( 193 "virtual-reg", LiveIn.VirtualRegister, 194 StringValue()); // Don't print the virtual register when it's empty. 195 } 196 197 static const bool flow = true; 198}; 199 200/// Serializable representation of stack object from the MachineFrameInfo class. 201/// 202/// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are 203/// determined by the object's type and frame information flags. 204/// Dead stack objects aren't serialized. 205/// 206/// The 'isPreallocated' flag is determined by the local offset. 207struct MachineStackObject { 208 enum ObjectType { DefaultType, SpillSlot, VariableSized }; 209 UnsignedValue ID; 210 StringValue Name; 211 // TODO: Serialize unnamed LLVM alloca reference. 212 ObjectType Type = DefaultType; 213 int64_t Offset = 0; 214 uint64_t Size = 0; 215 unsigned Alignment = 0; 216 TargetStackID::Value StackID; 217 StringValue CalleeSavedRegister; 218 bool CalleeSavedRestored = true; 219 Optional<int64_t> LocalOffset; 220 StringValue DebugVar; 221 StringValue DebugExpr; 222 StringValue DebugLoc; 223 224 bool operator==(const MachineStackObject &Other) const { 225 return ID == Other.ID && Name == Other.Name && Type == Other.Type && 226 Offset == Other.Offset && Size == Other.Size && 227 Alignment == Other.Alignment && 228 StackID == Other.StackID && 229 CalleeSavedRegister == Other.CalleeSavedRegister && 230 CalleeSavedRestored == Other.CalleeSavedRestored && 231 LocalOffset == Other.LocalOffset && DebugVar == Other.DebugVar && 232 DebugExpr == Other.DebugExpr && DebugLoc == Other.DebugLoc; 233 } 234}; 235 236template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> { 237 static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) { 238 IO.enumCase(Type, "default", MachineStackObject::DefaultType); 239 IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot); 240 IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized); 241 } 242}; 243 244template <> struct MappingTraits<MachineStackObject> { 245 static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) { 246 YamlIO.mapRequired("id", Object.ID); 247 YamlIO.mapOptional("name", Object.Name, 248 StringValue()); // Don't print out an empty name. 249 YamlIO.mapOptional( 250 "type", Object.Type, 251 MachineStackObject::DefaultType); // Don't print the default type. 252 YamlIO.mapOptional("offset", Object.Offset, (int64_t)0); 253 if (Object.Type != MachineStackObject::VariableSized) 254 YamlIO.mapRequired("size", Object.Size); 255 YamlIO.mapOptional("alignment", Object.Alignment, (unsigned)0); 256 YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); 257 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, 258 StringValue()); // Don't print it out when it's empty. 259 YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, 260 true); 261 YamlIO.mapOptional("local-offset", Object.LocalOffset, Optional<int64_t>()); 262 YamlIO.mapOptional("debug-info-variable", Object.DebugVar, 263 StringValue()); // Don't print it out when it's empty. 264 YamlIO.mapOptional("debug-info-expression", Object.DebugExpr, 265 StringValue()); // Don't print it out when it's empty. 266 YamlIO.mapOptional("debug-info-location", Object.DebugLoc, 267 StringValue()); // Don't print it out when it's empty. 268 } 269 270 static const bool flow = true; 271}; 272 273/// Serializable representation of the fixed stack object from the 274/// MachineFrameInfo class. 275struct FixedMachineStackObject { 276 enum ObjectType { DefaultType, SpillSlot }; 277 UnsignedValue ID; 278 ObjectType Type = DefaultType; 279 int64_t Offset = 0; 280 uint64_t Size = 0; 281 unsigned Alignment = 0; 282 TargetStackID::Value StackID; 283 bool IsImmutable = false; 284 bool IsAliased = false; 285 StringValue CalleeSavedRegister; 286 bool CalleeSavedRestored = true; 287 StringValue DebugVar; 288 StringValue DebugExpr; 289 StringValue DebugLoc; 290 291 bool operator==(const FixedMachineStackObject &Other) const { 292 return ID == Other.ID && Type == Other.Type && Offset == Other.Offset && 293 Size == Other.Size && Alignment == Other.Alignment && 294 StackID == Other.StackID && 295 IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased && 296 CalleeSavedRegister == Other.CalleeSavedRegister && 297 CalleeSavedRestored == Other.CalleeSavedRestored && 298 DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr 299 && DebugLoc == Other.DebugLoc; 300 } 301}; 302 303template <> 304struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> { 305 static void enumeration(yaml::IO &IO, 306 FixedMachineStackObject::ObjectType &Type) { 307 IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType); 308 IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot); 309 } 310}; 311 312template <> 313struct ScalarEnumerationTraits<TargetStackID::Value> { 314 static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) { 315 IO.enumCase(ID, "default", TargetStackID::Default); 316 IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill); 317 IO.enumCase(ID, "sve-vec", TargetStackID::SVEVector); 318 IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc); 319 } 320}; 321 322template <> struct MappingTraits<FixedMachineStackObject> { 323 static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) { 324 YamlIO.mapRequired("id", Object.ID); 325 YamlIO.mapOptional( 326 "type", Object.Type, 327 FixedMachineStackObject::DefaultType); // Don't print the default type. 328 YamlIO.mapOptional("offset", Object.Offset, (int64_t)0); 329 YamlIO.mapOptional("size", Object.Size, (uint64_t)0); 330 YamlIO.mapOptional("alignment", Object.Alignment, (unsigned)0); 331 YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); 332 if (Object.Type != FixedMachineStackObject::SpillSlot) { 333 YamlIO.mapOptional("isImmutable", Object.IsImmutable, false); 334 YamlIO.mapOptional("isAliased", Object.IsAliased, false); 335 } 336 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, 337 StringValue()); // Don't print it out when it's empty. 338 YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, 339 true); 340 YamlIO.mapOptional("debug-info-variable", Object.DebugVar, 341 StringValue()); // Don't print it out when it's empty. 342 YamlIO.mapOptional("debug-info-expression", Object.DebugExpr, 343 StringValue()); // Don't print it out when it's empty. 344 YamlIO.mapOptional("debug-info-location", Object.DebugLoc, 345 StringValue()); // Don't print it out when it's empty. 346 } 347 348 static const bool flow = true; 349}; 350 351 352/// Serializable representation of CallSiteInfo. 353struct CallSiteInfo { 354 // Representation of call argument and register which is used to 355 // transfer it. 356 struct ArgRegPair { 357 StringValue Reg; 358 uint16_t ArgNo; 359 360 bool operator==(const ArgRegPair &Other) const { 361 return Reg == Other.Reg && ArgNo == Other.ArgNo; 362 } 363 }; 364 365 /// Identifies call instruction location in machine function. 366 struct MachineInstrLoc { 367 unsigned BlockNum; 368 unsigned Offset; 369 370 bool operator==(const MachineInstrLoc &Other) const { 371 return BlockNum == Other.BlockNum && Offset == Other.Offset; 372 } 373 }; 374 375 MachineInstrLoc CallLocation; 376 std::vector<ArgRegPair> ArgForwardingRegs; 377 378 bool operator==(const CallSiteInfo &Other) const { 379 return CallLocation.BlockNum == Other.CallLocation.BlockNum && 380 CallLocation.Offset == Other.CallLocation.Offset; 381 } 382}; 383 384template <> struct MappingTraits<CallSiteInfo::ArgRegPair> { 385 static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) { 386 YamlIO.mapRequired("arg", ArgReg.ArgNo); 387 YamlIO.mapRequired("reg", ArgReg.Reg); 388 } 389 390 static const bool flow = true; 391}; 392} 393} 394 395LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair) 396 397namespace llvm { 398namespace yaml { 399 400template <> struct MappingTraits<CallSiteInfo> { 401 static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) { 402 YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum); 403 YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset); 404 YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs, 405 std::vector<CallSiteInfo::ArgRegPair>()); 406 } 407 408 static const bool flow = true; 409}; 410 411struct MachineConstantPoolValue { 412 UnsignedValue ID; 413 StringValue Value; 414 unsigned Alignment = 0; 415 bool IsTargetSpecific = false; 416 417 bool operator==(const MachineConstantPoolValue &Other) const { 418 return ID == Other.ID && Value == Other.Value && 419 Alignment == Other.Alignment && 420 IsTargetSpecific == Other.IsTargetSpecific; 421 } 422}; 423 424template <> struct MappingTraits<MachineConstantPoolValue> { 425 static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) { 426 YamlIO.mapRequired("id", Constant.ID); 427 YamlIO.mapOptional("value", Constant.Value, StringValue()); 428 YamlIO.mapOptional("alignment", Constant.Alignment, (unsigned)0); 429 YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false); 430 } 431}; 432 433struct MachineJumpTable { 434 struct Entry { 435 UnsignedValue ID; 436 std::vector<FlowStringValue> Blocks; 437 438 bool operator==(const Entry &Other) const { 439 return ID == Other.ID && Blocks == Other.Blocks; 440 } 441 }; 442 443 MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32; 444 std::vector<Entry> Entries; 445 446 bool operator==(const MachineJumpTable &Other) const { 447 return Kind == Other.Kind && Entries == Other.Entries; 448 } 449}; 450 451template <> struct MappingTraits<MachineJumpTable::Entry> { 452 static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) { 453 YamlIO.mapRequired("id", Entry.ID); 454 YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>()); 455 } 456}; 457 458} // end namespace yaml 459} // end namespace llvm 460 461LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn) 462LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) 463LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) 464LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) 465LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo) 466LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue) 467LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry) 468 469namespace llvm { 470namespace yaml { 471 472template <> struct MappingTraits<MachineJumpTable> { 473 static void mapping(IO &YamlIO, MachineJumpTable &JT) { 474 YamlIO.mapRequired("kind", JT.Kind); 475 YamlIO.mapOptional("entries", JT.Entries, 476 std::vector<MachineJumpTable::Entry>()); 477 } 478}; 479 480/// Serializable representation of MachineFrameInfo. 481/// 482/// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and 483/// 'RealignOption' as they are determined by the target and LLVM function 484/// attributes. 485/// It also doesn't serialize attributes like 'NumFixedObject' and 486/// 'HasVarSizedObjects' as they are determined by the frame objects themselves. 487struct MachineFrameInfo { 488 bool IsFrameAddressTaken = false; 489 bool IsReturnAddressTaken = false; 490 bool HasStackMap = false; 491 bool HasPatchPoint = false; 492 uint64_t StackSize = 0; 493 int OffsetAdjustment = 0; 494 unsigned MaxAlignment = 0; 495 bool AdjustsStack = false; 496 bool HasCalls = false; 497 StringValue StackProtector; 498 // TODO: Serialize FunctionContextIdx 499 unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet. 500 unsigned CVBytesOfCalleeSavedRegisters = 0; 501 bool HasOpaqueSPAdjustment = false; 502 bool HasVAStart = false; 503 bool HasMustTailInVarArgFunc = false; 504 unsigned LocalFrameSize = 0; 505 StringValue SavePoint; 506 StringValue RestorePoint; 507 508 bool operator==(const MachineFrameInfo &Other) const { 509 return IsFrameAddressTaken == Other.IsFrameAddressTaken && 510 IsReturnAddressTaken == Other.IsReturnAddressTaken && 511 HasStackMap == Other.HasStackMap && 512 HasPatchPoint == Other.HasPatchPoint && 513 StackSize == Other.StackSize && 514 OffsetAdjustment == Other.OffsetAdjustment && 515 MaxAlignment == Other.MaxAlignment && 516 AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls && 517 StackProtector == Other.StackProtector && 518 MaxCallFrameSize == Other.MaxCallFrameSize && 519 CVBytesOfCalleeSavedRegisters == 520 Other.CVBytesOfCalleeSavedRegisters && 521 HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment && 522 HasVAStart == Other.HasVAStart && 523 HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc && 524 LocalFrameSize == Other.LocalFrameSize && 525 SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint; 526 } 527}; 528 529template <> struct MappingTraits<MachineFrameInfo> { 530 static void mapping(IO &YamlIO, MachineFrameInfo &MFI) { 531 YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false); 532 YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false); 533 YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false); 534 YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false); 535 YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0); 536 YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0); 537 YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0); 538 YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false); 539 YamlIO.mapOptional("hasCalls", MFI.HasCalls, false); 540 YamlIO.mapOptional("stackProtector", MFI.StackProtector, 541 StringValue()); // Don't print it out when it's empty. 542 YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0); 543 YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters", 544 MFI.CVBytesOfCalleeSavedRegisters, 0U); 545 YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment, 546 false); 547 YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false); 548 YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc, 549 false); 550 YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0); 551 YamlIO.mapOptional("savePoint", MFI.SavePoint, 552 StringValue()); // Don't print it out when it's empty. 553 YamlIO.mapOptional("restorePoint", MFI.RestorePoint, 554 StringValue()); // Don't print it out when it's empty. 555 } 556}; 557 558/// Targets should override this in a way that mirrors the implementation of 559/// llvm::MachineFunctionInfo. 560struct MachineFunctionInfo { 561 virtual ~MachineFunctionInfo() {} 562 virtual void mappingImpl(IO &YamlIO) {} 563}; 564 565template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> { 566 static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) { 567 if (MFI) 568 MFI->mappingImpl(YamlIO); 569 } 570}; 571 572struct MachineFunction { 573 StringRef Name; 574 unsigned Alignment = 0; 575 bool ExposesReturnsTwice = false; 576 // GISel MachineFunctionProperties. 577 bool Legalized = false; 578 bool RegBankSelected = false; 579 bool Selected = false; 580 bool FailedISel = false; 581 // Register information 582 bool TracksRegLiveness = false; 583 bool HasWinCFI = false; 584 std::vector<VirtualRegisterDefinition> VirtualRegisters; 585 std::vector<MachineFunctionLiveIn> LiveIns; 586 Optional<std::vector<FlowStringValue>> CalleeSavedRegisters; 587 // TODO: Serialize the various register masks. 588 // Frame information 589 MachineFrameInfo FrameInfo; 590 std::vector<FixedMachineStackObject> FixedStackObjects; 591 std::vector<MachineStackObject> StackObjects; 592 std::vector<MachineConstantPoolValue> Constants; /// Constant pool. 593 std::unique_ptr<MachineFunctionInfo> MachineFuncInfo; 594 std::vector<CallSiteInfo> CallSitesInfo; 595 MachineJumpTable JumpTableInfo; 596 BlockStringValue Body; 597}; 598 599template <> struct MappingTraits<MachineFunction> { 600 static void mapping(IO &YamlIO, MachineFunction &MF) { 601 YamlIO.mapRequired("name", MF.Name); 602 YamlIO.mapOptional("alignment", MF.Alignment, (unsigned)0); 603 YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false); 604 YamlIO.mapOptional("legalized", MF.Legalized, false); 605 YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false); 606 YamlIO.mapOptional("selected", MF.Selected, false); 607 YamlIO.mapOptional("failedISel", MF.FailedISel, false); 608 YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false); 609 YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false); 610 YamlIO.mapOptional("registers", MF.VirtualRegisters, 611 std::vector<VirtualRegisterDefinition>()); 612 YamlIO.mapOptional("liveins", MF.LiveIns, 613 std::vector<MachineFunctionLiveIn>()); 614 YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters, 615 Optional<std::vector<FlowStringValue>>()); 616 YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo()); 617 YamlIO.mapOptional("fixedStack", MF.FixedStackObjects, 618 std::vector<FixedMachineStackObject>()); 619 YamlIO.mapOptional("stack", MF.StackObjects, 620 std::vector<MachineStackObject>()); 621 YamlIO.mapOptional("callSites", MF.CallSitesInfo, 622 std::vector<CallSiteInfo>()); 623 YamlIO.mapOptional("constants", MF.Constants, 624 std::vector<MachineConstantPoolValue>()); 625 YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo); 626 if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty()) 627 YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable()); 628 YamlIO.mapOptional("body", MF.Body, BlockStringValue()); 629 } 630}; 631 632} // end namespace yaml 633} // end namespace llvm 634 635#endif // LLVM_CODEGEN_MIRYAMLMAPPING_H 636