Skip to content

[SILGen] Handle arbitrary ObjC-to-Swift bridging for globals #12603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 68 additions & 4 deletions lib/SILGen/SILGenLValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1845,6 +1845,67 @@ namespace {
}
};

/// Remap an lvalue referencing an imported global variable to the
/// corresponding Swift type.
class BridgeToNativeComponent : public TranslationPathComponent {
AbstractionPattern OrigType;

public:
BridgeToNativeComponent(AbstractionPattern origType,
CanType substFormalType,
SILType loweredSubstType)
: TranslationPathComponent({ AbstractionPattern(substFormalType),
substFormalType, loweredSubstType },
OrigToSubstKind),
OrigType(origType)
{}

RValue untranslate(SILGenFunction &SGF, SILLocation loc,
RValue &&rv, SGFContext c) && override {
SILType originalLoweredType = SGF.getLoweredType(OrigType.getType());
auto bridging = Conversion::getBridging(Conversion::BridgeToObjC,
getSubstFormalType(),
OrigType.getType(),
originalLoweredType);
return RValue(SGF, loc, originalLoweredType.getSwiftRValueType(),
SGF.emitConvertedRValue(loc, bridging, c,
[&](SILGenFunction &SGF,
SILLocation loc,
SGFContext c) {
return std::move(rv).getScalarValue();
}));
}

RValue translate(SILGenFunction &SGF, SILLocation loc,
RValue &&rv, SGFContext c) && override {
auto bridging = Conversion::getBridging(Conversion::BridgeFromObjC,
OrigType.getType(),
getSubstFormalType(),
getTypeOfRValue());
return RValue(SGF, loc, getSubstFormalType(),
SGF.emitConvertedRValue(loc, bridging, c,
[&](SILGenFunction &SGF,
SILLocation loc,
SGFContext c) {
return std::move(rv).getScalarValue();
}));
}

std::unique_ptr<LogicalPathComponent>
clone(SILGenFunction &SGF, SILLocation loc) const override {
return llvm::make_unique<BridgeToNativeComponent>(OrigType,
getSubstFormalType(),
getTypeOfRValue());
}

void dump(raw_ostream &OS, unsigned indent) const override {
OS.indent(indent) << "BridgeToNativeComponent("
<< getOrigFormalType() << ", "
<< getSubstFormalType() << ", "
<< getTypeOfRValue() << ")\n";
}
};

/// Remap a weak value to Optional<T>*, or unowned pointer to T*.
class OwnershipComponent : public LogicalPathComponent {
public:
Expand Down Expand Up @@ -2219,6 +2280,13 @@ static LValue emitLValueForNonMemberVarDecl(SILGenFunction &SGF,

if (address.getType().is<ReferenceStorageType>())
lv.add<OwnershipComponent>(typeData);

AbstractionPattern pattern = SGF.SGM.Types.getAbstractionPattern(var);
if (pattern.isClangType() &&
lv.getTypeOfRValue().getSwiftRValueType() != formalRValueType) {
lv.add<BridgeToNativeComponent>(pattern, formalRValueType,
SGF.getLoweredType(formalRValueType));
}
break;
}

Expand Down Expand Up @@ -3213,9 +3281,6 @@ RValue SILGenFunction::emitLoadOfLValue(SILLocation loc, LValue &&src,
// Any writebacks should be scoped to after the load.
FormalEvaluationScope scope(*this);

// We shouldn't need to re-abstract here, but we might have to bridge.
// This should only happen if we have a global variable of NSString type.
auto origFormalType = src.getOrigFormalType();
auto substFormalType = src.getSubstFormalType();
auto &rvalueTL = getTypeLowering(src.getTypeOfRValue());

Expand All @@ -3229,7 +3294,6 @@ RValue SILGenFunction::emitLoadOfLValue(SILLocation loc, LValue &&src,
.offset(*this, loc, addr, AccessKind::Read);
return RValue(*this, loc, substFormalType,
emitLoad(loc, addr.getValue(),
origFormalType, substFormalType,
rvalueTL, C, IsNotTake,
isBaseGuaranteed));
}
Expand Down