InstBuilderManual.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. //===-- InstBuilder.cpp - SPIR-V instruction builder ------------*- 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. #include "clang/SPIRV/InstBuilder.h"
  10. #include "clang/SPIRV/String.h"
  11. #include "llvm/llvm_assert/assert.h"
  12. namespace clang {
  13. namespace spirv {
  14. std::vector<uint32_t> InstBuilder::take() {
  15. std::vector<uint32_t> result;
  16. if (TheStatus == Status::Success && Expectation.empty() && !TheInst.empty()) {
  17. TheInst.front() |= uint32_t(TheInst.size()) << 16;
  18. result.swap(TheInst);
  19. }
  20. return result;
  21. }
  22. InstBuilder &InstBuilder::unaryOp(spv::Op op, uint32_t result_type,
  23. uint32_t result_id, uint32_t operand) {
  24. if (!TheInst.empty()) {
  25. TheStatus = Status::NestedInst;
  26. return *this;
  27. }
  28. // TODO: check op range
  29. TheInst.reserve(4);
  30. TheInst.emplace_back(static_cast<uint32_t>(op));
  31. TheInst.emplace_back(result_type);
  32. TheInst.emplace_back(result_id);
  33. TheInst.emplace_back(operand);
  34. return *this;
  35. }
  36. InstBuilder &InstBuilder::binaryOp(spv::Op op, uint32_t result_type,
  37. uint32_t result_id, uint32_t lhs,
  38. uint32_t rhs) {
  39. if (!TheInst.empty()) {
  40. TheStatus = Status::NestedInst;
  41. return *this;
  42. }
  43. // TODO: check op range
  44. TheInst.reserve(5);
  45. TheInst.emplace_back(static_cast<uint32_t>(op));
  46. TheInst.emplace_back(result_type);
  47. TheInst.emplace_back(result_id);
  48. TheInst.emplace_back(lhs);
  49. TheInst.emplace_back(rhs);
  50. return *this;
  51. }
  52. InstBuilder &InstBuilder::specConstantBinaryOp(spv::Op op, uint32_t result_type,
  53. uint32_t result_id, uint32_t lhs,
  54. uint32_t rhs) {
  55. if (!TheInst.empty()) {
  56. TheStatus = Status::NestedInst;
  57. return *this;
  58. }
  59. // TODO: check op range
  60. TheInst.reserve(6);
  61. TheInst.emplace_back(static_cast<uint32_t>(spv::Op::OpSpecConstantOp));
  62. TheInst.emplace_back(result_type);
  63. TheInst.emplace_back(result_id);
  64. TheInst.emplace_back(static_cast<uint32_t>(op));
  65. TheInst.emplace_back(lhs);
  66. TheInst.emplace_back(rhs);
  67. return *this;
  68. }
  69. InstBuilder &InstBuilder::opConstant(uint32_t resultType, uint32_t resultId,
  70. uint32_t value) {
  71. if (!TheInst.empty()) {
  72. TheStatus = Status::NestedInst;
  73. return *this;
  74. }
  75. TheInst.reserve(4);
  76. TheInst.emplace_back(static_cast<uint32_t>(spv::Op::OpConstant));
  77. TheInst.emplace_back(resultType);
  78. TheInst.emplace_back(resultId);
  79. TheInst.emplace_back(value);
  80. return *this;
  81. }
  82. InstBuilder &InstBuilder::opImageSample(
  83. uint32_t result_type, uint32_t result_id, uint32_t sampled_image,
  84. uint32_t coordinate, uint32_t dref,
  85. llvm::Optional<spv::ImageOperandsMask> image_operands, bool is_explicit,
  86. bool is_sparse) {
  87. spv::Op op = spv::Op::Max;
  88. if (dref) {
  89. op = is_explicit ? (is_sparse ? spv::Op::OpImageSparseSampleDrefExplicitLod
  90. : spv::Op::OpImageSampleDrefExplicitLod)
  91. : (is_sparse ? spv::Op::OpImageSparseSampleDrefImplicitLod
  92. : spv::Op::OpImageSampleDrefImplicitLod);
  93. } else {
  94. op = is_explicit ? (is_sparse ? spv::Op::OpImageSparseSampleExplicitLod
  95. : spv::Op::OpImageSampleExplicitLod)
  96. : (is_sparse ? spv::Op::OpImageSparseSampleImplicitLod
  97. : spv::Op::OpImageSampleImplicitLod);
  98. }
  99. TheInst.emplace_back(static_cast<uint32_t>(op));
  100. TheInst.emplace_back(result_type);
  101. TheInst.emplace_back(result_id);
  102. TheInst.emplace_back(sampled_image);
  103. TheInst.emplace_back(coordinate);
  104. if (dref)
  105. TheInst.emplace_back(dref);
  106. if (image_operands.hasValue()) {
  107. const auto &val = image_operands.getValue();
  108. encodeImageOperands(val);
  109. }
  110. return *this;
  111. }
  112. InstBuilder &InstBuilder::opImageFetchRead(
  113. uint32_t result_type, uint32_t result_id, uint32_t image,
  114. uint32_t coordinate, llvm::Optional<spv::ImageOperandsMask> image_operands,
  115. bool is_fetch, bool is_sparse) {
  116. spv::Op op =
  117. is_fetch
  118. ? (is_sparse ? spv::Op::OpImageSparseFetch : spv::Op::OpImageFetch)
  119. : (is_sparse ? spv::Op::OpImageSparseRead : spv::Op::OpImageRead);
  120. TheInst.emplace_back(static_cast<uint32_t>(op));
  121. TheInst.emplace_back(result_type);
  122. TheInst.emplace_back(result_id);
  123. TheInst.emplace_back(image);
  124. TheInst.emplace_back(coordinate);
  125. if (image_operands.hasValue()) {
  126. const auto &val = image_operands.getValue();
  127. encodeImageOperands(val);
  128. }
  129. return *this;
  130. }
  131. InstBuilder &InstBuilder::opSpecConstant(uint32_t resultType, uint32_t resultId,
  132. uint32_t value) {
  133. if (!TheInst.empty()) {
  134. TheStatus = Status::NestedInst;
  135. return *this;
  136. }
  137. TheInst.reserve(4);
  138. TheInst.emplace_back(static_cast<uint32_t>(spv::Op::OpSpecConstant));
  139. TheInst.emplace_back(resultType);
  140. TheInst.emplace_back(resultId);
  141. TheInst.emplace_back(value);
  142. return *this;
  143. }
  144. void InstBuilder::encodeString(std::string value) {
  145. const auto &words = string::encodeSPIRVString(value);
  146. TheInst.insert(TheInst.end(), words.begin(), words.end());
  147. }
  148. } // end namespace spirv
  149. } // end namespace clang