MIRYamlMapping.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- MIRYamlMapping.h - Describe mapping between MIR and YAML--*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file implements the mapping between various MIR data structures and
  15. // their corresponding YAML representation.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CODEGEN_MIRYAMLMAPPING_H
  19. #define LLVM_CODEGEN_MIRYAMLMAPPING_H
  20. #include "llvm/ADT/StringRef.h"
  21. #include "llvm/CodeGen/MachineJumpTableInfo.h"
  22. #include "llvm/CodeGen/TargetFrameLowering.h"
  23. #include "llvm/Support/SMLoc.h"
  24. #include "llvm/Support/YAMLTraits.h"
  25. #include "llvm/Support/raw_ostream.h"
  26. #include <algorithm>
  27. #include <cstdint>
  28. #include <optional>
  29. #include <string>
  30. #include <vector>
  31. namespace llvm {
  32. namespace yaml {
  33. /// A wrapper around std::string which contains a source range that's being
  34. /// set during parsing.
  35. struct StringValue {
  36. std::string Value;
  37. SMRange SourceRange;
  38. StringValue() = default;
  39. StringValue(std::string Value) : Value(std::move(Value)) {}
  40. StringValue(const char Val[]) : Value(Val) {}
  41. bool operator==(const StringValue &Other) const {
  42. return Value == Other.Value;
  43. }
  44. };
  45. template <> struct ScalarTraits<StringValue> {
  46. static void output(const StringValue &S, void *, raw_ostream &OS) {
  47. OS << S.Value;
  48. }
  49. static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) {
  50. S.Value = Scalar.str();
  51. if (const auto *Node =
  52. reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
  53. S.SourceRange = Node->getSourceRange();
  54. return "";
  55. }
  56. static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  57. };
  58. struct FlowStringValue : StringValue {
  59. FlowStringValue() = default;
  60. FlowStringValue(std::string Value) : StringValue(std::move(Value)) {}
  61. };
  62. template <> struct ScalarTraits<FlowStringValue> {
  63. static void output(const FlowStringValue &S, void *, raw_ostream &OS) {
  64. return ScalarTraits<StringValue>::output(S, nullptr, OS);
  65. }
  66. static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) {
  67. return ScalarTraits<StringValue>::input(Scalar, Ctx, S);
  68. }
  69. static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  70. };
  71. struct BlockStringValue {
  72. StringValue Value;
  73. bool operator==(const BlockStringValue &Other) const {
  74. return Value == Other.Value;
  75. }
  76. };
  77. template <> struct BlockScalarTraits<BlockStringValue> {
  78. static void output(const BlockStringValue &S, void *Ctx, raw_ostream &OS) {
  79. return ScalarTraits<StringValue>::output(S.Value, Ctx, OS);
  80. }
  81. static StringRef input(StringRef Scalar, void *Ctx, BlockStringValue &S) {
  82. return ScalarTraits<StringValue>::input(Scalar, Ctx, S.Value);
  83. }
  84. };
  85. /// A wrapper around unsigned which contains a source range that's being set
  86. /// during parsing.
  87. struct UnsignedValue {
  88. unsigned Value = 0;
  89. SMRange SourceRange;
  90. UnsignedValue() = default;
  91. UnsignedValue(unsigned Value) : Value(Value) {}
  92. bool operator==(const UnsignedValue &Other) const {
  93. return Value == Other.Value;
  94. }
  95. };
  96. template <> struct ScalarTraits<UnsignedValue> {
  97. static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) {
  98. return ScalarTraits<unsigned>::output(Value.Value, Ctx, OS);
  99. }
  100. static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) {
  101. if (const auto *Node =
  102. reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
  103. Value.SourceRange = Node->getSourceRange();
  104. return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value);
  105. }
  106. static QuotingType mustQuote(StringRef Scalar) {
  107. return ScalarTraits<unsigned>::mustQuote(Scalar);
  108. }
  109. };
  110. template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> {
  111. static void enumeration(yaml::IO &IO,
  112. MachineJumpTableInfo::JTEntryKind &EntryKind) {
  113. IO.enumCase(EntryKind, "block-address",
  114. MachineJumpTableInfo::EK_BlockAddress);
  115. IO.enumCase(EntryKind, "gp-rel64-block-address",
  116. MachineJumpTableInfo::EK_GPRel64BlockAddress);
  117. IO.enumCase(EntryKind, "gp-rel32-block-address",
  118. MachineJumpTableInfo::EK_GPRel32BlockAddress);
  119. IO.enumCase(EntryKind, "label-difference32",
  120. MachineJumpTableInfo::EK_LabelDifference32);
  121. IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline);
  122. IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32);
  123. }
  124. };
  125. template <> struct ScalarTraits<MaybeAlign> {
  126. static void output(const MaybeAlign &Alignment, void *,
  127. llvm::raw_ostream &out) {
  128. out << uint64_t(Alignment ? Alignment->value() : 0U);
  129. }
  130. static StringRef input(StringRef Scalar, void *, MaybeAlign &Alignment) {
  131. unsigned long long n;
  132. if (getAsUnsignedInteger(Scalar, 10, n))
  133. return "invalid number";
  134. if (n > 0 && !isPowerOf2_64(n))
  135. return "must be 0 or a power of two";
  136. Alignment = MaybeAlign(n);
  137. return StringRef();
  138. }
  139. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  140. };
  141. template <> struct ScalarTraits<Align> {
  142. static void output(const Align &Alignment, void *, llvm::raw_ostream &OS) {
  143. OS << Alignment.value();
  144. }
  145. static StringRef input(StringRef Scalar, void *, Align &Alignment) {
  146. unsigned long long N;
  147. if (getAsUnsignedInteger(Scalar, 10, N))
  148. return "invalid number";
  149. if (!isPowerOf2_64(N))
  150. return "must be a power of two";
  151. Alignment = Align(N);
  152. return StringRef();
  153. }
  154. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  155. };
  156. } // end namespace yaml
  157. } // end namespace llvm
  158. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
  159. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
  160. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue)
  161. namespace llvm {
  162. namespace yaml {
  163. struct VirtualRegisterDefinition {
  164. UnsignedValue ID;
  165. StringValue Class;
  166. StringValue PreferredRegister;
  167. // TODO: Serialize the target specific register hints.
  168. bool operator==(const VirtualRegisterDefinition &Other) const {
  169. return ID == Other.ID && Class == Other.Class &&
  170. PreferredRegister == Other.PreferredRegister;
  171. }
  172. };
  173. template <> struct MappingTraits<VirtualRegisterDefinition> {
  174. static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
  175. YamlIO.mapRequired("id", Reg.ID);
  176. YamlIO.mapRequired("class", Reg.Class);
  177. YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
  178. StringValue()); // Don't print out when it's empty.
  179. }
  180. static const bool flow = true;
  181. };
  182. struct MachineFunctionLiveIn {
  183. StringValue Register;
  184. StringValue VirtualRegister;
  185. bool operator==(const MachineFunctionLiveIn &Other) const {
  186. return Register == Other.Register &&
  187. VirtualRegister == Other.VirtualRegister;
  188. }
  189. };
  190. template <> struct MappingTraits<MachineFunctionLiveIn> {
  191. static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) {
  192. YamlIO.mapRequired("reg", LiveIn.Register);
  193. YamlIO.mapOptional(
  194. "virtual-reg", LiveIn.VirtualRegister,
  195. StringValue()); // Don't print the virtual register when it's empty.
  196. }
  197. static const bool flow = true;
  198. };
  199. /// Serializable representation of stack object from the MachineFrameInfo class.
  200. ///
  201. /// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are
  202. /// determined by the object's type and frame information flags.
  203. /// Dead stack objects aren't serialized.
  204. ///
  205. /// The 'isPreallocated' flag is determined by the local offset.
  206. struct MachineStackObject {
  207. enum ObjectType { DefaultType, SpillSlot, VariableSized };
  208. UnsignedValue ID;
  209. StringValue Name;
  210. // TODO: Serialize unnamed LLVM alloca reference.
  211. ObjectType Type = DefaultType;
  212. int64_t Offset = 0;
  213. uint64_t Size = 0;
  214. MaybeAlign Alignment = std::nullopt;
  215. TargetStackID::Value StackID;
  216. StringValue CalleeSavedRegister;
  217. bool CalleeSavedRestored = true;
  218. std::optional<int64_t> LocalOffset;
  219. StringValue DebugVar;
  220. StringValue DebugExpr;
  221. StringValue DebugLoc;
  222. bool operator==(const MachineStackObject &Other) const {
  223. return ID == Other.ID && Name == Other.Name && Type == Other.Type &&
  224. Offset == Other.Offset && Size == Other.Size &&
  225. Alignment == Other.Alignment &&
  226. StackID == Other.StackID &&
  227. CalleeSavedRegister == Other.CalleeSavedRegister &&
  228. CalleeSavedRestored == Other.CalleeSavedRestored &&
  229. LocalOffset == Other.LocalOffset && DebugVar == Other.DebugVar &&
  230. DebugExpr == Other.DebugExpr && DebugLoc == Other.DebugLoc;
  231. }
  232. };
  233. template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> {
  234. static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) {
  235. IO.enumCase(Type, "default", MachineStackObject::DefaultType);
  236. IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot);
  237. IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized);
  238. }
  239. };
  240. template <> struct MappingTraits<MachineStackObject> {
  241. static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) {
  242. YamlIO.mapRequired("id", Object.ID);
  243. YamlIO.mapOptional("name", Object.Name,
  244. StringValue()); // Don't print out an empty name.
  245. YamlIO.mapOptional(
  246. "type", Object.Type,
  247. MachineStackObject::DefaultType); // Don't print the default type.
  248. YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
  249. if (Object.Type != MachineStackObject::VariableSized)
  250. YamlIO.mapRequired("size", Object.Size);
  251. YamlIO.mapOptional("alignment", Object.Alignment, std::nullopt);
  252. YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
  253. YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
  254. StringValue()); // Don't print it out when it's empty.
  255. YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
  256. true);
  257. YamlIO.mapOptional("local-offset", Object.LocalOffset,
  258. std::optional<int64_t>());
  259. YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
  260. StringValue()); // Don't print it out when it's empty.
  261. YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
  262. StringValue()); // Don't print it out when it's empty.
  263. YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
  264. StringValue()); // Don't print it out when it's empty.
  265. }
  266. static const bool flow = true;
  267. };
  268. /// Serializable representation of the fixed stack object from the
  269. /// MachineFrameInfo class.
  270. struct FixedMachineStackObject {
  271. enum ObjectType { DefaultType, SpillSlot };
  272. UnsignedValue ID;
  273. ObjectType Type = DefaultType;
  274. int64_t Offset = 0;
  275. uint64_t Size = 0;
  276. MaybeAlign Alignment = std::nullopt;
  277. TargetStackID::Value StackID;
  278. bool IsImmutable = false;
  279. bool IsAliased = false;
  280. StringValue CalleeSavedRegister;
  281. bool CalleeSavedRestored = true;
  282. StringValue DebugVar;
  283. StringValue DebugExpr;
  284. StringValue DebugLoc;
  285. bool operator==(const FixedMachineStackObject &Other) const {
  286. return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
  287. Size == Other.Size && Alignment == Other.Alignment &&
  288. StackID == Other.StackID &&
  289. IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
  290. CalleeSavedRegister == Other.CalleeSavedRegister &&
  291. CalleeSavedRestored == Other.CalleeSavedRestored &&
  292. DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr
  293. && DebugLoc == Other.DebugLoc;
  294. }
  295. };
  296. template <>
  297. struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
  298. static void enumeration(yaml::IO &IO,
  299. FixedMachineStackObject::ObjectType &Type) {
  300. IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
  301. IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
  302. }
  303. };
  304. template <>
  305. struct ScalarEnumerationTraits<TargetStackID::Value> {
  306. static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) {
  307. IO.enumCase(ID, "default", TargetStackID::Default);
  308. IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill);
  309. IO.enumCase(ID, "scalable-vector", TargetStackID::ScalableVector);
  310. IO.enumCase(ID, "wasm-local", TargetStackID::WasmLocal);
  311. IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc);
  312. }
  313. };
  314. template <> struct MappingTraits<FixedMachineStackObject> {
  315. static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
  316. YamlIO.mapRequired("id", Object.ID);
  317. YamlIO.mapOptional(
  318. "type", Object.Type,
  319. FixedMachineStackObject::DefaultType); // Don't print the default type.
  320. YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
  321. YamlIO.mapOptional("size", Object.Size, (uint64_t)0);
  322. YamlIO.mapOptional("alignment", Object.Alignment, std::nullopt);
  323. YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
  324. if (Object.Type != FixedMachineStackObject::SpillSlot) {
  325. YamlIO.mapOptional("isImmutable", Object.IsImmutable, false);
  326. YamlIO.mapOptional("isAliased", Object.IsAliased, false);
  327. }
  328. YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
  329. StringValue()); // Don't print it out when it's empty.
  330. YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
  331. true);
  332. YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
  333. StringValue()); // Don't print it out when it's empty.
  334. YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
  335. StringValue()); // Don't print it out when it's empty.
  336. YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
  337. StringValue()); // Don't print it out when it's empty.
  338. }
  339. static const bool flow = true;
  340. };
  341. /// A serializaable representation of a reference to a stack object or fixed
  342. /// stack object.
  343. struct FrameIndex {
  344. // The frame index as printed. This is always a positive number, even for
  345. // fixed objects. To obtain the real index,
  346. // MachineFrameInfo::getObjectIndexBegin has to be added.
  347. int FI;
  348. bool IsFixed;
  349. SMRange SourceRange;
  350. FrameIndex() = default;
  351. FrameIndex(int FI, const llvm::MachineFrameInfo &MFI);
  352. Expected<int> getFI(const llvm::MachineFrameInfo &MFI) const;
  353. };
  354. template <> struct ScalarTraits<FrameIndex> {
  355. static void output(const FrameIndex &FI, void *, raw_ostream &OS) {
  356. MachineOperand::printStackObjectReference(OS, FI.FI, FI.IsFixed, "");
  357. }
  358. static StringRef input(StringRef Scalar, void *Ctx, FrameIndex &FI) {
  359. FI.IsFixed = false;
  360. StringRef Num;
  361. if (Scalar.startswith("%stack.")) {
  362. Num = Scalar.substr(7);
  363. } else if (Scalar.startswith("%fixed-stack.")) {
  364. Num = Scalar.substr(13);
  365. FI.IsFixed = true;
  366. } else {
  367. return "Invalid frame index, needs to start with %stack. or "
  368. "%fixed-stack.";
  369. }
  370. if (Num.consumeInteger(10, FI.FI))
  371. return "Invalid frame index, not a valid number";
  372. if (const auto *Node =
  373. reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
  374. FI.SourceRange = Node->getSourceRange();
  375. return StringRef();
  376. }
  377. static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  378. };
  379. /// Serializable representation of CallSiteInfo.
  380. struct CallSiteInfo {
  381. // Representation of call argument and register which is used to
  382. // transfer it.
  383. struct ArgRegPair {
  384. StringValue Reg;
  385. uint16_t ArgNo;
  386. bool operator==(const ArgRegPair &Other) const {
  387. return Reg == Other.Reg && ArgNo == Other.ArgNo;
  388. }
  389. };
  390. /// Identifies call instruction location in machine function.
  391. struct MachineInstrLoc {
  392. unsigned BlockNum;
  393. unsigned Offset;
  394. bool operator==(const MachineInstrLoc &Other) const {
  395. return BlockNum == Other.BlockNum && Offset == Other.Offset;
  396. }
  397. };
  398. MachineInstrLoc CallLocation;
  399. std::vector<ArgRegPair> ArgForwardingRegs;
  400. bool operator==(const CallSiteInfo &Other) const {
  401. return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
  402. CallLocation.Offset == Other.CallLocation.Offset;
  403. }
  404. };
  405. template <> struct MappingTraits<CallSiteInfo::ArgRegPair> {
  406. static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) {
  407. YamlIO.mapRequired("arg", ArgReg.ArgNo);
  408. YamlIO.mapRequired("reg", ArgReg.Reg);
  409. }
  410. static const bool flow = true;
  411. };
  412. }
  413. }
  414. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair)
  415. namespace llvm {
  416. namespace yaml {
  417. template <> struct MappingTraits<CallSiteInfo> {
  418. static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) {
  419. YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum);
  420. YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
  421. YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
  422. std::vector<CallSiteInfo::ArgRegPair>());
  423. }
  424. static const bool flow = true;
  425. };
  426. /// Serializable representation of debug value substitutions.
  427. struct DebugValueSubstitution {
  428. unsigned SrcInst;
  429. unsigned SrcOp;
  430. unsigned DstInst;
  431. unsigned DstOp;
  432. unsigned Subreg;
  433. bool operator==(const DebugValueSubstitution &Other) const {
  434. return std::tie(SrcInst, SrcOp, DstInst, DstOp) ==
  435. std::tie(Other.SrcInst, Other.SrcOp, Other.DstInst, Other.DstOp);
  436. }
  437. };
  438. template <> struct MappingTraits<DebugValueSubstitution> {
  439. static void mapping(IO &YamlIO, DebugValueSubstitution &Sub) {
  440. YamlIO.mapRequired("srcinst", Sub.SrcInst);
  441. YamlIO.mapRequired("srcop", Sub.SrcOp);
  442. YamlIO.mapRequired("dstinst", Sub.DstInst);
  443. YamlIO.mapRequired("dstop", Sub.DstOp);
  444. YamlIO.mapRequired("subreg", Sub.Subreg);
  445. }
  446. static const bool flow = true;
  447. };
  448. } // namespace yaml
  449. } // namespace llvm
  450. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::DebugValueSubstitution)
  451. namespace llvm {
  452. namespace yaml {
  453. struct MachineConstantPoolValue {
  454. UnsignedValue ID;
  455. StringValue Value;
  456. MaybeAlign Alignment = std::nullopt;
  457. bool IsTargetSpecific = false;
  458. bool operator==(const MachineConstantPoolValue &Other) const {
  459. return ID == Other.ID && Value == Other.Value &&
  460. Alignment == Other.Alignment &&
  461. IsTargetSpecific == Other.IsTargetSpecific;
  462. }
  463. };
  464. template <> struct MappingTraits<MachineConstantPoolValue> {
  465. static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
  466. YamlIO.mapRequired("id", Constant.ID);
  467. YamlIO.mapOptional("value", Constant.Value, StringValue());
  468. YamlIO.mapOptional("alignment", Constant.Alignment, std::nullopt);
  469. YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false);
  470. }
  471. };
  472. struct MachineJumpTable {
  473. struct Entry {
  474. UnsignedValue ID;
  475. std::vector<FlowStringValue> Blocks;
  476. bool operator==(const Entry &Other) const {
  477. return ID == Other.ID && Blocks == Other.Blocks;
  478. }
  479. };
  480. MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
  481. std::vector<Entry> Entries;
  482. bool operator==(const MachineJumpTable &Other) const {
  483. return Kind == Other.Kind && Entries == Other.Entries;
  484. }
  485. };
  486. template <> struct MappingTraits<MachineJumpTable::Entry> {
  487. static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
  488. YamlIO.mapRequired("id", Entry.ID);
  489. YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>());
  490. }
  491. };
  492. } // end namespace yaml
  493. } // end namespace llvm
  494. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
  495. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
  496. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
  497. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
  498. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo)
  499. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
  500. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
  501. namespace llvm {
  502. namespace yaml {
  503. template <> struct MappingTraits<MachineJumpTable> {
  504. static void mapping(IO &YamlIO, MachineJumpTable &JT) {
  505. YamlIO.mapRequired("kind", JT.Kind);
  506. YamlIO.mapOptional("entries", JT.Entries,
  507. std::vector<MachineJumpTable::Entry>());
  508. }
  509. };
  510. /// Serializable representation of MachineFrameInfo.
  511. ///
  512. /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
  513. /// 'RealignOption' as they are determined by the target and LLVM function
  514. /// attributes.
  515. /// It also doesn't serialize attributes like 'NumFixedObject' and
  516. /// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
  517. struct MachineFrameInfo {
  518. bool IsFrameAddressTaken = false;
  519. bool IsReturnAddressTaken = false;
  520. bool HasStackMap = false;
  521. bool HasPatchPoint = false;
  522. uint64_t StackSize = 0;
  523. int OffsetAdjustment = 0;
  524. unsigned MaxAlignment = 0;
  525. bool AdjustsStack = false;
  526. bool HasCalls = false;
  527. StringValue StackProtector;
  528. StringValue FunctionContext;
  529. unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
  530. unsigned CVBytesOfCalleeSavedRegisters = 0;
  531. bool HasOpaqueSPAdjustment = false;
  532. bool HasVAStart = false;
  533. bool HasMustTailInVarArgFunc = false;
  534. bool HasTailCall = false;
  535. unsigned LocalFrameSize = 0;
  536. StringValue SavePoint;
  537. StringValue RestorePoint;
  538. bool operator==(const MachineFrameInfo &Other) const {
  539. return IsFrameAddressTaken == Other.IsFrameAddressTaken &&
  540. IsReturnAddressTaken == Other.IsReturnAddressTaken &&
  541. HasStackMap == Other.HasStackMap &&
  542. HasPatchPoint == Other.HasPatchPoint &&
  543. StackSize == Other.StackSize &&
  544. OffsetAdjustment == Other.OffsetAdjustment &&
  545. MaxAlignment == Other.MaxAlignment &&
  546. AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
  547. StackProtector == Other.StackProtector &&
  548. FunctionContext == Other.FunctionContext &&
  549. MaxCallFrameSize == Other.MaxCallFrameSize &&
  550. CVBytesOfCalleeSavedRegisters ==
  551. Other.CVBytesOfCalleeSavedRegisters &&
  552. HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
  553. HasVAStart == Other.HasVAStart &&
  554. HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
  555. HasTailCall == Other.HasTailCall &&
  556. LocalFrameSize == Other.LocalFrameSize &&
  557. SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint;
  558. }
  559. };
  560. template <> struct MappingTraits<MachineFrameInfo> {
  561. static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
  562. YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false);
  563. YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false);
  564. YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false);
  565. YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false);
  566. YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0);
  567. YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0);
  568. YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
  569. YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
  570. YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
  571. YamlIO.mapOptional("stackProtector", MFI.StackProtector,
  572. StringValue()); // Don't print it out when it's empty.
  573. YamlIO.mapOptional("functionContext", MFI.FunctionContext,
  574. StringValue()); // Don't print it out when it's empty.
  575. YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0);
  576. YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters",
  577. MFI.CVBytesOfCalleeSavedRegisters, 0U);
  578. YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,
  579. false);
  580. YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
  581. YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
  582. false);
  583. YamlIO.mapOptional("hasTailCall", MFI.HasTailCall, false);
  584. YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0);
  585. YamlIO.mapOptional("savePoint", MFI.SavePoint,
  586. StringValue()); // Don't print it out when it's empty.
  587. YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
  588. StringValue()); // Don't print it out when it's empty.
  589. }
  590. };
  591. /// Targets should override this in a way that mirrors the implementation of
  592. /// llvm::MachineFunctionInfo.
  593. struct MachineFunctionInfo {
  594. virtual ~MachineFunctionInfo() = default;
  595. virtual void mappingImpl(IO &YamlIO) {}
  596. };
  597. template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
  598. static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
  599. if (MFI)
  600. MFI->mappingImpl(YamlIO);
  601. }
  602. };
  603. struct MachineFunction {
  604. StringRef Name;
  605. MaybeAlign Alignment = std::nullopt;
  606. bool ExposesReturnsTwice = false;
  607. // GISel MachineFunctionProperties.
  608. bool Legalized = false;
  609. bool RegBankSelected = false;
  610. bool Selected = false;
  611. bool FailedISel = false;
  612. // Register information
  613. bool TracksRegLiveness = false;
  614. bool HasWinCFI = false;
  615. bool CallsEHReturn = false;
  616. bool CallsUnwindInit = false;
  617. bool HasEHCatchret = false;
  618. bool HasEHScopes = false;
  619. bool HasEHFunclets = false;
  620. bool FailsVerification = false;
  621. bool TracksDebugUserValues = false;
  622. bool UseDebugInstrRef = false;
  623. std::vector<VirtualRegisterDefinition> VirtualRegisters;
  624. std::vector<MachineFunctionLiveIn> LiveIns;
  625. std::optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
  626. // TODO: Serialize the various register masks.
  627. // Frame information
  628. MachineFrameInfo FrameInfo;
  629. std::vector<FixedMachineStackObject> FixedStackObjects;
  630. std::vector<MachineStackObject> StackObjects;
  631. std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
  632. std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
  633. std::vector<CallSiteInfo> CallSitesInfo;
  634. std::vector<DebugValueSubstitution> DebugValueSubstitutions;
  635. MachineJumpTable JumpTableInfo;
  636. std::vector<StringValue> MachineMetadataNodes;
  637. BlockStringValue Body;
  638. };
  639. template <> struct MappingTraits<MachineFunction> {
  640. static void mapping(IO &YamlIO, MachineFunction &MF) {
  641. YamlIO.mapRequired("name", MF.Name);
  642. YamlIO.mapOptional("alignment", MF.Alignment, std::nullopt);
  643. YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false);
  644. YamlIO.mapOptional("legalized", MF.Legalized, false);
  645. YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
  646. YamlIO.mapOptional("selected", MF.Selected, false);
  647. YamlIO.mapOptional("failedISel", MF.FailedISel, false);
  648. YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
  649. YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false);
  650. YamlIO.mapOptional("callsEHReturn", MF.CallsEHReturn, false);
  651. YamlIO.mapOptional("callsUnwindInit", MF.CallsUnwindInit, false);
  652. YamlIO.mapOptional("hasEHCatchret", MF.HasEHCatchret, false);
  653. YamlIO.mapOptional("hasEHScopes", MF.HasEHScopes, false);
  654. YamlIO.mapOptional("hasEHFunclets", MF.HasEHFunclets, false);
  655. YamlIO.mapOptional("debugInstrRef", MF.UseDebugInstrRef, false);
  656. YamlIO.mapOptional("failsVerification", MF.FailsVerification, false);
  657. YamlIO.mapOptional("tracksDebugUserValues", MF.TracksDebugUserValues,
  658. false);
  659. YamlIO.mapOptional("registers", MF.VirtualRegisters,
  660. std::vector<VirtualRegisterDefinition>());
  661. YamlIO.mapOptional("liveins", MF.LiveIns,
  662. std::vector<MachineFunctionLiveIn>());
  663. YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters,
  664. std::optional<std::vector<FlowStringValue>>());
  665. YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo());
  666. YamlIO.mapOptional("fixedStack", MF.FixedStackObjects,
  667. std::vector<FixedMachineStackObject>());
  668. YamlIO.mapOptional("stack", MF.StackObjects,
  669. std::vector<MachineStackObject>());
  670. YamlIO.mapOptional("callSites", MF.CallSitesInfo,
  671. std::vector<CallSiteInfo>());
  672. YamlIO.mapOptional("debugValueSubstitutions", MF.DebugValueSubstitutions,
  673. std::vector<DebugValueSubstitution>());
  674. YamlIO.mapOptional("constants", MF.Constants,
  675. std::vector<MachineConstantPoolValue>());
  676. YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
  677. if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
  678. YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
  679. if (!YamlIO.outputting() || !MF.MachineMetadataNodes.empty())
  680. YamlIO.mapOptional("machineMetadataNodes", MF.MachineMetadataNodes,
  681. std::vector<StringValue>());
  682. YamlIO.mapOptional("body", MF.Body, BlockStringValue());
  683. }
  684. };
  685. } // end namespace yaml
  686. } // end namespace llvm
  687. #endif // LLVM_CODEGEN_MIRYAMLMAPPING_H
  688. #ifdef __GNUC__
  689. #pragma GCC diagnostic pop
  690. #endif