@@ -3053,16 +3053,30 @@ namespace {
3053
3053
emitted.contextForReabstraction );
3054
3054
}
3055
3055
3056
+ CanType getAnyObjectType () {
3057
+ return SGF.getASTContext ()
3058
+ .getProtocol (KnownProtocolKind::AnyObject)
3059
+ ->getDeclaredType ()
3060
+ ->getCanonicalType ();
3061
+ }
3062
+ bool isAnyObjectType (CanType t) {
3063
+ return t == getAnyObjectType ();
3064
+ }
3065
+
3056
3066
ManagedValue emitNativeToBridgedArgument (ArgumentSource &&arg,
3057
3067
SILType loweredSubstArgType,
3058
3068
AbstractionPattern origParamType,
3059
3069
SILParameterInfo param) {
3060
- // TODO: We should take the opportunity to peephole certain sequences
3061
- // here. For instance, when going from concrete type -> Any -> id, we
3062
- // can skip the intermediate 'Any' boxing and directly bridge the concrete
3063
- // type to its object representation. Similarly, when bridging from
3064
- // NSFoo -> Foo -> NSFoo, we should elide the bridge altogether and pass
3065
- // the original object.
3070
+ // If we're bridging a concrete type to `id` via Any, skip the Any
3071
+ // boxing.
3072
+ // TODO: Generalize. Similarly, when bridging from NSFoo -> Foo -> NSFoo,
3073
+ // we should elide the bridge altogether and pass the original object.
3074
+ if (isAnyObjectType (param.getType ()) && !arg.isRValue ()) {
3075
+ return emitNativeToBridgedObjectArgument (std::move (arg).asKnownExpr (),
3076
+ loweredSubstArgType,
3077
+ origParamType, param);
3078
+ }
3079
+
3066
3080
auto emitted = emitArgumentFromSource (std::move (arg), loweredSubstArgType,
3067
3081
origParamType, param);
3068
3082
@@ -3072,6 +3086,67 @@ namespace {
3072
3086
3073
3087
}
3074
3088
3089
+ // / Emit an argument expression that we know will be bridged to an
3090
+ // / Objective-C object.
3091
+ ManagedValue emitNativeToBridgedObjectArgument (Expr *argExpr,
3092
+ SILType loweredSubstArgType,
3093
+ AbstractionPattern origParamType,
3094
+ SILParameterInfo param) {
3095
+ argExpr = argExpr->getSemanticsProvidingExpr ();
3096
+
3097
+ // Look through ErasureExprs and try to bridge the underlying
3098
+ // concrete value instead.
3099
+ while (auto erasure = dyn_cast<ErasureExpr>(argExpr))
3100
+ argExpr = erasure->getSubExpr ();
3101
+
3102
+ // Emit the argument.
3103
+ auto contexts = getRValueEmissionContexts (loweredSubstArgType, param);
3104
+ ManagedValue emittedArg = SGF.emitRValue (argExpr, contexts.ForEmission )
3105
+ .getScalarValue ();
3106
+
3107
+ // If the argument is not already a class instance, bridge it.
3108
+ if (!argExpr->getType ()->mayHaveSuperclass ()
3109
+ && !argExpr->getType ()->isClassExistentialType ()) {
3110
+ emittedArg = SGF.emitNativeToBridgedValue (argExpr, emittedArg,
3111
+ Rep, param.getType ());
3112
+ }
3113
+ auto emittedArgTy = emittedArg.getType ().getSwiftRValueType ();
3114
+ assert (emittedArgTy->mayHaveSuperclass ()
3115
+ || emittedArgTy->isClassExistentialType ());
3116
+
3117
+ // Upcast reference types to AnyObject.
3118
+ if (!isAnyObjectType (emittedArgTy)) {
3119
+ // Open class existentials first to upcast the reference inside.
3120
+ if (emittedArgTy->isClassExistentialType ()) {
3121
+ emittedArgTy = ArchetypeType::getOpened (emittedArgTy);
3122
+ auto opened = SGF.B .createOpenExistentialRef (argExpr,
3123
+ emittedArg.getValue (),
3124
+ SILType::getPrimitiveObjectType (emittedArgTy));
3125
+ emittedArg = ManagedValue (opened, emittedArg.getCleanup ());
3126
+ }
3127
+
3128
+ // Erase to AnyObject.
3129
+ auto conformance = SGF.SGM .SwiftModule ->lookupConformance (
3130
+ emittedArgTy,
3131
+ SGF.getASTContext ().getProtocol (KnownProtocolKind::AnyObject),
3132
+ nullptr );
3133
+ assert (conformance &&
3134
+ " no AnyObject conformance for class?!" );
3135
+
3136
+ ArrayRef<ProtocolConformanceRef> conformances (*conformance);
3137
+ auto ctxConformances = SGF.getASTContext ().AllocateCopy (conformances);
3138
+
3139
+ auto erased = SGF.B .createInitExistentialRef (argExpr,
3140
+ SILType::getPrimitiveObjectType (getAnyObjectType ()),
3141
+ emittedArgTy, emittedArg.getValue (),
3142
+ ctxConformances);
3143
+ emittedArg = ManagedValue (erased, emittedArg.getCleanup ());
3144
+ }
3145
+
3146
+ assert (isAnyObjectType (emittedArg.getSwiftType ()));
3147
+ return emittedArg;
3148
+ }
3149
+
3075
3150
struct EmittedArgument {
3076
3151
SILLocation loc;
3077
3152
RValue value;
0 commit comments