Skip to content

Commit ab35362

Browse files
committed
[SIL] Added new test_specification instruction.
The new instruction exists only to be used in tests. The idea is to specify tests that ought to be run "in the context" of the containing function.
1 parent 5d832bf commit ab35362

File tree

19 files changed

+175
-2
lines changed

19 files changed

+175
-2
lines changed

docs/SIL.rst

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3924,6 +3924,52 @@ SIL DIExpression can have elements with various types, like AST nodes or strings
39243924

39253925
The ``[trace]`` flag is available for compiler unit testing. It is not produced during normal compilation. It is used combination with internal logging and optimization controls to select specific values to trace or to transform. For example, liveness analysis combines all "traced" values into a single live range with multiple definitions. This exposes corner cases that cannot be represented by passing valid SIL through the pipeline.
39263926

3927+
Testing
3928+
~~~~~~~
3929+
3930+
test_specification
3931+
``````````````````
3932+
::
3933+
3934+
sil-instruction ::= 'test_specification' string-literal
3935+
3936+
test_specification "parsing @trace[3] @function[other].block[2].instruction[1]"
3937+
3938+
Exists only for writing FileCheck tests. Specifies a list of test arguments
3939+
which should be used in order to run a particular test "in the context" of the
3940+
function containing the instruction.
3941+
3942+
Parsing of these test arguments is done via ``parseTestArgumentsFromSpecification``.
3943+
3944+
The following types of test arguments are supported:
3945+
3946+
- boolean: true false
3947+
- unsigned integer: 0...ULONG_MAX
3948+
- string
3949+
- function: @function <-- the current function
3950+
@function[uint] <-- function at index ``uint``
3951+
@function[name] <-- function named ``name``
3952+
- block: @block <-- the first block
3953+
@block[uint] <-- the block at index ``uint``
3954+
@{function}.{block} <-- the indicated block in the indicated function
3955+
Example: @function[foo].block[2]
3956+
- trace: @trace <-- the first ``debug_value [trace]`` in the current function
3957+
@trace[uint] <-- the ``debug_value [trace]`` at index ``uint``
3958+
@{function}.{trace} <-- the indicated trace in the indicated function
3959+
Example: @function[bar].trace
3960+
- instruction: @instruction <-- the first instruction
3961+
@instruction[uint] <-- the instruction at index ``uint``
3962+
@{function}.{instruction} <-- the indicated instruction in the indicated function
3963+
Example: @function[baz].instruction[19]
3964+
@{block}.{instruction} <-- the indicated instruction in the indicated block
3965+
Example: @function[bam].block.instruction
3966+
- operand: @operand <-- the first operand
3967+
@operand[uint] <-- the operand at index ``uint``
3968+
@{instruction}.{operand} <-- the indicated operand of the indicated instruction
3969+
Example: @block[19].instruction[2].operand[3]
3970+
Example: @function[2].instruction.operand
3971+
3972+
39273973
Profiling
39283974
~~~~~~~~~
39293975

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,8 @@ ERROR(expected_sil_profiler_counter_total,none,
539539
"expected profiler counter total", ())
540540
ERROR(expected_sil_profiler_counter_hash,none,
541541
"expected profiler counter hash", ())
542+
ERROR(expected_sil_test_specification_body,none,
543+
"expected a string consisting of the space-separated test arguments", ())
542544

543545
// SIL Values
544546
ERROR(sil_value_redefinition,none,

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,13 @@ class SILBuilder {
988988
return createDebugValue(Loc, src, Var);
989989
}
990990

991+
TestSpecificationInst *
992+
createTestSpecificationInst(SILLocation Loc,
993+
StringRef ArgumentsSpecification) {
994+
return insert(TestSpecificationInst::create(
995+
getSILDebugLocation(Loc), ArgumentsSpecification, getModule()));
996+
}
997+
991998
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
992999
Load##Name##Inst *createLoad##Name(SILLocation Loc, \
9931000
SILValue src, \

include/swift/SIL/SILCloner.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,6 +2631,15 @@ void SILCloner<ImplClass>::visitIncrementProfilerCounterInst(
26312631
Inst->getNumCounters(), Inst->getPGOFuncHash()));
26322632
}
26332633

2634+
template <typename ImplClass>
2635+
void SILCloner<ImplClass>::visitTestSpecificationInst(
2636+
TestSpecificationInst *Inst) {
2637+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2638+
recordClonedInstruction(Inst, getBuilder().createTestSpecificationInst(
2639+
getOpLocation(Inst->getLoc()),
2640+
Inst->getArgumentsSpecification()));
2641+
}
2642+
26342643
template<typename ImplClass>
26352644
void
26362645
SILCloner<ImplClass>::visitIndexAddrInst(IndexAddrInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4933,6 +4933,32 @@ class DebugValueInst final
49334933
}
49344934
};
49354935

4936+
class TestSpecificationInst final
4937+
: public InstructionBase<SILInstructionKind::TestSpecificationInst,
4938+
NonValueInstruction>,
4939+
private llvm::TrailingObjects<TestSpecificationInst, char> {
4940+
friend TrailingObjects;
4941+
friend SILBuilder;
4942+
4943+
unsigned ArgumentsSpecificationLength;
4944+
4945+
TestSpecificationInst(SILDebugLocation Loc,
4946+
unsigned ArgumentsSpecificationLength)
4947+
: InstructionBase(Loc),
4948+
ArgumentsSpecificationLength(ArgumentsSpecificationLength) {}
4949+
4950+
static TestSpecificationInst *
4951+
create(SILDebugLocation Loc, StringRef argumentsSpecification, SILModule &M);
4952+
4953+
public:
4954+
StringRef getArgumentsSpecification() const {
4955+
return StringRef(getTrailingObjects<char>(), ArgumentsSpecificationLength);
4956+
}
4957+
4958+
ArrayRef<Operand> getAllOperands() const { return {}; }
4959+
MutableArrayRef<Operand> getAllOperands() { return {}; }
4960+
};
4961+
49364962
/// An abstract class representing a load from some kind of reference storage.
49374963
template <SILInstructionKind K>
49384964
class LoadReferenceInstBase

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,8 @@ NON_VALUE_INST(MarkFunctionEscapeInst, mark_function_escape,
765765
SILInstruction, None, DoesNotRelease)
766766
NON_VALUE_INST(DebugValueInst, debug_value,
767767
SILInstruction, None, DoesNotRelease)
768+
NON_VALUE_INST(TestSpecificationInst, test_specification,
769+
SILInstruction, None, DoesNotRelease)
768770
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
769771
NON_VALUE_INST(Store##Name##Inst, store_##name, \
770772
SILInstruction, MayWrite, DoesNotRelease)

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,9 @@ class IRGenSILFunction :
13841384
void visitLinearFunctionExtractInst(LinearFunctionExtractInst *i);
13851385
void visitDifferentiabilityWitnessFunctionInst(
13861386
DifferentiabilityWitnessFunctionInst *i);
1387+
void visitTestSpecificationInst(TestSpecificationInst *i) {
1388+
llvm_unreachable("test-only instruction in Lowered SIL?!");
1389+
}
13871390

13881391
#define LOADABLE_REF_STORAGE_HELPER(Name) \
13891392
void visitRefTo##Name##Inst(RefTo##Name##Inst *i); \

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ SHOULD_NEVER_VISIT_INST(ReleaseValueAddr)
120120
SHOULD_NEVER_VISIT_INST(StrongRelease)
121121
SHOULD_NEVER_VISIT_INST(GetAsyncContinuation)
122122
SHOULD_NEVER_VISIT_INST(IncrementProfilerCounter)
123+
SHOULD_NEVER_VISIT_INST(TestSpecification)
123124

124125
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
125126
SHOULD_NEVER_VISIT_INST(StrongRetain##Name) \

lib/SIL/IR/SILInstructions.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,21 @@ IncrementProfilerCounterInst *IncrementProfilerCounterInst::create(
456456
return Inst;
457457
}
458458

459+
TestSpecificationInst *
460+
TestSpecificationInst::create(SILDebugLocation Loc,
461+
StringRef ArgumentsSpecification, SILModule &M) {
462+
auto ArgumentsSpecificationLength = ArgumentsSpecification.size();
463+
auto Size = totalSizeToAlloc<char>(ArgumentsSpecificationLength);
464+
auto Buffer = M.allocateInst(Size, alignof(TestSpecificationInst));
465+
466+
auto *Inst =
467+
::new (Buffer) TestSpecificationInst(Loc, ArgumentsSpecificationLength);
468+
std::uninitialized_copy(ArgumentsSpecification.begin(),
469+
ArgumentsSpecification.end(),
470+
Inst->getTrailingObjects<char>());
471+
return Inst;
472+
}
473+
459474
InitBlockStorageHeaderInst *
460475
InitBlockStorageHeaderInst::create(SILFunction &F,
461476
SILDebugLocation DebugLoc, SILValue BlockStorage,

lib/SIL/IR/SILPrinter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2410,7 +2410,11 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
24102410
void visitReturnInst(ReturnInst *RI) {
24112411
*this << getIDAndType(RI->getOperand());
24122412
}
2413-
2413+
2414+
void visitTestSpecificationInst(TestSpecificationInst *TSI) {
2415+
*this << QuotedString(TSI->getArgumentsSpecification());
2416+
}
2417+
24142418
void visitThrowInst(ThrowInst *TI) {
24152419
*this << getIDAndType(TI->getOperand());
24162420
}

0 commit comments

Comments
 (0)