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);
|
||||
}
|
||||
|
||||
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) {
|
||||
PrettyStackTraceExpr debugStack(Ctx, "verify ABISafeConversionExpr", E);
|
||||
|
||||
|
||||
@@ -468,6 +468,7 @@ namespace {
|
||||
|
||||
RValue visitStringLiteralExpr(StringLiteralExpr *E, SGFContext C);
|
||||
RValue visitLoadExpr(LoadExpr *E, SGFContext C);
|
||||
RValue visitBorrowExpr(BorrowExpr *E, SGFContext C);
|
||||
RValue visitDerivedToBaseExpr(DerivedToBaseExpr *E, SGFContext C);
|
||||
RValue visitMetatypeConversionExpr(MetatypeConversionExpr *E,
|
||||
SGFContext C);
|
||||
@@ -1103,6 +1104,24 @@ RValue RValueEmitter::visitLoadExpr(LoadExpr *E, SGFContext C) {
|
||||
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,
|
||||
HasDynamicLifetime_t dynamic,
|
||||
IsLexical_t isLexical,
|
||||
|
||||
@@ -1131,6 +1131,16 @@ bool TypeChecker::checkedCastMaySucceed(Type t1, Type t2, DeclContext *dc) {
|
||||
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 *
|
||||
TypeChecker::addImplicitLoadExpr(ASTContext &Context, Expr *expr,
|
||||
std::function<Type(Expr *)> getType,
|
||||
|
||||
@@ -882,6 +882,12 @@ Expr *addImplicitLoadExpr(
|
||||
std::function<void(Expr *, Type)> setType =
|
||||
[](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
|
||||
/// existential subtype of, the given protocol.
|
||||
///
|
||||
|
||||
@@ -83,7 +83,7 @@ func asyncFunc(_ arg: String) async throws -> Int {
|
||||
return 1
|
||||
}
|
||||
func testUnaryExprs() async throws {
|
||||
let str = String()
|
||||
var str = String()
|
||||
let foo = try await asyncFunc(_borrow str)
|
||||
let bar = copy foo
|
||||
let baz = consume foo
|
||||
|
||||
@@ -5,11 +5,6 @@ func testGlobal() {
|
||||
let _ = _borrow global
|
||||
}
|
||||
|
||||
func testLet() {
|
||||
let t = String()
|
||||
let _ = _borrow t
|
||||
}
|
||||
|
||||
func testVar() {
|
||||
var t = String()
|
||||
t = String()
|
||||
|
||||
Reference in New Issue
Block a user