mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
SILGen: add RValue emission for BorrowExpr
This commit is contained in:
@@ -2508,6 +2508,24 @@ public:
|
|||||||
verifyCheckedBase(E);
|
verifyCheckedBase(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void verifyChecked(BorrowExpr *E) {
|
||||||
|
PrettyStackTraceExpr debugStack(Ctx, "verifying BorrowExpr", E);
|
||||||
|
|
||||||
|
auto toType = E->getType();
|
||||||
|
auto fromType = E->getSubExpr()->getType();
|
||||||
|
|
||||||
|
// FIXME: doesStorageProduceLValue should not return false for a 'let',
|
||||||
|
// so that you can borrow from it.
|
||||||
|
if (!fromType->hasLValueType())
|
||||||
|
error("borrow source must be an l-value", E);
|
||||||
|
|
||||||
|
// Result type can be either l-value or r-value.
|
||||||
|
// Ensure underlying type matches.
|
||||||
|
if (fromType->getRValueType()->getCanonicalType() !=
|
||||||
|
toType->getRValueType()->getCanonicalType())
|
||||||
|
error("borrow should not be performing a cast", E);
|
||||||
|
}
|
||||||
|
|
||||||
void verifyChecked(ABISafeConversionExpr *E) {
|
void verifyChecked(ABISafeConversionExpr *E) {
|
||||||
PrettyStackTraceExpr debugStack(Ctx, "verify ABISafeConversionExpr", E);
|
PrettyStackTraceExpr debugStack(Ctx, "verify ABISafeConversionExpr", E);
|
||||||
|
|
||||||
|
|||||||
@@ -468,6 +468,7 @@ namespace {
|
|||||||
|
|
||||||
RValue visitStringLiteralExpr(StringLiteralExpr *E, SGFContext C);
|
RValue visitStringLiteralExpr(StringLiteralExpr *E, SGFContext C);
|
||||||
RValue visitLoadExpr(LoadExpr *E, SGFContext C);
|
RValue visitLoadExpr(LoadExpr *E, SGFContext C);
|
||||||
|
RValue visitBorrowExpr(BorrowExpr *E, SGFContext C);
|
||||||
RValue visitDerivedToBaseExpr(DerivedToBaseExpr *E, SGFContext C);
|
RValue visitDerivedToBaseExpr(DerivedToBaseExpr *E, SGFContext C);
|
||||||
RValue visitMetatypeConversionExpr(MetatypeConversionExpr *E,
|
RValue visitMetatypeConversionExpr(MetatypeConversionExpr *E,
|
||||||
SGFContext C);
|
SGFContext C);
|
||||||
@@ -1103,6 +1104,24 @@ RValue RValueEmitter::visitLoadExpr(LoadExpr *E, SGFContext C) {
|
|||||||
C.withFollowingSideEffects());
|
C.withFollowingSideEffects());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RValue RValueEmitter::visitBorrowExpr(BorrowExpr *E, SGFContext C_Ignored) {
|
||||||
|
// NOTE: You should NOT add an evaluation scope here!
|
||||||
|
//
|
||||||
|
// The callers of this visitor should have established a scope already that
|
||||||
|
// encompasses the use of the borrowed RValue that we return.
|
||||||
|
ASSERT(SGF.isInFormalEvaluationScope() && "emit borrow_expr without scope?");
|
||||||
|
|
||||||
|
auto accessKind =
|
||||||
|
SGF.getTypeLowering(E->getType()).isAddress()
|
||||||
|
? SGFAccessKind::BorrowedAddressRead
|
||||||
|
: SGFAccessKind::BorrowedObjectRead;
|
||||||
|
|
||||||
|
LValue lv = SGF.emitLValue(E->getSubExpr(), accessKind);
|
||||||
|
auto substFormalType = lv.getSubstFormalType();
|
||||||
|
ManagedValue mv = SGF.emitBorrowedLValue(E, std::move(lv));
|
||||||
|
return RValue(SGF, E, substFormalType, mv);
|
||||||
|
}
|
||||||
|
|
||||||
SILValue SILGenFunction::emitTemporaryAllocation(SILLocation loc, SILType ty,
|
SILValue SILGenFunction::emitTemporaryAllocation(SILLocation loc, SILType ty,
|
||||||
HasDynamicLifetime_t dynamic,
|
HasDynamicLifetime_t dynamic,
|
||||||
IsLexical_t isLexical,
|
IsLexical_t isLexical,
|
||||||
|
|||||||
@@ -1131,6 +1131,16 @@ bool TypeChecker::checkedCastMaySucceed(Type t1, Type t2, DeclContext *dc) {
|
|||||||
return (kind != CheckedCastKind::Unresolved);
|
return (kind != CheckedCastKind::Unresolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
TypeChecker::addImplicitBorrowExpr(ASTContext &Ctx, Expr *E,
|
||||||
|
std::function<Type(Expr *)> getType,
|
||||||
|
std::function<void(Expr *, Type)> setType) {
|
||||||
|
auto objectType = getType(E)->getRValueType();
|
||||||
|
auto *BE = BorrowExpr::createImplicit(Ctx, E->getLoc(), E, objectType);
|
||||||
|
setType(BE, objectType);
|
||||||
|
return BE;
|
||||||
|
}
|
||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
TypeChecker::addImplicitLoadExpr(ASTContext &Context, Expr *expr,
|
TypeChecker::addImplicitLoadExpr(ASTContext &Context, Expr *expr,
|
||||||
std::function<Type(Expr *)> getType,
|
std::function<Type(Expr *)> getType,
|
||||||
|
|||||||
@@ -882,6 +882,12 @@ Expr *addImplicitLoadExpr(
|
|||||||
std::function<void(Expr *, Type)> setType =
|
std::function<void(Expr *, Type)> setType =
|
||||||
[](Expr *E, Type type) { E->setType(type); });
|
[](Expr *E, Type type) { E->setType(type); });
|
||||||
|
|
||||||
|
Expr *addImplicitBorrowExpr(
|
||||||
|
ASTContext &Context, Expr *expr,
|
||||||
|
std::function<Type(Expr *)> getType = [](Expr *E) { return E->getType(); },
|
||||||
|
std::function<void(Expr *, Type)> setType =
|
||||||
|
[](Expr *E, Type type) { E->setType(type); });
|
||||||
|
|
||||||
/// Determine whether the given type either conforms to, or itself an
|
/// Determine whether the given type either conforms to, or itself an
|
||||||
/// existential subtype of, the given protocol.
|
/// existential subtype of, the given protocol.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func asyncFunc(_ arg: String) async throws -> Int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
func testUnaryExprs() async throws {
|
func testUnaryExprs() async throws {
|
||||||
let str = String()
|
var str = String()
|
||||||
let foo = try await asyncFunc(_borrow str)
|
let foo = try await asyncFunc(_borrow str)
|
||||||
let bar = copy foo
|
let bar = copy foo
|
||||||
let baz = consume foo
|
let baz = consume foo
|
||||||
|
|||||||
@@ -5,11 +5,6 @@ func testGlobal() {
|
|||||||
let _ = _borrow global
|
let _ = _borrow global
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLet() {
|
|
||||||
let t = String()
|
|
||||||
let _ = _borrow t
|
|
||||||
}
|
|
||||||
|
|
||||||
func testVar() {
|
func testVar() {
|
||||||
var t = String()
|
var t = String()
|
||||||
t = String()
|
t = String()
|
||||||
|
|||||||
Reference in New Issue
Block a user