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 // The MIR serialization library is currently a work in progress. It can't 11 // serialize machine functions at this time. 12 // 13 // This file implements the mapping between various MIR data structures and 14 // their corresponding YAML representation. 15 // 16 //===----------------------------------------------------------------------===// 17 18 #ifndef LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H 19 #define LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H 20 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/CodeGen/MachineJumpTableInfo.h" 23 #include "llvm/Support/YAMLTraits.h" 24 #include <vector> 25 26 namespace llvm { 27 namespace yaml { 28 29 /// A wrapper around std::string which contains a source range that's being 30 /// set during parsing. 31 struct StringValue { 32 std::string Value; 33 SMRange SourceRange; 34 StringValueStringValue35 StringValue() {} StringValueStringValue36 StringValue(std::string Value) : Value(std::move(Value)) {} 37 38 bool operator==(const StringValue &Other) const { 39 return Value == Other.Value; 40 } 41 }; 42 43 template <> struct ScalarTraits<StringValue> { 44 static void output(const StringValue &S, void *, llvm::raw_ostream &OS) { 45 OS << S.Value; 46 } 47 48 static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) { 49 S.Value = Scalar.str(); 50 if (const auto *Node = 51 reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode()) 52 S.SourceRange = Node->getSourceRange(); 53 return ""; 54 } 55 56 static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); } 57 }; 58 59 struct FlowStringValue : StringValue { 60 FlowStringValue() {} 61 FlowStringValue(std::string Value) : StringValue(Value) {} 62 }; 63 64 template <> struct ScalarTraits<FlowStringValue> { 65 static void output(const FlowStringValue &S, void *, llvm::raw_ostream &OS) { 66 return ScalarTraits<StringValue>::output(S, nullptr, OS); 67 } 68 69 static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) { 70 return ScalarTraits<StringValue>::input(Scalar, Ctx, S); 71 } 72 73 static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); } 74 }; 75 76 struct BlockStringValue { 77 StringValue Value; 78 }; 79 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); 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. 92 struct 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 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); 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 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); 134 } 135 }; 136 137 } // end namespace yaml 138 } // end namespace llvm 139 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) 143 144 namespace llvm { 145 namespace yaml { 146 147 struct VirtualRegisterDefinition { 148 UnsignedValue ID; 149 StringValue Class; 150 StringValue PreferredRegister; 151 // TODO: Serialize the target specific register hints. 152 }; 153 154 template <> struct MappingTraits<VirtualRegisterDefinition> { 155 static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) { 156 YamlIO.mapRequired("id", Reg.ID); 157 YamlIO.mapRequired("class", Reg.Class); 158 YamlIO.mapOptional("preferred-register", Reg.PreferredRegister, 159 StringValue()); // Don't print out when it's empty. 160 } 161 162 static const bool flow = true; 163 }; 164 165 struct MachineFunctionLiveIn { 166 StringValue Register; 167 StringValue VirtualRegister; 168 }; 169 170 template <> struct MappingTraits<MachineFunctionLiveIn> { 171 static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) { 172 YamlIO.mapRequired("reg", LiveIn.Register); 173 YamlIO.mapOptional( 174 "virtual-reg", LiveIn.VirtualRegister, 175 StringValue()); // Don't print the virtual register when it's empty. 176 } 177 178 static const bool flow = true; 179 }; 180 181 /// Serializable representation of stack object from the MachineFrameInfo class. 182 /// 183 /// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are 184 /// determined by the object's type and frame information flags. 185 /// Dead stack objects aren't serialized. 186 /// 187 /// The 'isPreallocated' flag is determined by the local offset. 188 struct MachineStackObject { 189 enum ObjectType { DefaultType, SpillSlot, VariableSized }; 190 UnsignedValue ID; 191 StringValue Name; 192 // TODO: Serialize unnamed LLVM alloca reference. 193 ObjectType Type = DefaultType; 194 int64_t Offset = 0; 195 uint64_t Size = 0; 196 unsigned Alignment = 0; 197 StringValue CalleeSavedRegister; 198 Optional<int64_t> LocalOffset; 199 StringValue DebugVar; 200 StringValue DebugExpr; 201 StringValue DebugLoc; 202 }; 203 204 template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> { 205 static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) { 206 IO.enumCase(Type, "default", MachineStackObject::DefaultType); 207 IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot); 208 IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized); 209 } 210 }; 211 212 template <> struct MappingTraits<MachineStackObject> { 213 static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) { 214 YamlIO.mapRequired("id", Object.ID); 215 YamlIO.mapOptional("name", Object.Name, 216 StringValue()); // Don't print out an empty name. 217 YamlIO.mapOptional( 218 "type", Object.Type, 219 MachineStackObject::DefaultType); // Don't print the default type. 220 YamlIO.mapOptional("offset", Object.Offset); 221 if (Object.Type != MachineStackObject::VariableSized) 222 YamlIO.mapRequired("size", Object.Size); 223 YamlIO.mapOptional("alignment", Object.Alignment); 224 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, 225 StringValue()); // Don't print it out when it's empty. 226 YamlIO.mapOptional("local-offset", Object.LocalOffset); 227 YamlIO.mapOptional("di-variable", Object.DebugVar, 228 StringValue()); // Don't print it out when it's empty. 229 YamlIO.mapOptional("di-expression", Object.DebugExpr, 230 StringValue()); // Don't print it out when it's empty. 231 YamlIO.mapOptional("di-location", Object.DebugLoc, 232 StringValue()); // Don't print it out when it's empty. 233 } 234 235 static const bool flow = true; 236 }; 237 238 /// Serializable representation of the fixed stack object from the 239 /// MachineFrameInfo class. 240 struct FixedMachineStackObject { 241 enum ObjectType { DefaultType, SpillSlot }; 242 UnsignedValue ID; 243 ObjectType Type = DefaultType; 244 int64_t Offset = 0; 245 uint64_t Size = 0; 246 unsigned Alignment = 0; 247 bool IsImmutable = false; 248 bool IsAliased = false; 249 StringValue CalleeSavedRegister; 250 }; 251 252 template <> 253 struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> { 254 static void enumeration(yaml::IO &IO, 255 FixedMachineStackObject::ObjectType &Type) { 256 IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType); 257 IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot); 258 } 259 }; 260 261 template <> struct MappingTraits<FixedMachineStackObject> { 262 static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) { 263 YamlIO.mapRequired("id", Object.ID); 264 YamlIO.mapOptional( 265 "type", Object.Type, 266 FixedMachineStackObject::DefaultType); // Don't print the default type. 267 YamlIO.mapOptional("offset", Object.Offset); 268 YamlIO.mapOptional("size", Object.Size); 269 YamlIO.mapOptional("alignment", Object.Alignment); 270 if (Object.Type != FixedMachineStackObject::SpillSlot) { 271 YamlIO.mapOptional("isImmutable", Object.IsImmutable); 272 YamlIO.mapOptional("isAliased", Object.IsAliased); 273 } 274 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, 275 StringValue()); // Don't print it out when it's empty. 276 } 277 278 static const bool flow = true; 279 }; 280 281 struct MachineConstantPoolValue { 282 UnsignedValue ID; 283 StringValue Value; 284 unsigned Alignment = 0; 285 }; 286 287 template <> struct MappingTraits<MachineConstantPoolValue> { 288 static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) { 289 YamlIO.mapRequired("id", Constant.ID); 290 YamlIO.mapOptional("value", Constant.Value); 291 YamlIO.mapOptional("alignment", Constant.Alignment); 292 } 293 }; 294 295 struct MachineJumpTable { 296 struct Entry { 297 UnsignedValue ID; 298 std::vector<FlowStringValue> Blocks; 299 }; 300 301 MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32; 302 std::vector<Entry> Entries; 303 }; 304 305 template <> struct MappingTraits<MachineJumpTable::Entry> { 306 static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) { 307 YamlIO.mapRequired("id", Entry.ID); 308 YamlIO.mapOptional("blocks", Entry.Blocks); 309 } 310 }; 311 312 } // end namespace yaml 313 } // end namespace llvm 314 315 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn) 316 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) 317 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) 318 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) 319 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue) 320 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry) 321 322 namespace llvm { 323 namespace yaml { 324 325 template <> struct MappingTraits<MachineJumpTable> { 326 static void mapping(IO &YamlIO, MachineJumpTable &JT) { 327 YamlIO.mapRequired("kind", JT.Kind); 328 YamlIO.mapOptional("entries", JT.Entries); 329 } 330 }; 331 332 /// Serializable representation of MachineFrameInfo. 333 /// 334 /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and 335 /// 'RealignOption' as they are determined by the target and LLVM function 336 /// attributes. 337 /// It also doesn't serialize attributes like 'NumFixedObject' and 338 /// 'HasVarSizedObjects' as they are determined by the frame objects themselves. 339 struct MachineFrameInfo { 340 bool IsFrameAddressTaken = false; 341 bool IsReturnAddressTaken = false; 342 bool HasStackMap = false; 343 bool HasPatchPoint = false; 344 uint64_t StackSize = 0; 345 int OffsetAdjustment = 0; 346 unsigned MaxAlignment = 0; 347 bool AdjustsStack = false; 348 bool HasCalls = false; 349 StringValue StackProtector; 350 // TODO: Serialize FunctionContextIdx 351 unsigned MaxCallFrameSize = 0; 352 bool HasOpaqueSPAdjustment = false; 353 bool HasVAStart = false; 354 bool HasMustTailInVarArgFunc = false; 355 StringValue SavePoint; 356 StringValue RestorePoint; 357 }; 358 359 template <> struct MappingTraits<MachineFrameInfo> { 360 static void mapping(IO &YamlIO, MachineFrameInfo &MFI) { 361 YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken); 362 YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken); 363 YamlIO.mapOptional("hasStackMap", MFI.HasStackMap); 364 YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint); 365 YamlIO.mapOptional("stackSize", MFI.StackSize); 366 YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment); 367 YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment); 368 YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack); 369 YamlIO.mapOptional("hasCalls", MFI.HasCalls); 370 YamlIO.mapOptional("stackProtector", MFI.StackProtector, 371 StringValue()); // Don't print it out when it's empty. 372 YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize); 373 YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment); 374 YamlIO.mapOptional("hasVAStart", MFI.HasVAStart); 375 YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc); 376 YamlIO.mapOptional("savePoint", MFI.SavePoint, 377 StringValue()); // Don't print it out when it's empty. 378 YamlIO.mapOptional("restorePoint", MFI.RestorePoint, 379 StringValue()); // Don't print it out when it's empty. 380 } 381 }; 382 383 struct MachineFunction { 384 StringRef Name; 385 unsigned Alignment = 0; 386 bool ExposesReturnsTwice = false; 387 bool HasInlineAsm = false; 388 // Register information 389 bool IsSSA = false; 390 bool TracksRegLiveness = false; 391 bool TracksSubRegLiveness = false; 392 std::vector<VirtualRegisterDefinition> VirtualRegisters; 393 std::vector<MachineFunctionLiveIn> LiveIns; 394 Optional<std::vector<FlowStringValue>> CalleeSavedRegisters; 395 // TODO: Serialize the various register masks. 396 // Frame information 397 MachineFrameInfo FrameInfo; 398 std::vector<FixedMachineStackObject> FixedStackObjects; 399 std::vector<MachineStackObject> StackObjects; 400 std::vector<MachineConstantPoolValue> Constants; /// Constant pool. 401 MachineJumpTable JumpTableInfo; 402 BlockStringValue Body; 403 }; 404 405 template <> struct MappingTraits<MachineFunction> { 406 static void mapping(IO &YamlIO, MachineFunction &MF) { 407 YamlIO.mapRequired("name", MF.Name); 408 YamlIO.mapOptional("alignment", MF.Alignment); 409 YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice); 410 YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm); 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