Skip to content

Commit 1e80674

Browse files
authored
Merge pull request #60843 from kavon/5.7-preconcurrency-var-access
[5.7🍒] Add missing function conversion for member access to preconcurrency
2 parents 4c347d2 + 1b65e46 commit 1e80674

File tree

14 files changed

+198
-19
lines changed

14 files changed

+198
-19
lines changed

include/swift/AST/Expr.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3122,6 +3122,19 @@ class LoadExpr : public ImplicitConversionExpr {
31223122
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Load; }
31233123
};
31243124

3125+
/// ABISafeConversion - models a type conversion on an l-value that has no
3126+
/// material affect on the ABI of the type, while *preserving* the l-valueness
3127+
/// of the type.
3128+
class ABISafeConversionExpr : public ImplicitConversionExpr {
3129+
public:
3130+
ABISafeConversionExpr(Expr *subExpr, Type type)
3131+
: ImplicitConversionExpr(ExprKind::ABISafeConversion, subExpr, type) {}
3132+
3133+
static bool classof(const Expr *E) {
3134+
return E->getKind() == ExprKind::ABISafeConversion;
3135+
}
3136+
};
3137+
31253138
/// This is a conversion from an expression of UnresolvedType to an arbitrary
31263139
/// other type, and from an arbitrary type to UnresolvedType. This node does
31273140
/// not appear in valid code, only in code involving diagnostics.

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ ABSTRACT_EXPR(Apply, Expr)
151151
EXPR_RANGE(Apply, Call, ConstructorRefCall)
152152
ABSTRACT_EXPR(ImplicitConversion, Expr)
153153
EXPR(Load, ImplicitConversionExpr)
154+
EXPR(ABISafeConversion, ImplicitConversionExpr)
154155
EXPR(DestructureTuple, ImplicitConversionExpr)
155156
EXPR(UnresolvedTypeConversion, ImplicitConversionExpr)
156157
EXPR(FunctionConversion, ImplicitConversionExpr)

include/swift/Sema/ConstraintSystem.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4530,7 +4530,8 @@ class ConstraintSystem {
45304530
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
45314531
DeclContext *UseDC,
45324532
ConstraintLocator *memberLocator = nullptr,
4533-
bool wantInterfaceType = false);
4533+
bool wantInterfaceType = false,
4534+
bool adjustForPreconcurrency = true);
45344535

45354536
/// Return the type-of-reference of the given value.
45364537
///
@@ -4552,6 +4553,7 @@ class ConstraintSystem {
45524553
llvm::function_ref<Type(VarDecl *)> getType,
45534554
ConstraintLocator *memberLocator = nullptr,
45544555
bool wantInterfaceType = false,
4556+
bool adjustForPreconcurrency = true,
45554557
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType =
45564558
[](const AbstractClosureExpr *) {
45574559
return Type();

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,6 +2265,11 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
22652265
printRec(E->getSubExpr());
22662266
PrintWithColorRAII(OS, ParenthesisColor) << ')';
22672267
}
2268+
void visitABISafeConversionExpr(ABISafeConversionExpr *E) {
2269+
printCommon(E, "abi_safe_conversion_expr") << '\n';
2270+
printRec(E->getSubExpr());
2271+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2272+
}
22682273
void visitMetatypeConversionExpr(MetatypeConversionExpr *E) {
22692274
printCommon(E, "metatype_conversion_expr") << '\n';
22702275
printRec(E->getSubExpr());

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4712,6 +4712,9 @@ void PrintAST::visitConstructorRefCallExpr(ConstructorRefCallExpr *expr) {
47124712
}
47134713
}
47144714

4715+
void PrintAST::visitABISafeConversionExpr(ABISafeConversionExpr *expr) {
4716+
}
4717+
47154718
void PrintAST::visitFunctionConversionExpr(FunctionConversionExpr *expr) {
47164719
}
47174720

lib/AST/ASTVerifier.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,17 @@ class Verifier : public ASTWalker {
240240
pushScope(DC);
241241
}
242242

243+
/// Emit an error message and abort, optionally dumping the expression.
244+
/// \param E if non-null, the expression to dump() followed by a new-line.
245+
void error(llvm::StringRef msg, Expr *E = nullptr) {
246+
Out << msg << "\n";
247+
if (E) {
248+
E->dump(Out);
249+
Out << "\n";
250+
}
251+
abort();
252+
}
253+
243254
public:
244255
Verifier(ModuleDecl *M, DeclContext *DC)
245256
: Verifier(PointerUnion<ModuleDecl *, SourceFile *>(M), DC) {}
@@ -2317,6 +2328,34 @@ class Verifier : public ASTWalker {
23172328
verifyCheckedBase(E);
23182329
}
23192330

2331+
void verifyChecked(ABISafeConversionExpr *E) {
2332+
PrettyStackTraceExpr debugStack(Ctx, "verify ABISafeConversionExpr", E);
2333+
2334+
auto toType = E->getType();
2335+
auto fromType = E->getSubExpr()->getType();
2336+
2337+
if (!fromType->hasLValueType())
2338+
error("conversion source must be an l-value", E);
2339+
2340+
if (!toType->hasLValueType())
2341+
error("conversion result must be an l-value", E);
2342+
2343+
{
2344+
// At the moment, "ABI Safe" means concurrency features can be stripped.
2345+
// Since we don't know how deeply the stripping is happening, to verify
2346+
// in a fuzzy way, strip everything to see if they're the same type.
2347+
auto strippedFrom = fromType->getRValueType()
2348+
->stripConcurrency(/*recurse*/true,
2349+
/*dropGlobalActor*/true);
2350+
auto strippedTo = toType->getRValueType()
2351+
->stripConcurrency(/*recurse*/true,
2352+
/*dropGlobalActor*/true);
2353+
2354+
if (!strippedFrom->isEqual(strippedTo))
2355+
error("possibly non-ABI safe conversion", E);
2356+
}
2357+
}
2358+
23202359
void verifyChecked(ValueDecl *VD) {
23212360
if (VD->getInterfaceType()->hasError()) {
23222361
Out << "checked decl cannot have error type\n";

lib/AST/Expr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
413413
PASS_THROUGH_REFERENCE(Load, getSubExpr);
414414
NO_REFERENCE(DestructureTuple);
415415
NO_REFERENCE(UnresolvedTypeConversion);
416+
PASS_THROUGH_REFERENCE(ABISafeConversion, getSubExpr);
416417
PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr);
417418
PASS_THROUGH_REFERENCE(CovariantFunctionConversion, getSubExpr);
418419
PASS_THROUGH_REFERENCE(CovariantReturnConversion, getSubExpr);
@@ -738,6 +739,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
738739
return false;
739740

740741
case ExprKind::Load:
742+
case ExprKind::ABISafeConversion:
741743
case ExprKind::DestructureTuple:
742744
case ExprKind::UnresolvedTypeConversion:
743745
case ExprKind::FunctionConversion:
@@ -909,6 +911,7 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
909911
case ExprKind::Load:
910912
case ExprKind::DestructureTuple:
911913
case ExprKind::UnresolvedTypeConversion:
914+
case ExprKind::ABISafeConversion:
912915
case ExprKind::FunctionConversion:
913916
case ExprKind::CovariantFunctionConversion:
914917
case ExprKind::CovariantReturnConversion:

lib/SILGen/LValue.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class PathComponent {
105105
CoroutineAccessorKind, // coroutine accessor
106106
ValueKind, // random base pointer as an lvalue
107107
PhysicalKeyPathApplicationKind, // applying a key path
108+
ABISafeConversionKind, // unchecked_addr_cast
108109

109110
// Logical LValue kinds
110111
GetterSetterKind, // property or subscript getter/setter

lib/SILGen/SILGenExpr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@ namespace {
443443
RValue visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E, SGFContext C);
444444
RValue visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E,
445445
SGFContext C);
446+
RValue visitABISafeConversionExpr(ABISafeConversionExpr *E, SGFContext C) {
447+
llvm_unreachable("cannot appear in rvalue");
448+
}
446449
RValue visitFunctionConversionExpr(FunctionConversionExpr *E,
447450
SGFContext C);
448451
RValue visitCovariantFunctionConversionExpr(

lib/SILGen/SILGenLValue.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenLValue
323323
LValue visitKeyPathApplicationExpr(KeyPathApplicationExpr *e,
324324
SGFAccessKind accessKind,
325325
LValueOptions options);
326+
LValue visitABISafeConversionExpr(ABISafeConversionExpr *e,
327+
SGFAccessKind accessKind,
328+
LValueOptions options);
326329

327330
// Expressions that wrap lvalues
328331

@@ -2200,6 +2203,29 @@ namespace {
22002203
OS.indent(indent) << "PhysicalKeyPathApplicationComponent\n";
22012204
}
22022205
};
2206+
2207+
/// A physical component which performs an unchecked_addr_cast
2208+
class ABISafeConversionComponent final : public PhysicalPathComponent {
2209+
public:
2210+
ABISafeConversionComponent(LValueTypeData typeData)
2211+
: PhysicalPathComponent(typeData, ABISafeConversionKind,
2212+
/*actorIsolation=*/None) {}
2213+
2214+
ManagedValue project(SILGenFunction &SGF, SILLocation loc,
2215+
ManagedValue base) && override {
2216+
auto toType = SGF.getLoweredType(getTypeData().SubstFormalType)
2217+
.getAddressType();
2218+
2219+
if (base.getType() == toType)
2220+
return base; // nothing to do
2221+
2222+
return SGF.B.createUncheckedAddrCast(loc, base, toType);
2223+
}
2224+
2225+
void dump(raw_ostream &OS, unsigned indent) const override {
2226+
OS.indent(indent) << "ABISafeConversionComponent\n";
2227+
}
2228+
};
22032229
} // end anonymous namespace
22042230

22052231
RValue
@@ -3709,6 +3735,17 @@ LValue SILGenLValue::visitInOutExpr(InOutExpr *e, SGFAccessKind accessKind,
37093735
return visitRec(e->getSubExpr(), accessKind, options);
37103736
}
37113737

3738+
LValue SILGenLValue::visitABISafeConversionExpr(ABISafeConversionExpr *e,
3739+
SGFAccessKind accessKind,
3740+
LValueOptions options) {
3741+
LValue lval = visitRec(e->getSubExpr(), accessKind, options);
3742+
auto typeData = getValueTypeData(SGF, accessKind, e);
3743+
3744+
lval.add<ABISafeConversionComponent>(typeData);
3745+
3746+
return lval;
3747+
}
3748+
37123749
/// Emit an lvalue that refers to the given property. This is
37133750
/// designed to work with ManagedValue 'base's that are either +0 or +1.
37143751
LValue SILGenFunction::emitPropertyLValue(SILLocation loc, ManagedValue base,

0 commit comments

Comments
 (0)