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