@@ -4148,6 +4148,7 @@ RValue CallEmission::applyNormalCall(SGFContext C) {
4148
4148
cast<FunctionType>(calleeTypeInfo.substResultType ).getResult ();
4149
4149
}
4150
4150
4151
+ assert (callSite.hasValue ());
4151
4152
ResultPlanPtr resultPlan = ResultPlanBuilder::computeResultPlan (
4152
4153
SGF, calleeTypeInfo, callSite->Loc , uncurriedContext);
4153
4154
@@ -6255,20 +6256,12 @@ static ManagedValue emitDynamicPartialApply(SILGenFunction &SGF,
6255
6256
return result;
6256
6257
}
6257
6258
6258
- RValue SILGenFunction::emitDynamicMemberRef (SILLocation loc, SILValue operand,
6259
+ RValue SILGenFunction::emitDynamicMemberRef (SILLocation loc,
6260
+ ManagedValue operandMV,
6259
6261
ConcreteDeclRef memberRef,
6260
6262
CanType refTy, SGFContext C) {
6261
6263
assert (refTy->isOptional ());
6262
6264
6263
- if (!memberRef.getDecl ()->isInstanceMember ()) {
6264
- auto metatype = operand->getType ().castTo <MetatypeType>();
6265
- assert (metatype->getRepresentation () == MetatypeRepresentation::Thick);
6266
- metatype = CanMetatypeType::get (metatype.getInstanceType (),
6267
- MetatypeRepresentation::ObjC);
6268
- operand = B.createThickToObjCMetatype (
6269
- loc, operand, SILType::getPrimitiveObjectType (metatype));
6270
- }
6271
-
6272
6265
// Create the continuation block.
6273
6266
SILBasicBlock *contBB = createBasicBlock ();
6274
6267
@@ -6280,74 +6273,127 @@ RValue SILGenFunction::emitDynamicMemberRef(SILLocation loc, SILValue operand,
6280
6273
6281
6274
const TypeLowering &optTL = getTypeLowering (refTy);
6282
6275
auto loweredOptTy = optTL.getLoweredType ();
6283
-
6284
6276
SILValue optTemp = emitTemporaryAllocation (loc, loweredOptTy);
6285
6277
6286
- // Create the branch.
6278
+ // Prepare for the has-member case
6279
+ auto memberDecl = memberRef.getDecl ();
6280
+
6287
6281
FuncDecl *memberFunc;
6288
- if (auto *VD = dyn_cast<VarDecl>(memberRef. getDecl () )) {
6282
+ if (auto *VD = dyn_cast<VarDecl>(memberDecl )) {
6289
6283
memberFunc = VD->getOpaqueAccessor (AccessorKind::Get);
6290
6284
} else {
6291
- memberFunc = cast<FuncDecl>(memberRef. getDecl () );
6285
+ memberFunc = cast<FuncDecl>(memberDecl );
6292
6286
}
6293
- auto member = SILDeclRef (memberFunc, SILDeclRef::Kind::Func)
6294
- .asForeign ();
6287
+ auto member = SILDeclRef (memberFunc, SILDeclRef::Kind::Func).asForeign ();
6288
+ auto operand = operandMV.getValue ();
6289
+
6290
+ // adjust operand
6291
+ if (!memberDecl->isInstanceMember ()) {
6292
+ auto metatype = operand->getType ().castTo <MetatypeType>();
6293
+ assert (metatype->getRepresentation () == MetatypeRepresentation::Thick);
6294
+ metatype = CanMetatypeType::get (metatype.getInstanceType (),
6295
+ MetatypeRepresentation::ObjC);
6296
+ operand = B.createThickToObjCMetatype (
6297
+ loc, operand, SILType::getPrimitiveObjectType (metatype));
6298
+ operandMV = ManagedValue::forUnmanaged (operand);
6299
+ }
6300
+
6301
+ // Create the branch to test whether the member exists.
6295
6302
B.createDynamicMethodBranch (loc, operand, member, hasMemberBB, noMemberBB);
6296
6303
6297
6304
// Create the has-member branch.
6298
6305
{
6299
6306
B.emitBlock (hasMemberBB);
6300
6307
6301
6308
FullExpr hasMemberScope (Cleanups, CleanupLocation (loc));
6309
+ FormalEvaluationScope writebackScope (*this );
6302
6310
6303
- // The argument to the has-member block is the uncurried method.
6304
- const CanType valueTy = refTy.getOptionalObjectType ();
6305
- CanFunctionType methodTy;
6311
+ // -------------
6306
6312
6307
- // For a computed variable, we want the getter.
6308
- if (isa<VarDecl>(memberRef.getDecl ())) {
6309
- // FIXME: Verify ExtInfo state is correct, not working by accident.
6310
- CanFunctionType::ExtInfo info;
6311
- methodTy = CanFunctionType::get ({}, valueTy, info);
6312
- } else {
6313
- methodTy = cast<FunctionType>(valueTy);
6314
- }
6313
+ // If the member exists, then we need to wrap that function-value in an
6314
+ // optional. To get the function-value, we partially-apply `self` to the
6315
+ // method.
6315
6316
6316
- // Build a partially-applied foreign formal type.
6317
- // TODO: instead of building this and then potentially converting, we
6318
- // should just build a single thunk.
6319
- auto foreignMethodTy =
6320
- getPartialApplyOfDynamicMethodFormalType (SGM, member, memberRef);
6317
+ CanType protocolSelfType = operand->getType ().getASTType ();
6318
+ Callee callee = Callee::forWitnessMethod (*this , protocolSelfType, member,
6319
+ memberRef.getSubstitutions (), loc);
6321
6320
6322
- // FIXME: Verify ExtInfo state is correct, not working by accident.
6323
- CanFunctionType::ExtInfo info;
6324
- FunctionType::Param arg (operand->getType ().getASTType ());
6325
- auto memberFnTy = CanFunctionType::get ({arg}, methodTy, info);
6321
+ CallEmission emission (*this , std::move (callee), std::move (writebackScope));
6326
6322
6327
- auto loweredMethodTy = getDynamicMethodLoweredType (SGM.M , member,
6328
- memberFnTy);
6329
- SILValue memberArg =
6330
- hasMemberBB->createPhiArgument (loweredMethodTy, OwnershipKind::Owned);
6323
+ CanType operandTy = operand->getType ().getASTType ();
6324
+ FunctionType::Param selfArg (operandTy);
6325
+
6326
+ // emission.addSelfParam(loc,
6327
+ // ArgumentSource(loc, RValue(*this, loc, operandTy, operandMV)), selfArg);
6328
+
6329
+ PreparedArguments preparedArgs;
6330
+ preparedArgs.emplace ({selfArg});
6331
+ // SmallVector<AnyFunctionType::Param> params;
6332
+ // PreparedArguments preparedArgs(params);
6333
+ preparedArgs.addArbitrary (ArgumentSource (loc, RValue (*this , loc, operandTy, operandMV)));
6334
+
6335
+ emission.addCallSite (CallSite (loc, std::move (preparedArgs)));
6336
+
6337
+ RValue resultRV = emission.apply ();
6338
+
6339
+
6340
+ // if ()
6331
6341
6332
- // Create the result value.
6333
- Scope applyScope (Cleanups, CleanupLocation (loc));
6334
- ManagedValue result = emitDynamicPartialApply (
6335
- *this , loc, memberArg, operand, foreignMethodTy, methodTy);
6336
6342
6337
- RValue resultRV;
6338
- if (isa<VarDecl>(memberRef.getDecl ())) {
6339
- resultRV =
6340
- emitMonomorphicApply (loc, result, {}, foreignMethodTy.getResult (),
6341
- valueTy, ApplyOptions (), None, None);
6342
- } else {
6343
- resultRV = RValue (*this , loc, valueTy, result);
6344
- }
6343
+
6344
+
6345
+
6346
+
6347
+ // -------------
6348
+
6349
+ // The argument to the has-member block is the uncurried method.
6350
+ // const CanType valueTy = refTy.getOptionalObjectType();
6351
+ // CanFunctionType methodTy;
6352
+ //
6353
+ // // For a computed variable, we want the getter.
6354
+ // if (isa<VarDecl>(memberRef.getDecl())) {
6355
+ // // FIXME: Verify ExtInfo state is correct, not working by accident.
6356
+ // CanFunctionType::ExtInfo info;
6357
+ // methodTy = CanFunctionType::get({}, valueTy, info);
6358
+ // } else {
6359
+ // methodTy = cast<FunctionType>(valueTy);
6360
+ // }
6361
+ //
6362
+ // // Build a partially-applied foreign formal type.
6363
+ // // TODO: instead of building this and then potentially converting, we
6364
+ // // should just build a single thunk.
6365
+ // auto foreignMethodTy =
6366
+ // getPartialApplyOfDynamicMethodFormalType(SGM, member, memberRef);
6367
+ //
6368
+ // // FIXME: Verify ExtInfo state is correct, not working by accident.
6369
+ // CanFunctionType::ExtInfo info;
6370
+ // FunctionType::Param arg(operand->getType().getASTType());
6371
+ // auto memberFnTy = CanFunctionType::get({arg}, methodTy, info);
6372
+ //
6373
+ // auto loweredMethodTy = getDynamicMethodLoweredType(SGM.M, member,
6374
+ // memberFnTy);
6375
+ // SILValue memberArg =
6376
+ // hasMemberBB->createPhiArgument(loweredMethodTy, OwnershipKind::Owned);
6377
+ //
6378
+ // // Create the result value.
6379
+ // Scope applyScope(Cleanups, CleanupLocation(loc));
6380
+ // ManagedValue result = emitDynamicPartialApply(
6381
+ // *this, loc, memberArg, operand, foreignMethodTy, methodTy);
6382
+ //
6383
+ // RValue resultRV;
6384
+ // if (isa<VarDecl>(memberRef.getDecl())) {
6385
+ // resultRV =
6386
+ // emitMonomorphicApply(loc, result, {}, foreignMethodTy.getResult(),
6387
+ // valueTy, ApplyOptions(), None, None);
6388
+ // } else {
6389
+ // resultRV = RValue(*this, loc, valueTy, result);
6390
+ // }
6345
6391
6346
6392
// Package up the result in an optional.
6347
6393
emitInjectOptionalValueInto (loc, {loc, std::move (resultRV)}, optTemp,
6348
6394
optTL);
6349
6395
6350
- applyScope.pop ();
6396
+ // applyScope.pop();
6351
6397
// Branch to the continuation block.
6352
6398
B.createBranch (loc, contBB);
6353
6399
}
0 commit comments