@@ -118,6 +118,23 @@ SILInstruction *getInstructionOffsetFrom(SILInstruction *base, long offset) {
118
118
llvm_unreachable (" never found instruction in its own function!?" );
119
119
}
120
120
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
+
121
138
SILBasicBlock *getBlock (SILFunction *function, unsigned long index) {
122
139
auto iterator = function->begin ();
123
140
for (unsigned long i = 0 ; i < index; ++i) {
@@ -217,9 +234,28 @@ class ParseArgumentSpecification {
217
234
return retval;
218
235
}
219
236
220
- Optional<TaggedUnion<unsigned long long , StringRef>> parseSubscript () {
237
+ Optional<TaggedUnion<unsigned long long , long long , StringRef>>
238
+ parseSubscript () {
221
239
if (!consumePrefix (" [" ))
222
240
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
+ }
223
259
unsigned long long index = 0 ;
224
260
if (!llvm::consumeUnsignedInteger (specification, /* radix=*/ 10 , index)) {
225
261
demandPrefix (" ]" );
@@ -308,6 +344,13 @@ class ParseArgumentSpecification {
308
344
return getInstructionAtIndex (0 , *within);
309
345
}
310
346
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
+ }
311
354
auto index = subscript->get <unsigned long long >();
312
355
return getInstructionAtIndex (index,
313
356
within.getValueOr (context->getFunction ()));
@@ -340,11 +383,15 @@ class ParseArgumentSpecification {
340
383
return block;
341
384
}
342
385
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 >());
345
392
}
346
393
auto index = subscript->get <unsigned long long >();
347
- auto *block = getBlock (within, index);
394
+ auto *block = getBlock (within ? within : context-> getFunction () , index);
348
395
return block;
349
396
}
350
397
llvm_unreachable (" bad suffix after 'block'!?" );
0 commit comments