Skip to content

Commit a66951a

Browse files
authored
Merge pull request #60521 from kavon/preconcurrency-var-access
Add missing function conversion for member access to preconcurrency vardecl.
2 parents 506cccc + a4d661d commit a66951a

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
@@ -3097,6 +3097,19 @@ class LoadExpr : public ImplicitConversionExpr {
30973097
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Load; }
30983098
};
30993099

3100+
/// ABISafeConversion - models a type conversion on an l-value that has no
3101+
/// material affect on the ABI of the type, while *preserving* the l-valueness
3102+
/// of the type.
3103+
class ABISafeConversionExpr : public ImplicitConversionExpr {
3104+
public:
3105+
ABISafeConversionExpr(Expr *subExpr, Type type)
3106+
: ImplicitConversionExpr(ExprKind::ABISafeConversion, subExpr, type) {}
3107+
3108+
static bool classof(const Expr *E) {
3109+
return E->getKind() == ExprKind::ABISafeConversion;
3110+
}
3111+
};
3112+
31003113
/// This is a conversion from an expression of UnresolvedType to an arbitrary
31013114
/// other type, and from an arbitrary type to UnresolvedType. This node does
31023115
/// 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
@@ -152,6 +152,7 @@ ABSTRACT_EXPR(Apply, Expr)
152152
EXPR_RANGE(Apply, Call, ConstructorRefCall)
153153
ABSTRACT_EXPR(ImplicitConversion, Expr)
154154
EXPR(Load, ImplicitConversionExpr)
155+
EXPR(ABISafeConversion, ImplicitConversionExpr)
155156
EXPR(DestructureTuple, ImplicitConversionExpr)
156157
EXPR(UnresolvedTypeConversion, ImplicitConversionExpr)
157158
EXPR(FunctionConversion, ImplicitConversionExpr)

include/swift/Sema/ConstraintSystem.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4764,7 +4764,8 @@ class ConstraintSystem {
47644764
Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
47654765
DeclContext *UseDC,
47664766
ConstraintLocator *memberLocator = nullptr,
4767-
bool wantInterfaceType = false);
4767+
bool wantInterfaceType = false,
4768+
bool adjustForPreconcurrency = true);
47684769

47694770
/// Return the type-of-reference of the given value.
47704771
///
@@ -4786,6 +4787,7 @@ class ConstraintSystem {
47864787
llvm::function_ref<Type(VarDecl *)> getType,
47874788
ConstraintLocator *memberLocator = nullptr,
47884789
bool wantInterfaceType = false,
4790+
bool adjustForPreconcurrency = true,
47894791
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType =
47904792
[](const AbstractClosureExpr *) {
47914793
return Type();

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,11 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
22982298
printRec(E->getSubExpr());
22992299
PrintWithColorRAII(OS, ParenthesisColor) << ')';
23002300
}
2301+
void visitABISafeConversionExpr(ABISafeConversionExpr *E) {
2302+
printCommon(E, "abi_safe_conversion_expr") << '\n';
2303+
printRec(E->getSubExpr());
2304+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2305+
}
23012306
void visitMetatypeConversionExpr(MetatypeConversionExpr *E) {
23022307
printCommon(E, "metatype_conversion_expr") << '\n';
23032308
printRec(E->getSubExpr());

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4811,6 +4811,9 @@ void PrintAST::visitConstructorRefCallExpr(ConstructorRefCallExpr *expr) {
48114811
}
48124812
}
48134813

4814+
void PrintAST::visitABISafeConversionExpr(ABISafeConversionExpr *expr) {
4815+
}
4816+
48144817
void PrintAST::visitFunctionConversionExpr(FunctionConversionExpr *expr) {
48154818
}
48164819

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) {}
@@ -2306,6 +2317,34 @@ class Verifier : public ASTWalker {
23062317
verifyCheckedBase(E);
23072318
}
23082319

2320+
void verifyChecked(ABISafeConversionExpr *E) {
2321+
PrettyStackTraceExpr debugStack(Ctx, "verify ABISafeConversionExpr", E);
2322+
2323+
auto toType = E->getType();
2324+
auto fromType = E->getSubExpr()->getType();
2325+
2326+
if (!fromType->hasLValueType())
2327+
error("conversion source must be an l-value", E);
2328+
2329+
if (!toType->hasLValueType())
2330+
error("conversion result must be an l-value", E);
2331+
2332+
{
2333+
// At the moment, "ABI Safe" means concurrency features can be stripped.
2334+
// Since we don't know how deeply the stripping is happening, to verify
2335+
// in a fuzzy way, strip everything to see if they're the same type.
2336+
auto strippedFrom = fromType->getRValueType()
2337+
->stripConcurrency(/*recurse*/true,
2338+
/*dropGlobalActor*/true);
2339+
auto strippedTo = toType->getRValueType()
2340+
->stripConcurrency(/*recurse*/true,
2341+
/*dropGlobalActor*/true);
2342+
2343+
if (!strippedFrom->isEqual(strippedTo))
2344+
error("possibly non-ABI safe conversion", E);
2345+
}
2346+
}
2347+
23092348
void verifyChecked(ValueDecl *VD) {
23102349
if (VD->getInterfaceType()->hasError()) {
23112350
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
@@ -414,6 +414,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
414414
PASS_THROUGH_REFERENCE(Load, getSubExpr);
415415
NO_REFERENCE(DestructureTuple);
416416
NO_REFERENCE(UnresolvedTypeConversion);
417+
PASS_THROUGH_REFERENCE(ABISafeConversion, getSubExpr);
417418
PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr);
418419
PASS_THROUGH_REFERENCE(CovariantFunctionConversion, getSubExpr);
419420
PASS_THROUGH_REFERENCE(CovariantReturnConversion, getSubExpr);
@@ -741,6 +742,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
741742
return false;
742743

743744
case ExprKind::Load:
745+
case ExprKind::ABISafeConversion:
744746
case ExprKind::DestructureTuple:
745747
case ExprKind::UnresolvedTypeConversion:
746748
case ExprKind::FunctionConversion:
@@ -914,6 +916,7 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
914916
case ExprKind::Load:
915917
case ExprKind::DestructureTuple:
916918
case ExprKind::UnresolvedTypeConversion:
919+
case ExprKind::ABISafeConversion:
917920
case ExprKind::FunctionConversion:
918921
case ExprKind::CovariantFunctionConversion:
919922
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
@@ -453,6 +453,9 @@ namespace {
453453
RValue visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E, SGFContext C);
454454
RValue visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E,
455455
SGFContext C);
456+
RValue visitABISafeConversionExpr(ABISafeConversionExpr *E, SGFContext C) {
457+
llvm_unreachable("cannot appear in rvalue");
458+
}
456459
RValue visitFunctionConversionExpr(FunctionConversionExpr *E,
457460
SGFContext C);
458461
RValue visitCovariantFunctionConversionExpr(

lib/SILGen/SILGenLValue.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenLValue
327327
LValueOptions options);
328328
LValue visitMoveExpr(MoveExpr *e, SGFAccessKind accessKind,
329329
LValueOptions options);
330+
LValue visitABISafeConversionExpr(ABISafeConversionExpr *e,
331+
SGFAccessKind accessKind,
332+
LValueOptions options);
330333

331334
// Expressions that wrap lvalues
332335

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

21992225
RValue
@@ -3724,6 +3750,17 @@ LValue SILGenLValue::visitMoveExpr(MoveExpr *e, SGFAccessKind accessKind,
37243750
toAddr->getType().getASTType());
37253751
}
37263752

3753+
LValue SILGenLValue::visitABISafeConversionExpr(ABISafeConversionExpr *e,
3754+
SGFAccessKind accessKind,
3755+
LValueOptions options) {
3756+
LValue lval = visitRec(e->getSubExpr(), accessKind, options);
3757+
auto typeData = getValueTypeData(SGF, accessKind, e);
3758+
3759+
lval.add<ABISafeConversionComponent>(typeData);
3760+
3761+
return lval;
3762+
}
3763+
37273764
/// Emit an lvalue that refers to the given property. This is
37283765
/// designed to work with ManagedValue 'base's that are either +0 or +1.
37293766
LValue SILGenFunction::emitPropertyLValue(SILLocation loc, ManagedValue base,

0 commit comments

Comments
 (0)