for (auto it = id_to_uses_[before].cbegin(); it != id_to_uses_[before].cend();
++it) {
- // Make the modification in the instruction.
- it->inst->SetOperand(it->operand_index, {after});
+ const uint32_t type_result_id_count =
+ (it->inst->result_id() != 0) + (it->inst->type_id() != 0);
+ if (!it->operand_index) {
+ assert(it->inst->type_id() != 0 &&
+ "result type id considered as using while the instruction doesn't "
+ "have a result type id");
+ it->inst->SetResultType(after);
+ } else {
+ assert(it->operand_index >= type_result_id_count &&
+ "the operand to be set is not an in-operand.");
+ uint32_t in_operand_pos = it->operand_index - type_result_id_count;
+ // Make the modification in the instruction.
+ it->inst->SetInOperand(in_operand_pos, {after});
+ }
// Register the use of |after| id into id_to_uses_.
// TODO(antiagainst): de-duplication.
id_to_uses_[after].push_back({it->inst, it->operand_index});
};
// 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.
+// operand, including the result id (if any) and result type id (if any). It
+// may also contain line-related debug instruction (OpLine, OpNoLine) directly
+// appearing before this instruction. Note that the result id of an instruction
+// should never change after the instruction being built. If the result id
+// needs to change, the user should create a new instruction instead.
class Instruction {
public:
// Creates a default OpNop instruction.
// 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);
+ // Sets the |index|-th in-operand's data to the given |data|.
+ inline void SetInOperand(uint32_t index, std::vector<uint32_t>&& data);
+ // Sets the result type id.
+ inline void SetResultType(uint32_t ty_id);
// The following methods are similar to the above, but are for in operands.
uint32_t NumInOperands() const {
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 void Instruction::SetInOperand(uint32_t index,
+ std::vector<uint32_t>&& data) {
+ assert(index + TypeResultIdCount() < operands_.size() &&
+ "operand index out of bound");
+ operands_[index + TypeResultIdCount()].words = std::move(data);
+}
+
+inline void Instruction::SetResultType(uint32_t ty_id) {
+ if (type_id_ != 0) {
+ type_id_ = ty_id;
+ assert(operands_.front().type == SPV_OPERAND_TYPE_TYPE_ID);
+ operands_.front().words = {ty_id};
+ }
}
inline bool Instruction::IsNop() const {