Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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/StringRef.h"
18
#include "llvm/CodeGen/MachineJumpTableInfo.h"
19
#include "llvm/CodeGen/TargetFrameLowering.h"
20
#include "llvm/Support/SMLoc.h"
21
#include "llvm/Support/YAMLTraits.h"
22
#include "llvm/Support/raw_ostream.h"
23
#include <algorithm>
24
#include <cstdint>
25
#include <optional>
26
#include <string>
27
#include <vector>
28
 
29
namespace llvm {
30
namespace yaml {
31
 
32
/// A wrapper around std::string which contains a source range that's being
33
/// set during parsing.
34
struct 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
 
47
template <> 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
 
63
struct FlowStringValue : StringValue {
64
  FlowStringValue() = default;
65
  FlowStringValue(std::string Value) : StringValue(std::move(Value)) {}
66
};
67
 
68
template <> 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
 
80
struct BlockStringValue {
81
  StringValue Value;
82
 
83
  bool operator==(const BlockStringValue &Other) const {
84
    return Value == Other.Value;
85
  }
86
};
87
 
88
template <> 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.
100
struct 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
 
112
template <> 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
 
129
template <> 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
template <> 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
 
162
template <> 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
 
178
} // end namespace yaml
179
} // end namespace llvm
180
 
181
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
182
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
183
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
184
 
185
namespace llvm {
186
namespace yaml {
187
 
188
struct 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
 
201
template <> 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
 
212
struct 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
 
222
template <> 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.
240
struct 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;
248
  MaybeAlign Alignment = std::nullopt;
249
  TargetStackID::Value StackID;
250
  StringValue CalleeSavedRegister;
251
  bool CalleeSavedRestored = true;
252
  std::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
 
269
template <> 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
 
277
template <> 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);
288
    YamlIO.mapOptional("alignment", Object.Alignment, std::nullopt);
289
    YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
290
    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,
295
                       std::optional<int64_t>());
296
    YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
297
                       StringValue()); // Don't print it out when it's empty.
298
    YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
299
                       StringValue()); // Don't print it out when it's empty.
300
    YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
301
                       StringValue()); // Don't print it out when it's empty.
302
  }
303
 
304
  static const bool flow = true;
305
};
306
 
307
/// Serializable representation of the fixed stack object from the
308
/// MachineFrameInfo class.
309
struct FixedMachineStackObject {
310
  enum ObjectType { DefaultType, SpillSlot };
311
  UnsignedValue ID;
312
  ObjectType Type = DefaultType;
313
  int64_t Offset = 0;
314
  uint64_t Size = 0;
315
  MaybeAlign Alignment = std::nullopt;
316
  TargetStackID::Value StackID;
317
  bool IsImmutable = false;
318
  bool IsAliased = false;
319
  StringValue CalleeSavedRegister;
320
  bool CalleeSavedRestored = true;
321
  StringValue DebugVar;
322
  StringValue DebugExpr;
323
  StringValue DebugLoc;
324
 
325
  bool operator==(const FixedMachineStackObject &Other) const {
326
    return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
327
           Size == Other.Size && Alignment == Other.Alignment &&
328
           StackID == Other.StackID &&
329
           IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
330
           CalleeSavedRegister == Other.CalleeSavedRegister &&
331
           CalleeSavedRestored == Other.CalleeSavedRestored &&
332
           DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr
333
           && DebugLoc == Other.DebugLoc;
334
  }
335
};
336
 
337
template <>
338
struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
339
  static void enumeration(yaml::IO &IO,
340
                          FixedMachineStackObject::ObjectType &Type) {
341
    IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
342
    IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
343
  }
344
};
345
 
346
template <>
347
struct ScalarEnumerationTraits<TargetStackID::Value> {
348
  static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) {
349
    IO.enumCase(ID, "default", TargetStackID::Default);
350
    IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill);
351
    IO.enumCase(ID, "scalable-vector", TargetStackID::ScalableVector);
352
    IO.enumCase(ID, "wasm-local", TargetStackID::WasmLocal);
353
    IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc);
354
  }
355
};
356
 
357
template <> struct MappingTraits<FixedMachineStackObject> {
358
  static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
359
    YamlIO.mapRequired("id", Object.ID);
360
    YamlIO.mapOptional(
361
        "type", Object.Type,
362
        FixedMachineStackObject::DefaultType); // Don't print the default type.
363
    YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
364
    YamlIO.mapOptional("size", Object.Size, (uint64_t)0);
365
    YamlIO.mapOptional("alignment", Object.Alignment, std::nullopt);
366
    YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
367
    if (Object.Type != FixedMachineStackObject::SpillSlot) {
368
      YamlIO.mapOptional("isImmutable", Object.IsImmutable, false);
369
      YamlIO.mapOptional("isAliased", Object.IsAliased, false);
370
    }
371
    YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
372
                       StringValue()); // Don't print it out when it's empty.
373
    YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
374
                     true);
375
    YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
376
                       StringValue()); // Don't print it out when it's empty.
377
    YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
378
                       StringValue()); // Don't print it out when it's empty.
379
    YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
380
                       StringValue()); // Don't print it out when it's empty.
381
  }
382
 
383
  static const bool flow = true;
384
};
385
 
386
/// A serializaable representation of a reference to a stack object or fixed
387
/// stack object.
388
struct FrameIndex {
389
  // The frame index as printed. This is always a positive number, even for
390
  // fixed objects. To obtain the real index,
391
  // MachineFrameInfo::getObjectIndexBegin has to be added.
392
  int FI;
393
  bool IsFixed;
394
  SMRange SourceRange;
395
 
396
  FrameIndex() = default;
397
  FrameIndex(int FI, const llvm::MachineFrameInfo &MFI);
398
 
399
  Expected<int> getFI(const llvm::MachineFrameInfo &MFI) const;
400
};
401
 
402
template <> struct ScalarTraits<FrameIndex> {
403
  static void output(const FrameIndex &FI, void *, raw_ostream &OS) {
404
    MachineOperand::printStackObjectReference(OS, FI.FI, FI.IsFixed, "");
405
  }
406
 
407
  static StringRef input(StringRef Scalar, void *Ctx, FrameIndex &FI) {
408
    FI.IsFixed = false;
409
    StringRef Num;
410
    if (Scalar.startswith("%stack.")) {
411
      Num = Scalar.substr(7);
412
    } else if (Scalar.startswith("%fixed-stack.")) {
413
      Num = Scalar.substr(13);
414
      FI.IsFixed = true;
415
    } else {
416
      return "Invalid frame index, needs to start with %stack. or "
417
             "%fixed-stack.";
418
    }
419
    if (Num.consumeInteger(10, FI.FI))
420
      return "Invalid frame index, not a valid number";
421
 
422
    if (const auto *Node =
423
            reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
424
      FI.SourceRange = Node->getSourceRange();
425
    return StringRef();
426
  }
427
 
428
  static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
429
};
430
 
431
/// Serializable representation of CallSiteInfo.
432
struct CallSiteInfo {
433
  // Representation of call argument and register which is used to
434
  // transfer it.
435
  struct ArgRegPair {
436
    StringValue Reg;
437
    uint16_t ArgNo;
438
 
439
    bool operator==(const ArgRegPair &Other) const {
440
      return Reg == Other.Reg && ArgNo == Other.ArgNo;
441
    }
442
  };
443
 
444
  /// Identifies call instruction location in machine function.
445
  struct MachineInstrLoc {
446
    unsigned BlockNum;
447
    unsigned Offset;
448
 
449
    bool operator==(const MachineInstrLoc &Other) const {
450
      return BlockNum == Other.BlockNum && Offset == Other.Offset;
451
    }
452
  };
453
 
454
  MachineInstrLoc CallLocation;
455
  std::vector<ArgRegPair> ArgForwardingRegs;
456
 
457
  bool operator==(const CallSiteInfo &Other) const {
458
    return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
459
           CallLocation.Offset == Other.CallLocation.Offset;
460
  }
461
};
462
 
463
template <> struct MappingTraits<CallSiteInfo::ArgRegPair> {
464
  static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) {
465
    YamlIO.mapRequired("arg", ArgReg.ArgNo);
466
    YamlIO.mapRequired("reg", ArgReg.Reg);
467
  }
468
 
469
  static const bool flow = true;
470
};
471
}
472
}
473
 
474
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair)
475
 
476
namespace llvm {
477
namespace yaml {
478
 
479
template <> struct MappingTraits<CallSiteInfo> {
480
  static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) {
481
    YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum);
482
    YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
483
    YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
484
                       std::vector<CallSiteInfo::ArgRegPair>());
485
  }
486
 
487
  static const bool flow = true;
488
};
489
 
490
/// Serializable representation of debug value substitutions.
491
struct DebugValueSubstitution {
492
  unsigned SrcInst;
493
  unsigned SrcOp;
494
  unsigned DstInst;
495
  unsigned DstOp;
496
  unsigned Subreg;
497
 
498
  bool operator==(const DebugValueSubstitution &Other) const {
499
    return std::tie(SrcInst, SrcOp, DstInst, DstOp) ==
500
           std::tie(Other.SrcInst, Other.SrcOp, Other.DstInst, Other.DstOp);
501
  }
502
};
503
 
504
template <> struct MappingTraits<DebugValueSubstitution> {
505
  static void mapping(IO &YamlIO, DebugValueSubstitution &Sub) {
506
    YamlIO.mapRequired("srcinst", Sub.SrcInst);
507
    YamlIO.mapRequired("srcop", Sub.SrcOp);
508
    YamlIO.mapRequired("dstinst", Sub.DstInst);
509
    YamlIO.mapRequired("dstop", Sub.DstOp);
510
    YamlIO.mapRequired("subreg", Sub.Subreg);
511
  }
512
 
513
  static const bool flow = true;
514
};
515
} // namespace yaml
516
} // namespace llvm
517
 
518
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::DebugValueSubstitution)
519
 
520
namespace llvm {
521
namespace yaml {
522
struct MachineConstantPoolValue {
523
  UnsignedValue ID;
524
  StringValue Value;
525
  MaybeAlign Alignment = std::nullopt;
526
  bool IsTargetSpecific = false;
527
 
528
  bool operator==(const MachineConstantPoolValue &Other) const {
529
    return ID == Other.ID && Value == Other.Value &&
530
           Alignment == Other.Alignment &&
531
           IsTargetSpecific == Other.IsTargetSpecific;
532
  }
533
};
534
 
535
template <> struct MappingTraits<MachineConstantPoolValue> {
536
  static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
537
    YamlIO.mapRequired("id", Constant.ID);
538
    YamlIO.mapOptional("value", Constant.Value, StringValue());
539
    YamlIO.mapOptional("alignment", Constant.Alignment, std::nullopt);
540
    YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false);
541
  }
542
};
543
 
544
struct MachineJumpTable {
545
  struct Entry {
546
    UnsignedValue ID;
547
    std::vector<FlowStringValue> Blocks;
548
 
549
    bool operator==(const Entry &Other) const {
550
      return ID == Other.ID && Blocks == Other.Blocks;
551
    }
552
  };
553
 
554
  MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
555
  std::vector<Entry> Entries;
556
 
557
  bool operator==(const MachineJumpTable &Other) const {
558
    return Kind == Other.Kind && Entries == Other.Entries;
559
  }
560
};
561
 
562
template <> struct MappingTraits<MachineJumpTable::Entry> {
563
  static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
564
    YamlIO.mapRequired("id", Entry.ID);
565
    YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>());
566
  }
567
};
568
 
569
} // end namespace yaml
570
} // end namespace llvm
571
 
572
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
573
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
574
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
575
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
576
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo)
577
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
578
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
579
 
580
namespace llvm {
581
namespace yaml {
582
 
583
template <> struct MappingTraits<MachineJumpTable> {
584
  static void mapping(IO &YamlIO, MachineJumpTable &JT) {
585
    YamlIO.mapRequired("kind", JT.Kind);
586
    YamlIO.mapOptional("entries", JT.Entries,
587
                       std::vector<MachineJumpTable::Entry>());
588
  }
589
};
590
 
591
/// Serializable representation of MachineFrameInfo.
592
///
593
/// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
594
/// 'RealignOption' as they are determined by the target and LLVM function
595
/// attributes.
596
/// It also doesn't serialize attributes like 'NumFixedObject' and
597
/// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
598
struct MachineFrameInfo {
599
  bool IsFrameAddressTaken = false;
600
  bool IsReturnAddressTaken = false;
601
  bool HasStackMap = false;
602
  bool HasPatchPoint = false;
603
  uint64_t StackSize = 0;
604
  int OffsetAdjustment = 0;
605
  unsigned MaxAlignment = 0;
606
  bool AdjustsStack = false;
607
  bool HasCalls = false;
608
  StringValue StackProtector;
609
  StringValue FunctionContext;
610
  unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
611
  unsigned CVBytesOfCalleeSavedRegisters = 0;
612
  bool HasOpaqueSPAdjustment = false;
613
  bool HasVAStart = false;
614
  bool HasMustTailInVarArgFunc = false;
615
  bool HasTailCall = false;
616
  unsigned LocalFrameSize = 0;
617
  StringValue SavePoint;
618
  StringValue RestorePoint;
619
 
620
  bool operator==(const MachineFrameInfo &Other) const {
621
    return IsFrameAddressTaken == Other.IsFrameAddressTaken &&
622
           IsReturnAddressTaken == Other.IsReturnAddressTaken &&
623
           HasStackMap == Other.HasStackMap &&
624
           HasPatchPoint == Other.HasPatchPoint &&
625
           StackSize == Other.StackSize &&
626
           OffsetAdjustment == Other.OffsetAdjustment &&
627
           MaxAlignment == Other.MaxAlignment &&
628
           AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
629
           StackProtector == Other.StackProtector &&
630
           FunctionContext == Other.FunctionContext &&
631
           MaxCallFrameSize == Other.MaxCallFrameSize &&
632
           CVBytesOfCalleeSavedRegisters ==
633
               Other.CVBytesOfCalleeSavedRegisters &&
634
           HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
635
           HasVAStart == Other.HasVAStart &&
636
           HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
637
           HasTailCall == Other.HasTailCall &&
638
           LocalFrameSize == Other.LocalFrameSize &&
639
           SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint;
640
  }
641
};
642
 
643
template <> struct MappingTraits<MachineFrameInfo> {
644
  static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
645
    YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false);
646
    YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false);
647
    YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false);
648
    YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false);
649
    YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0);
650
    YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0);
651
    YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
652
    YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
653
    YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
654
    YamlIO.mapOptional("stackProtector", MFI.StackProtector,
655
                       StringValue()); // Don't print it out when it's empty.
656
    YamlIO.mapOptional("functionContext", MFI.FunctionContext,
657
                       StringValue()); // Don't print it out when it's empty.
658
    YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0);
659
    YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters",
660
                       MFI.CVBytesOfCalleeSavedRegisters, 0U);
661
    YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,
662
                       false);
663
    YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
664
    YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
665
                       false);
666
    YamlIO.mapOptional("hasTailCall", MFI.HasTailCall, false);
667
    YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0);
668
    YamlIO.mapOptional("savePoint", MFI.SavePoint,
669
                       StringValue()); // Don't print it out when it's empty.
670
    YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
671
                       StringValue()); // Don't print it out when it's empty.
672
  }
673
};
674
 
675
/// Targets should override this in a way that mirrors the implementation of
676
/// llvm::MachineFunctionInfo.
677
struct MachineFunctionInfo {
678
  virtual ~MachineFunctionInfo() = default;
679
  virtual void mappingImpl(IO &YamlIO) {}
680
};
681
 
682
template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
683
  static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
684
    if (MFI)
685
      MFI->mappingImpl(YamlIO);
686
  }
687
};
688
 
689
struct MachineFunction {
690
  StringRef Name;
691
  MaybeAlign Alignment = std::nullopt;
692
  bool ExposesReturnsTwice = false;
693
  // GISel MachineFunctionProperties.
694
  bool Legalized = false;
695
  bool RegBankSelected = false;
696
  bool Selected = false;
697
  bool FailedISel = false;
698
  // Register information
699
  bool TracksRegLiveness = false;
700
  bool HasWinCFI = false;
701
 
702
  bool CallsEHReturn = false;
703
  bool CallsUnwindInit = false;
704
  bool HasEHCatchret = false;
705
  bool HasEHScopes = false;
706
  bool HasEHFunclets = false;
707
 
708
  bool FailsVerification = false;
709
  bool TracksDebugUserValues = false;
710
  bool UseDebugInstrRef = false;
711
  std::vector<VirtualRegisterDefinition> VirtualRegisters;
712
  std::vector<MachineFunctionLiveIn> LiveIns;
713
  std::optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
714
  // TODO: Serialize the various register masks.
715
  // Frame information
716
  MachineFrameInfo FrameInfo;
717
  std::vector<FixedMachineStackObject> FixedStackObjects;
718
  std::vector<MachineStackObject> StackObjects;
719
  std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
720
  std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
721
  std::vector<CallSiteInfo> CallSitesInfo;
722
  std::vector<DebugValueSubstitution> DebugValueSubstitutions;
723
  MachineJumpTable JumpTableInfo;
724
  std::vector<StringValue> MachineMetadataNodes;
725
  BlockStringValue Body;
726
};
727
 
728
template <> struct MappingTraits<MachineFunction> {
729
  static void mapping(IO &YamlIO, MachineFunction &MF) {
730
    YamlIO.mapRequired("name", MF.Name);
731
    YamlIO.mapOptional("alignment", MF.Alignment, std::nullopt);
732
    YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false);
733
    YamlIO.mapOptional("legalized", MF.Legalized, false);
734
    YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
735
    YamlIO.mapOptional("selected", MF.Selected, false);
736
    YamlIO.mapOptional("failedISel", MF.FailedISel, false);
737
    YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
738
    YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false);
739
 
740
    YamlIO.mapOptional("callsEHReturn", MF.CallsEHReturn, false);
741
    YamlIO.mapOptional("callsUnwindInit", MF.CallsUnwindInit, false);
742
    YamlIO.mapOptional("hasEHCatchret", MF.HasEHCatchret, false);
743
    YamlIO.mapOptional("hasEHScopes", MF.HasEHScopes, false);
744
    YamlIO.mapOptional("hasEHFunclets", MF.HasEHFunclets, false);
745
    YamlIO.mapOptional("debugInstrRef", MF.UseDebugInstrRef, false);
746
 
747
    YamlIO.mapOptional("failsVerification", MF.FailsVerification, false);
748
    YamlIO.mapOptional("tracksDebugUserValues", MF.TracksDebugUserValues,
749
                       false);
750
    YamlIO.mapOptional("registers", MF.VirtualRegisters,
751
                       std::vector<VirtualRegisterDefinition>());
752
    YamlIO.mapOptional("liveins", MF.LiveIns,
753
                       std::vector<MachineFunctionLiveIn>());
754
    YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters,
755
                       std::optional<std::vector<FlowStringValue>>());
756
    YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo());
757
    YamlIO.mapOptional("fixedStack", MF.FixedStackObjects,
758
                       std::vector<FixedMachineStackObject>());
759
    YamlIO.mapOptional("stack", MF.StackObjects,
760
                       std::vector<MachineStackObject>());
761
    YamlIO.mapOptional("callSites", MF.CallSitesInfo,
762
                       std::vector<CallSiteInfo>());
763
    YamlIO.mapOptional("debugValueSubstitutions", MF.DebugValueSubstitutions,
764
                       std::vector<DebugValueSubstitution>());
765
    YamlIO.mapOptional("constants", MF.Constants,
766
                       std::vector<MachineConstantPoolValue>());
767
    YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
768
    if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
769
      YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
770
    if (!YamlIO.outputting() || !MF.MachineMetadataNodes.empty())
771
      YamlIO.mapOptional("machineMetadataNodes", MF.MachineMetadataNodes,
772
                         std::vector<StringValue>());
773
    YamlIO.mapOptional("body", MF.Body, BlockStringValue());
774
  }
775
};
776
 
777
} // end namespace yaml
778
} // end namespace llvm
779
 
780
#endif // LLVM_CODEGEN_MIRYAMLMAPPING_H