@@ -39,6 +39,25 @@ void findAndDeleteTraceValues(SILFunction *function,
39
39
}
40
40
}
41
41
42
+ bool isDeleteableTestInstruction (SILInstruction const *instruction) {
43
+ if (auto *dvi = dyn_cast<DebugValueInst>(instruction))
44
+ return dvi->hasTrace ();
45
+ if (isa<TestSpecificationInst>(instruction))
46
+ return true ;
47
+ return false ;
48
+ }
49
+
50
+ SILInstruction *findAnchorInstructionAfter (TestSpecificationInst *tsi) {
51
+ for (auto *instruction = tsi->getNextInstruction (); instruction;
52
+ instruction = instruction->getNextInstruction ()) {
53
+ if (!isDeleteableTestInstruction (instruction))
54
+ return instruction;
55
+ }
56
+ // This can't happen because a TestSpecificationInst isn't a terminator itself
57
+ // nor are any deleteable instructions.
58
+ llvm_unreachable (" found no anchor after TestSpecificationInst!?" );
59
+ }
60
+
42
61
// Helpers: Looking up subobjects by index
43
62
44
63
SILInstruction *getInstruction (SILFunction *function, unsigned long index) {
@@ -89,14 +108,14 @@ class ParseTestSpecification;
89
108
class ParseArgumentSpecification {
90
109
ParseTestSpecification &outer;
91
110
StringRef specification;
111
+ SILInstruction *context;
92
112
93
- SILFunction *getFunction ();
94
113
SILValue getTraceValue (unsigned index, SILFunction *function);
95
114
96
115
public:
97
116
ParseArgumentSpecification (ParseTestSpecification &outer,
98
- StringRef specification)
99
- : outer(outer), specification(specification) {}
117
+ StringRef specification, SILInstruction *context )
118
+ : outer(outer), specification(specification), context(context) {}
100
119
101
120
Argument parse () {
102
121
auto argument = parseArgument ();
@@ -183,6 +202,10 @@ class ParseArgumentSpecification {
183
202
SILValue parseTraceComponent (SILFunction *within) {
184
203
if (!consumePrefix (" trace" ))
185
204
return SILValue ();
205
+ // TODO: Use a bare @trace (i.e. within == nullptr) to refer to the value
206
+ // which appears in the debug_value [trace] instruction.
207
+ if (!within)
208
+ within = context->getFunction ();
186
209
if (empty () || peekPrefix (" ." ))
187
210
return getTraceValue (0 , within);
188
211
if (auto subscript = parseSubscript ()) {
@@ -228,11 +251,13 @@ class ParseArgumentSpecification {
228
251
return OperandArgument{operand};
229
252
}
230
253
231
- SILInstruction *parseInstructionComponent (
232
- TaggedUnion<SILFunction *, SILBasicBlock *> within) {
254
+ using InstructionContext = TaggedUnion<SILFunction *, SILBasicBlock *>;
255
+
256
+ SILInstruction *
257
+ parseInstructionComponent (Optional<InstructionContext> within) {
233
258
if (!consumePrefix (" instruction" ))
234
259
return nullptr ;
235
- auto getInstructionAtIndex = [within ](unsigned index) {
260
+ auto getInstructionAtIndex = [](unsigned index, InstructionContext within ) {
236
261
if (within.isa <SILFunction *>()) {
237
262
auto *function = within.get <SILFunction *>();
238
263
return getInstruction (function, index);
@@ -241,17 +266,23 @@ class ParseArgumentSpecification {
241
266
return getInstruction (block, index);
242
267
};
243
268
if (empty () || peekPrefix (" ." )) {
244
- return getInstructionAtIndex (0 );
269
+ if (!within) {
270
+ // If this is a bare @instruction reference, it refers to to the
271
+ // context of the test_specification.
272
+ return context;
273
+ }
274
+ return getInstructionAtIndex (0 , *within);
245
275
}
246
276
if (auto subscript = parseSubscript ()) {
247
277
auto index = subscript->get <unsigned long long >();
248
- return getInstructionAtIndex (index);
278
+ return getInstructionAtIndex (index,
279
+ within.getValueOr (context->getFunction ()));
249
280
}
250
281
llvm_unreachable (" bad suffix after 'instruction'!?" );
251
282
}
252
283
253
- Optional<Argument> parseInstructionReference (
254
- TaggedUnion<SILFunction *, SILBasicBlock * > within) {
284
+ Optional<Argument>
285
+ parseInstructionReference (Optional<InstructionContext > within) {
255
286
auto *instruction = parseInstructionComponent (within);
256
287
if (!instruction)
257
288
return llvm::None;
@@ -266,10 +297,18 @@ class ParseArgumentSpecification {
266
297
if (!consumePrefix (" block" ))
267
298
return nullptr ;
268
299
if (empty () || peekPrefix (" ." )) {
300
+ // If this is a bare @block reference, it refers to the block containing
301
+ // the test_specification instruction.
302
+ if (!within) {
303
+ return context->getParent ();
304
+ }
269
305
auto *block = getBlock (within, 0 );
270
306
return block;
271
307
}
272
308
if (auto subscript = parseSubscript ()) {
309
+ if (!within) {
310
+ within = context->getFunction ();
311
+ }
273
312
auto index = subscript->get <unsigned long long >();
274
313
auto *block = getBlock (within, index);
275
314
return block;
@@ -283,7 +322,7 @@ class ParseArgumentSpecification {
283
322
return llvm::None;
284
323
if (!consumePrefix (" ." ))
285
324
return BlockArgument{block};
286
- if (auto arg = parseInstructionReference (block))
325
+ if (auto arg = parseInstructionReference ({ block} ))
287
326
return *arg;
288
327
llvm_unreachable (" unhandled suffix after 'block'!?" );
289
328
}
@@ -292,16 +331,24 @@ class ParseArgumentSpecification {
292
331
if (!consumePrefix (" function" ))
293
332
return nullptr ;
294
333
if (empty () || peekPrefix (" ." )) {
295
- return getFunction ();
334
+ // If this is a bare @function reference, it refers to the function
335
+ // containing the test_specification instruction.
336
+ if (!within) {
337
+ return context->getFunction ();
338
+ }
339
+ return ::getFunction (within, 0 );
296
340
}
297
341
if (auto subscript = parseSubscript ()) {
342
+ if (!within) {
343
+ within = &context->getFunction ()->getModule ();
344
+ }
298
345
if (subscript->isa <unsigned long long >()) {
299
346
auto index = subscript->get <unsigned long long >();
300
347
auto *fn = ::getFunction (within, index);
301
348
return fn;
302
349
} else {
303
350
auto name = subscript->get <StringRef>();
304
- auto *specified = getFunction ()-> getModule (). lookUpFunction (name);
351
+ auto *specified = within-> lookUpFunction (name);
305
352
if (!specified)
306
353
llvm_unreachable (" unknown function name!?" );
307
354
return specified;
@@ -316,7 +363,7 @@ class ParseArgumentSpecification {
316
363
return llvm::None;
317
364
if (!consumePrefix (" ." ))
318
365
return FunctionArgument{function};
319
- if (auto arg = parseInstructionReference (function))
366
+ if (auto arg = parseInstructionReference ({ function} ))
320
367
return *arg;
321
368
if (auto arg = parseTraceReference (function))
322
369
return *arg;
@@ -328,15 +375,16 @@ class ParseArgumentSpecification {
328
375
Optional<Argument> parseReference () {
329
376
if (!consumePrefix (" @" ))
330
377
return llvm::None;
331
- if (auto arg = parseTraceReference (getFunction () ))
378
+ if (auto arg = parseTraceReference (nullptr ))
332
379
return *arg;
333
- if (auto arg = parseOperandReference (getInstruction (getFunction (), 0 )))
380
+ if (auto arg =
381
+ parseOperandReference (getInstruction (context->getFunction (), 0 )))
334
382
return *arg;
335
- if (auto arg = parseInstructionReference (getFunction () ))
383
+ if (auto arg = parseInstructionReference (llvm::None ))
336
384
return *arg;
337
- if (auto arg = parseBlockReference (getFunction () ))
385
+ if (auto arg = parseBlockReference (nullptr ))
338
386
return *arg;
339
- if (auto arg = parseFunctionReference (& getFunction ()-> getModule () ))
387
+ if (auto arg = parseFunctionReference (nullptr ))
340
388
return *arg;
341
389
return llvm::None;
342
390
}
@@ -384,21 +432,20 @@ class ParseTestSpecification {
384
432
SmallVectorImpl<StringRef> &components)
385
433
: function(function), components(components) {}
386
434
387
- void parse (StringRef specification, Arguments &arguments) {
388
- specification.split (components, " " );
435
+ void parse (UnparsedSpecification const &specification, Arguments &arguments) {
436
+ StringRef specificationString = specification.string ;
437
+ specificationString.split (components, " " );
389
438
for (unsigned long index = 0 , size = components.size (); index < size;
390
439
++index) {
391
- auto component = components[index];
392
- ParseArgumentSpecification parser (*this , component);
440
+ auto componentString = components[index];
441
+ ParseArgumentSpecification parser (*this , componentString,
442
+ specification.context );
393
443
auto argument = parser.parse ();
394
444
arguments.storage .push_back (argument);
395
445
}
396
446
}
397
447
};
398
448
399
- SILFunction *ParseArgumentSpecification::getFunction () {
400
- return outer.function ;
401
- }
402
449
SILValue ParseArgumentSpecification::getTraceValue (unsigned index,
403
450
SILFunction *function) {
404
451
return outer.getTraceValue (index, function);
@@ -409,22 +456,24 @@ SILValue ParseArgumentSpecification::getTraceValue(unsigned index,
409
456
// API
410
457
411
458
void swift::test::getTestSpecifications (
412
- SILFunction *function, SmallVectorImpl<std::string> &specifications) {
459
+ SILFunction *function,
460
+ SmallVectorImpl<UnparsedSpecification> &specifications) {
413
461
InstructionDeleter deleter;
414
462
for (auto &block : *function) {
415
463
for (SILInstruction *inst : deleter.updatingRange (&block)) {
416
464
if (auto *tsi = dyn_cast<TestSpecificationInst>(inst)) {
417
465
auto ref = tsi->getArgumentsSpecification ();
418
- specifications.push_back (std::string (ref.begin (), ref.end ()));
466
+ auto *anchor = findAnchorInstructionAfter (tsi);
467
+ specifications.push_back ({std::string (ref.begin (), ref.end ()), anchor});
419
468
deleter.forceDelete (tsi);
420
469
}
421
470
}
422
471
}
423
472
}
424
473
425
474
void swift::test::parseTestArgumentsFromSpecification (
426
- SILFunction *function, StringRef specification, Arguments &arguments ,
427
- SmallVectorImpl<StringRef> &argumentStrings) {
475
+ SILFunction *function, UnparsedSpecification const &specification ,
476
+ Arguments &arguments, SmallVectorImpl<StringRef> &argumentStrings) {
428
477
ParseTestSpecification parser (function, argumentStrings);
429
478
parser.parse (specification, arguments);
430
479
}
0 commit comments