SpirvEvalInfo.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //===------- SpirvEvalInfo.h - SPIR-V Evaluation Info -----------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines a struct containing SPIR-V information from evaluating
  10. // a Clang AST node.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_CLANG_LIB_SPIRV_SPIRVEVALINFO_H
  14. #define LLVM_CLANG_LIB_SPIRV_SPIRVEVALINFO_H
  15. #include "spirv/unified1/spirv.hpp11"
  16. namespace clang {
  17. namespace spirv {
  18. /// Struct contains SPIR-V information from evaluating a Clang AST node.
  19. ///
  20. /// We need to report more information than just the <result-id> for SPIR-V:
  21. ///
  22. /// * Storage class: for getting correct (pointer) types
  23. /// * Layout rule: for getting correct (pointer) types
  24. /// * LValue or RValue
  25. /// * Constness: enables generating SPIR-V constant instructions
  26. /// * Relaxed precision: for emitting PrelaxedPrecision decoration
  27. ///
  28. /// For most cases, the evaluation result of a Clang AST node will just be
  29. /// a SPIR-V <result-id> with storage class Function, layout rule Void,
  30. /// not constant, and not relaxed precision.
  31. ///
  32. /// So the constructor only takes in a <result-id>. It initializes storage
  33. /// class to Function, layout rule to Void, constness to false, relaxed
  34. /// precision to false. It sets the <result-id> as lvalue. Setters are
  35. /// provided to tweak these bits.
  36. ///
  37. /// The evaluation result of a Clang Expr can be considered as SPIR-V constant
  38. /// as long as all its operands are SPIR-V constants and we are creating a
  39. /// composite out of them.
  40. ///
  41. /// We derive storage class or layout rule from a base variable. Access chains
  42. /// and load/store/insertion/extraction of the base variable retains the same
  43. /// storage class or layout rule. Other operations will likely turn the storage
  44. /// class into Function and layout rule into Void.
  45. ///
  46. /// Relaxed precision decorated on a variable propagates to all operations
  47. /// involving that variable.
  48. ///
  49. /// This struct has utilities to allow implicit constructing from or converting
  50. /// to a uint32_t value (for <result-id>) since that's the most commonly used
  51. /// information out of evaluating a Clang AST node. When doing such construction
  52. /// or conversion, all other information are defaulted to what are meaningful
  53. /// for a function temporary variable.
  54. class SpirvEvalInfo {
  55. public:
  56. /// Implicit constructor
  57. inline SpirvEvalInfo(uint32_t id);
  58. /// Changes the <result-id> in this eval info.
  59. inline SpirvEvalInfo &setResultId(uint32_t id);
  60. /// Returns a new eval info with the given <result-id> and inheriting all
  61. /// other bits from this eval info.
  62. inline SpirvEvalInfo substResultId(uint32_t id) const;
  63. /// Handy implicit conversion to get the <result-id>.
  64. operator uint32_t() const { return resultId; }
  65. /// Handly implicit conversion to test whether the <result-id> is valid.
  66. operator bool() const { return resultId != 0; }
  67. inline SpirvEvalInfo &setContainsAliasComponent(bool);
  68. bool containsAliasComponent() const { return containsAlias; }
  69. inline SpirvEvalInfo &setStorageClass(spv::StorageClass sc);
  70. spv::StorageClass getStorageClass() const { return storageClass; }
  71. inline SpirvEvalInfo &setLayoutRule(LayoutRule rule);
  72. LayoutRule getLayoutRule() const { return layoutRule; }
  73. inline SpirvEvalInfo &setRValue(bool rvalue = true);
  74. bool isRValue() const { return isRValue_; }
  75. inline SpirvEvalInfo &setConstant();
  76. bool isConstant() const { return isConstant_; }
  77. inline SpirvEvalInfo &setSpecConstant();
  78. bool isSpecConstant() const { return isSpecConstant_; }
  79. inline SpirvEvalInfo &setRelaxedPrecision();
  80. bool isRelaxedPrecision() const { return isRelaxedPrecision_; }
  81. private:
  82. uint32_t resultId;
  83. /// Indicates whether this evaluation result contains alias variables
  84. ///
  85. /// This field should only be true for stand-alone alias variables, which is
  86. /// of pointer-to-pointer type, or struct variables containing alias fields.
  87. /// After dereferencing the alias variable, this should be set to false to let
  88. /// CodeGen fall back to normal handling path.
  89. ///
  90. /// Note: legalization specific code
  91. bool containsAlias;
  92. spv::StorageClass storageClass;
  93. LayoutRule layoutRule;
  94. bool isRValue_;
  95. bool isConstant_;
  96. bool isSpecConstant_;
  97. bool isRelaxedPrecision_;
  98. };
  99. SpirvEvalInfo::SpirvEvalInfo(uint32_t id)
  100. : resultId(id), containsAlias(false),
  101. storageClass(spv::StorageClass::Function), layoutRule(LayoutRule::Void),
  102. isRValue_(false), isConstant_(false), isSpecConstant_(false),
  103. isRelaxedPrecision_(false) {}
  104. SpirvEvalInfo &SpirvEvalInfo::setResultId(uint32_t id) {
  105. resultId = id;
  106. return *this;
  107. }
  108. SpirvEvalInfo SpirvEvalInfo::substResultId(uint32_t newId) const {
  109. SpirvEvalInfo info = *this;
  110. info.resultId = newId;
  111. return info;
  112. }
  113. SpirvEvalInfo &SpirvEvalInfo::setContainsAliasComponent(bool contains) {
  114. containsAlias = contains;
  115. return *this;
  116. }
  117. SpirvEvalInfo &SpirvEvalInfo::setStorageClass(spv::StorageClass sc) {
  118. storageClass = sc;
  119. return *this;
  120. }
  121. SpirvEvalInfo &SpirvEvalInfo::setLayoutRule(LayoutRule rule) {
  122. layoutRule = rule;
  123. return *this;
  124. }
  125. SpirvEvalInfo &SpirvEvalInfo::setRValue(bool rvalue) {
  126. isRValue_ = rvalue;
  127. return *this;
  128. }
  129. SpirvEvalInfo &SpirvEvalInfo::setConstant() {
  130. isConstant_ = true;
  131. return *this;
  132. }
  133. SpirvEvalInfo &SpirvEvalInfo::setSpecConstant() {
  134. // Specialization constant is also a kind of constant.
  135. isConstant_ = isSpecConstant_ = true;
  136. return *this;
  137. }
  138. SpirvEvalInfo &SpirvEvalInfo::setRelaxedPrecision() {
  139. isRelaxedPrecision_ = true;
  140. return *this;
  141. }
  142. } // end namespace spirv
  143. } // end namespace clang
  144. #endif