123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- //===-- InstBuilder.cpp - SPIR-V instruction builder ------------*- C++ -*-===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/SPIRV/InstBuilder.h"
- #include "clang/SPIRV/String.h"
- #include "llvm/llvm_assert/assert.h"
- namespace clang {
- namespace spirv {
- std::vector<uint32_t> InstBuilder::take() {
- std::vector<uint32_t> result;
- if (TheStatus == Status::Success && Expectation.empty() && !TheInst.empty()) {
- TheInst.front() |= uint32_t(TheInst.size()) << 16;
- result.swap(TheInst);
- }
- return result;
- }
- InstBuilder &InstBuilder::unaryOp(spv::Op op, uint32_t result_type,
- uint32_t result_id, uint32_t operand) {
- if (!TheInst.empty()) {
- TheStatus = Status::NestedInst;
- return *this;
- }
- // TODO: check op range
- TheInst.reserve(4);
- TheInst.emplace_back(static_cast<uint32_t>(op));
- TheInst.emplace_back(result_type);
- TheInst.emplace_back(result_id);
- TheInst.emplace_back(operand);
- return *this;
- }
- InstBuilder &InstBuilder::binaryOp(spv::Op op, uint32_t result_type,
- uint32_t result_id, uint32_t lhs,
- uint32_t rhs) {
- if (!TheInst.empty()) {
- TheStatus = Status::NestedInst;
- return *this;
- }
- // TODO: check op range
- TheInst.reserve(5);
- TheInst.emplace_back(static_cast<uint32_t>(op));
- TheInst.emplace_back(result_type);
- TheInst.emplace_back(result_id);
- TheInst.emplace_back(lhs);
- TheInst.emplace_back(rhs);
- return *this;
- }
- InstBuilder &InstBuilder::specConstantBinaryOp(spv::Op op, uint32_t result_type,
- uint32_t result_id, uint32_t lhs,
- uint32_t rhs) {
- if (!TheInst.empty()) {
- TheStatus = Status::NestedInst;
- return *this;
- }
- // TODO: check op range
- TheInst.reserve(6);
- TheInst.emplace_back(static_cast<uint32_t>(spv::Op::OpSpecConstantOp));
- TheInst.emplace_back(result_type);
- TheInst.emplace_back(result_id);
- TheInst.emplace_back(static_cast<uint32_t>(op));
- TheInst.emplace_back(lhs);
- TheInst.emplace_back(rhs);
- return *this;
- }
- InstBuilder &InstBuilder::groupNonUniformOp(spv::Op op, uint32_t result_type,
- uint32_t result_id,
- uint32_t exec_scope) {
- if (!TheInst.empty()) {
- TheStatus = Status::NestedInst;
- return *this;
- }
- // TODO: check op range
- TheInst.reserve(4);
- TheInst.emplace_back(static_cast<uint32_t>(op));
- TheInst.emplace_back(result_type);
- TheInst.emplace_back(result_id);
- TheInst.emplace_back(exec_scope);
- return *this;
- }
- InstBuilder &InstBuilder::groupNonUniformUnaryOp(
- spv::Op op, uint32_t result_type, uint32_t result_id, uint32_t exec_scope,
- llvm::Optional<spv::GroupOperation> groupOp, uint32_t operand) {
- if (!TheInst.empty()) {
- TheStatus = Status::NestedInst;
- return *this;
- }
- // TODO: check op range
- TheInst.reserve(5);
- TheInst.emplace_back(static_cast<uint32_t>(op));
- TheInst.emplace_back(result_type);
- TheInst.emplace_back(result_id);
- TheInst.emplace_back(exec_scope);
- if (groupOp.hasValue())
- TheInst.emplace_back(static_cast<uint32_t>(groupOp.getValue()));
- TheInst.emplace_back(operand);
- return *this;
- }
- InstBuilder &
- InstBuilder::groupNonUniformBinaryOp(spv::Op op, uint32_t result_type,
- uint32_t result_id, uint32_t exec_scope,
- uint32_t operand1, uint32_t operand2) {
- if (!TheInst.empty()) {
- TheStatus = Status::NestedInst;
- return *this;
- }
- // TODO: check op range
- TheInst.reserve(6);
- TheInst.emplace_back(static_cast<uint32_t>(op));
- TheInst.emplace_back(result_type);
- TheInst.emplace_back(result_id);
- TheInst.emplace_back(exec_scope);
- TheInst.emplace_back(operand1);
- TheInst.emplace_back(operand2);
- return *this;
- }
- InstBuilder &InstBuilder::opConstant(uint32_t resultType, uint32_t resultId,
- uint32_t value) {
- if (!TheInst.empty()) {
- TheStatus = Status::NestedInst;
- return *this;
- }
- TheInst.reserve(4);
- TheInst.emplace_back(static_cast<uint32_t>(spv::Op::OpConstant));
- TheInst.emplace_back(resultType);
- TheInst.emplace_back(resultId);
- TheInst.emplace_back(value);
- return *this;
- }
- InstBuilder &InstBuilder::opImageSample(
- uint32_t result_type, uint32_t result_id, uint32_t sampled_image,
- uint32_t coordinate, uint32_t dref,
- llvm::Optional<spv::ImageOperandsMask> image_operands, bool is_explicit,
- bool is_sparse) {
- spv::Op op = spv::Op::Max;
- if (dref) {
- op = is_explicit ? (is_sparse ? spv::Op::OpImageSparseSampleDrefExplicitLod
- : spv::Op::OpImageSampleDrefExplicitLod)
- : (is_sparse ? spv::Op::OpImageSparseSampleDrefImplicitLod
- : spv::Op::OpImageSampleDrefImplicitLod);
- } else {
- op = is_explicit ? (is_sparse ? spv::Op::OpImageSparseSampleExplicitLod
- : spv::Op::OpImageSampleExplicitLod)
- : (is_sparse ? spv::Op::OpImageSparseSampleImplicitLod
- : spv::Op::OpImageSampleImplicitLod);
- }
- TheInst.emplace_back(static_cast<uint32_t>(op));
- TheInst.emplace_back(result_type);
- TheInst.emplace_back(result_id);
- TheInst.emplace_back(sampled_image);
- TheInst.emplace_back(coordinate);
- if (dref)
- TheInst.emplace_back(dref);
- if (image_operands.hasValue()) {
- const auto &val = image_operands.getValue();
- encodeImageOperands(val);
- }
- return *this;
- }
- InstBuilder &InstBuilder::opImageFetchRead(
- uint32_t result_type, uint32_t result_id, uint32_t image,
- uint32_t coordinate, llvm::Optional<spv::ImageOperandsMask> image_operands,
- bool is_fetch, bool is_sparse) {
- spv::Op op =
- is_fetch
- ? (is_sparse ? spv::Op::OpImageSparseFetch : spv::Op::OpImageFetch)
- : (is_sparse ? spv::Op::OpImageSparseRead : spv::Op::OpImageRead);
- TheInst.emplace_back(static_cast<uint32_t>(op));
- TheInst.emplace_back(result_type);
- TheInst.emplace_back(result_id);
- TheInst.emplace_back(image);
- TheInst.emplace_back(coordinate);
- if (image_operands.hasValue()) {
- const auto &val = image_operands.getValue();
- encodeImageOperands(val);
- }
- return *this;
- }
- InstBuilder &InstBuilder::opSpecConstant(uint32_t resultType, uint32_t resultId,
- uint32_t value) {
- if (!TheInst.empty()) {
- TheStatus = Status::NestedInst;
- return *this;
- }
- TheInst.reserve(4);
- TheInst.emplace_back(static_cast<uint32_t>(spv::Op::OpSpecConstant));
- TheInst.emplace_back(resultType);
- TheInst.emplace_back(resultId);
- TheInst.emplace_back(value);
- return *this;
- }
- void InstBuilder::encodeString(std::string value) {
- const auto &words = string::encodeSPIRVString(value);
- TheInst.insert(TheInst.end(), words.begin(), words.end());
- }
- } // end namespace spirv
- } // end namespace clang
|