Skip to content

Commit fe8cc46

Browse files
committed
[SIL] Allow test_spec insts to take values.
Tests can now say %foo to refer to a value in addition to @Instruction or @argument or similar.
1 parent dc6d784 commit fe8cc46

File tree

5 files changed

+129
-13
lines changed

5 files changed

+129
-13
lines changed

include/swift/SIL/ParseTestSpecification.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,15 @@ struct UnparsedSpecification {
210210
/// (@{instruction|block|function}) can be parsed in terms of this
211211
/// anchor.
212212
SILInstruction *context;
213+
/// Map from names used in the specification to the corresponding SILValues.
214+
llvm::StringMap<SILValue> values;
213215
};
214216

217+
/// Populates the array \p components with the elements of \p
218+
/// specificationString.
219+
void getTestSpecificationComponents(StringRef specificationString,
220+
SmallVectorImpl<StringRef> &components);
221+
215222
/// Finds and deletes each test_specification instruction in \p function and
216223
/// appends its string payload to the provided vector.
217224
void getTestSpecifications(

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "llvm/ADT/APFloat.h"
4545
#include "llvm/ADT/APInt.h"
4646
#include "llvm/ADT/SmallPtrSet.h"
47+
#include "llvm/ADT/StringMap.h"
4748
#include "llvm/ADT/ilist.h"
4849
#include "llvm/ADT/ilist_node.h"
4950
#include "llvm/Support/TrailingObjects.h"
@@ -5162,6 +5163,7 @@ class TestSpecificationInst final
51625163
friend TrailingObjects;
51635164
friend SILBuilder;
51645165

5166+
llvm::StringMap<SILValue> values;
51655167
unsigned ArgumentsSpecificationLength;
51665168

51675169
TestSpecificationInst(SILDebugLocation Loc,
@@ -5173,6 +5175,8 @@ class TestSpecificationInst final
51735175
create(SILDebugLocation Loc, StringRef argumentsSpecification, SILModule &M);
51745176

51755177
public:
5178+
void setValueForName(StringRef name, SILValue value) { values[name] = value; }
5179+
llvm::StringMap<SILValue> const &getValues() { return values; }
51765180
StringRef getArgumentsSpecification() const {
51775181
return StringRef(getTrailingObjects<char>(), ArgumentsSpecificationLength);
51785182
}

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/SIL/AbstractionPattern.h"
3131
#include "swift/SIL/InstructionUtils.h"
3232
#include "swift/SIL/OwnershipUtils.h"
33+
#include "swift/SIL/ParseTestSpecification.h"
3334
#include "swift/SIL/SILArgument.h"
3435
#include "swift/SIL/SILBuilder.h"
3536
#include "swift/SIL/SILDebugScope.h"
@@ -187,6 +188,8 @@ namespace swift {
187188

188189
/// Data structures used to perform name lookup for local values.
189190
llvm::StringMap<ValueBase*> LocalValues;
191+
llvm::StringMap<llvm::SmallVector<TestSpecificationInst *>>
192+
TestSpecsWithRefs;
190193
llvm::StringMap<SourceLoc> ForwardRefLocalValues;
191194

192195
Type performTypeResolution(TypeRepr *TyR, bool IsSILType,
@@ -799,6 +802,12 @@ void SILParser::setLocalValue(ValueBase *Value, StringRef Name,
799802
Value->getType().getRawASTType());
800803
HadError = true;
801804
} else {
805+
if (TestSpecsWithRefs.find(Name) != TestSpecsWithRefs.end()) {
806+
for (auto *tsi : TestSpecsWithRefs[Name]) {
807+
tsi->setValueForName(Name, Value);
808+
}
809+
}
810+
802811
// Forward references only live here if they have a single result.
803812
Entry->replaceAllUsesWith(Value);
804813
::delete cast<PlaceholderValue>(Entry);
@@ -807,6 +816,12 @@ void SILParser::setLocalValue(ValueBase *Value, StringRef Name,
807816
return;
808817
}
809818

819+
if (TestSpecsWithRefs.find(Name) != TestSpecsWithRefs.end()) {
820+
for (auto *tsi : TestSpecsWithRefs[Name]) {
821+
tsi->setValueForName(Name, Value);
822+
}
823+
}
824+
810825
// Otherwise, just store it in our map.
811826
Entry = Value;
812827
}
@@ -3770,7 +3785,33 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
37703785
auto ArgumentsSpecification =
37713786
P.Tok.getText().drop_front(numQuotes).drop_back(numQuotes).trim();
37723787
P.consumeToken(tok::string_literal);
3773-
ResultVal = B.createTestSpecificationInst(InstLoc, ArgumentsSpecification);
3788+
auto *tsi = B.createTestSpecificationInst(InstLoc, ArgumentsSpecification);
3789+
SmallVector<StringRef, 4> components;
3790+
test::getTestSpecificationComponents(ArgumentsSpecification, components);
3791+
for (auto component : components) {
3792+
auto offset = 0;
3793+
size_t nameStart = StringRef::npos;
3794+
while ((nameStart = component.find_if([](char c) { return c == '%'; },
3795+
offset)) != StringRef::npos) {
3796+
auto nameEnd = component.find_if_not(
3797+
[](char c) { return clang::isAsciiIdentifierContinue(c); },
3798+
nameStart + 1);
3799+
if (nameEnd == StringRef::npos)
3800+
nameEnd = component.size();
3801+
auto name = component.substr(nameStart, nameEnd);
3802+
component = component.drop_front(nameEnd);
3803+
if (nameStart + 1 == nameEnd) {
3804+
continue;
3805+
}
3806+
auto *&entry = LocalValues[name];
3807+
if (entry) {
3808+
tsi->setValueForName(name, entry);
3809+
} else {
3810+
TestSpecsWithRefs[name].push_back(tsi);
3811+
}
3812+
}
3813+
}
3814+
ResultVal = tsi;
37743815
break;
37753816
}
37763817

lib/SIL/Parser/ParseTestSpecification.cpp

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,16 @@ class ParseArgumentSpecification {
179179
ParseTestSpecification &outer;
180180
StringRef specification;
181181
SILInstruction *context;
182+
llvm::StringMap<SILValue> values;
182183

183184
SILValue getTraceValue(unsigned index, SILFunction *function);
184185

185186
public:
186187
ParseArgumentSpecification(ParseTestSpecification &outer,
187-
StringRef specification, SILInstruction *context)
188-
: outer(outer), specification(specification), context(context) {}
188+
StringRef specification, SILInstruction *context,
189+
llvm::StringMap<SILValue> values)
190+
: outer(outer), specification(specification), context(context),
191+
values(values) {}
189192

190193
Argument parse() {
191194
auto argument = parseArgument();
@@ -501,6 +504,38 @@ class ParseArgumentSpecification {
501504
llvm_unreachable("unhandled suffix after 'function'!?");
502505
}
503506

507+
SILValue parseValueComponent() {
508+
if (!peekPrefix("%"))
509+
return SILValue();
510+
auto nameEnd = specification.find_if_not(
511+
[](char c) { return clang::isAsciiIdentifierContinue(c); }, 1);
512+
if (nameEnd == StringRef::npos)
513+
nameEnd = specification.size();
514+
auto name = specification.take_front(nameEnd);
515+
specification = specification.drop_front(nameEnd);
516+
if (!empty() && !peekPrefix(".")) {
517+
llvm::errs() << specification << "\n";
518+
llvm::report_fatal_error("bad suffix on value!?");
519+
}
520+
auto value = values[name];
521+
if (!value) {
522+
llvm::errs() << "unknown value '" << name << "'\n"
523+
<< "have the following name->value pairs:\n";
524+
for (auto &pair : values) {
525+
llvm::errs() << pair.getKey() << "->" << pair.getValue() << "\n";
526+
}
527+
llvm::report_fatal_error("unknown value!?");
528+
}
529+
return value;
530+
}
531+
532+
llvm::Optional<Argument> parseValueReference() {
533+
auto value = parseValueComponent();
534+
if (!value)
535+
return llvm::None;
536+
return ValueArgument{value};
537+
}
538+
504539
llvm::Optional<Argument> parseReference() {
505540
if (!consumePrefix("@"))
506541
return llvm::None;
@@ -525,6 +560,8 @@ class ParseArgumentSpecification {
525560
return *arg;
526561
if (auto arg = parseUInt())
527562
return *arg;
563+
if (auto arg = parseValueReference())
564+
return *arg;
528565
if (auto arg = parseReference())
529566
return *arg;
530567
// Parse strings last--everything parses as a string.
@@ -563,15 +600,10 @@ class ParseTestSpecification {
563600

564601
void parse(UnparsedSpecification const &specification, Arguments &arguments) {
565602
StringRef specificationString = specification.string;
566-
specificationString.split(components, " ");
567-
for (unsigned long index = 0, size = components.size(); index < size;
568-
++index) {
569-
auto componentString = components[index].trim();
570-
if (componentString.empty())
571-
continue;
572-
573-
ParseArgumentSpecification parser(*this, componentString,
574-
specification.context);
603+
getTestSpecificationComponents(specificationString, components);
604+
for (auto componentString : components) {
605+
ParseArgumentSpecification parser(
606+
*this, componentString, specification.context, specification.values);
575607
auto argument = parser.parse();
576608
arguments.storage.push_back(argument);
577609
}
@@ -627,6 +659,19 @@ void Argument::print(llvm::raw_ostream &os) {
627659

628660
// API
629661

662+
void swift::test::getTestSpecificationComponents(
663+
StringRef specificationString, SmallVectorImpl<StringRef> &components) {
664+
SmallVector<StringRef, 16> rawComponents;
665+
specificationString.split(rawComponents, " ");
666+
for (unsigned long index = 0, size = rawComponents.size(); index < size;
667+
++index) {
668+
auto componentString = rawComponents[index].trim();
669+
if (componentString.empty())
670+
continue;
671+
components.push_back(componentString);
672+
}
673+
}
674+
630675
void swift::test::getTestSpecifications(
631676
SILFunction *function,
632677
SmallVectorImpl<UnparsedSpecification> &specifications) {
@@ -635,7 +680,8 @@ void swift::test::getTestSpecifications(
635680
if (auto *tsi = dyn_cast<TestSpecificationInst>(&inst)) {
636681
auto ref = tsi->getArgumentsSpecification();
637682
auto *anchor = findAnchorInstructionAfter(tsi);
638-
specifications.push_back({std::string(ref.begin(), ref.end()), anchor});
683+
specifications.push_back(
684+
{std::string(ref.begin(), ref.end()), anchor, tsi->getValues()});
639685
tsi->eraseFromParent();
640686
}
641687
}

test/SILOptimizer/unit_test.sil

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,21 @@ exit:
187187
%retval = tuple ()
188188
return %retval : $()
189189
}
190+
191+
// CHECK-LABEL: begin running test {{.*}} on test_value_literal_parsing: test-specification-parsing with: VVVV, %0, %1, %2, %3
192+
// CHECK: value: %0 = argument of bb0 : $Builtin.Int1
193+
// CHECK: value: %2 = integer_literal $Builtin.Int64, 1
194+
// CHECK: value: %1 = integer_literal $Builtin.Int64, 2
195+
// CHECK: value: %3 = integer_literal $Builtin.Int64, 3
196+
// CHECK-LABEL: end running test {{.*}} on test_value_literal_parsing: test-specification-parsing with: VVVV, %0, %1, %2, %3
197+
sil @test_value_literal_parsing : $(Builtin.Int1) -> () {
198+
entry(%0 : $Builtin.Int1):
199+
%2 = integer_literal $Builtin.Int64, 2
200+
test_specification "test-specification-parsing VVVV %0 %1 %2 %3"
201+
%1 = integer_literal $Builtin.Int64, 1
202+
%3 = integer_literal $Builtin.Int64, 3
203+
apply undef(%2) : $@convention(thin) (Builtin.Int64) -> ()
204+
apply undef(%3) : $@convention(thin) (Builtin.Int64) -> ()
205+
%retval = tuple ()
206+
return %retval : $()
207+
}

0 commit comments

Comments
 (0)