Skip to content

Commit 21480b8

Browse files
authored
Merge pull request #80708 from atrick/irgen-addressable
Fix IRGen for @_addressable params which may be "captured".
2 parents 3490c73 + 2d9df8f commit 21480b8

File tree

4 files changed

+97
-25
lines changed

4 files changed

+97
-25
lines changed

include/swift/AST/Types.h

+15
Original file line numberDiff line numberDiff line change
@@ -5452,6 +5452,10 @@ class SILFunctionType final
54525452
return getParameters().back();
54535453
}
54545454

5455+
unsigned getSelfParameterIndex() const {
5456+
return NumParameters - 1;
5457+
}
5458+
54555459
/// Return SILParameterInfo for the isolated parameter in this SILFunctionType
54565460
/// if one exists. Returns None otherwise.
54575461
std::optional<SILParameterInfo> maybeGetIsolatedParameter() const {
@@ -5656,6 +5660,17 @@ class SILFunctionType final
56565660
/// Defined in SILType.cpp.
56575661
bool isAddressable(unsigned paramIdx, SILFunction *caller);
56585662

5663+
/// Return true of the specified parameter is addressable based on its type
5664+
/// lowering. This includes @_addressableForDependencies parameter types.
5665+
///
5666+
/// 'genericEnv' may be null.
5667+
///
5668+
/// Defined in SILType.cpp.
5669+
bool isAddressable(unsigned paramIdx, SILModule &module,
5670+
GenericEnvironment *genericEnv,
5671+
Lowering::TypeConverter &typeConverter,
5672+
TypeExpansionContext expansion);
5673+
56595674
/// Returns true if the function type stores a Clang type that cannot
56605675
/// be derived from its Swift type. Returns false otherwise, including if
56615676
/// the function type is not @convention(c) or @convention(block).

lib/IRGen/GenCall.cpp

+32-19
Original file line numberDiff line numberDiff line change
@@ -305,13 +305,14 @@ static void addDereferenceableAttributeToBuilder(IRGenModule &IGM,
305305
static void addIndirectValueParameterAttributes(IRGenModule &IGM,
306306
llvm::AttributeList &attrs,
307307
const TypeInfo &ti,
308-
unsigned argIndex) {
308+
unsigned argIndex,
309+
bool addressable) {
309310
llvm::AttrBuilder b(IGM.getLLVMContext());
310311
// Value parameter pointers can't alias or be captured.
311312
b.addAttribute(llvm::Attribute::NoAlias);
312313
// Bitwise takable value types are guaranteed not to capture
313314
// a pointer into itself.
314-
if (ti.isBitwiseTakable(ResilienceExpansion::Maximal))
315+
if (!addressable && ti.isBitwiseTakable(ResilienceExpansion::Maximal))
315316
b.addAttribute(llvm::Attribute::NoCapture);
316317
// The parameter must reference dereferenceable memory of the type.
317318
addDereferenceableAttributeToBuilder(IGM, b, ti);
@@ -340,7 +341,7 @@ static void addPackParameterAttributes(IRGenModule &IGM,
340341
static void addInoutParameterAttributes(IRGenModule &IGM, SILType paramSILType,
341342
llvm::AttributeList &attrs,
342343
const TypeInfo &ti, unsigned argIndex,
343-
bool aliasable) {
344+
bool aliasable, bool addressable) {
344345
llvm::AttrBuilder b(IGM.getLLVMContext());
345346
// Thanks to exclusivity checking, it is not possible to alias inouts except
346347
// those that are inout_aliasable.
@@ -351,7 +352,7 @@ static void addInoutParameterAttributes(IRGenModule &IGM, SILType paramSILType,
351352
}
352353
// Bitwise takable value types are guaranteed not to capture
353354
// a pointer into itself.
354-
if (ti.isBitwiseTakable(ResilienceExpansion::Maximal))
355+
if (!addressable && ti.isBitwiseTakable(ResilienceExpansion::Maximal))
355356
b.addAttribute(llvm::Attribute::NoCapture);
356357
// The inout must reference dereferenceable memory of the type.
357358
addDereferenceableAttributeToBuilder(IGM, b, ti);
@@ -600,9 +601,11 @@ namespace {
600601
Signature getSignature();
601602

602603
private:
603-
const TypeInfo &expand(SILParameterInfo param);
604+
const TypeInfo &expand(unsigned paramIdx);
604605
llvm::Type *addIndirectResult(SILType resultType, bool useInReg = false);
605606

607+
bool isAddressableParam(unsigned paramIdx);
608+
606609
SILFunctionConventions getSILFuncConventions() const {
607610
return SILFunctionConventions(FnType, IGM.getSILModule());
608611
}
@@ -1781,24 +1784,27 @@ static ArrayRef<llvm::Type *> expandScalarOrStructTypeToArray(llvm::Type *&ty) {
17811784
return expandedTys;
17821785
}
17831786

1784-
const TypeInfo &SignatureExpansion::expand(SILParameterInfo param) {
1787+
const TypeInfo &SignatureExpansion::expand(unsigned paramIdx) {
1788+
auto param = FnType->getParameters()[paramIdx];
17851789
auto paramSILType = getSILFuncConventions().getSILType(
17861790
param, IGM.getMaximalTypeExpansionContext());
17871791
auto &ti = IGM.getTypeInfo(paramSILType);
17881792
switch (auto conv = param.getConvention()) {
17891793
case ParameterConvention::Indirect_In:
17901794
case ParameterConvention::Indirect_In_Guaranteed:
17911795
case ParameterConvention::Indirect_In_CXX:
1792-
addIndirectValueParameterAttributes(IGM, Attrs, ti, ParamIRTypes.size());
1796+
addIndirectValueParameterAttributes(IGM, Attrs, ti, ParamIRTypes.size(),
1797+
isAddressableParam(paramIdx));
17931798
addPointerParameter(IGM.getStorageType(getSILFuncConventions().getSILType(
17941799
param, IGM.getMaximalTypeExpansionContext())));
17951800
return ti;
17961801

17971802
case ParameterConvention::Indirect_Inout:
17981803
case ParameterConvention::Indirect_InoutAliasable:
17991804
addInoutParameterAttributes(
1800-
IGM, paramSILType, Attrs, ti, ParamIRTypes.size(),
1801-
conv == ParameterConvention::Indirect_InoutAliasable);
1805+
IGM, paramSILType, Attrs, ti, ParamIRTypes.size(),
1806+
conv == ParameterConvention::Indirect_InoutAliasable,
1807+
isAddressableParam(paramIdx));
18021808
addPointerParameter(IGM.getStorageType(getSILFuncConventions().getSILType(
18031809
param, IGM.getMaximalTypeExpansionContext())));
18041810
return ti;
@@ -1822,7 +1828,8 @@ const TypeInfo &SignatureExpansion::expand(SILParameterInfo param) {
18221828
auto &nativeSchema = ti.nativeParameterValueSchema(IGM);
18231829
if (nativeSchema.requiresIndirect()) {
18241830
addIndirectValueParameterAttributes(IGM, Attrs, ti,
1825-
ParamIRTypes.size());
1831+
ParamIRTypes.size(),
1832+
/*addressable*/ false);
18261833
ParamIRTypes.push_back(ti.getStorageType()->getPointerTo());
18271834
return ti;
18281835
}
@@ -1842,6 +1849,13 @@ const TypeInfo &SignatureExpansion::expand(SILParameterInfo param) {
18421849
llvm_unreachable("bad parameter convention");
18431850
}
18441851

1852+
bool SignatureExpansion::isAddressableParam(unsigned paramIdx) {
1853+
return FnType->isAddressable(paramIdx, IGM.IRGen.SIL,
1854+
IGM.getGenericEnvironment(),
1855+
IGM.getSILTypes(),
1856+
IGM.getMaximalTypeExpansionContext());
1857+
}
1858+
18451859
/// Does the given function type have a self parameter that should be
18461860
/// given the special treatment for self parameters?
18471861
///
@@ -1887,7 +1901,6 @@ static void addParamInfo(SignatureExpansionABIDetails *details,
18871901
}
18881902

18891903
void SignatureExpansion::expandKeyPathAccessorParameters() {
1890-
auto params = FnType->getParameters();
18911904
unsigned numArgsToExpand;
18921905
SmallVector<llvm::Type *, 4> tailParams;
18931906

@@ -1933,7 +1946,7 @@ void SignatureExpansion::expandKeyPathAccessorParameters() {
19331946
llvm_unreachable("non keypath accessor convention");
19341947
}
19351948
for (unsigned i = 0; i < numArgsToExpand; i++) {
1936-
expand(params[i]);
1949+
expand(i);
19371950
}
19381951
for (auto tailParam : tailParams) {
19391952
ParamIRTypes.push_back(tailParam);
@@ -1987,9 +2000,9 @@ void SignatureExpansion::expandParameters(
19872000
params = params.drop_back();
19882001
}
19892002

1990-
for (auto param : params) {
1991-
const TypeInfo &ti = expand(param);
1992-
addParamInfo(recordedABIDetails, ti, param.getConvention());
2003+
for (auto pair : enumerate(params)) {
2004+
const TypeInfo &ti = expand(pair.index());
2005+
addParamInfo(recordedABIDetails, ti, pair.value().getConvention());
19932006
}
19942007
if (recordedABIDetails && FnType->hasSelfParam() && !hasSelfContext)
19952008
recordedABIDetails->parameters.back().isSelf = true;
@@ -2015,7 +2028,7 @@ void SignatureExpansion::expandParameters(
20152028

20162029
if (claimSelf())
20172030
IGM.addSwiftSelfAttributes(Attrs, curLength);
2018-
expand(FnType->getSelfParameter());
2031+
expand(FnType->getSelfParameterIndex());
20192032
if (recordedABIDetails)
20202033
recordedABIDetails->hasTrailingSelfParam = true;
20212034
assert(ParamIRTypes.size() == curLength + 1 &&
@@ -2260,8 +2273,8 @@ void SignatureExpansion::expandAsyncEntryType() {
22602273
params = params.drop_back();
22612274
}
22622275

2263-
for (auto param : params) {
2264-
expand(param);
2276+
for (unsigned i : range(params.size())) {
2277+
expand(i);
22652278
}
22662279

22672280
// Next, the generic signature.
@@ -2279,7 +2292,7 @@ void SignatureExpansion::expandAsyncEntryType() {
22792292
if (hasSelfContext) {
22802293
auto curLength = ParamIRTypes.size();
22812294
(void)curLength;
2282-
expand(FnType->getSelfParameter());
2295+
expand(FnType->getSelfParameterIndex());
22832296
assert(ParamIRTypes.size() == curLength + 1 &&
22842297
"adding 'self' added unexpected number of parameters");
22852298
if (claimSelf())

lib/SIL/IR/SILType.cpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,17 @@ bool SILFunctionType::isNoReturnFunction(SILModule &M,
707707
}
708708

709709
bool SILFunctionType::isAddressable(unsigned paramIdx, SILFunction *caller) {
710+
return isAddressable(paramIdx, caller->getModule(),
711+
caller->getGenericEnvironment(),
712+
caller->getModule().Types,
713+
caller->getTypeExpansionContext());
714+
}
715+
716+
// 'genericEnv' may be null.
717+
bool SILFunctionType::isAddressable(unsigned paramIdx, SILModule &module,
718+
GenericEnvironment *genericEnv,
719+
Lowering::TypeConverter &typeConverter,
720+
TypeExpansionContext expansion) {
710721
SILParameterInfo paramInfo = getParameters()[paramIdx];
711722
for (auto &depInfo : getLifetimeDependencies()) {
712723
auto *addressableIndices = depInfo.getAddressableIndices();
@@ -715,13 +726,12 @@ bool SILFunctionType::isAddressable(unsigned paramIdx, SILFunction *caller) {
715726
}
716727
auto *condAddressableIndices = depInfo.getConditionallyAddressableIndices();
717728
if (condAddressableIndices && condAddressableIndices->contains(paramIdx)) {
718-
CanType argType = paramInfo.getArgumentType(
719-
caller->getModule(), this, caller->getTypeExpansionContext());
720-
CanType contextType =
721-
argType->hasTypeParameter()
722-
? caller->mapTypeIntoContext(argType)->getCanonicalType()
729+
CanType argType = paramInfo.getArgumentType(module, this, expansion);
730+
CanType contextType = genericEnv
731+
? genericEnv->mapTypeIntoContext(argType)->getCanonicalType()
723732
: argType;
724-
auto &tl = caller->getTypeLowering(contextType);
733+
assert(!contextType->hasTypeParameter());
734+
auto &tl = typeConverter.getTypeLowering(contextType, expansion);
725735
if (tl.getRecursiveProperties().isAddressableForDependencies())
726736
return true;
727737
}

test/IRGen/addressable.swift

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-swift-frontend -module-name A -emit-ir -primary-file %s \
2+
// RUN: -enable-experimental-feature LifetimeDependence \
3+
// RUN: -enable-experimental-feature AddressableTypes \
4+
// RUN: | %FileCheck %s
5+
6+
// REQUIRES: swift_feature_AddressableTypes
7+
// REQUIRES: swift_feature_LifetimeDependence
8+
9+
public struct NE: ~Escapable {}
10+
11+
@_addressableForDependencies
12+
public struct Holder {}
13+
14+
@_silgen_name("holder_NE")
15+
@lifetime(borrow holder)
16+
func getNE(_ holder: Holder) -> NE
17+
18+
@_silgen_name("holder_mut_NE")
19+
@lifetime(&holder)
20+
func getMutNE(_ holder: inout Holder) -> NE
21+
22+
// The parameter cannot be 'nocapture'.
23+
//
24+
// CHECK-LABEL: define{{.*}} swiftcc void @"$s1A17testAddressableInyAA2NEVAA6HolderVF"(ptr noalias %0)
25+
public func testAddressableIn(_ holder: Holder) -> NE {
26+
getNE(holder)
27+
}
28+
29+
// The parameter cannot be 'nocapture'.
30+
//
31+
// CHECK-LABEL: define{{.*}} swiftcc void @"$s1A20testAddressableInoutyAA2NEVAA6HolderVzF"(ptr %0)
32+
public func testAddressableInout(_ holder: inout Holder) -> NE {
33+
getMutNE(&holder)
34+
}

0 commit comments

Comments
 (0)