13
13
#define DEBUG_TYPE " sil-access-utils"
14
14
15
15
#include " swift/SIL/MemAccessUtils.h"
16
+ #include " swift/SIL/SILGlobalVariable.h"
16
17
#include " swift/SIL/SILUndef.h"
17
18
18
19
using namespace swift ;
@@ -28,6 +29,14 @@ AccessedStorage::Kind AccessedStorage::classify(SILValue base) {
28
29
return Stack;
29
30
case ValueKind::GlobalAddrInst:
30
31
return Global;
32
+ case ValueKind::ApplyInst: {
33
+ FullApplySite apply (cast<ApplyInst>(base));
34
+ if (auto *funcRef = apply.getReferencedFunction ()) {
35
+ if (getVariableOfGlobalInit (funcRef))
36
+ return Global;
37
+ }
38
+ return Unidentified;
39
+ }
31
40
case ValueKind::RefElementAddrInst:
32
41
return Class;
33
42
// A function argument is effectively a nested access, enforced
@@ -67,7 +76,19 @@ AccessedStorage::AccessedStorage(SILValue base, Kind kind) {
67
76
paramIndex = cast<SILFunctionArgument>(base)->getIndex ();
68
77
break ;
69
78
case Global:
70
- global = cast<GlobalAddrInst>(base)->getReferencedGlobal ();
79
+ if (auto *GAI = dyn_cast<GlobalAddrInst>(base))
80
+ global = GAI->getReferencedGlobal ();
81
+ else {
82
+ FullApplySite apply (cast<ApplyInst>(base));
83
+ auto *funcRef = apply.getReferencedFunction ();
84
+ assert (funcRef);
85
+ global = getVariableOfGlobalInit (funcRef);
86
+ assert (global);
87
+ // Require a decl for all formally accessed globals defined in this
88
+ // module. (Access of globals defined elsewhere has Unidentified storage).
89
+ // AccessEnforcementWMO requires this.
90
+ assert (global->getDecl ());
91
+ }
71
92
break ;
72
93
case Class: {
73
94
// Do a best-effort to find the identity of the object being projected
@@ -149,6 +170,17 @@ void AccessedStorage::print(raw_ostream &os) const {
149
170
150
171
void AccessedStorage::dump () const { print (llvm::dbgs ()); }
151
172
173
+ // Return true if the given apply invokes a global addressor defined in another
174
+ // module.
175
+ static bool isExternalGlobalAddressor (ApplyInst *AI) {
176
+ FullApplySite apply (AI);
177
+ auto *funcRef = apply.getReferencedFunction ();
178
+ if (!funcRef)
179
+ return false ;
180
+
181
+ return funcRef->isGlobalInit () && funcRef->isExternalDeclaration ();
182
+ }
183
+
152
184
// Given an address base is a block argument, verify that it is actually a box
153
185
// projected from a switch_enum. This is a valid pattern at any SIL stage
154
186
// resulting in a block-type phi. In later SIL stages, the optimizer may form
@@ -186,12 +218,16 @@ static bool isAddressForLocalInitOnly(SILValue sourceAddr) {
186
218
}
187
219
}
188
220
221
+ // AccessEnforcementWMO makes a strong assumption that all accesses are either
222
+ // identified or are *not* accessing a global variable or class property defined
223
+ // in this module. Consequently, we cannot simply bail out on
224
+ // PointerToAddressInst as an Unidentified access.
189
225
AccessedStorage swift::findAccessedStorage (SILValue sourceAddr) {
190
226
SILValue address = sourceAddr;
191
227
while (true ) {
192
228
AccessedStorage::Kind kind = AccessedStorage::classify (address);
193
- // First handle identified cases: these are always valid as the base of a
194
- // formal access.
229
+ // First handle identified cases: these are always valid as the base of
230
+ // a formal access.
195
231
if (kind != AccessedStorage::Unidentified)
196
232
return AccessedStorage (address, kind);
197
233
@@ -202,10 +238,16 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
202
238
return AccessedStorage (address, AccessedStorage::Unidentified);
203
239
return AccessedStorage ();
204
240
205
- case ValueKind::PointerToAddressInst:
206
241
case ValueKind::SILUndef:
207
242
return AccessedStorage (address, AccessedStorage::Unidentified);
208
243
244
+ case ValueKind::ApplyInst:
245
+ if (isExternalGlobalAddressor (cast<ApplyInst>(address)))
246
+ return AccessedStorage (address, AccessedStorage::Unidentified);
247
+
248
+ // Don't currently allow any other calls to return an accessed address.
249
+ return AccessedStorage ();
250
+
209
251
// A block argument may be a box value projected out of
210
252
// switch_enum. Address-type block arguments are not allowed.
211
253
case ValueKind::SILPHIArgument:
@@ -218,17 +260,22 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
218
260
// Load a box from an indirect payload of an opaque enum.
219
261
// We must have peeked past the project_box earlier in this loop.
220
262
// (the indirectness makes it a box, the load is for address-only).
221
- //
263
+ //
222
264
// %payload_adr = unchecked_take_enum_data_addr %enum : $*Enum, #Enum.case
223
265
// %box = load [take] %payload_adr : $*{ var Enum }
224
266
//
225
267
// FIXME: this case should go away with opaque values.
268
+ //
269
+ // Otherwise return invalid AccessedStorage.
226
270
case ValueKind::LoadInst: {
227
- assert (address->getType ().is <SILBoxType>());
228
- address = cast<LoadInst>(address)->getOperand ();
229
- assert (isa<UncheckedTakeEnumDataAddrInst>(address));
230
- continue ;
271
+ if (address->getType ().is <SILBoxType>()) {
272
+ address = cast<LoadInst>(address)->getOperand ();
273
+ assert (isa<UncheckedTakeEnumDataAddrInst>(address));
274
+ continue ;
275
+ }
276
+ return AccessedStorage ();
231
277
}
278
+
232
279
// Inductive cases:
233
280
// Look through address casts to find the source address.
234
281
case ValueKind::MarkUninitializedInst:
@@ -249,6 +296,30 @@ AccessedStorage swift::findAccessedStorage(SILValue sourceAddr) {
249
296
address = cast<SingleValueInstruction>(address)->getOperand (0 );
250
297
continue ;
251
298
299
+ // Access to a Builtin.RawPointer. Treat this like the inductive cases
300
+ // above because some RawPointer's originate from identified locations. See
301
+ // the special case for global addressors, which return RawPointer above.
302
+ //
303
+ // If the inductive search does not find a valid addressor, it will
304
+ // eventually reach the default case that returns in invalid location. This
305
+ // is correct for RawPointer because, although accessing a RawPointer is
306
+ // legal SIL, there is no way to guarantee that it doesn't access class or
307
+ // global storage, so returning a valid unidentified storage object would be
308
+ // incorrect. It is the caller's responsibility to know that formal access
309
+ // to such a location can be safely ignored.
310
+ //
311
+ // For example:
312
+ //
313
+ // - KeyPath Builtins access RawPointer. However, the caller can check
314
+ // that the access `isFromBuilin` and ignore the storage.
315
+ //
316
+ // - lldb generates RawPointer access for debugger variables, but SILGen
317
+ // marks debug VarDecl access as 'Unsafe' and SIL passes don't need the
318
+ // AccessedStorage for 'Unsafe' access.
319
+ case ValueKind::PointerToAddressInst:
320
+ address = cast<SingleValueInstruction>(address)->getOperand (0 );
321
+ continue ;
322
+
252
323
// Subobject projections.
253
324
case ValueKind::StructElementAddrInst:
254
325
case ValueKind::TupleElementAddrInst:
0 commit comments