MIRYamlMapping.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  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/Optional.h"
  21. #include "llvm/ADT/StringRef.h"
  22. #include "llvm/CodeGen/MachineJumpTableInfo.h"
  23. #include "llvm/CodeGen/TargetFrameLowering.h"
  24. #include "llvm/Support/SMLoc.h"
  25. #include "llvm/Support/YAMLTraits.h"
  26. #include "llvm/Support/raw_ostream.h"
  27. #include <algorithm>
  28. #include <cstdint>
  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 = None;
  215. TargetStackID::Value StackID;
  216. StringValue CalleeSavedRegister;
  217. bool CalleeSavedRestored = true;
  218. 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, None);
  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, Optional<int64_t>());
  258. YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
  259. StringValue()); // Don't print it out when it's empty.
  260. YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
  261. StringValue()); // Don't print it out when it's empty.
  262. YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
  263. StringValue()); // Don't print it out when it's empty.
  264. }
  265. static const bool flow = true;
  266. };
  267. /// Serializable representation of the fixed stack object from the
  268. /// MachineFrameInfo class.
  269. struct FixedMachineStackObject {
  270. enum ObjectType { DefaultType, SpillSlot };
  271. UnsignedValue ID;
  272. ObjectType Type = DefaultType;
  273. int64_t Offset = 0;
  274. uint64_t Size = 0;
  275. MaybeAlign Alignment = None;
  276. TargetStackID::Value StackID;
  277. bool IsImmutable = false;
  278. bool IsAliased = false;
  279. StringValue CalleeSavedRegister;
  280. bool CalleeSavedRestored = true;
  281. StringValue DebugVar;
  282. StringValue DebugExpr;
  283. StringValue DebugLoc;
  284. bool operator==(const FixedMachineStackObject &Other) const {
  285. return ID == Other.ID && Type == Other.Type && Offset == Other.Offset &&
  286. Size == Other.Size && Alignment == Other.Alignment &&
  287. StackID == Other.StackID &&
  288. IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased &&
  289. CalleeSavedRegister == Other.CalleeSavedRegister &&
  290. CalleeSavedRestored == Other.CalleeSavedRestored &&
  291. DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr
  292. && DebugLoc == Other.DebugLoc;
  293. }
  294. };
  295. template <>
  296. struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> {
  297. static void enumeration(yaml::IO &IO,
  298. FixedMachineStackObject::ObjectType &Type) {
  299. IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType);
  300. IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot);
  301. }
  302. };
  303. template <>
  304. struct ScalarEnumerationTraits<TargetStackID::Value> {
  305. static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) {
  306. IO.enumCase(ID, "default", TargetStackID::Default);
  307. IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill);
  308. IO.enumCase(ID, "scalable-vector", TargetStackID::ScalableVector);
  309. IO.enumCase(ID, "wasm-local", TargetStackID::WasmLocal);
  310. IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc);
  311. }
  312. };
  313. template <> struct MappingTraits<FixedMachineStackObject> {
  314. static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) {
  315. YamlIO.mapRequired("id", Object.ID);
  316. YamlIO.mapOptional(
  317. "type", Object.Type,
  318. FixedMachineStackObject::DefaultType); // Don't print the default type.
  319. YamlIO.mapOptional("offset", Object.Offset, (int64_t)0);
  320. YamlIO.mapOptional("size", Object.Size, (uint64_t)0);
  321. YamlIO.mapOptional("alignment", Object.Alignment, None);
  322. YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default);
  323. if (Object.Type != FixedMachineStackObject::SpillSlot) {
  324. YamlIO.mapOptional("isImmutable", Object.IsImmutable, false);
  325. YamlIO.mapOptional("isAliased", Object.IsAliased, false);
  326. }
  327. YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister,
  328. StringValue()); // Don't print it out when it's empty.
  329. YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored,
  330. true);
  331. YamlIO.mapOptional("debug-info-variable", Object.DebugVar,
  332. StringValue()); // Don't print it out when it's empty.
  333. YamlIO.mapOptional("debug-info-expression", Object.DebugExpr,
  334. StringValue()); // Don't print it out when it's empty.
  335. YamlIO.mapOptional("debug-info-location", Object.DebugLoc,
  336. StringValue()); // Don't print it out when it's empty.
  337. }
  338. static const bool flow = true;
  339. };
  340. /// A serializaable representation of a reference to a stack object or fixed
  341. /// stack object.
  342. struct FrameIndex {
  343. // The frame index as printed. This is always a positive number, even for
  344. // fixed objects. To obtain the real index,
  345. // MachineFrameInfo::getObjectIndexBegin has to be added.
  346. int FI;
  347. bool IsFixed;
  348. SMRange SourceRange;
  349. FrameIndex() = default;
  350. FrameIndex(int FI, const llvm::MachineFrameInfo &MFI);
  351. Expected<int> getFI(const llvm::MachineFrameInfo &MFI) const;
  352. };
  353. template <> struct ScalarTraits<FrameIndex> {
  354. static void output(const FrameIndex &FI, void *, raw_ostream &OS) {
  355. MachineOperand::printStackObjectReference(OS, FI.FI, FI.IsFixed, "");
  356. }
  357. static StringRef input(StringRef Scalar, void *Ctx, FrameIndex &FI) {
  358. FI.IsFixed = false;
  359. StringRef Num;
  360. if (Scalar.startswith("%stack.")) {
  361. Num = Scalar.substr(7);
  362. } else if (Scalar.startswith("%fixed-stack.")) {
  363. Num = Scalar.substr(13);
  364. FI.IsFixed = true;
  365. } else {
  366. return "Invalid frame index, needs to start with %stack. or "
  367. "%fixed-stack.";
  368. }
  369. if (Num.consumeInteger(10, FI.FI))
  370. return "Invalid frame index, not a valid number";
  371. if (const auto *Node =
  372. reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
  373. FI.SourceRange = Node->getSourceRange();
  374. return StringRef();
  375. }
  376. static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
  377. };
  378. /// Serializable representation of CallSiteInfo.
  379. struct CallSiteInfo {
  380. // Representation of call argument and register which is used to
  381. // transfer it.
  382. struct ArgRegPair {
  383. StringValue Reg;
  384. uint16_t ArgNo;
  385. bool operator==(const ArgRegPair &Other) const {
  386. return Reg == Other.Reg && ArgNo == Other.ArgNo;
  387. }
  388. };
  389. /// Identifies call instruction location in machine function.
  390. struct MachineInstrLoc {
  391. unsigned BlockNum;
  392. unsigned Offset;
  393. bool operator==(const MachineInstrLoc &Other) const {
  394. return BlockNum == Other.BlockNum && Offset == Other.Offset;
  395. }
  396. };
  397. MachineInstrLoc CallLocation;
  398. std::vector<ArgRegPair> ArgForwardingRegs;
  399. bool operator==(const CallSiteInfo &Other) const {
  400. return CallLocation.BlockNum == Other.CallLocation.BlockNum &&
  401. CallLocation.Offset == Other.CallLocation.Offset;
  402. }
  403. };
  404. template <> struct MappingTraits<CallSiteInfo::ArgRegPair> {
  405. static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) {
  406. YamlIO.mapRequired("arg", ArgReg.ArgNo);
  407. YamlIO.mapRequired("reg", ArgReg.Reg);
  408. }
  409. static const bool flow = true;
  410. };
  411. }
  412. }
  413. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair)
  414. namespace llvm {
  415. namespace yaml {
  416. template <> struct MappingTraits<CallSiteInfo> {
  417. static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) {
  418. YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum);
  419. YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset);
  420. YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs,
  421. std::vector<CallSiteInfo::ArgRegPair>());
  422. }
  423. static const bool flow = true;
  424. };
  425. /// Serializable representation of debug value substitutions.
  426. struct DebugValueSubstitution {
  427. unsigned SrcInst;
  428. unsigned SrcOp;
  429. unsigned DstInst;
  430. unsigned DstOp;
  431. unsigned Subreg;
  432. bool operator==(const DebugValueSubstitution &Other) const {
  433. return std::tie(SrcInst, SrcOp, DstInst, DstOp) ==
  434. std::tie(Other.SrcInst, Other.SrcOp, Other.DstInst, Other.DstOp);
  435. }
  436. };
  437. template <> struct MappingTraits<DebugValueSubstitution> {
  438. static void mapping(IO &YamlIO, DebugValueSubstitution &Sub) {
  439. YamlIO.mapRequired("srcinst", Sub.SrcInst);
  440. YamlIO.mapRequired("srcop", Sub.SrcOp);
  441. YamlIO.mapRequired("dstinst", Sub.DstInst);
  442. YamlIO.mapRequired("dstop", Sub.DstOp);
  443. YamlIO.mapRequired("subreg", Sub.Subreg);
  444. }
  445. static const bool flow = true;
  446. };
  447. } // namespace yaml
  448. } // namespace llvm
  449. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::DebugValueSubstitution)
  450. namespace llvm {
  451. namespace yaml {
  452. struct MachineConstantPoolValue {
  453. UnsignedValue ID;
  454. StringValue Value;
  455. MaybeAlign Alignment = None;
  456. bool IsTargetSpecific = false;
  457. bool operator==(const MachineConstantPoolValue &Other) const {
  458. return ID == Other.ID && Value == Other.Value &&
  459. Alignment == Other.Alignment &&
  460. IsTargetSpecific == Other.IsTargetSpecific;
  461. }
  462. };
  463. template <> struct MappingTraits<MachineConstantPoolValue> {
  464. static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) {
  465. YamlIO.mapRequired("id", Constant.ID);
  466. YamlIO.mapOptional("value", Constant.Value, StringValue());
  467. YamlIO.mapOptional("alignment", Constant.Alignment, None);
  468. YamlIO.mapOptional("isTargetSpecific", Constant.IsTargetSpecific, false);
  469. }
  470. };
  471. struct MachineJumpTable {
  472. struct Entry {
  473. UnsignedValue ID;
  474. std::vector<FlowStringValue> Blocks;
  475. bool operator==(const Entry &Other) const {
  476. return ID == Other.ID && Blocks == Other.Blocks;
  477. }
  478. };
  479. MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32;
  480. std::vector<Entry> Entries;
  481. bool operator==(const MachineJumpTable &Other) const {
  482. return Kind == Other.Kind && Entries == Other.Entries;
  483. }
  484. };
  485. template <> struct MappingTraits<MachineJumpTable::Entry> {
  486. static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) {
  487. YamlIO.mapRequired("id", Entry.ID);
  488. YamlIO.mapOptional("blocks", Entry.Blocks, std::vector<FlowStringValue>());
  489. }
  490. };
  491. } // end namespace yaml
  492. } // end namespace llvm
  493. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn)
  494. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
  495. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject)
  496. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject)
  497. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo)
  498. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue)
  499. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry)
  500. namespace llvm {
  501. namespace yaml {
  502. template <> struct MappingTraits<MachineJumpTable> {
  503. static void mapping(IO &YamlIO, MachineJumpTable &JT) {
  504. YamlIO.mapRequired("kind", JT.Kind);
  505. YamlIO.mapOptional("entries", JT.Entries,
  506. std::vector<MachineJumpTable::Entry>());
  507. }
  508. };
  509. /// Serializable representation of MachineFrameInfo.
  510. ///
  511. /// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and
  512. /// 'RealignOption' as they are determined by the target and LLVM function
  513. /// attributes.
  514. /// It also doesn't serialize attributes like 'NumFixedObject' and
  515. /// 'HasVarSizedObjects' as they are determined by the frame objects themselves.
  516. struct MachineFrameInfo {
  517. bool IsFrameAddressTaken = false;
  518. bool IsReturnAddressTaken = false;
  519. bool HasStackMap = false;
  520. bool HasPatchPoint = false;
  521. uint64_t StackSize = 0;
  522. int OffsetAdjustment = 0;
  523. unsigned MaxAlignment = 0;
  524. bool AdjustsStack = false;
  525. bool HasCalls = false;
  526. StringValue StackProtector;
  527. // TODO: Serialize FunctionContextIdx
  528. unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
  529. unsigned CVBytesOfCalleeSavedRegisters = 0;
  530. bool HasOpaqueSPAdjustment = false;
  531. bool HasVAStart = false;
  532. bool HasMustTailInVarArgFunc = false;
  533. bool HasTailCall = false;
  534. unsigned LocalFrameSize = 0;
  535. StringValue SavePoint;
  536. StringValue RestorePoint;
  537. bool operator==(const MachineFrameInfo &Other) const {
  538. return IsFrameAddressTaken == Other.IsFrameAddressTaken &&
  539. IsReturnAddressTaken == Other.IsReturnAddressTaken &&
  540. HasStackMap == Other.HasStackMap &&
  541. HasPatchPoint == Other.HasPatchPoint &&
  542. StackSize == Other.StackSize &&
  543. OffsetAdjustment == Other.OffsetAdjustment &&
  544. MaxAlignment == Other.MaxAlignment &&
  545. AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
  546. StackProtector == Other.StackProtector &&
  547. MaxCallFrameSize == Other.MaxCallFrameSize &&
  548. CVBytesOfCalleeSavedRegisters ==
  549. Other.CVBytesOfCalleeSavedRegisters &&
  550. HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment &&
  551. HasVAStart == Other.HasVAStart &&
  552. HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc &&
  553. HasTailCall == Other.HasTailCall &&
  554. LocalFrameSize == Other.LocalFrameSize &&
  555. SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint;
  556. }
  557. };
  558. template <> struct MappingTraits<MachineFrameInfo> {
  559. static void mapping(IO &YamlIO, MachineFrameInfo &MFI) {
  560. YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken, false);
  561. YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false);
  562. YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false);
  563. YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false);
  564. YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0);
  565. YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0);
  566. YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
  567. YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
  568. YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
  569. YamlIO.mapOptional("stackProtector", MFI.StackProtector,
  570. StringValue()); // Don't print it out when it's empty.
  571. YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize, (unsigned)~0);
  572. YamlIO.mapOptional("cvBytesOfCalleeSavedRegisters",
  573. MFI.CVBytesOfCalleeSavedRegisters, 0U);
  574. YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment,
  575. false);
  576. YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false);
  577. YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc,
  578. false);
  579. YamlIO.mapOptional("hasTailCall", MFI.HasTailCall, false);
  580. YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0);
  581. YamlIO.mapOptional("savePoint", MFI.SavePoint,
  582. StringValue()); // Don't print it out when it's empty.
  583. YamlIO.mapOptional("restorePoint", MFI.RestorePoint,
  584. StringValue()); // Don't print it out when it's empty.
  585. }
  586. };
  587. /// Targets should override this in a way that mirrors the implementation of
  588. /// llvm::MachineFunctionInfo.
  589. struct MachineFunctionInfo {
  590. virtual ~MachineFunctionInfo() = default;
  591. virtual void mappingImpl(IO &YamlIO) {}
  592. };
  593. template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
  594. static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
  595. if (MFI)
  596. MFI->mappingImpl(YamlIO);
  597. }
  598. };
  599. struct MachineFunction {
  600. StringRef Name;
  601. MaybeAlign Alignment = None;
  602. bool ExposesReturnsTwice = false;
  603. // GISel MachineFunctionProperties.
  604. bool Legalized = false;
  605. bool RegBankSelected = false;
  606. bool Selected = false;
  607. bool FailedISel = false;
  608. // Register information
  609. bool TracksRegLiveness = false;
  610. bool HasWinCFI = false;
  611. bool FailsVerification = false;
  612. bool TracksDebugUserValues = false;
  613. std::vector<VirtualRegisterDefinition> VirtualRegisters;
  614. std::vector<MachineFunctionLiveIn> LiveIns;
  615. Optional<std::vector<FlowStringValue>> CalleeSavedRegisters;
  616. // TODO: Serialize the various register masks.
  617. // Frame information
  618. MachineFrameInfo FrameInfo;
  619. std::vector<FixedMachineStackObject> FixedStackObjects;
  620. std::vector<MachineStackObject> StackObjects;
  621. std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
  622. std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
  623. std::vector<CallSiteInfo> CallSitesInfo;
  624. std::vector<DebugValueSubstitution> DebugValueSubstitutions;
  625. MachineJumpTable JumpTableInfo;
  626. std::vector<StringValue> MachineMetadataNodes;
  627. BlockStringValue Body;
  628. };
  629. template <> struct MappingTraits<MachineFunction> {
  630. static void mapping(IO &YamlIO, MachineFunction &MF) {
  631. YamlIO.mapRequired("name", MF.Name);
  632. YamlIO.mapOptional("alignment", MF.Alignment, None);
  633. YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice, false);
  634. YamlIO.mapOptional("legalized", MF.Legalized, false);
  635. YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false);
  636. YamlIO.mapOptional("selected", MF.Selected, false);
  637. YamlIO.mapOptional("failedISel", MF.FailedISel, false);
  638. YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false);
  639. YamlIO.mapOptional("hasWinCFI", MF.HasWinCFI, false);
  640. YamlIO.mapOptional("failsVerification", MF.FailsVerification, false);
  641. YamlIO.mapOptional("tracksDebugUserValues", MF.TracksDebugUserValues,
  642. false);
  643. YamlIO.mapOptional("registers", MF.VirtualRegisters,
  644. std::vector<VirtualRegisterDefinition>());
  645. YamlIO.mapOptional("liveins", MF.LiveIns,
  646. std::vector<MachineFunctionLiveIn>());
  647. YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters,
  648. Optional<std::vector<FlowStringValue>>());
  649. YamlIO.mapOptional("frameInfo", MF.FrameInfo, MachineFrameInfo());
  650. YamlIO.mapOptional("fixedStack", MF.FixedStackObjects,
  651. std::vector<FixedMachineStackObject>());
  652. YamlIO.mapOptional("stack", MF.StackObjects,
  653. std::vector<MachineStackObject>());
  654. YamlIO.mapOptional("callSites", MF.CallSitesInfo,
  655. std::vector<CallSiteInfo>());
  656. YamlIO.mapOptional("debugValueSubstitutions", MF.DebugValueSubstitutions,
  657. std::vector<DebugValueSubstitution>());
  658. YamlIO.mapOptional("constants", MF.Constants,
  659. std::vector<MachineConstantPoolValue>());
  660. YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
  661. if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
  662. YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
  663. if (!YamlIO.outputting() || !MF.MachineMetadataNodes.empty())
  664. YamlIO.mapOptional("machineMetadataNodes", MF.MachineMetadataNodes,
  665. std::vector<StringValue>());
  666. YamlIO.mapOptional("body", MF.Body, BlockStringValue());
  667. }
  668. };
  669. } // end namespace yaml
  670. } // end namespace llvm
  671. #endif // LLVM_CODEGEN_MIRYAMLMAPPING_H
  672. #ifdef __GNUC__
  673. #pragma GCC diagnostic pop
  674. #endif