Merge pull request #61887 from nate-chandler/opaque-values/1/20221102

[OpaqueValues] Handle Builtin.addressOfBorrow.
This commit is contained in:
nate-chandler
2022-11-03 14:46:02 -07:00
committed by GitHub
8 changed files with 71 additions and 0 deletions

View File

@@ -915,6 +915,24 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(EndAsyncLet, "endAsyncLet", "", Special)
/// until the endAsyncLet.
BUILTIN_MISC_OPERATION(EndAsyncLetLifetime, "endAsyncLetLifetime", "", Special)
/// addressOfBorrowOpaque (__shared T) -> Builtin.RawPointer
/// Returns a RawPointer pointing to a borrowed rvalue. The returned pointer is
/// only valid within the scope of the borrow.
///
/// Differs from addressOfBorrow only in that it is not lowered until
/// AddressLowering.
BUILTIN_MISC_OPERATION(AddressOfBorrowOpaque, "addressOfBorrowOpaque", "", Special)
/// unprotectedAddressOfBorrowOpaque (__shared T) -> Builtin.RawPointer
/// Returns a RawPointer pointing to a borrowed rvalue. The returned pointer is only
/// valid within the scope of the borrow.
/// In contrast to `addressOfBorrowOpaque`, this builtin doesn't trigger an
/// insertion of stack protectors.
///
/// Differs from unprotectedAddressOfBorrow only in that it is not lowered until
/// AddressLowering.
BUILTIN_MISC_OPERATION(UnprotectedAddressOfBorrowOpaque, "unprotectedAddressOfBorrowOpaque", "", Special)
/// createAsyncTask(): (
/// Int, // task-creation flags
/// @escaping () async throws -> T // function

View File

@@ -2701,7 +2701,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
return getLegacyCondFailOperation(Context, Id);
case BuiltinValueKind::AddressOfBorrow:
case BuiltinValueKind::AddressOfBorrowOpaque:
case BuiltinValueKind::UnprotectedAddressOfBorrow:
case BuiltinValueKind::UnprotectedAddressOfBorrowOpaque:
if (!Types.empty()) return nullptr;
return getAddressOfBorrowOperation(Context, Id);

View File

@@ -678,6 +678,8 @@ struct OperandOwnershipBuiltinClassifier
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, ErrorInMain)
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, UnexpectedError)
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, WillThrow)
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, AddressOfBorrowOpaque)
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, UnprotectedAddressOfBorrowOpaque)
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, AShr)
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, GenericAShr)
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, Add)

View File

@@ -382,6 +382,8 @@ struct ValueOwnershipKindBuiltinVisitor
// This returns a value at +1 that is destroyed strictly /after/ the
// UnsafeGuaranteedEnd. This provides the guarantee that we want.
CONSTANT_OWNERSHIP_BUILTIN(Owned, COWBufferForReading)
CONSTANT_OWNERSHIP_BUILTIN(None, AddressOfBorrowOpaque)
CONSTANT_OWNERSHIP_BUILTIN(None, UnprotectedAddressOfBorrowOpaque)
CONSTANT_OWNERSHIP_BUILTIN(None, AShr)
CONSTANT_OWNERSHIP_BUILTIN(None, GenericAShr)
CONSTANT_OWNERSHIP_BUILTIN(None, Add)

View File

@@ -478,6 +478,17 @@ static ManagedValue emitBuiltinAddressOfBorrowBuiltins(SILGenFunction &SGF,
// naturally emitted borrowed in memory.
auto borrow = SGF.emitRValue(argument, SGFContext::AllowGuaranteedPlusZero)
.getAsSingleValue(SGF, argument);
if (!SGF.F.getConventions().useLoweredAddresses()) {
auto &context = SGF.getASTContext();
auto identifier =
stackProtected
? context.getIdentifier("addressOfBorrowOpaque")
: context.getIdentifier("unprotectedAddressOfBorrowOpaque");
auto builtin = SGF.B.createBuiltin(loc, identifier, rawPointerType,
substitutions, {borrow.getValue()});
return ManagedValue::forUnmanaged(builtin);
}
if (!borrow.isPlusZero() || !borrow.getType().isAddress()) {
SGF.SGM.diagnose(argument->getLoc(), diag::non_borrowed_indirect_addressof);
return SGF.emitUndef(rawPointerType);

View File

@@ -2617,6 +2617,16 @@ protected:
vmi->setOperand(opAddr);
}
void visitAddressOfBorrowBuiltinInst(BuiltinInst *bi, bool stackProtected) {
SILValue value = bi->getOperand(0);
SILValue addr = pass.valueStorageMap.getStorage(value).storageAddress;
auto &astCtx = pass.getModule()->getASTContext();
SILType rawPointerType = SILType::getRawPointerType(astCtx);
SILValue result = builder.createAddressToPointer(
bi->getLoc(), addr, rawPointerType, stackProtected);
bi->replaceAllUsesWith(result);
}
void visitBuiltinInst(BuiltinInst *bi) {
switch (bi->getBuiltinKind().getValueOr(BuiltinValueKind::None)) {
case BuiltinValueKind::Copy: {
@@ -2624,6 +2634,12 @@ protected:
bi->setOperand(0, opAddr);
break;
}
case BuiltinValueKind::AddressOfBorrowOpaque:
visitAddressOfBorrowBuiltinInst(bi, /*stackProtected=*/true);
break;
case BuiltinValueKind::UnprotectedAddressOfBorrowOpaque:
visitAddressOfBorrowBuiltinInst(bi, /*stackProtected=*/false);
break;
default:
bi->dump();
llvm::report_fatal_error("^^^ Unimplemented builtin opaque value use.");

View File

@@ -193,6 +193,8 @@ static bool isBarrier(SILInstruction *inst) {
case BuiltinValueKind::ResumeThrowingContinuationThrowing:
case BuiltinValueKind::AutoDiffProjectTopLevelSubcontext:
case BuiltinValueKind::AutoDiffAllocateSubcontext:
case BuiltinValueKind::AddressOfBorrowOpaque:
case BuiltinValueKind::UnprotectedAddressOfBorrowOpaque:
return true;
}
}

View File

@@ -31,4 +31,22 @@ public func _copy<T>(_ value: T) -> T {
#endif
}
// CHECK-LABEL: sil hidden @getRawPointer : {{.*}} {
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] : $*T):
// CHECK: [[PTR:%[^,]+]] = address_to_pointer [stack_protection] [[ADDR]]
// CHECK: return [[PTR]]
// CHECK-LABEL: } // end sil function 'getRawPointer'
@_silgen_name("getRawPointer")
func getRawPointer<T>(to value: T) -> Builtin.RawPointer {
return Builtin.addressOfBorrow(value)
}
// CHECK-LABEL: sil hidden @getUnprotectedRawPointer : {{.*}} {
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] : $*T):
// CHECK: [[PTR:%[^,]+]] = address_to_pointer [[ADDR]]
// CHECK: return [[PTR]]
// CHECK-LABEL: } // end sil function 'getUnprotectedRawPointer'
@_silgen_name("getUnprotectedRawPointer")
func getUnprotectedRawPointer<T>(to value: T) -> Builtin.RawPointer {
return Builtin.unprotectedAddressOfBorrow(value)
}