blob: 4a7406473b11783cf4a38e7971b1bbc0f71005ec [file] [log] [blame]
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001//===- MIRYamlMapping.h - Describe mapping between MIR and YAML--*- C++ -*-===//
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01002//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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"
Andrew Walbran3d2c1972020-04-07 12:24:26 +010020#include "llvm/CodeGen/TargetFrameLowering.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010021#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)) {}
Andrew Walbran3d2c1972020-04-07 12:24:26 +010040 StringValue(const char Val[]) : Value(Val) {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010041
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
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200145template <> 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
162template <> struct ScalarTraits<Align> {
163 static void output(const Align &Alignment, void *, llvm::raw_ostream &OS) {
164 OS << Alignment.value();
165 }
166 static StringRef input(StringRef Scalar, void *, Align &Alignment) {
167 unsigned long long N;
168 if (getAsUnsignedInteger(Scalar, 10, N))
169 return "invalid number";
170 if (!isPowerOf2_64(N))
171 return "must be a power of two";
172 Alignment = Align(N);
173 return StringRef();
174 }
175 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
176};
177
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100178} // end namespace yaml
179} // end namespace llvm
180
181LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
182LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
183LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
184
185namespace llvm {
186namespace yaml {
187
188struct VirtualRegisterDefinition {
189 UnsignedValue ID;
190 StringValue Class;
191 StringValue PreferredRegister;
192
193 // TODO: Serialize the target specific register hints.
194
195 bool operator==(const VirtualRegisterDefinition &Other) const {
196 return ID == Other.ID && Class == Other.Class &&
197 PreferredRegister == Other.PreferredRegister;
198 }
199};
200
201template <> struct MappingTraits<VirtualRegisterDefinition> {
202 static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
203 YamlIO.mapRequired("id", Reg.ID);
204 YamlIO.mapRequired("class", Reg.Class);
205 YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
206 StringValue()); // Don't print out when it's empty.
207 }
208
209 static const bool flow = true;
210};
211
212struct MachineFunctionLiveIn {
213 StringValue Register;
214 StringValue VirtualRegister;
215
216 bool operator==(const MachineFunctionLiveIn &Other) const {
217 return Register == Other.Register &&
218 VirtualRegister == Other.VirtualRegister;
219 }
220};
221
222template <> struct MappingTraits<MachineFunctionLiveIn> {
223 static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
224 YamlIO.mapRequired("reg", LiveIn.Register);
225 YamlIO.mapOptional(
226 "virtual-reg", LiveIn.VirtualRegister,
227 StringValue()); // Don't print the virtual register when it's empty.
228 }
229
230 static const bool flow = true;
231};
232
233/// Serializable representation of stack object from the MachineFrameInfo class.
234///
235/// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
236/// determined by the object's type and frame information flags.
237/// Dead stack objects aren't serialized.
238///
239/// The 'isPreallocated' flag is determined by the local offset.
240struct MachineStackObject {
241 enum ObjectType { DefaultType, SpillSlot, VariableSized };
242 UnsignedValue ID;
243 StringValue Name;
244 // TODO: Serialize unnamed LLVM alloca reference.
245 ObjectType Type = DefaultType;
246 int64_t Offset = 0;
247 uint64_t Size = 0;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200248 MaybeAlign Alignment = None;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100249 TargetStackID::Value StackID;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100250 StringValue CalleeSavedRegister;
251 bool CalleeSavedRestored = true;
252 Optional<int64_t> LocalOffset;
253 StringValue DebugVar;
254 StringValue DebugExpr;
255 StringValue DebugLoc;
256
257 bool operator==(const MachineStackObject &Other) const {
258 return ID == Other.ID && Name == Other.Name && Type == Other.Type &&
259 Offset == Other.Offset && Size == Other.Size &&
260 Alignment == Other.Alignment &&
261 StackID == Other.StackID &&
262 CalleeSavedRegister == Other.CalleeSavedRegister &&
263 CalleeSavedRestored == Other.CalleeSavedRestored &&
264 LocalOffset == Other.LocalOffset && DebugVar == Other.DebugVar &&
265 DebugExpr == Other.DebugExpr && DebugLoc == Other.DebugLoc;
266 }
267};
268
269template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
270 static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
271 IO.enumCase(Type, "default", MachineStackObject::DefaultType);
272 IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
273 IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
274 }
275};
276
277template <> struct MappingTraits<MachineStackObject> {
278 static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
279 YamlIO.mapRequired("id", Object.ID);
280 YamlIO.mapOptional("name", Object.Name,
281 StringValue()); // Don't print out an empty name.
282 YamlIO.mapOptional(
283 "type", Object.Type,
284 MachineStackObject::DefaultType); // Don't print the default type.
285 YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
286 if (Object.Type != MachineStackObject::VariableSized)
287 YamlIO.mapRequired("size", Object.Size);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200288 YamlIO.mapOptional("alignment", Object.Alignment, None);
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100289 YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100290 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
291 StringValue()); // Don't print it out when it's empty.
292 YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
293 true);
294 YamlIO.mapOptional("local-offset", Object.LocalOffset, Optional<int64_t>());
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100295 YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100296 StringValue()); // Don't print it out when it's empty.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100297 YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100298 StringValue()); // Don't print it out when it's empty.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100299 YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100300 StringValue()); // Don't print it out when it's empty.
301 }
302
303 static const bool flow = true;
304};
305
306/// Serializable representation of the fixed stack object from the
307/// MachineFrameInfo class.
308struct FixedMachineStackObject {
309 enum ObjectType { DefaultType, SpillSlot };
310 UnsignedValue ID;
311 ObjectType Type = DefaultType;
312 int64_t Offset = 0;
313 uint64_t Size = 0;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200314 MaybeAlign Alignment = None;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100315 TargetStackID::Value StackID;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100316 bool IsImmutable = false;
317 bool IsAliased = false;
318 StringValue CalleeSavedRegister;
319 bool CalleeSavedRestored = true;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100320 StringValue DebugVar;
321 StringValue DebugExpr;
322 StringValue DebugLoc;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100323
324 bool operator==(const FixedMachineStackObject &Other) const {
325 return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
326 Size == Other.Size && Alignment == Other.Alignment &&
327 StackID == Other.StackID &&
328 IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
329 CalleeSavedRegister == Other.CalleeSavedRegister &&
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100330 CalleeSavedRestored == Other.CalleeSavedRestored &&
331 DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr
332 && DebugLoc == Other.DebugLoc;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100333 }
334};
335
336template <>
337struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
338 static void enumeration(yaml::IO &IO,
339 FixedMachineStackObject::ObjectType &Type) {
340 IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
341 IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
342 }
343};
344
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100345template <>
346struct ScalarEnumerationTraits<TargetStackID::Value> {
347 static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) {
348 IO.enumCase(ID, "default", TargetStackID::Default);
349 IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200350 IO.enumCase(ID, "scalable-vector", TargetStackID::ScalableVector);
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100351 IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc);
352 }
353};
354
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100355template <> struct MappingTraits<FixedMachineStackObject> {
356 static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
357 YamlIO.mapRequired("id", Object.ID);
358 YamlIO.mapOptional(
359 "type", Object.Type,
360 FixedMachineStackObject::DefaultType); // Don't print the default type.
361 YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
362 YamlIO.mapOptional("size", Object.Size, (uint64_t)0);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200363 YamlIO.mapOptional("alignment", Object.Alignment, None);
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100364 YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100365 if (Object.Type != FixedMachineStackObject::SpillSlot) {
366 YamlIO.mapOptional("isImmutable", Object.IsImmutable, false);
367 YamlIO.mapOptional("isAliased", Object.IsAliased, false);
368 }
369 YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
370 StringValue()); // Don't print it out when it's empty.
371 YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
372 true);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100373 YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
374 StringValue()); // Don't print it out when it's empty.
375 YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
376 StringValue()); // Don't print it out when it's empty.
377 YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
378 StringValue()); // Don't print it out when it's empty.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100379 }
380
381 static const bool flow = true;
382};
383
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100384
385/// Serializable representation of CallSiteInfo.
386struct CallSiteInfo {
387 // Representation of call argument and register which is used to
388 // transfer it.
389 struct ArgRegPair {
390 StringValue Reg;
391 uint16_t ArgNo;
392
393 bool operator==(const ArgRegPair &Other) const {
394 return Reg == Other.Reg && ArgNo == Other.ArgNo;
395 }
396 };
397
398 /// Identifies call instruction location in machine function.
399 struct MachineInstrLoc {
400 unsigned BlockNum;
401 unsigned Offset;
402
403 bool operator==(const MachineInstrLoc &Other) const {
404 return BlockNum == Other.BlockNum && Offset == Other.Offset;
405 }
406 };
407
408 MachineInstrLoc CallLocation;
409 std::vector<ArgRegPair> ArgForwardingRegs;
410
411 bool operator==(const CallSiteInfo &Other) const {
412 return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
413 CallLocation.Offset == Other.CallLocation.Offset;
414 }
415};
416
417template <> struct MappingTraits<CallSiteInfo::ArgRegPair> {
418 static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) {
419 YamlIO.mapRequired("arg", ArgReg.ArgNo);
420 YamlIO.mapRequired("reg", ArgReg.Reg);
421 }
422
423 static const bool flow = true;
424};
425}
426}
427
428LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair)
429
430namespace llvm {
431namespace yaml {
432
433template <> struct MappingTraits<CallSiteInfo> {
434 static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) {
435 YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum);
436 YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
437 YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
438 std::vector<CallSiteInfo::ArgRegPair>());
439 }
440
441 static const bool flow = true;
442};
443
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200444/// Serializable representation of debug value substitutions.
445struct DebugValueSubstitution {
446 unsigned SrcInst;
447 unsigned SrcOp;
448 unsigned DstInst;
449 unsigned DstOp;
450
451 bool operator==(const DebugValueSubstitution &Other) const {
452 return std::tie(SrcInst, SrcOp, DstInst, DstOp) ==
453 std::tie(Other.SrcInst, Other.SrcOp, Other.DstInst, Other.DstOp);
454 }
455};
456
457template <> struct MappingTraits<DebugValueSubstitution> {
458 static void mapping(IO &YamlIO, DebugValueSubstitution &Sub) {
459 YamlIO.mapRequired("srcinst", Sub.SrcInst);
460 YamlIO.mapRequired("srcop", Sub.SrcOp);
461 YamlIO.mapRequired("dstinst", Sub.DstInst);
462 YamlIO.mapRequired("dstop", Sub.DstOp);
463 }
464
465 static const bool flow = true;
466};
467} // namespace yaml
468} // namespace llvm
469
470LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::DebugValueSubstitution)
471
472namespace llvm {
473namespace yaml {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100474struct MachineConstantPoolValue {
475 UnsignedValue ID;
476 StringValue Value;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200477 MaybeAlign Alignment = None;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100478 bool IsTargetSpecific = false;
479
480 bool operator==(const MachineConstantPoolValue &Other) const {
481 return ID == Other.ID && Value == Other.Value &&
482 Alignment == Other.Alignment &&
483 IsTargetSpecific == Other.IsTargetSpecific;
484 }
485};
486
487template <> struct MappingTraits<MachineConstantPoolValue> {
488 static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
489 YamlIO.mapRequired("id", Constant.ID);
490 YamlIO.mapOptional("value", Constant.Value, StringValue());
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200491 YamlIO.mapOptional("alignment", Constant.Alignment, None);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100492 YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false);
493 }
494};
495
496struct MachineJumpTable {
497 struct Entry {
498 UnsignedValue ID;
499 std::vector<FlowStringValue> Blocks;
500
501 bool operator==(const Entry &Other) const {
502 return ID == Other.ID && Blocks == Other.Blocks;
503 }
504 };
505
506 MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
507 std::vector<Entry> Entries;
508
509 bool operator==(const MachineJumpTable &Other) const {
510 return Kind == Other.Kind && Entries == Other.Entries;
511 }
512};
513
514template <> struct MappingTraits<MachineJumpTable::Entry> {
515 static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
516 YamlIO.mapRequired("id", Entry.ID);
517 YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>());
518 }
519};
520
521} // end namespace yaml
522} // end namespace llvm
523
524LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
525LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
526LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
527LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100528LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100529LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
530LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
531
532namespace llvm {
533namespace yaml {
534
535template <> struct MappingTraits<MachineJumpTable> {
536 static void mapping(IO &YamlIO, MachineJumpTable &JT) {
537 YamlIO.mapRequired("kind", JT.Kind);
538 YamlIO.mapOptional("entries", JT.Entries,
539 std::vector<MachineJumpTable::Entry>());
540 }
541};
542
543/// Serializable representation of MachineFrameInfo.
544///
545/// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
546/// 'RealignOption' as they are determined by the target and LLVM function
547/// attributes.
548/// It also doesn't serialize attributes like 'NumFixedObject' and
549/// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
550struct MachineFrameInfo {
551 bool IsFrameAddressTaken = false;
552 bool IsReturnAddressTaken = false;
553 bool HasStackMap = false;
554 bool HasPatchPoint = false;
555 uint64_t StackSize = 0;
556 int OffsetAdjustment = 0;
557 unsigned MaxAlignment = 0;
558 bool AdjustsStack = false;
559 bool HasCalls = false;
560 StringValue StackProtector;
561 // TODO: Serialize FunctionContextIdx
562 unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
Andrew Scull0372a572018-11-16 15:47:06 +0000563 unsigned CVBytesOfCalleeSavedRegisters = 0;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100564 bool HasOpaqueSPAdjustment = false;
565 bool HasVAStart = false;
566 bool HasMustTailInVarArgFunc = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100567 unsigned LocalFrameSize = 0;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100568 StringValue SavePoint;
569 StringValue RestorePoint;
570
571 bool operator==(const MachineFrameInfo &Other) const {
572 return IsFrameAddressTaken == Other.IsFrameAddressTaken &&
573 IsReturnAddressTaken == Other.IsReturnAddressTaken &&
574 HasStackMap == Other.HasStackMap &&
575 HasPatchPoint == Other.HasPatchPoint &&
576 StackSize == Other.StackSize &&
577 OffsetAdjustment == Other.OffsetAdjustment &&
578 MaxAlignment == Other.MaxAlignment &&
579 AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
580 StackProtector == Other.StackProtector &&
581 MaxCallFrameSize == Other.MaxCallFrameSize &&
Andrew Scull0372a572018-11-16 15:47:06 +0000582 CVBytesOfCalleeSavedRegisters ==
583 Other.CVBytesOfCalleeSavedRegisters &&
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100584 HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
585 HasVAStart == Other.HasVAStart &&
586 HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100587 LocalFrameSize == Other.LocalFrameSize &&
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100588 SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint;
589 }
590};
591
592template <> struct MappingTraits<MachineFrameInfo> {
593 static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
594 YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false);
595 YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false);
596 YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false);
597 YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false);
598 YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0);
599 YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0);
600 YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
601 YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
602 YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
603 YamlIO.mapOptional("stackProtector", MFI.StackProtector,
604 StringValue()); // Don't print it out when it's empty.
605 YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0);
Andrew Scull0372a572018-11-16 15:47:06 +0000606 YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters",
607 MFI.CVBytesOfCalleeSavedRegisters, 0U);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100608 YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,
609 false);
610 YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
611 YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
612 false);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100613 YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100614 YamlIO.mapOptional("savePoint", MFI.SavePoint,
615 StringValue()); // Don't print it out when it's empty.
616 YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
617 StringValue()); // Don't print it out when it's empty.
618 }
619};
620
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100621/// Targets should override this in a way that mirrors the implementation of
622/// llvm::MachineFunctionInfo.
623struct MachineFunctionInfo {
624 virtual ~MachineFunctionInfo() {}
625 virtual void mappingImpl(IO &YamlIO) {}
626};
627
628template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
629 static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
630 if (MFI)
631 MFI->mappingImpl(YamlIO);
632 }
633};
634
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100635struct MachineFunction {
636 StringRef Name;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200637 MaybeAlign Alignment = None;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100638 bool ExposesReturnsTwice = false;
639 // GISel MachineFunctionProperties.
640 bool Legalized = false;
641 bool RegBankSelected = false;
642 bool Selected = false;
643 bool FailedISel = false;
644 // Register information
645 bool TracksRegLiveness = false;
Andrew Walbran16937d02019-10-22 13:54:20 +0100646 bool HasWinCFI = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100647 std::vector<VirtualRegisterDefinition> VirtualRegisters;
648 std::vector<MachineFunctionLiveIn> LiveIns;
649 Optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
650 // TODO: Serialize the various register masks.
651 // Frame information
652 MachineFrameInfo FrameInfo;
653 std::vector<FixedMachineStackObject> FixedStackObjects;
654 std::vector<MachineStackObject> StackObjects;
655 std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100656 std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
657 std::vector<CallSiteInfo> CallSitesInfo;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200658 std::vector<DebugValueSubstitution> DebugValueSubstitutions;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100659 MachineJumpTable JumpTableInfo;
660 BlockStringValue Body;
661};
662
663template <> struct MappingTraits<MachineFunction> {
664 static void mapping(IO &YamlIO, MachineFunction &MF) {
665 YamlIO.mapRequired("name", MF.Name);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200666 YamlIO.mapOptional("alignment", MF.Alignment, None);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100667 YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false);
668 YamlIO.mapOptional("legalized", MF.Legalized, false);
669 YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
670 YamlIO.mapOptional("selected", MF.Selected, false);
671 YamlIO.mapOptional("failedISel", MF.FailedISel, false);
672 YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
Andrew Walbran16937d02019-10-22 13:54:20 +0100673 YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100674 YamlIO.mapOptional("registers", MF.VirtualRegisters,
675 std::vector<VirtualRegisterDefinition>());
676 YamlIO.mapOptional("liveins", MF.LiveIns,
677 std::vector<MachineFunctionLiveIn>());
678 YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters,
679 Optional<std::vector<FlowStringValue>>());
680 YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo());
681 YamlIO.mapOptional("fixedStack", MF.FixedStackObjects,
682 std::vector<FixedMachineStackObject>());
683 YamlIO.mapOptional("stack", MF.StackObjects,
684 std::vector<MachineStackObject>());
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100685 YamlIO.mapOptional("callSites", MF.CallSitesInfo,
686 std::vector<CallSiteInfo>());
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200687 YamlIO.mapOptional("debugValueSubstitutions", MF.DebugValueSubstitutions,
688 std::vector<DebugValueSubstitution>());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100689 YamlIO.mapOptional("constants", MF.Constants,
690 std::vector<MachineConstantPoolValue>());
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100691 YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100692 if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
693 YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
694 YamlIO.mapOptional("body", MF.Body, BlockStringValue());
695 }
696};
697
698} // end namespace yaml
699} // end namespace llvm
700
701#endif // LLVM_CODEGEN_MIRYAMLMAPPING_H