mirror of
https://github.com/xenia-project/SPIRV-Tools.git
synced 2024-11-23 11:19:41 +00:00
Add classes for representing SPIR-V language constructs in memory.
This commit is contained in:
parent
df37653333
commit
3df8f7cebd
@ -120,6 +120,8 @@ add_custom_command(OUTPUT ${SPIRV_TOOLS_BUILD_VERSION_INC}
|
||||
add_custom_target(spirv-tools-build-version
|
||||
DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC})
|
||||
|
||||
add_subdirectory(opt)
|
||||
|
||||
set(SPIRV_SOURCES
|
||||
${spirv-tools_SOURCE_DIR}/include/spirv-tools/libspirv.h
|
||||
|
||||
|
17
source/opt/CMakeLists.txt
Normal file
17
source/opt/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
add_library(SPIRV-Tools-opt
|
||||
basic_block.h
|
||||
function.h
|
||||
instruction.h
|
||||
module.h
|
||||
reflect.h
|
||||
|
||||
function.cpp
|
||||
instruction.cpp
|
||||
module.cpp
|
||||
)
|
||||
|
||||
spvtools_default_compile_options(SPIRV-Tools-opt)
|
||||
target_include_directories(SPIRV-Tools-opt
|
||||
PRIVATE ${spirv-tools_SOURCE_DIR}/include
|
||||
PUBLIC ${SPIRV_HEADER_INCLUDE_DIR}
|
||||
)
|
87
source/opt/basic_block.h
Normal file
87
source/opt/basic_block.h
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
// This file defines the language constructs for representing a SPIR-V
|
||||
// module in memory.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_BASIC_BLOCK_H_
|
||||
#define LIBSPIRV_OPT_BASIC_BLOCK_H_
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "instruction.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace ir {
|
||||
|
||||
class Function;
|
||||
|
||||
// A SPIR-V basic block.
|
||||
class BasicBlock {
|
||||
public:
|
||||
// Creates a basic block with the given enclosing |function| and starting
|
||||
// |label|.
|
||||
BasicBlock(Instruction&& label)
|
||||
: function_(nullptr), label_(std::move(label)) {}
|
||||
|
||||
// Sets the enclosing function for this basic block.
|
||||
void SetParent(Function* function) { function_ = function; }
|
||||
// Appends an instruction to this basic block.
|
||||
void AddInstruction(Instruction&& i) { insts_.push_back(std::move(i)); }
|
||||
|
||||
// Runs the given function |f| on each instruction in this basic block.
|
||||
inline void ForEachInst(const std::function<void(Instruction*)>& f);
|
||||
|
||||
// Pushes the binary segments for this instruction into the back of *|binary|.
|
||||
// If |skip_nop| is true and this is a OpNop, do nothing.
|
||||
inline void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
|
||||
|
||||
private:
|
||||
Function* function_; // The enclosing function.
|
||||
Instruction label_; // The label starting this basic block.
|
||||
std::vector<Instruction> insts_; // Instructions inside this basic block.
|
||||
};
|
||||
|
||||
inline void BasicBlock::ForEachInst(
|
||||
const std::function<void(Instruction*)>& f) {
|
||||
label_.ForEachInst(f);
|
||||
for (auto& inst : insts_) f(&inst);
|
||||
}
|
||||
|
||||
inline void BasicBlock::ToBinary(std::vector<uint32_t>* binary,
|
||||
bool skip_nop) const {
|
||||
label_.ToBinary(binary, skip_nop);
|
||||
for (const auto& inst : insts_) inst.ToBinary(binary, skip_nop);
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_BASIC_BLOCK_H_
|
49
source/opt/function.cpp
Normal file
49
source/opt/function.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "function.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace ir {
|
||||
|
||||
void Function::ForEachInst(const std::function<void(Instruction*)>& f) {
|
||||
def_inst_.ForEachInst(f);
|
||||
for (auto& param : params_) param.ForEachInst(f);
|
||||
for (auto& bb : blocks_) bb.ForEachInst(f);
|
||||
end_inst_.ForEachInst(f);
|
||||
}
|
||||
|
||||
void Function::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
|
||||
def_inst_.ToBinary(binary, skip_nop);
|
||||
for (const auto& param : params_) param.ToBinary(binary, skip_nop);
|
||||
for (const auto& bb : blocks_) bb.ToBinary(binary, skip_nop);
|
||||
end_inst_.ToBinary(binary, skip_nop);
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
80
source/opt/function.h
Normal file
80
source/opt/function.h
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_CONSTRUCTS_H_
|
||||
#define LIBSPIRV_OPT_CONSTRUCTS_H_
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "basic_block.h"
|
||||
#include "instruction.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace ir {
|
||||
|
||||
class Module;
|
||||
|
||||
// A SPIR-V function.
|
||||
class Function {
|
||||
public:
|
||||
Function(Instruction&& def_inst)
|
||||
: module_(nullptr),
|
||||
def_inst_(std::move(def_inst)),
|
||||
end_inst_(SpvOpFunctionEnd) {}
|
||||
|
||||
// Sets the enclosing module for this function.
|
||||
void SetParent(Module* module) { module_ = module; }
|
||||
// Appends a parameter to this function.
|
||||
void AddParameter(Instruction&& p) { params_.push_back(std::move(p)); }
|
||||
// Appends a basic block to this function.
|
||||
void AddBasicBlock(BasicBlock&& b) { blocks_.push_back(std::move(b)); }
|
||||
|
||||
const std::vector<BasicBlock>& basic_blocks() const { return blocks_; }
|
||||
std::vector<BasicBlock>& basic_blocks() { return blocks_; }
|
||||
|
||||
// Runs the given function |f| on each instruction in this basic block.
|
||||
void ForEachInst(const std::function<void(Instruction*)>& f);
|
||||
|
||||
// Pushes the binary segments for this instruction into the back of *|binary|.
|
||||
// If |skip_nop| is true and this is a OpNop, do nothing.
|
||||
void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
|
||||
|
||||
private:
|
||||
Module* module_; // The enclosing module.
|
||||
Instruction def_inst_; // The instruction definining this function.
|
||||
std::vector<Instruction> params_; // All parameters to this function.
|
||||
std::vector<BasicBlock> blocks_; // All basic blocks inside this function.
|
||||
Instruction end_inst_; // The OpFunctionEnd instruction.
|
||||
};
|
||||
|
||||
} // namespace ir
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_CONSTRUCTS_H_
|
82
source/opt/instruction.cpp
Normal file
82
source/opt/instruction.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "instruction.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "reflect.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace ir {
|
||||
|
||||
Instruction::Instruction(const spv_parsed_instruction_t& inst,
|
||||
std::vector<Instruction>&& dbg_line)
|
||||
: opcode_(static_cast<SpvOp>(inst.opcode)),
|
||||
type_id_(inst.type_id),
|
||||
result_id_(inst.result_id),
|
||||
dbg_line_insts_(std::move(dbg_line)) {
|
||||
assert((!IsDebugLineInst(opcode_) || dbg_line.empty()) &&
|
||||
"Op(No)Line attaching to Op(No)Line found");
|
||||
for (uint32_t i = 0; i < inst.num_operands; ++i) {
|
||||
const auto& current_payload = inst.operands[i];
|
||||
std::vector<uint32_t> words(
|
||||
inst.words + current_payload.offset,
|
||||
inst.words + current_payload.offset + current_payload.num_words);
|
||||
operands_.emplace_back(current_payload.type, std::move(words));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Instruction::GetSingleWordOperand(uint32_t index) const {
|
||||
const auto& words = GetOperand(index).words;
|
||||
assert(words.size() == 1 && "expected the operand only taking one word");
|
||||
return words.front();
|
||||
}
|
||||
|
||||
uint32_t Instruction::NumInOperandWords() const {
|
||||
uint32_t size = 0;
|
||||
for (uint32_t i = TypeResultIdCount(); i < operands_.size(); ++i)
|
||||
size += static_cast<uint32_t>(operands_[i].words.size());
|
||||
return size;
|
||||
}
|
||||
|
||||
void Instruction::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
|
||||
for (const auto& dbg_line : dbg_line_insts_) {
|
||||
dbg_line.ToBinary(binary, skip_nop);
|
||||
}
|
||||
|
||||
if (skip_nop && IsNop()) return;
|
||||
|
||||
const uint32_t num_words = 1 + NumOperandWords();
|
||||
binary->push_back((num_words << 16) | static_cast<uint16_t>(opcode_));
|
||||
for (const auto& operand : operands_)
|
||||
binary->insert(binary->end(), operand.words.begin(), operand.words.end());
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
191
source/opt/instruction.h
Normal file
191
source/opt/instruction.h
Normal file
@ -0,0 +1,191 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_INSTRUCTION_H_
|
||||
#define LIBSPIRV_OPT_INSTRUCTION_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv/1.1/spirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace ir {
|
||||
|
||||
class Function;
|
||||
class Module;
|
||||
|
||||
// About operand:
|
||||
//
|
||||
// In the SPIR-V specification, the term "operand" is used to mean any single
|
||||
// SPIR-V word following the leading wordcount-opcode word. Here, the term
|
||||
// "operand" is used to mean a *logical* operand. A logical operand may consist
|
||||
// of mulitple SPIR-V words, which together make up the same component. For
|
||||
// example, a logical operand of a 64-bit integer needs two words to express.
|
||||
//
|
||||
// Further, we categorize logical operands into *in* and *out* operands.
|
||||
// In operands are operands actually serve as input to operations, while out
|
||||
// operands are operands that represent ids generated from operations (result
|
||||
// type id or result id). For example, for "OpIAdd %rtype %rid %inop1 %inop2",
|
||||
// "%inop1" and "%inop2" are in operands, while "%rtype" and "%rid" are out
|
||||
// operands.
|
||||
|
||||
// A *logical* operand to a SPIR-V instruction. It can be the type id, result
|
||||
// id, or other additional operands carried in an instruction.
|
||||
struct Operand {
|
||||
Operand(spv_operand_type_t t, std::vector<uint32_t>&& w)
|
||||
: type(t), words(std::move(w)) {}
|
||||
|
||||
spv_operand_type_t type; // Type of this logical operand.
|
||||
std::vector<uint32_t> words; // Binary segments of this logical operand.
|
||||
|
||||
// TODO(antiagainst): create fields for literal number kind, width, etc.
|
||||
};
|
||||
|
||||
// A SPIR-V instruction. It contains the opcode and any additional logical
|
||||
// operand. It may also contain line-related debug instruction (OpLine,
|
||||
// OpNoLine) directly appearing before this instruction.
|
||||
class Instruction {
|
||||
public:
|
||||
// Creates a default OpNop instruction.
|
||||
Instruction() : opcode_(SpvOpNop), type_id_(0), result_id_(0) {}
|
||||
// Creates an instruction with the given opcode |op| and no additional logical
|
||||
// operands.
|
||||
Instruction(SpvOp op) : opcode_(op), type_id_(0), result_id_(0) {}
|
||||
// Creates an instruction using the given spv_parsed_instruction_t |inst|. All
|
||||
// the data inside |inst| will be copied and owned in this instance. And keep
|
||||
// record of line-related debug instructions |dbg_line| ahead of this
|
||||
// instruction, if any.
|
||||
Instruction(const spv_parsed_instruction_t& inst,
|
||||
std::vector<Instruction>&& dbg_line = {});
|
||||
|
||||
SpvOp opcode() const { return opcode_; }
|
||||
uint32_t type_id() const { return type_id_; }
|
||||
uint32_t result_id() const { return result_id_; }
|
||||
// Returns the vector of line-related debug instructions attached to this
|
||||
// instruction and the caller can directly modify them.
|
||||
std::vector<Instruction>& dbg_line_insts() { return dbg_line_insts_; }
|
||||
const std::vector<Instruction>& dbg_line_insts() const {
|
||||
return dbg_line_insts_;
|
||||
}
|
||||
|
||||
// Gets the number of logical operands.
|
||||
uint32_t NumOperands() const {
|
||||
return static_cast<uint32_t>(operands_.size());
|
||||
}
|
||||
// Gets the number of SPIR-V words occupied by all logical operands.
|
||||
uint32_t NumOperandWords() const {
|
||||
return NumInOperandWords() + TypeResultIdCount();
|
||||
}
|
||||
// Gets the |index|-th logical operand.
|
||||
inline const Operand& GetOperand(uint32_t index) const;
|
||||
// Gets the |index|-th logical operand as a single SPIR-V word. This method is
|
||||
// not expected to be used with logical operands consisting of multiple SPIR-V
|
||||
// words.
|
||||
uint32_t GetSingleWordOperand(uint32_t index) const;
|
||||
// Sets the |index|-th operand's data to the given |data|.
|
||||
inline void SetOperand(uint32_t index, std::vector<uint32_t>&& data);
|
||||
|
||||
// The following methods are similar to the above, but are for in operands.
|
||||
uint32_t NumInOperands() const {
|
||||
return static_cast<uint32_t>(operands_.size() - TypeResultIdCount());
|
||||
}
|
||||
uint32_t NumInOperandWords() const;
|
||||
const Operand& GetInOperand(uint32_t index) const {
|
||||
return GetOperand(index + TypeResultIdCount());
|
||||
}
|
||||
uint32_t GetSingleWordInOperand(uint32_t index) const {
|
||||
return GetSingleWordOperand(index + TypeResultIdCount());
|
||||
}
|
||||
|
||||
// Returns true if this instruction is OpNop.
|
||||
inline bool IsNop() const;
|
||||
// Turns this instruction to OpNop. This does not clear out all preceding
|
||||
// line-related debug instructions.
|
||||
inline void ToNop();
|
||||
|
||||
// Runs the given function |f| on this instruction and preceding debug
|
||||
// instructions.
|
||||
inline void ForEachInst(const std::function<void(Instruction*)>& f);
|
||||
|
||||
// Pushes the binary segments for this instruction into the back of *|binary|.
|
||||
// If |skip_nop| is true and this is a OpNop, do nothing.
|
||||
void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
|
||||
|
||||
private:
|
||||
// Returns the toal count of result type id and result id.
|
||||
uint32_t TypeResultIdCount() const {
|
||||
return (type_id_ != 0) + (result_id_ != 0);
|
||||
}
|
||||
|
||||
SpvOp opcode_; // Opcode
|
||||
uint32_t type_id_; // Result type id. A value of 0 means no result type id.
|
||||
uint32_t result_id_; // Result id. A value of 0 means no result id.
|
||||
// All logical operands, including result type id and result id.
|
||||
std::vector<Operand> operands_;
|
||||
// Opline and OpNoLine instructions preceding this instruction. Note that for
|
||||
// Instructions representing OpLine or OpNonLine itself, this field should be
|
||||
// empty.
|
||||
std::vector<Instruction> dbg_line_insts_;
|
||||
};
|
||||
|
||||
inline const Operand& Instruction::GetOperand(uint32_t index) const {
|
||||
assert(index < operands_.size() && "operand index out of bound");
|
||||
return operands_[index];
|
||||
};
|
||||
|
||||
inline void Instruction::SetOperand(uint32_t index,
|
||||
std::vector<uint32_t>&& data) {
|
||||
assert(index < operands_.size() && "operand index out of bound");
|
||||
operands_[index].words = std::move(data);
|
||||
}
|
||||
|
||||
inline bool Instruction::IsNop() const {
|
||||
return opcode_ == SpvOpNop && type_id_ == 0 && result_id_ == 0 &&
|
||||
operands_.empty();
|
||||
}
|
||||
|
||||
inline void Instruction::ToNop() {
|
||||
opcode_ = SpvOpNop;
|
||||
type_id_ = result_id_ = 0;
|
||||
operands_.clear();
|
||||
}
|
||||
|
||||
inline void Instruction::ForEachInst(
|
||||
const std::function<void(Instruction*)>& f) {
|
||||
for (auto& dbg_line : dbg_line_insts_) f(&dbg_line);
|
||||
f(this);
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_INSTRUCTION_H_
|
81
source/opt/module.cpp
Normal file
81
source/opt/module.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "module.h"
|
||||
#include "reflect.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace ir {
|
||||
|
||||
std::vector<Instruction*> Module::types() {
|
||||
std::vector<Instruction*> insts;
|
||||
for (uint32_t i = 0; i < types_and_constants_.size(); ++i) {
|
||||
if (IsTypeInst(types_and_constants_[i].opcode()))
|
||||
insts.push_back(&types_and_constants_[i]);
|
||||
}
|
||||
return insts;
|
||||
};
|
||||
|
||||
void Module::ForEachInst(const std::function<void(Instruction*)>& f) {
|
||||
for (auto& i : capabilities_) f(&i);
|
||||
for (auto& i : extensions_) f(&i);
|
||||
for (auto& i : ext_inst_sets_) f(&i);
|
||||
f(&memory_model_);
|
||||
for (auto& i : entry_points_) f(&i);
|
||||
for (auto& i : execution_modes_) f(&i);
|
||||
for (auto& i : debugs_) f(&i);
|
||||
for (auto& i : annotations_) f(&i);
|
||||
for (auto& i : types_and_constants_) f(&i);
|
||||
for (auto& i : variables_) f(&i);
|
||||
for (auto& i : functions_) i.ForEachInst(f);
|
||||
}
|
||||
|
||||
void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
|
||||
binary->push_back(header_.magic_number);
|
||||
binary->push_back(header_.version);
|
||||
// TODO(antiagainst): should we change the generator number?
|
||||
binary->push_back(header_.generator);
|
||||
binary->push_back(header_.bound);
|
||||
binary->push_back(header_.reserved);
|
||||
|
||||
// TODO(antiagainst): wow, looks like a duplication of the above.
|
||||
for (const auto& c : capabilities_) c.ToBinary(binary, skip_nop);
|
||||
for (const auto& e : extensions_) e.ToBinary(binary, skip_nop);
|
||||
for (const auto& e : ext_inst_sets_) e.ToBinary(binary, skip_nop);
|
||||
memory_model_.ToBinary(binary, skip_nop);
|
||||
for (const auto& e : entry_points_) e.ToBinary(binary, skip_nop);
|
||||
for (const auto& e : execution_modes_) e.ToBinary(binary, skip_nop);
|
||||
for (const auto& d : debugs_) d.ToBinary(binary, skip_nop);
|
||||
for (const auto& a : annotations_) a.ToBinary(binary, skip_nop);
|
||||
for (const auto& t : types_and_constants_) t.ToBinary(binary, skip_nop);
|
||||
for (const auto& v : variables_) v.ToBinary(binary, skip_nop);
|
||||
for (const auto& f : functions_) f.ToBinary(binary, skip_nop);
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
135
source/opt/module.h
Normal file
135
source/opt/module.h
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_MODULE_H_
|
||||
#define LIBSPIRV_OPT_MODULE_H_
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "function.h"
|
||||
#include "instruction.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace ir {
|
||||
|
||||
// A struct for containing the module header information.
|
||||
struct ModuleHeader {
|
||||
uint32_t magic_number;
|
||||
uint32_t version;
|
||||
uint32_t generator;
|
||||
uint32_t bound;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
// A SPIR-V module. It contains all the information for a SPIR-V module and
|
||||
// serves as the backbone of optimization transformations.
|
||||
class Module {
|
||||
public:
|
||||
// Creates an empty module with zero'd header.
|
||||
Module() : header_({}) {}
|
||||
|
||||
// Sets the header to the given |header|.
|
||||
void SetHeader(const ModuleHeader& header) { header_ = header; }
|
||||
// Appends a capability instruction to this module.
|
||||
void AddCapability(Instruction&& c) { capabilities_.push_back(std::move(c)); }
|
||||
// Appends an extension instruction to this module.
|
||||
void AddExtension(Instruction&& e) { extensions_.push_back(std::move(e)); }
|
||||
// Appends an extended instruction set instruction to this module.
|
||||
void AddExtInstSet(Instruction&& e) {
|
||||
ext_inst_sets_.push_back(std::move(e));
|
||||
}
|
||||
// Appends a memory model instruction to this module.
|
||||
void SetMemoryModel(Instruction&& m) { memory_model_ = std::move(m); }
|
||||
// Appends an entry point instruction to this module.
|
||||
void AddEntryPoint(Instruction&& e) { entry_points_.push_back(std::move(e)); }
|
||||
// Appends an execution mode instruction to this module.
|
||||
void AddExecutionMode(Instruction&& e) {
|
||||
execution_modes_.push_back(std::move(e));
|
||||
}
|
||||
// Appends a debug instruction (excluding OpLine & OpNoLine) to this module.
|
||||
void AddDebugInst(Instruction&& d) { debugs_.push_back(std::move(d)); }
|
||||
// Appends an annotation instruction to this module.
|
||||
void AddAnnotationInst(Instruction&& a) {
|
||||
annotations_.push_back(std::move(a));
|
||||
}
|
||||
// Appends a type-declaration instruction to this module.
|
||||
void AddType(Instruction&& t) {
|
||||
types_and_constants_.push_back(std::move(t));
|
||||
}
|
||||
// Appends a constant-creation instruction to this module.
|
||||
void AddConstant(Instruction&& c) {
|
||||
types_and_constants_.push_back(std::move(c));
|
||||
}
|
||||
// Appends a variable-declaration instruction to this module.
|
||||
void AddVariable(Instruction&& v) { variables_.push_back(std::move(v)); }
|
||||
// Appends a function to this module.
|
||||
void AddFunction(Function&& f) { functions_.push_back(std::move(f)); }
|
||||
|
||||
// Returns a vector of pointers to type-declaration instructions in this
|
||||
// module.
|
||||
std::vector<Instruction*> types();
|
||||
const std::vector<Instruction>& debugs() const { return debugs_; }
|
||||
std::vector<Instruction>& debugs() { return debugs_; }
|
||||
const std::vector<Instruction>& annotations() const { return annotations_; }
|
||||
std::vector<Instruction>& annotations() { return annotations_; }
|
||||
const std::vector<Function>& functions() const { return functions_; }
|
||||
std::vector<Function>& functions() { return functions_; }
|
||||
|
||||
// Invokes function |f| on all instructions in this module.
|
||||
void ForEachInst(const std::function<void(Instruction*)>& f);
|
||||
|
||||
// Pushes the binary segments for this instruction into the back of *|binary|.
|
||||
// If |skip_nop| is true and this is a OpNop, do nothing.
|
||||
void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
|
||||
|
||||
private:
|
||||
ModuleHeader header_; // Module header
|
||||
|
||||
// The following fields respect the "Logical Layout of a Module" in
|
||||
// Section 2.4 of the SPIR-V specification.
|
||||
std::vector<Instruction> capabilities_;
|
||||
std::vector<Instruction> extensions_;
|
||||
std::vector<Instruction> ext_inst_sets_;
|
||||
Instruction memory_model_; // A module only has one memory model instruction.
|
||||
std::vector<Instruction> entry_points_;
|
||||
std::vector<Instruction> execution_modes_;
|
||||
std::vector<Instruction> debugs_;
|
||||
std::vector<Instruction> annotations_;
|
||||
// Types and constants may depends on each other; thus they are grouped
|
||||
// together.
|
||||
std::vector<Instruction> types_and_constants_;
|
||||
std::vector<Instruction> variables_;
|
||||
std::vector<Function> functions_;
|
||||
};
|
||||
|
||||
} // namespace ir
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_MODULE_H_
|
65
source/opt/reflect.h
Normal file
65
source/opt/reflect.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_REFLECT_H_
|
||||
#define LIBSPIRV_OPT_REFLECT_H_
|
||||
|
||||
#include "spirv/1.1/spirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace ir {
|
||||
|
||||
// Note that as SPIR-V evolves over time, new opcodes may appear. So the
|
||||
// following functions tend to be outdated and should be updated when SPIR-V
|
||||
// version bumps.
|
||||
|
||||
inline bool IsDebugInst(SpvOp opcode) {
|
||||
return (opcode >= SpvOpSourceContinued && opcode <= SpvOpLine) ||
|
||||
opcode == SpvOpNoLine || opcode == SpvOpModuleProcessed;
|
||||
}
|
||||
inline bool IsDebugLineInst(SpvOp opcode) {
|
||||
return opcode == SpvOpLine || opcode == SpvOpNoLine;
|
||||
}
|
||||
inline bool IsAnnotationInst(SpvOp opcode) {
|
||||
return opcode >= SpvOpDecorate && opcode <= SpvOpGroupMemberDecorate;
|
||||
}
|
||||
inline bool IsTypeInst(SpvOp opcode) {
|
||||
return (opcode >= SpvOpTypeVoid && opcode <= SpvOpTypeForwardPointer) ||
|
||||
opcode == SpvOpTypePipeStorage || opcode == SpvOpTypeNamedBarrier;
|
||||
}
|
||||
inline bool IsConstantInst(SpvOp opcode) {
|
||||
return opcode >= SpvOpConstantTrue && opcode <= SpvOpSpecConstantOp;
|
||||
}
|
||||
inline bool IsTerminatorInst(SpvOp opcode) {
|
||||
return opcode >= SpvOpBranch && opcode <= SpvOpUnreachable;
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_REFLECT_H_
|
Loading…
Reference in New Issue
Block a user