Skip to content

Commit ee2ee0b

Browse files
committed
SILGen: Global constants are addressable.
A global or static `let` has a stable address, which is addressable when its representation is naturally fully abstracted.
1 parent 96900f9 commit ee2ee0b

File tree

4 files changed

+69
-9
lines changed

4 files changed

+69
-9
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3568,8 +3568,8 @@ SILGenFunction::tryEmitAddressableParameterAsAddress(ArgumentSource &&arg,
35683568
}
35693569
if (auto dre = dyn_cast<DeclRefExpr>(expr)) {
35703570
if (auto param = dyn_cast<VarDecl>(dre->getDecl())) {
3571-
if (auto addr = getLocalVariableAddressableBuffer(param, expr,
3572-
ownership)) {
3571+
if (auto addr = getVariableAddressableBuffer(param, expr,
3572+
ownership)) {
35733573
return ManagedValue::forBorrowedAddressRValue(addr);
35743574
}
35753575
}

lib/SILGen/SILGenDecl.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,12 +2263,41 @@ SILGenFunction::enterLocalVariableAddressableBufferScope(VarDecl *decl,
22632263
Cleanups.pushCleanup<DeallocateLocalVariableAddressableBuffer>(decl, destroyCleanup);
22642264
}
22652265

2266+
static bool isFullyAbstractedLowering(SILGenFunction &SGF,
2267+
Type formalType, SILType loweredType) {
2268+
return SGF.getLoweredType(AbstractionPattern::getOpaque(), formalType)
2269+
.getASTType()
2270+
== loweredType.getASTType();
2271+
}
2272+
2273+
static bool isNaturallyFullyAbstractedType(SILGenFunction &SGF,
2274+
Type formalType) {
2275+
return isFullyAbstractedLowering(SGF, formalType, SGF.getLoweredType(formalType));
2276+
}
2277+
22662278
SILValue
2267-
SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
2268-
SILLocation curLoc,
2269-
ValueOwnership ownership) {
2279+
SILGenFunction::getVariableAddressableBuffer(VarDecl *decl,
2280+
SILLocation curLoc,
2281+
ValueOwnership ownership) {
2282+
// For locals, we might be able to retroactively produce a local addressable
2283+
// representation.
22702284
auto foundVarLoc = VarLocs.find(decl);
22712285
if (foundVarLoc == VarLocs.end()) {
2286+
// If it's not local, is it at least a global stored variable?
2287+
if (decl->isGlobalStorage()) {
2288+
// Is the global immutable?
2289+
if (!decl->isLet()) {
2290+
return SILValue();
2291+
}
2292+
2293+
// Does the storage naturally have a fully abstracted representation?
2294+
if (!isNaturallyFullyAbstractedType(*this, decl->getTypeInContext())) {
2295+
return SILValue();
2296+
}
2297+
2298+
// We can get the stable address via the addressor.
2299+
return emitGlobalVariableRef(curLoc, decl, std::nullopt).getUnmanagedValue();
2300+
}
22722301
return SILValue();
22732302
}
22742303

@@ -2282,7 +2311,8 @@ SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
22822311
// Check whether the bound value is inherently suitable for addressability.
22832312
// It must already be in memory and fully abstracted.
22842313
if (value->getType().isAddress()
2285-
&& fullyAbstractedTy.getASTType() == value->getType().getASTType()) {
2314+
&& isFullyAbstractedLowering(*this, decl->getTypeInContext()->getRValueType(),
2315+
value->getType())) {
22862316
SILValue address = value;
22872317
// Begin an access if the address is mutable.
22882318
if (access != SILAccessEnforcement::Unknown) {

lib/SILGen/SILGenFunction.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,9 +576,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
576576

577577
/// Get a stable address which is suitable for forming dependent pointers
578578
/// if possible.
579-
SILValue getLocalVariableAddressableBuffer(VarDecl *decl,
580-
SILLocation loc,
581-
ValueOwnership ownership);
579+
SILValue getVariableAddressableBuffer(VarDecl *decl,
580+
SILLocation loc,
581+
ValueOwnership ownership);
582582

583583
/// The local auxiliary declarations for the parameters of this function that
584584
/// need to be emitted inside the next brace statement.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-swift-emit-silgen -parse-as-library -disable-availability-checking %s | %FileCheck %s
2+
3+
enum Color {
4+
case R, G, B
5+
}
6+
7+
let colors: InlineArray<_, Color> = [
8+
.G, .G, .R, .G, .G, .B,
9+
.G, .G, .B, .G, .G, .R,
10+
.B, .R, .G, .R, .B, .G,
11+
.G, .G, .B, .G, .G, .R,
12+
.G, .G, .R, .G, .G, .B,
13+
.R, .B, .G, .B, .R, .G,
14+
]
15+
16+
// CHECK-LABEL: sil{{.*}} @$s{{.*}}4main
17+
func main() {
18+
// CHECK: [[POINTER:%.*]] = apply {{.*}}() : $@convention(thin) () -> Builtin.RawPointer
19+
// CHECK: [[ADDRESS:%.*]] = pointer_to_address [[POINTER]]
20+
// CHECK: [[GET_SPAN:%.*]] = function_ref @$s{{.*}}11InlineArray{{.*}}4span
21+
// CHECK: apply [[GET_SPAN]]<{{.*}}>([[ADDRESS]])
22+
let span = colors.span
23+
for elem in [3, 9, 8] {
24+
switch span[elem] {
25+
case .R: print(0)
26+
case .G: print(1)
27+
case .B: print(2)
28+
}
29+
}
30+
}

0 commit comments

Comments
 (0)