1 //===- MIRYAMLMapping.h - Describes the mapping between MIR and YAML ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // The MIR serialization library is currently a work in progress. It can't
11 // serialize machine functions at this time.
13 // This file implements the mapping between various MIR data structures and
14 // their corresponding YAML representation.
16 //===----------------------------------------------------------------------===//
18 #ifndef LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
19 #define LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/CodeGen/MachineJumpTableInfo.h"
23 #include "llvm/Support/YAMLTraits.h"
29 /// A wrapper around std::string which contains a source range that's being
30 /// set during parsing.
36 StringValue(std::string Value) : Value(std::move(Value)) {}
38 bool operator==(const StringValue &Other) const {
39 return Value == Other.Value;
43 template <> struct ScalarTraits<StringValue> {
44 static void output(const StringValue &S, void *, llvm::raw_ostream &OS) {
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();
56 static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
59 struct FlowStringValue : StringValue {
61 FlowStringValue(std::string Value) : StringValue(Value) {}
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);
69 static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) {
70 return ScalarTraits<StringValue>::input(Scalar, Ctx, S);
73 static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
76 struct BlockStringValue {
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);
85 static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) {
86 return ScalarTraits<StringValue>::input(Scalar, Ctx, S.Value);
90 /// A wrapper around unsigned which contains a source range that's being set
92 struct UnsignedValue {
96 UnsignedValue() : Value(0) {}
97 UnsignedValue(unsigned Value) : Value(Value) {}
99 bool operator==(const UnsignedValue &Other) const {
100 return Value == Other.Value;
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);
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);
116 static bool mustQuote(StringRef Scalar) {
117 return ScalarTraits<unsigned>::mustQuote(Scalar);
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);
137 } // end namespace yaml
138 } // end namespace llvm
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)
147 struct VirtualRegisterDefinition {
150 StringValue PreferredRegister;
151 // TODO: Serialize the target specific register hints.
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.
162 static const bool flow = true;
165 struct MachineFunctionLiveIn {
166 StringValue Register;
167 StringValue VirtualRegister;
170 template <> struct MappingTraits<MachineFunctionLiveIn> {
171 static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
172 YamlIO.mapRequired("reg", LiveIn.Register);
174 "virtual-reg", LiveIn.VirtualRegister,
175 StringValue()); // Don't print the virtual register when it's empty.
178 static const bool flow = true;
181 /// Serializable representation of stack object from the MachineFrameInfo class.
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.
187 /// The 'isPreallocated' flag is determined by the local offset.
188 struct MachineStackObject {
189 enum ObjectType { DefaultType, SpillSlot, VariableSized };
192 // TODO: Serialize unnamed LLVM alloca reference.
193 ObjectType Type = DefaultType;
196 unsigned Alignment = 0;
197 StringValue CalleeSavedRegister;
198 Optional<int64_t> LocalOffset;
199 StringValue DebugVar;
200 StringValue DebugExpr;
201 StringValue DebugLoc;
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);
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.
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.
235 static const bool flow = true;
238 /// Serializable representation of the fixed stack object from the
239 /// MachineFrameInfo class.
240 struct FixedMachineStackObject {
241 enum ObjectType { DefaultType, SpillSlot };
243 ObjectType Type = DefaultType;
246 unsigned Alignment = 0;
247 bool IsImmutable = false;
248 bool IsAliased = false;
249 StringValue CalleeSavedRegister;
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);
261 template <> struct MappingTraits<FixedMachineStackObject> {
262 static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
263 YamlIO.mapRequired("id", Object.ID);
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);
274 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
275 StringValue()); // Don't print it out when it's empty.
278 static const bool flow = true;
281 struct MachineConstantPoolValue {
284 unsigned Alignment = 0;
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);
295 struct MachineJumpTable {
298 std::vector<FlowStringValue> Blocks;
301 MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
302 std::vector<Entry> Entries;
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);
312 } // end namespace yaml
313 } // end namespace llvm
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)
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);
332 /// Serializable representation of MachineFrameInfo.
334 /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
335 /// 'RealignOption' as they are determined by the target and LLVM function
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;
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.
383 struct MachineFunction {
385 unsigned Alignment = 0;
386 bool ExposesReturnsTwice = false;
387 bool HasInlineAsm = false;
388 // Register information
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.
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;
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);
427 } // end namespace yaml
428 } // end namespace llvm