Skip to content

Commit a9fb8ae

Browse files
Merge pull request swiftlang#252 from kateinoigakukun/katei/fix-keypath
[WASM] Fix KeyPath on WebAssembly
2 parents e9f0bda + 60186b6 commit a9fb8ae

File tree

4 files changed

+51
-9
lines changed

4 files changed

+51
-9
lines changed

Diff for: lib/IRGen/GenKeyPath.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,8 @@ getAccessorForComputedComponent(IRGenModule &IGM,
222222
componentArgsBuf = params.claimNext();
223223
// Pass the argument pointer down to the underlying function, if it
224224
// wants it.
225-
if (hasSubscriptIndices) {
225+
// Always forward extra argument to match callee and caller signature on WebAssembly
226+
if (hasSubscriptIndices || IGM.TargetInfo.OutputObjectFormat == llvm::Triple::Wasm) {
226227
forwardedArgs.add(componentArgsBuf);
227228
}
228229
break;

Diff for: lib/SIL/SILVerifier.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ void verifyKeyPathComponent(SILModule &M,
277277
SILFunctionTypeRepresentation::Thin,
278278
"getter should be a thin function");
279279

280-
require(substGetterType->getNumParameters() == 1 + hasIndices,
280+
require(substGetterType->getNumParameters() == 1 + (hasIndices || C.LangOpts.Target.isOSBinFormatWasm()),
281281
"getter should have one parameter");
282282
auto baseParam = substGetterType->getParameters()[0];
283283
require(baseParam.getConvention() == normalArgConvention,
@@ -325,7 +325,7 @@ void verifyKeyPathComponent(SILModule &M,
325325
SILFunctionTypeRepresentation::Thin,
326326
"setter should be a thin function");
327327

328-
require(substSetterType->getNumParameters() == 2 + hasIndices,
328+
require(substSetterType->getNumParameters() == 2 + (hasIndices || C.LangOpts.Target.isOSBinFormatWasm()),
329329
"setter should have two parameters");
330330

331331
auto newValueParam = substSetterType->getParameters()[0];

Diff for: lib/SILGen/SILGenExpr.cpp

+35-4
Original file line numberDiff line numberDiff line change
@@ -2680,6 +2680,7 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM,
26802680
}
26812681
}
26822682

2683+
auto Target = SGM.getASTContext().LangOpts.Target;
26832684
auto genericSig =
26842685
genericEnv ? genericEnv->getGenericSignature().getCanonicalSignature()
26852686
: nullptr;
@@ -2688,6 +2689,14 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM,
26882689
genericEnv = nullptr;
26892690
}
26902691

2692+
// Add empty generic type parameter to match function signature on WebAssembly
2693+
if (!genericSig && Target.isOSBinFormatWasm()) {
2694+
auto param = GenericTypeParamType::get(0, 0, SGM.getASTContext());
2695+
auto sig = GenericSignature::get(param, { });
2696+
genericSig = CanGenericSignature(sig);
2697+
genericEnv = sig->getGenericEnvironment();
2698+
}
2699+
26912700
// Build the signature of the thunk as expected by the keypath runtime.
26922701
auto signature = [&]() {
26932702
CanType loweredBaseTy, loweredPropTy;
@@ -2703,7 +2712,8 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM,
27032712
SmallVector<SILParameterInfo, 2> params;
27042713
params.push_back({loweredBaseTy, paramConvention});
27052714
auto &C = SGM.getASTContext();
2706-
if (!indexes.empty())
2715+
// Always take indexes parameter to match callee and caller signature on WebAssembly
2716+
if (!indexes.empty() || C.LangOpts.Target.isOSBinFormatWasm())
27072717
params.push_back({C.getUnsafeRawPointerDecl()->getDeclaredType()
27082718
->getCanonicalType(),
27092719
ParameterConvention::Direct_Unowned});
@@ -2759,7 +2769,8 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM,
27592769
auto resultArg = entry->createFunctionArgument(resultArgTy);
27602770
auto baseArg = entry->createFunctionArgument(baseArgTy);
27612771
SILValue indexPtrArg;
2762-
if (!indexes.empty()) {
2772+
// Always take indexes parameter to match callee and caller signature on WebAssembly
2773+
if (!indexes.empty() || Target.isOSBinFormatWasm()) {
27632774
auto indexArgTy = signature->getParameters()[1].getSILStorageType(
27642775
SGM.M, signature);
27652776
indexPtrArg = entry->createFunctionArgument(indexArgTy);
@@ -2821,6 +2832,7 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
28212832
}
28222833
}
28232834

2835+
auto Target = SGM.getASTContext().LangOpts.Target;
28242836
auto genericSig =
28252837
genericEnv ? genericEnv->getGenericSignature().getCanonicalSignature()
28262838
: nullptr;
@@ -2829,6 +2841,14 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
28292841
genericEnv = nullptr;
28302842
}
28312843

2844+
// Add empty generic type parameter to match function signature on WebAssembly
2845+
if (!genericSig && Target.isOSBinFormatWasm()) {
2846+
auto param = GenericTypeParamType::get(0, 0, SGM.getASTContext());
2847+
auto sig = GenericSignature::get(param, { });
2848+
genericSig = CanGenericSignature(sig);
2849+
genericEnv = sig->getGenericEnvironment();
2850+
}
2851+
28322852
// Build the signature of the thunk as expected by the keypath runtime.
28332853
auto signature = [&]() {
28342854
CanType loweredBaseTy, loweredPropTy;
@@ -2854,7 +2874,8 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
28542874
? ParameterConvention::Indirect_Inout
28552875
: paramConvention});
28562876
// indexes
2857-
if (!indexes.empty())
2877+
// Always take indexes parameter to match callee and caller signature on WebAssembly
2878+
if (!indexes.empty() || C.LangOpts.Target.isOSBinFormatWasm())
28582879
params.push_back({C.getUnsafeRawPointerDecl()->getDeclaredType()
28592880
->getCanonicalType(),
28602881
ParameterConvention::Direct_Unowned});
@@ -2910,7 +2931,8 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM,
29102931
auto baseArg = entry->createFunctionArgument(baseArgTy);
29112932
SILValue indexPtrArg;
29122933

2913-
if (!indexes.empty()) {
2934+
// Always take indexes parameter to match callee and caller signature on WebAssembly
2935+
if (!indexes.empty() || Target.isOSBinFormatWasm()) {
29142936
auto indexArgTy = signature->getParameters()[2].getSILStorageType(
29152937
SGM.M, signature);
29162938
indexPtrArg = entry->createFunctionArgument(indexArgTy);
@@ -2992,6 +3014,7 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM,
29923014
return;
29933015
}
29943016

3017+
auto Target = SGM.getASTContext().LangOpts.Target;
29953018
auto genericSig =
29963019
genericEnv ? genericEnv->getGenericSignature().getCanonicalSignature()
29973020
: nullptr;
@@ -3001,6 +3024,14 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM,
30013024
genericEnv = nullptr;
30023025
}
30033026

3027+
// Add empty generic type parameter to match function signature on WebAssembly
3028+
if (!genericSig && Target.isOSBinFormatWasm()) {
3029+
auto param = GenericTypeParamType::get(0, 0, SGM.getASTContext());
3030+
auto sig = GenericSignature::get(param, { });
3031+
genericSig = CanGenericSignature(sig);
3032+
genericEnv = sig->getGenericEnvironment();
3033+
}
3034+
30043035
auto &C = SGM.getASTContext();
30053036
auto unsafeRawPointerTy = C.getUnsafeRawPointerDecl()->getDeclaredType()
30063037
->getCanonicalType();

Diff for: stdlib/public/core/KeyPath.swift

+12-2
Original file line numberDiff line numberDiff line change
@@ -2543,9 +2543,19 @@ internal protocol KeyPathPatternVisitor {
25432543

25442544
internal func _resolveRelativeAddress(_ base: UnsafeRawPointer,
25452545
_ offset: Int32) -> UnsafeRawPointer {
2546+
#if arch(wasm32)
2547+
// FIXME: If offset is 0, it means the pointer is null.
2548+
// For real relative pointer, it always calculates valid non-null address
2549+
// because the base address is always valid.
2550+
// But hacked absolute pointer can be null pointer.
2551+
// The return type doesn't allow nil, so return given base temporarily.
2552+
if offset == 0 { return base }
2553+
return UnsafeRawPointer(bitPattern: Int(offset)).unsafelyUnwrapped
2554+
#else
25462555
// Sign-extend the offset to pointer width and add with wrap on overflow.
25472556
return UnsafeRawPointer(bitPattern: Int(bitPattern: base) &+ Int(offset))
25482557
.unsafelyUnwrapped
2558+
#endif
25492559
}
25502560
internal func _resolveRelativeIndirectableAddress(_ base: UnsafeRawPointer,
25512561
_ offset: Int32)
@@ -3189,7 +3199,7 @@ internal struct InstantiateKeyPathBuffer: KeyPathPatternVisitor {
31893199

31903200
case .pointer:
31913201
// Resolve the sign-extended relative reference.
3192-
var absoluteID: UnsafeRawPointer? = idValueBase + Int(idValue)
3202+
var absoluteID: UnsafeRawPointer? = _resolveRelativeAddress(idValueBase, idValue)
31933203

31943204
// If the pointer ID is unresolved, then it needs work to get to
31953205
// the final value.
@@ -3287,7 +3297,7 @@ internal struct InstantiateKeyPathBuffer: KeyPathPatternVisitor {
32873297
for i in externalArgs.indices {
32883298
let base = externalArgs.baseAddress.unsafelyUnwrapped + i
32893299
let offset = base.pointee
3290-
let metadataRef = UnsafeRawPointer(base) + Int(offset)
3300+
let metadataRef = _resolveRelativeAddress(UnsafeRawPointer(base), offset)
32913301
let result = _resolveKeyPathGenericArgReference(
32923302
metadataRef,
32933303
genericEnvironment: genericEnvironment,

0 commit comments

Comments
 (0)