-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathSIL.cpp
455 lines (380 loc) · 15.2 KB
/
SIL.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
//===--- SIL.cpp - Implements random SIL functionality --------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILDeclRef.h"
#include "swift/SIL/SILType.h"
#include "swift/SIL/SILUndef.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/AnyFunctionRef.h"
#include "swift/AST/Decl.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/Basic/Assertions.h"
#include "swift/ClangImporter/ClangModule.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
using namespace swift;
FormalLinkage swift::getDeclLinkage(const ValueDecl *D) {
const DeclContext *fileContext = D->getDeclContext()->getModuleScopeContext();
// Clang declarations are public and can't be assured of having a
// unique defining location.
if (isa<ClangModuleUnit>(fileContext) &&
!D->getObjCImplementationDecl())
return FormalLinkage::PublicNonUnique;
switch (D->getEffectiveAccess()) {
case AccessLevel::Package:
return FormalLinkage::PackageUnique;
case AccessLevel::Public:
case AccessLevel::Open:
return FormalLinkage::PublicUnique;
case AccessLevel::Internal:
return FormalLinkage::HiddenUnique;
case AccessLevel::FilePrivate:
case AccessLevel::Private:
return FormalLinkage::Private;
}
llvm_unreachable("Unhandled access level in switch.");
}
SILLinkage swift::getSILLinkage(FormalLinkage linkage,
ForDefinition_t forDefinition) {
switch (linkage) {
case FormalLinkage::PublicUnique:
return (forDefinition ? SILLinkage::Public : SILLinkage::PublicExternal);
case FormalLinkage::PublicNonUnique:
// FIXME: any place we have to do this that actually requires
// uniqueness is buggy.
return (forDefinition ? SILLinkage::Shared : SILLinkage::PublicExternal);
case FormalLinkage::PackageUnique:
return (forDefinition ? SILLinkage::Package : SILLinkage::PackageExternal);
case FormalLinkage::HiddenUnique:
return (forDefinition ? SILLinkage::Hidden : SILLinkage::HiddenExternal);
case FormalLinkage::Private:
return SILLinkage::Private;
}
llvm_unreachable("bad formal linkage");
}
SILLinkage
swift::getLinkageForProtocolConformance(const ProtocolConformance *C,
ForDefinition_t definition) {
// If the conformance was synthesized, give it shared linkage.
if (C->getRootConformance()->isSynthesized())
return SILLinkage::Shared;
auto typeDecl = C->getDeclContext()->getSelfNominalTypeDecl();
AccessLevel access = std::min(C->getProtocol()->getEffectiveAccess(),
typeDecl->getEffectiveAccess());
switch (access) {
case AccessLevel::Private:
case AccessLevel::FilePrivate:
return SILLinkage::Private;
case AccessLevel::Internal:
return (definition ? SILLinkage::Hidden : SILLinkage::HiddenExternal);
case AccessLevel::Package:
return (definition ? SILLinkage::Package : SILLinkage::PackageExternal);
case AccessLevel::Public:
case AccessLevel::Open:
return (definition ? SILLinkage::Public : SILLinkage::PublicExternal);
}
}
bool SILModule::isTypeMetadataAccessible(CanType type) {
// SILModules built for the debugger have special powers to access metadata
// for types in other files/modules.
if (getASTContext().LangOpts.DebuggerSupport)
return true;
assert(type->isLegalFormalType());
return !type.findIf([&](CanType type) {
// Note that this function returns true if the type is *illegal* to use.
// Ignore non-nominal types -- except for opaque result types which can be
// private and in a different translation unit in which case they can't be
// accessed.
ValueDecl *decl = type.getNominalOrBoundGenericNominal();
if (!decl)
decl = isa<OpaqueTypeArchetypeType>(type)
? cast<OpaqueTypeArchetypeType>(type)->getDecl()
: nullptr;
if (!decl)
return false;
// Check whether the declaration is inaccessible from the current context.
switch (getDeclLinkage(decl)) {
// Public declarations are accessible from everywhere.
case FormalLinkage::PublicUnique:
case FormalLinkage::PublicNonUnique:
case FormalLinkage::PackageUnique:
return false;
// Hidden declarations are inaccessible from different modules.
case FormalLinkage::HiddenUnique:
return (decl->getModuleContext() != getSwiftModule());
// Private declarations are inaccessible from different files unless
// this is WMO and we're in the same module.
case FormalLinkage::Private: {
// The associated DC should be either a SourceFile or, in WMO mode,
// a ModuleDecl. In the WMO modes, IRGen will ensure that private
// declarations are usable throughout the module. Therefore, in
// either case we just need to make sure that the declaration comes
// from within the associated DC.
auto declDC = decl->getDeclContext();
return !(declDC == AssociatedDeclContext ||
declDC->isChildContextOf(AssociatedDeclContext));
}
}
llvm_unreachable("bad linkage");
});
}
/// Return the formal linkage of the component restrictions of this
/// generic signature. This is the appropriate linkage for a lazily-
/// emitted entity derived from the generic signature.
///
/// This function never returns PublicUnique.
FormalLinkage swift::getGenericSignatureLinkage(CanGenericSignature sig) {
// This can only be PublicNonUnique or HiddenUnique. Signatures can
// never be PublicUnique in the first place, and we short-circuit on
// Private. So we only ever update it when we see HiddenUnique linkage.
FormalLinkage linkage = FormalLinkage::PublicNonUnique;
for (auto &req : sig.getRequirements()) {
// The first type can be ignored because it should always be
// a dependent type.
switch (req.getKind()) {
case RequirementKind::SameShape:
case RequirementKind::Layout:
continue;
case RequirementKind::Conformance:
case RequirementKind::SameType:
case RequirementKind::Superclass:
switch (getTypeLinkage(CanType(req.getSecondType()))) {
case FormalLinkage::PublicUnique:
case FormalLinkage::PublicNonUnique:
case FormalLinkage::PackageUnique:
continue;
case FormalLinkage::HiddenUnique:
linkage = FormalLinkage::HiddenUnique;
continue;
case FormalLinkage::Private:
// We can short-circuit with this.
return linkage;
}
}
}
return linkage;
}
/// Return the formal linkage of the given formal type.
/// This in the appropriate linkage for a lazily-emitted entity
/// derived from the type.
///
/// This function never returns PublicUnique, which means that,
/// even if a type is simply a reference to a non-generic
/// uniquely-emitted nominal type, the formal linkage of that
/// type may differ from the formal linkage of the underlying
/// type declaration.
FormalLinkage swift::getTypeLinkage(CanType t) {
assert(t->isLegalFormalType());
class Walker : public TypeWalker {
public:
FormalLinkage Linkage;
Walker() : Linkage(FormalLinkage::PublicNonUnique) {}
Action walkToTypePre(Type ty) override {
// Non-nominal types are always available.
auto decl = ty->getNominalOrBoundGenericNominal();
if (!decl)
return Action::Continue;
Linkage = std::max(Linkage, getDeclLinkage(decl));
return Action::Continue;
}
};
Walker w;
t.walk(w);
return w.Linkage;
}
/// Answer whether IRGen's emitTypeMetadataForLayout can fetch metadata for
/// a type, which is the necessary condition for being able to do value
/// operations on the type using dynamic metadata.
static bool isTypeMetadataForLayoutAccessible(SILModule &M, SILType type) {
// Look through types that aren't necessarily legal formal types:
// - tuples
if (auto tupleType = type.getAs<TupleType>()) {
for (auto index : indices(tupleType.getElementTypes())) {
if (!isTypeMetadataForLayoutAccessible(M, type.getTupleElementType(index)))
return false;
}
return true;
}
// - optionals
if (auto objType = type.getOptionalObjectType()) {
return isTypeMetadataForLayoutAccessible(M, objType);
}
// - function types
if (type.is<SILFunctionType>())
return true;
// - metatypes
if (type.is<AnyMetatypeType>())
return true;
// - pack expansion types
if (auto expansionType = type.getAs<PackExpansionType>()) {
auto patternType = SILType::getPrimitiveType(expansionType.getPatternType(),
type.getCategory());
return isTypeMetadataForLayoutAccessible(M, patternType);
}
// - lowered pack types
if (auto packType = type.getAs<SILPackType>()) {
for (auto eltType : packType.getElementTypes()) {
if (!isTypeMetadataForLayoutAccessible(
M, SILType::getPrimitiveAddressType(eltType)))
return false;
}
return true;
}
// Otherwise, check that we can fetch the type metadata.
return M.isTypeMetadataAccessible(type.getASTType());
}
/// Can we perform value operations on the given type? We have no way
/// of doing value operations on resilient-layout types from other modules
/// that are ABI-private to their defining module. But if the type is not
/// ABI-private, we can always at least fetch its metadata and use the
/// value witness table stored there.
bool SILModule::isTypeABIAccessible(SILType type,
TypeExpansionContext forExpansion) {
// Fixed-ABI types can have value operations done without metadata.
if (Types.getTypeLowering(type, forExpansion).isFixedABI())
return true;
assert(!type.is<ReferenceStorageType>() &&
!type.is<SILFunctionType>() &&
!type.is<AnyMetatypeType>() &&
"unexpected SIL lowered-only type with non-fixed layout");
// Otherwise, we need to be able to fetch layout-metadata for the type.
return isTypeMetadataForLayoutAccessible(type);
}
bool SILModule::isTypeMetadataForLayoutAccessible(SILType type) {
if (type.is<ReferenceStorageType>() || type.is<SILFunctionType>() ||
type.is<AnyMetatypeType>() || type.is<SILPackType>())
return false;
return ::isTypeMetadataForLayoutAccessible(*this, type);
}
static bool isUnsupportedKeyPathValueType(Type ty) {
// Visit lowered positions.
if (auto tupleTy = ty->getAs<TupleType>()) {
for (auto eltTy : tupleTy->getElementTypes()) {
if (eltTy->is<PackExpansionType>())
return true;
if (isUnsupportedKeyPathValueType(eltTy))
return true;
}
return false;
}
if (auto objTy = ty->getOptionalObjectType())
ty = objTy;
// FIXME: Remove this once isUnimplementableVariadicFunctionAbstraction()
// goes away in SILGenPoly.cpp.
if (auto funcTy = ty->getAs<FunctionType>()) {
for (auto param : funcTy->getParams()) {
auto paramTy = param.getPlainType();
if (paramTy->is<PackExpansionType>())
return true;
if (isUnsupportedKeyPathValueType(paramTy))
return true;
}
if (isUnsupportedKeyPathValueType(funcTy->getResult()))
return true;
}
// Noncopyable types aren't supported by key paths in their current form.
// They would also need a new ABI that's yet to be implemented in order to
// be properly supported, so let's suppress the descriptor for now if either
// the container or storage type of the declaration is non-copyable.
if (ty->isNoncopyable())
return true;
return false;
}
bool AbstractStorageDecl::exportsPropertyDescriptor() const {
// The storage needs a descriptor if it sits at a module's ABI boundary,
// meaning it has public linkage.
if (!isStatic()) {
if (auto contextTy = getDeclContext()->getDeclaredTypeInContext()) {
if (contextTy->isNoncopyable()) {
return false;
}
}
}
// TODO: Global properties ought to eventually be referenceable
// as key paths from ().
if (!getDeclContext()->isTypeContext())
return false;
// Protocol requirements do not need property descriptors.
if (isa<ProtocolDecl>(getDeclContext()))
return false;
// Static properties declared directly in protocol do not need
// descriptors as existential Any.Type will not resolve to a value.
if (isStatic() && isa<ProtocolDecl>(getDeclContext()))
return false;
// FIXME: We should support properties and subscripts with '_read' accessors;
// 'get' is not part of the opaque accessor set there.
auto *getter = getOpaqueAccessor(AccessorKind::Get);
if (!getter)
return false;
// If the getter is mutating, we cannot form a keypath to it at all.
if (isGetterMutating())
return false;
// If the storage is an ABI-compatible override of another declaration, we're
// not going to be emitting a property descriptor either.
if (!isValidKeyPathComponent())
return false;
// TODO: If previous versions of an ABI-stable binary needed the descriptor,
// then we still do.
// Check the linkage of the declaration.
auto getterLinkage = SILDeclRef(getter).getLinkage(ForDefinition);
switch (getterLinkage) {
case SILLinkage::Public:
case SILLinkage::PublicNonABI:
case SILLinkage::Package:
case SILLinkage::PackageNonABI:
// We may need a descriptor.
break;
case SILLinkage::Shared:
case SILLinkage::Private:
case SILLinkage::Hidden:
// Don't need a public descriptor.
return false;
case SILLinkage::HiddenExternal:
case SILLinkage::PublicExternal:
case SILLinkage::PackageExternal:
llvm_unreachable("should be definition linkage?");
}
auto typeInContext = getInnermostDeclContext()->mapTypeIntoContext(
getValueInterfaceType());
if (isUnsupportedKeyPathValueType(typeInContext)) {
return false;
}
// Subscripts with inout arguments (FIXME)and reabstracted arguments(/FIXME)
// don't have descriptors either.
if (auto sub = dyn_cast<SubscriptDecl>(this)) {
for (auto *index : *sub->getIndices()) {
// Keypaths can't capture inout indices.
if (index->isInOut())
return false;
auto indexTy = index->getInterfaceType()
->getReducedType(sub->getGenericSignatureOfContext());
// TODO: Handle reabstraction and tuple explosion in thunk generation.
// This wasn't previously a concern because anything that was Hashable
// had only one abstraction level and no explosion.
if (isa<TupleType>(indexTy))
return false;
auto indexObjTy = indexTy;
if (auto objTy = indexObjTy.getOptionalObjectType())
indexObjTy = objTy;
if (isa<AnyFunctionType>(indexObjTy)
|| isa<AnyMetatypeType>(indexObjTy))
return false;
}
}
return true;
}