Skip to content

Commit 36bf2ae

Browse files
authored
Merge pull request #72592 from Azoy/raw-layout-inst
[IRGen] Add Builtin.addressOfRawLayout
2 parents 576a4ba + e1ec457 commit 36bf2ae

File tree

15 files changed

+142
-19
lines changed

15 files changed

+142
-19
lines changed

include/swift/AST/Builtins.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,19 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(InjectEnumTag, "injectEnumTag", "", Special)
11071107
/// `any Actor` existential that refers to the local actor.
11081108
BUILTIN_MISC_OPERATION_WITH_SILGEN(DistributedActorAsAnyActor, "distributedActorAsAnyActor", "n", Special)
11091109

1110+
/// addressOfRawLayout: <T: ~Copyable>(_: borrowing T) -> Builtin.RawPointer
1111+
///
1112+
/// Returns a raw pointer to the address of the raw layout type. This address is
1113+
/// only valid during a borrow access of the raw layout type or until the value
1114+
/// is either moved or consumed.
1115+
///
1116+
/// Note: The purpose of this builtin is to get an opaque pointer to the address
1117+
/// of the raw layout type. We explicitly do not want the optimizer looking into
1118+
/// this pointer or address thereof to start assuming things about mutability or
1119+
/// immutability. This builtin _must_ persist throughout all of SIL and must be
1120+
/// lowered away at IRGen, no sooner.
1121+
BUILTIN_MISC_OPERATION_WITH_SILGEN(AddressOfRawLayout, "addressOfRawLayout", "n", Special)
1122+
11101123
/// Builtins for instrumentation added by sanitizers during SILGen.
11111124
#ifndef BUILTIN_SANITIZER_OPERATION
11121125
#define BUILTIN_SANITIZER_OPERATION(Id, Name, Attrs) BUILTIN(Id, Name, Attrs)

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ LANGUAGE_FEATURE(ExpressionMacroDefaultArguments, 422, "Expression macro as call
175175
LANGUAGE_FEATURE(BuiltinStoreRaw, 0, "Builtin.storeRaw")
176176
LANGUAGE_FEATURE(BuiltinCreateTask, 0, "Builtin.createTask and Builtin.createDiscardingTask")
177177
SUPPRESSIBLE_LANGUAGE_FEATURE(AssociatedTypeImplements, 0, "@_implements on associated types")
178+
LANGUAGE_FEATURE(BuiltinAddressOfRawLayout, 0, "Builtin.addressOfRawLayout")
178179

179180
// Swift 6
180181
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)

include/swift/SIL/AddressWalker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ TransitiveAddressWalker<Impl>::walk(SILValue projectedAddress) && {
276276
case BuiltinValueKind::ZeroInitializer:
277277
case BuiltinValueKind::GetEnumTag:
278278
case BuiltinValueKind::InjectEnumTag:
279+
case BuiltinValueKind::AddressOfRawLayout:
279280
callVisitUse(op);
280281
continue;
281282
default:

lib/AST/Builtins.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,6 +2141,15 @@ static ValueDecl *getInjectEnumTag(ASTContext &ctx, Identifier id) {
21412141
return builder.build(id);
21422142
}
21432143

2144+
static ValueDecl *getAddressOfRawLayout(ASTContext &ctx, Identifier id) {
2145+
BuiltinFunctionBuilder builder(ctx, /* genericParamCount */ 1);
2146+
2147+
builder.addParameter(makeGenericParam(), ParamSpecifier::Borrowing);
2148+
builder.setResult(makeConcrete(ctx.TheRawPointerType));
2149+
2150+
return builder.build(id);
2151+
}
2152+
21442153
/// An array of the overloaded builtin kinds.
21452154
static const OverloadedBuiltinKind OverloadedBuiltinKinds[] = {
21462155
OverloadedBuiltinKind::None,
@@ -3214,6 +3223,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
32143223

32153224
case BuiltinValueKind::DistributedActorAsAnyActor:
32163225
return getDistributedActorAsAnyActor(Context, Id);
3226+
3227+
case BuiltinValueKind::AddressOfRawLayout:
3228+
return getAddressOfRawLayout(Context, Id);
32173229
}
32183230

32193231
llvm_unreachable("bad builtin value!");

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ static bool usesFeatureExpressionMacroDefaultArguments(Decl *decl) {
359359
}
360360

361361
UNINTERESTING_FEATURE(BuiltinStoreRaw)
362+
UNINTERESTING_FEATURE(BuiltinAddressOfRawLayout)
362363

363364
// ----------------------------------------------------------------------------
364365
// MARK: - Upcoming Features

lib/IRGen/GenBuiltin.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,5 +1488,15 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
14881488
return;
14891489
}
14901490

1491+
// LLVM must not see the address generated here as 'invariant' or immutable
1492+
// ever. A raw layout's address defies all formal access, so immutable looking
1493+
// uses may actually mutate the underlying value!
1494+
if (Builtin.ID == BuiltinValueKind::AddressOfRawLayout) {
1495+
auto addr = args.claimNext();
1496+
auto value = IGF.Builder.CreateBitCast(addr, IGF.IGM.Int8PtrTy);
1497+
out.add(value);
1498+
return;
1499+
}
1500+
14911501
llvm_unreachable("IRGen unimplemented for this builtin!");
14921502
}

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,7 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, TargetOSVersionAtLeast)
892892
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, GetEnumTag)
893893
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, InjectEnumTag)
894894
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, DistributedActorAsAnyActor)
895+
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, AddressOfRawLayout)
895896
OperandOwnership OperandOwnershipBuiltinClassifier::visitCopy(BuiltinInst *bi,
896897
StringRef) {
897898
if (bi->getFunction()->getConventions().useLoweredAddresses()) {

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@ CONSTANT_OWNERSHIP_BUILTIN(None, GetEnumTag)
633633
CONSTANT_OWNERSHIP_BUILTIN(None, InjectEnumTag)
634634
CONSTANT_OWNERSHIP_BUILTIN(Owned, DistributedActorAsAnyActor)
635635
CONSTANT_OWNERSHIP_BUILTIN(Guaranteed, ExtractFunctionIsolation) // unreachable
636+
CONSTANT_OWNERSHIP_BUILTIN(None, AddressOfRawLayout)
636637

637638
#undef CONSTANT_OWNERSHIP_BUILTIN
638639

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,6 +2667,7 @@ static void visitBuiltinAddress(BuiltinInst *builtin,
26672667
// These builtins take a generic 'T' as their operand.
26682668
case BuiltinValueKind::GetEnumTag:
26692669
case BuiltinValueKind::InjectEnumTag:
2670+
case BuiltinValueKind::AddressOfRawLayout:
26702671
visitor(&builtin->getAllOperands()[0]);
26712672
return;
26722673

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,12 @@ struct ImmutableAddressUseVerifier {
600600
if (builtinKind == BuiltinValueKind::GetEnumTag) {
601601
return false;
602602
}
603+
604+
// The optimizer cannot reason about a raw layout type's address due
605+
// to it not respecting formal access scopes.
606+
if (builtinKind == BuiltinValueKind::AddressOfRawLayout) {
607+
return false;
608+
}
603609
}
604610

605611
// Otherwise this is a builtin that we are not expecting to see, so bail

0 commit comments

Comments
 (0)