Add Instruction begin and end mutable iterators

Refactored the instuction test.
This commit is contained in:
David Neto 2016-08-25 17:45:08 -04:00
parent 2607bbf30b
commit 53013cc816
2 changed files with 73 additions and 24 deletions

View File

@ -79,6 +79,7 @@ struct Operand {
// needs to change, the user should create a new instruction instead.
class Instruction {
public:
using iterator = std::vector<Operand>::iterator;
using const_iterator = std::vector<Operand>::const_iterator;
// Creates a default OpNop instruction.
@ -119,6 +120,9 @@ class Instruction {
return dbg_line_insts_;
}
// Begin and end iterators for operands.
iterator begin() { return operands_.begin(); }
iterator end() { return operands_.end(); }
// Const begin and end iterators for operands.
const_iterator cbegin() const { return operands_.cbegin(); }
const_iterator cend() const { return operands_.cend(); }

View File

@ -47,6 +47,7 @@ TEST(InstructionTest, CreateTrivial) {
EXPECT_EQ(0u, empty.NumOperandWords());
EXPECT_EQ(0u, empty.NumInOperandWords());
EXPECT_EQ(empty.cend(), empty.cbegin());
EXPECT_EQ(empty.end(), empty.begin());
}
TEST(InstructionTest, CreateWithOpcodeAndNoOperands) {
@ -58,48 +59,92 @@ TEST(InstructionTest, CreateWithOpcodeAndNoOperands) {
EXPECT_EQ(0u, inst.NumOperandWords());
EXPECT_EQ(0u, inst.NumInOperandWords());
EXPECT_EQ(inst.cend(), inst.cbegin());
EXPECT_EQ(inst.end(), inst.begin());
}
TEST(InstructionTest, CreateWithOpcodeAndOperands) {
auto i32 = MakeInstruction(SpvOpTypeInt, {44, 32, 1});
spv_parsed_operand_t parsed_operands[] = {
{1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
{2, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 32},
{3, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 1},
};
spv_parsed_instruction_t parsed_inst{i32.data(),
uint16_t(i32.size()),
uint16_t(SpvOpTypeInt),
SPV_EXT_INST_TYPE_NONE,
0, // type id
i32[1], // result id
parsed_operands,
3};
// The words for an OpTypeInt for 32-bit signed integer resulting in Id 44.
uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(SpvOpTypeInt), 44,
32, 1};
// The operands that would be parsed from kSampleInstructionWords
spv_parsed_operand_t kSampleParsedOperands[] = {
{1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
{2, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 32},
{3, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 1},
};
Instruction inst(parsed_inst);
// A valid parse of kSampleParsedOperands.
spv_parsed_instruction_t kSampleParsedInstruction = {kSampleInstructionWords,
uint16_t(4),
uint16_t(SpvOpTypeInt),
SPV_EXT_INST_TYPE_NONE,
0, // type id
44, // result id
kSampleParsedOperands,
3};
TEST(InstructionTest, CreateWithOpcodeAndOperands) {
Instruction inst(kSampleParsedInstruction);
EXPECT_EQ(SpvOpTypeInt, inst.opcode());
EXPECT_EQ(0u, inst.type_id());
EXPECT_EQ(44u, inst.result_id());
EXPECT_EQ(3u, inst.NumOperands());
EXPECT_EQ(3u, inst.NumOperandWords());
EXPECT_EQ(2u, inst.NumInOperandWords());
}
TEST(InstructionTest, OperandConstIterators) {
Instruction inst(kSampleParsedInstruction);
// Spot check iteration across operands.
auto cbegin = inst.cbegin();
auto cend = inst.cend();
EXPECT_NE(cend, inst.cbegin());
// Spot check iteration across operands.
auto iter = inst.cbegin();
for (int i = 0; i < 3; ++i, ++iter) {
const auto& operand = *iter;
EXPECT_THAT(operand.type, Eq(parsed_operands[i].type));
EXPECT_THAT(operand.words, Eq(std::vector<uint32_t>{i32[i + 1]}));
EXPECT_NE(cend, iter);
auto citer = inst.cbegin();
for (int i = 0; i < 3; ++i, ++citer) {
const auto& operand = *citer;
EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
EXPECT_THAT(operand.words,
Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
EXPECT_NE(cend, citer);
}
EXPECT_EQ(cend, iter);
EXPECT_EQ(cend, citer);
// Check that cbegin and cend have not changed.
EXPECT_EQ(cbegin, inst.cbegin());
EXPECT_EQ(cend, inst.cend());
// Check arithmetic.
const Operand& operand2 = *(inst.cbegin() + 2);
EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
}
TEST(InstructionTest, OperandIterators) {
Instruction inst(kSampleParsedInstruction);
// Spot check iteration across operands, with mutable iterators.
auto begin = inst.begin();
auto end = inst.end();
EXPECT_NE(end, inst.begin());
auto iter = inst.begin();
for (int i = 0; i < 3; ++i, ++iter) {
const auto& operand = *iter;
EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
EXPECT_THAT(operand.words,
Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
EXPECT_NE(end, iter);
}
EXPECT_EQ(end, iter);
// Check that begin and end have not changed.
EXPECT_EQ(begin, inst.begin());
EXPECT_EQ(end, inst.end());
// Check arithmetic.
Operand& operand2 = *(inst.begin() + 2);
EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
// Check mutation through an iterator.
operand2.type = SPV_OPERAND_TYPE_TYPE_ID;
EXPECT_EQ(SPV_OPERAND_TYPE_TYPE_ID, (*(inst.cbegin() + 2)).type);
}
} // anonymous namespace