Skip to content

Commit 4d45840

Browse files
authored
Merge pull request #1027 from swiftwasm/master
[pull] swiftwasm from master
2 parents 1298bde + eec5c01 commit 4d45840

File tree

10 files changed

+120
-57
lines changed

10 files changed

+120
-57
lines changed

docs/SIL.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -5461,7 +5461,7 @@ unconditional_checked_cast_addr
54615461
sil-type 'in' sil-operand 'to'
54625462
sil-type 'in' sil-operand
54635463

5464-
unconditional_checked_cast_addr $A in %0 : $*@thick A to $B in $*@thick B
5464+
unconditional_checked_cast_addr $A in %0 : $*@thick A to $B in %1 : $*@thick B
54655465
// $A and $B must be both addresses
54665466
// %1 will be of type $*B
54675467
// $A is destroyed during the conversion. There is no implicit copy.

lib/SILGen/ManagedValue.h

+7
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ class ManagedValue {
121121
return ManagedValue::forOwnedObjectRValue(value, cleanup);
122122
}
123123

124+
static ManagedValue
125+
forExclusivelyBorrowedOwnedObjectRValue(SILValue value,
126+
CleanupHandle cleanup) {
127+
assert(value->getType().isObject());
128+
return ManagedValue::forOwnedObjectRValue(value, cleanup);
129+
}
130+
124131
/// Create a managed value for a +0 borrowed non-trivial rvalue object.
125132
static ManagedValue
126133
forBorrowedObjectRValue(SILValue value) {

lib/SILGen/SILGenApply.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
12431243
if (superMV.getValue() != SGF.InitDelegationSelf.getValue()) {
12441244
SILValue underlyingSelf = SGF.InitDelegationSelf.getValue();
12451245
SGF.InitDelegationSelf = ManagedValue::forUnmanaged(underlyingSelf);
1246-
CleanupHandle newWriteback = SGF.enterDelegateInitSelfWritebackCleanup(
1246+
CleanupHandle newWriteback = SGF.enterOwnedValueWritebackCleanup(
12471247
SGF.InitDelegationLoc.getValue(), SGF.InitDelegationSelfBox,
12481248
superMV.forward(SGF));
12491249
SGF.SuperInitDelegationSelf =

lib/SILGen/SILGenExpr.cpp

+14-16
Original file line numberDiff line numberDiff line change
@@ -717,20 +717,20 @@ SILValue SILGenFunction::emitEmptyTuple(SILLocation loc) {
717717

718718
namespace {
719719

720-
/// This is a simple cleanup class that is only meant to help with delegating
721-
/// initializers. Specifically, if the delegating initializer fails to consume
722-
/// the loaded self, we want to write back self into the slot to ensure that
723-
/// ownership is preserved.
724-
struct DelegateInitSelfWritebackCleanup : Cleanup {
720+
/// This is a simple cleanup class that at the end of a lexical scope consumes
721+
/// an owned value by writing it back to memory. The user can forward this
722+
/// cleanup to take ownership of the value and thus prevent it form being
723+
/// written back.
724+
struct OwnedValueWritebackCleanup final : Cleanup {
725725

726726
/// We store our own loc so that we can ensure that DI ignores our writeback.
727727
SILLocation loc;
728728

729729
SILValue lvalueAddress;
730730
SILValue value;
731731

732-
DelegateInitSelfWritebackCleanup(SILLocation loc, SILValue lvalueAddress,
733-
SILValue value)
732+
OwnedValueWritebackCleanup(SILLocation loc, SILValue lvalueAddress,
733+
SILValue value)
734734
: loc(loc), lvalueAddress(lvalueAddress), value(value) {}
735735

736736
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
@@ -749,14 +749,13 @@ struct DelegateInitSelfWritebackCleanup : Cleanup {
749749
lvalueObjTy);
750750
}
751751

752-
auto &lowering = SGF.B.getTypeLowering(lvalueAddress->getType());
753-
lowering.emitStore(SGF.B, loc, valueToStore, lvalueAddress,
754-
StoreOwnershipQualifier::Init);
752+
SGF.B.emitStoreValueOperation(loc, valueToStore, lvalueAddress,
753+
StoreOwnershipQualifier::Init);
755754
}
756755

757756
void dump(SILGenFunction &) const override {
758757
#ifndef NDEBUG
759-
llvm::errs() << "SimpleWritebackCleanup "
758+
llvm::errs() << "OwnedValueWritebackCleanup "
760759
<< "State:" << getState() << "\n"
761760
<< "lvalueAddress:" << lvalueAddress << "value:" << value
762761
<< "\n";
@@ -766,10 +765,9 @@ struct DelegateInitSelfWritebackCleanup : Cleanup {
766765

767766
} // end anonymous namespace
768767

769-
CleanupHandle SILGenFunction::enterDelegateInitSelfWritebackCleanup(
768+
CleanupHandle SILGenFunction::enterOwnedValueWritebackCleanup(
770769
SILLocation loc, SILValue address, SILValue newValue) {
771-
Cleanups.pushCleanup<DelegateInitSelfWritebackCleanup>(loc, address,
772-
newValue);
770+
Cleanups.pushCleanup<OwnedValueWritebackCleanup>(loc, address, newValue);
773771
return Cleanups.getTopCleanup();
774772
}
775773

@@ -815,8 +813,8 @@ RValue SILGenFunction::emitRValueForSelfInDelegationInit(SILLocation loc,
815813
// Forward our initial value for init delegation self and create a new
816814
// cleanup that performs a writeback at the end of lexical scope if our
817815
// value is not consumed.
818-
InitDelegationSelf = ManagedValue(
819-
self, enterDelegateInitSelfWritebackCleanup(*InitDelegationLoc, addr, self));
816+
InitDelegationSelf = ManagedValue::forExclusivelyBorrowedOwnedObjectRValue(
817+
self, enterOwnedValueWritebackCleanup(*InitDelegationLoc, addr, self));
820818
InitDelegationSelfBox = addr;
821819
return RValue(*this, loc, refType, InitDelegationSelf);
822820
}

lib/SILGen/SILGenFunction.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -1188,9 +1188,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
11881188
CleanupHandle enterDeallocateUninitializedArrayCleanup(SILValue array);
11891189
void emitUninitializedArrayDeallocation(SILLocation loc, SILValue array);
11901190

1191-
CleanupHandle enterDelegateInitSelfWritebackCleanup(SILLocation loc,
1192-
SILValue address,
1193-
SILValue newValue);
1191+
CleanupHandle enterOwnedValueWritebackCleanup(SILLocation loc,
1192+
SILValue address,
1193+
SILValue newValue);
11941194

11951195
SILValue emitConversionToSemanticRValue(SILLocation loc, SILValue value,
11961196
const TypeLowering &valueTL);

lib/Sema/CSSimplify.cpp

+25-28
Original file line numberDiff line numberDiff line change
@@ -7683,10 +7683,30 @@ ConstraintSystem::simplifyKeyPathConstraint(
76837683
return true;
76847684
};
76857685

7686-
// We have a hole, the solver can't infer the key path type. So let's
7687-
// just assume this is solved.
7688-
if (shouldAttemptFixes() && keyPathTy->isHole()) {
7689-
return SolutionKind::Solved;
7686+
// If we have a hole somewhere in the key path, the solver won't be able to
7687+
// infer the key path type. So let's just assume this is solved.
7688+
if (shouldAttemptFixes()) {
7689+
if (keyPathTy->isHole())
7690+
return SolutionKind::Solved;
7691+
7692+
// If the root type has been bound to a hole, we cannot infer it.
7693+
if (getFixedTypeRecursive(rootTy, /*wantRValue*/ true)->isHole())
7694+
return SolutionKind::Solved;
7695+
7696+
// If we have e.g a missing member somewhere, a component type variable
7697+
// will have been marked as a potential hole.
7698+
// FIXME: This relies on the fact that we only mark an overload type
7699+
// variable as a potential hole once we've added a corresponding fix. We
7700+
// can't use 'isHole' instead, as that doesn't handle cases where the
7701+
// overload type variable gets bound to another type from the context rather
7702+
// than a hole. We need to come up with a better way of handling the
7703+
// relationship between key paths and overloads.
7704+
if (llvm::any_of(componentTypeVars, [&](TypeVariableType *tv) {
7705+
return tv->getImpl().getLocator()->isForKeyPathComponent() &&
7706+
tv->getImpl().canBindToHole();
7707+
})) {
7708+
return SolutionKind::Solved;
7709+
}
76907710
}
76917711

76927712
// If we're fixed to a bound generic type, trying harvesting context from it.
@@ -7737,34 +7757,11 @@ ConstraintSystem::simplifyKeyPathConstraint(
77377757
// to determine whether the result will be a function type vs BGT KeyPath
77387758
// type, so continue through components to create new constraint at the
77397759
// end.
7740-
if (!overload || anyComponentsUnresolved) {
7760+
if (!overload) {
77417761
if (flags.contains(TMF_GenerateConstraints)) {
77427762
anyComponentsUnresolved = true;
77437763
continue;
77447764
}
7745-
7746-
if (shouldAttemptFixes()) {
7747-
auto typeVar =
7748-
llvm::find_if(componentTypeVars, [&](TypeVariableType *typeVar) {
7749-
auto *locator = typeVar->getImpl().getLocator();
7750-
auto elt = locator->findLast<LocatorPathElt::KeyPathComponent>();
7751-
return elt && elt->getIndex() == i;
7752-
});
7753-
7754-
// If one of the components haven't been resolved, let's check
7755-
// whether it has been determined to be a "hole" and if so,
7756-
// let's allow component validation to contiunue.
7757-
//
7758-
// This helps to, for example, diagnose problems with missing
7759-
// members used as part of a key path.
7760-
if (typeVar != componentTypeVars.end() &&
7761-
(*typeVar)->getImpl().canBindToHole()) {
7762-
anyComponentsUnresolved = true;
7763-
capability = ReadOnly;
7764-
continue;
7765-
}
7766-
}
7767-
77687765
return SolutionKind::Unsolved;
77697766
}
77707767

test/CMakeLists.txt

+6-6
Original file line numberDiff line numberDiff line change
@@ -121,26 +121,26 @@ set(LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py")
121121
# instead of by the path, which is good for CI. In this mode lit also updates
122122
# the mtime on the failed tests, which makes them run first on the
123123
# consecutive execution, which makes local builds fail faster.
124-
set(SWIFT_TEST_EXTRA_ARGS "--incremental")
124+
set(SWIFT_LIT_ARGS "--incremental" CACHE STRING "Arguments to pass to lit")
125125

126126
if(NOT SWIFT_INCLUDE_TOOLS)
127-
list(APPEND SWIFT_TEST_EXTRA_ARGS
127+
list(APPEND SWIFT_LIT_ARGS
128128
"--path=${SWIFT_NATIVE_LLVM_TOOLS_PATH}"
129129
"--path=${SWIFT_NATIVE_CLANG_TOOLS_PATH}"
130130
"--path=${SWIFT_NATIVE_SWIFT_TOOLS_PATH}")
131131
if(SWIFT_BUILD_STDLIB)
132-
list(APPEND SWIFT_TEST_EXTRA_ARGS
132+
list(APPEND SWIFT_LIT_ARGS
133133
"--param" "test_resource_dir=${SWIFTLIB_DIR}")
134134
endif()
135135
endif()
136136

137137
option(SWIFT_TEST_USE_LEAKS "Run Swift stdlib tests under leaks" FALSE)
138138
if (SWIFT_TEST_USE_LEAKS)
139-
list(APPEND SWIFT_TEST_EXTRA_ARGS "--param" "leaks-all")
139+
list(APPEND SWIFT_LIT_ARGS "--param" "leaks-all")
140140
endif()
141141

142142
if(NOT CMAKE_CFG_INTDIR STREQUAL ".")
143-
list(APPEND SWIFT_TEST_EXTRA_ARGS
143+
list(APPEND SWIFT_LIT_ARGS
144144
"--param" "build_mode=${CMAKE_CFG_INTDIR}")
145145
endif()
146146

@@ -337,7 +337,7 @@ _Block_release(void) { }\n")
337337
COMMENT "Uploading stdlib")
338338

339339
foreach(test_mode ${TEST_MODES})
340-
set(LIT_ARGS "${SWIFT_TEST_EXTRA_ARGS} ${LLVM_LIT_ARGS}")
340+
set(LIT_ARGS "${SWIFT_LIT_ARGS} ${LLVM_LIT_ARGS}")
341341
separate_arguments(LIT_ARGS)
342342

343343
if(NOT SWIFT_BUILD_STDLIB AND NOT SWIFT_PATH_TO_EXTERNAL_STDLIB_BUILD)

test/Constraints/rdar62201037.swift

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-swift-frontend %s -verify -emit-sil -o /dev/null
2+
3+
struct R<T> {
4+
var str: String?
5+
}
6+
7+
func map<A, B>(e: (A) -> B) -> () -> R<B> {
8+
fatalError()
9+
}
10+
func map<A, B>(_ : (A) -> B) -> (A?) -> B? {
11+
fatalError()
12+
}
13+
14+
infix operator |>
15+
func |> <A, B> (g: A, h: (A) -> B) -> B { h(g) }
16+
17+
infix operator ^^^
18+
func ^^^ <A, B, C>(j: ((B) -> C) -> A, k: String) {}
19+
20+
extension WritableKeyPath {
21+
static func ^^^ (l: WritableKeyPath, m: Value) -> (Root) -> Root {
22+
fatalError()
23+
}
24+
}
25+
26+
func foo<T>(_ s: String, _ rt: R<T>?) -> String? {
27+
return rt.flatMap { _ in
28+
rt |> map(\.str ^^^ s)
29+
}
30+
.flatMap(\.str)
31+
}

test/expr/unary/keypath/keypath.swift

+29
Original file line numberDiff line numberDiff line change
@@ -895,11 +895,40 @@ struct SR_12290 {
895895

896896
func testKeyPathHole() {
897897
_ = \.x // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{8-8=<#Root#>}}
898+
_ = \.x.y // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{8-8=<#Root#>}}
899+
898900
let _ : AnyKeyPath = \.x
899901
// expected-error@-1 {{'AnyKeyPath' does not provide enough context for root type to be inferred; consider explicitly specifying a root type}} {{25-25=<#Root#>}}
902+
let _ : AnyKeyPath = \.x.y
903+
// expected-error@-1 {{'AnyKeyPath' does not provide enough context for root type to be inferred; consider explicitly specifying a root type}} {{25-25=<#Root#>}}
900904

901905
func f(_ i: Int) {}
902906
f(\.x) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{6-6=<#Root#>}}
907+
f(\.x.y) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{6-6=<#Root#>}}
908+
909+
// FIXME(SR-12827): Instead of "generic parameter 'T' could not be inferred",
910+
// we should offer the same diagnostic as above.
911+
func provideValueButNotRoot<T>(_ fn: (T) -> String) {} // expected-note 2{{in call to function 'provideValueButNotRoot'}}
912+
provideValueButNotRoot(\.x) // expected-error {{generic parameter 'T' could not be inferred}}
913+
provideValueButNotRoot(\.x.y) // expected-error {{generic parameter 'T' could not be inferred}}
914+
provideValueButNotRoot(\String.foo) // expected-error {{value of type 'String' has no member 'foo'}}
915+
916+
func provideKPValueButNotRoot<T>(_ kp: KeyPath<T, String>) {} // expected-note 3{{in call to function 'provideKPValueButNotRoot'}}
917+
provideKPValueButNotRoot(\.x) // expected-error {{generic parameter 'T' could not be inferred}}
918+
provideKPValueButNotRoot(\.x.y) // expected-error {{generic parameter 'T' could not be inferred}}
919+
provideKPValueButNotRoot(\String.foo)
920+
// expected-error@-1 {{value of type 'String' has no member 'foo'}}
921+
// expected-error@-2 {{generic parameter 'T' could not be inferred}}
922+
}
923+
924+
func testMissingMember() {
925+
let _: KeyPath<String, String> = \.foo // expected-error {{value of type 'String' has no member 'foo'}}
926+
let _: KeyPath<String, String> = \.foo.bar // expected-error {{value of type 'String' has no member 'foo'}}
927+
928+
let _: PartialKeyPath<String> = \.foo // expected-error {{value of type 'String' has no member 'foo'}}
929+
let _: PartialKeyPath<String> = \.foo.bar // expected-error {{value of type 'String' has no member 'foo'}}
930+
931+
_ = \String.x.y // expected-error {{value of type 'String' has no member 'x'}}
903932
}
904933

905934
func testSyntaxErrors() { // expected-note{{}}

validation-test/Sanitizers/fuzzer.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ import MSVCRT
1717
#endif
1818

1919
@_cdecl("LLVMFuzzerTestOneInput")
20-
public func test(_ start: UnsafeRawPointer, _ count: Int) -> CInt {
20+
public func testHexDigits(_ start: UnsafeRawPointer, _ count: Int) -> CInt {
2121
let bytes = UnsafeRawBufferPointer(start: start, count: count)
22-
if bytes.starts(with: "ABC".utf8) {
22+
let string = String(decoding: bytes, as: Unicode.UTF8.self)
23+
if let number = Int(string, radix: 16), (0x10...0xFF).contains(number) {
2324
print("Crash!")
2425
fflush(stdout)
2526
exit(EXIT_FAILURE)

0 commit comments

Comments
 (0)