Skip to content

Commit 94c077a

Browse files
authored
Merge pull request swiftlang#73957 from Azoy/60-address-of-raw-layout
[6.0] [IRGen] Add Builtin.addressOfRawLayout
2 parents 9746fe7 + 15c5df4 commit 94c077a

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
@@ -196,6 +196,7 @@ SUPPRESSIBLE_LANGUAGE_FEATURE(NoncopyableGenerics, 427, "Noncopyable generics")
196196
SUPPRESSIBLE_LANGUAGE_FEATURE(ConformanceSuppression, 426, "Suppressible inferred conformances")
197197
SUPPRESSIBLE_LANGUAGE_FEATURE(BitwiseCopyable2, 426, "BitwiseCopyable feature")
198198
LANGUAGE_FEATURE(BodyMacros, 415, "Function body macros")
199+
LANGUAGE_FEATURE(BuiltinAddressOfRawLayout, 0, "Builtin.addressOfRawLayout")
199200

200201
// Swift 6
201202
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
@@ -1498,5 +1498,15 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
14981498
return;
14991499
}
15001500

1501+
// LLVM must not see the address generated here as 'invariant' or immutable
1502+
// ever. A raw layout's address defies all formal access, so immutable looking
1503+
// uses may actually mutate the underlying value!
1504+
if (Builtin.ID == BuiltinValueKind::AddressOfRawLayout) {
1505+
auto addr = args.claimNext();
1506+
auto value = IGF.Builder.CreateBitCast(addr, IGF.IGM.Int8PtrTy);
1507+
out.add(value);
1508+
return;
1509+
}
1510+
15011511
llvm_unreachable("IRGen unimplemented for this builtin!");
15021512
}

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
@@ -620,6 +620,7 @@ CONSTANT_OWNERSHIP_BUILTIN(None, GetEnumTag)
620620
CONSTANT_OWNERSHIP_BUILTIN(None, InjectEnumTag)
621621
CONSTANT_OWNERSHIP_BUILTIN(Owned, DistributedActorAsAnyActor)
622622
CONSTANT_OWNERSHIP_BUILTIN(Guaranteed, ExtractFunctionIsolation) // unreachable
623+
CONSTANT_OWNERSHIP_BUILTIN(None, AddressOfRawLayout)
623624

624625
#undef CONSTANT_OWNERSHIP_BUILTIN
625626

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
@@ -611,6 +611,12 @@ struct ImmutableAddressUseVerifier {
611611
if (builtinKind == BuiltinValueKind::GetEnumTag) {
612612
return false;
613613
}
614+
615+
// The optimizer cannot reason about a raw layout type's address due
616+
// to it not respecting formal access scopes.
617+
if (builtinKind == BuiltinValueKind::AddressOfRawLayout) {
618+
return false;
619+
}
614620
}
615621

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

0 commit comments

Comments
 (0)