Add classes for representing SPIR-V language constructs in memory.

This commit is contained in:
Lei Zhang 2016-05-22 14:11:24 -04:00
parent df37653333
commit 3df8f7cebd
10 changed files with 789 additions and 0 deletions

View File

@ -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
View 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
View 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
View 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
View 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_

View 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
View 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
View 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
View 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
View 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_