@@ -477,6 +477,29 @@ static ManagedValue emitBuiltinUnprotectedAddressOf(SILGenFunction &SGF,
477
477
/* stackProtected=*/ false );
478
478
}
479
479
480
+ // Like `tryEmitAddressableParameterAsAddress`, but also handles struct element projections.
481
+ static SILValue emitAddressOf (Expr *e, SILGenFunction &SGF, SILLocation loc) {
482
+
483
+ if (auto *memberRef = dyn_cast<MemberRefExpr>(e)) {
484
+ VarDecl *fieldDecl = dyn_cast<VarDecl>(memberRef->getDecl ().getDecl ());
485
+ if (!fieldDecl)
486
+ return SILValue ();
487
+ SILValue addr = emitAddressOf (memberRef->getBase (), SGF, loc);
488
+ if (!addr)
489
+ return SILValue ();
490
+ if (addr->getType ().getStructOrBoundGenericStruct () != fieldDecl->getDeclContext ())
491
+ return SILValue ();
492
+ return SGF.B .createStructElementAddr (loc, addr, fieldDecl);
493
+ }
494
+
495
+ if (auto addressableAddr = SGF.tryEmitAddressableParameterAsAddress (
496
+ ArgumentSource (e),
497
+ ValueOwnership::Shared)) {
498
+ return addressableAddr.getValue ();
499
+ }
500
+ return SILValue ();
501
+ }
502
+
480
503
// / Specialized emitter for Builtin.addressOfBorrow.
481
504
static ManagedValue emitBuiltinAddressOfBorrowBuiltins (SILGenFunction &SGF,
482
505
SILLocation loc,
@@ -491,15 +514,11 @@ static ManagedValue emitBuiltinAddressOfBorrowBuiltins(SILGenFunction &SGF,
491
514
492
515
auto argument = (*argsOrError)[0 ];
493
516
494
- SILValue addr;
495
517
// Try to borrow the argument at +0 indirect.
496
518
// If the argument is a reference to a borrowed addressable parameter, then
497
519
// use that parameter's stable address.
498
- if (auto addressableAddr = SGF.tryEmitAddressableParameterAsAddress (
499
- ArgumentSource (argument),
500
- ValueOwnership::Shared)) {
501
- addr = addressableAddr.getValue ();
502
- } else {
520
+ SILValue addr = emitAddressOf (argument, SGF, loc);
521
+ if (!addr) {
503
522
// We otherwise only support the builtin applied to values that
504
523
// are naturally emitted borrowed in memory. (But it would probably be good
505
524
// to phase this out since it's not really well-defined how long
0 commit comments