Skip to content

Commit 8397a21

Browse files
committed
[Test] Allow specifying blocks by offset.
1 parent 0d7d891 commit 8397a21

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

docs/SIL.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3950,6 +3950,8 @@ The following types of test arguments are supported:
39503950
@function[uint] <-- function at index ``uint``
39513951
@function[name] <-- function named ``name``
39523952
- block: @block <-- the block containing the test_specification instruction
3953+
@block[+uint] <-- the block ``uint`` blocks after the containing block
3954+
@block[-uint] <-- the block ``uint`` blocks before the containing block
39533955
@block[uint] <-- the block at index ``uint``
39543956
@{function}.{block} <-- the indicated block in the indicated function
39553957
Example: @function[foo].block[2]

lib/SILOptimizer/UtilityPasses/ParseTestSpecification.cpp

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,23 @@ SILInstruction *getInstructionOffsetFrom(SILInstruction *base, long offset) {
118118
llvm_unreachable("never found instruction in its own function!?");
119119
}
120120

121+
SILBasicBlock *getBlockOffsetFrom(SILBasicBlock *base, long offset) {
122+
if (offset == 0)
123+
return base;
124+
if (offset < 0) {
125+
auto iterator = base->getIterator();
126+
for (auto counter = 0; counter > offset; --counter) {
127+
iterator = std::prev(iterator);
128+
}
129+
return &*iterator;
130+
}
131+
auto iterator = base->getIterator();
132+
for (auto counter = 0; counter < offset; ++counter) {
133+
iterator = std::next(iterator);
134+
}
135+
return &*iterator;
136+
}
137+
121138
SILBasicBlock *getBlock(SILFunction *function, unsigned long index) {
122139
auto iterator = function->begin();
123140
for (unsigned long i = 0; i < index; ++i) {
@@ -217,9 +234,28 @@ class ParseArgumentSpecification {
217234
return retval;
218235
}
219236

220-
Optional<TaggedUnion<unsigned long long, StringRef>> parseSubscript() {
237+
Optional<TaggedUnion<unsigned long long, long long, StringRef>>
238+
parseSubscript() {
221239
if (!consumePrefix("["))
222240
return llvm::None;
241+
if (peekPrefix("+") || peekPrefix("-")) {
242+
bool positive = false;
243+
if (consumePrefix("+")) {
244+
positive = true;
245+
} else {
246+
bool consumed = consumePrefix("-");
247+
assert(consumed && "peeked a +/- but can't consume one!?");
248+
(void)consumed;
249+
positive = false;
250+
}
251+
unsigned long long index = 0;
252+
bool consumed =
253+
llvm::consumeUnsignedInteger(specification, /*radix=*/10, index);
254+
assert(!consumed && "didn't find uint after sign!?");
255+
demandPrefix("]");
256+
long long offset = positive ? index : -index;
257+
return {offset};
258+
}
223259
unsigned long long index = 0;
224260
if (!llvm::consumeUnsignedInteger(specification, /*radix=*/10, index)) {
225261
demandPrefix("]");
@@ -308,6 +344,13 @@ class ParseArgumentSpecification {
308344
return getInstructionAtIndex(0, *within);
309345
}
310346
if (auto subscript = parseSubscript()) {
347+
// If this is a bare @instruction[...] reference, it can refer either to
348+
// an instruction counting from the beginning of the function or else to
349+
// an instruction offset from the context of the test_specification.
350+
if (!within && subscript->isa<long long>()) {
351+
auto offset = subscript->get<long long>();
352+
return getInstructionOffsetFrom(context, offset);
353+
}
311354
auto index = subscript->get<unsigned long long>();
312355
return getInstructionAtIndex(index,
313356
within.getValueOr(context->getFunction()));
@@ -340,11 +383,15 @@ class ParseArgumentSpecification {
340383
return block;
341384
}
342385
if (auto subscript = parseSubscript()) {
343-
if (!within) {
344-
within = context->getFunction();
386+
// If this is a bare @block[...] reference, it can refer either to a block
387+
// counting from the beginning of the function or else to a block offset
388+
// from the block containing the context of the test_specification.
389+
if (!within && subscript->isa<long long>()) {
390+
return getBlockOffsetFrom(context->getParent(),
391+
subscript->get<long long>());
345392
}
346393
auto index = subscript->get<unsigned long long>();
347-
auto *block = getBlock(within, index);
394+
auto *block = getBlock(within ? within : context->getFunction(), index);
348395
return block;
349396
}
350397
llvm_unreachable("bad suffix after 'block'!?");

test/SILOptimizer/unit_test.sil

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,18 @@ bb1:
104104
// CHECK: instruction: return
105105
// CHECK-LABEL: end running test 3 of {{[^,]+}} on test_contextual_arg_parsing: test-specification-parsing
106106
// CHECK-LABEL: begin running test 4 of {{[^,]+}} on test_contextual_arg_parsing: test-specification-parsing
107-
// CHECK: function: test_contextual_arg_parsing
107+
// CHECK: block
108+
// CHECK: bb0
109+
// CHECK: block
110+
// CHECK: bb1
111+
// CHECK: block
112+
// CHECK: bb2
113+
// CHECK: block
114+
// CHECK: bb3
108115
// CHECK-LABEL: end running test 4 of {{[^,]+}} on test_contextual_arg_parsing: test-specification-parsing
116+
// CHECK-LABEL: begin running test 5 of {{[^,]+}} on test_contextual_arg_parsing: test-specification-parsing
117+
// CHECK: function: test_contextual_arg_parsing
118+
// CHECK-LABEL: end running test 5 of {{[^,]+}} on test_contextual_arg_parsing: test-specification-parsing
109119
sil [ossa] @test_contextual_arg_parsing : $() -> () {
110120
entry:
111121
br one
@@ -115,6 +125,7 @@ one:
115125
two:
116126
test_specification "test-specification-parsing I @instruction"
117127
test_specification "test-specification-parsing IIII @instruction[-1] @instruction[+0] @instruction[+1] @instruction[+2]"
128+
test_specification "test-specification-parsing BBBB @block[-2] @block[-1] @block[+0] @block[+1]"
118129
%retval = tuple ()
119130
br exit
120131
exit:

0 commit comments

Comments
 (0)