Skip to content

Commit 9f6a375

Browse files
Merge pull request #4765 from swiftwasm/main
[pull] swiftwasm from main
2 parents 3b5f884 + 72cef81 commit 9f6a375

File tree

102 files changed

+1609
-444
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+1609
-444
lines changed

docs/SIL.rst

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2762,6 +2762,32 @@ sil-opt, one will see that we actually have an ownership violation due to the
27622762
two uses of "value", one for initializing value2 and the other for the return
27632763
value.
27642764

2765+
Move Only Types
2766+
---------------
2767+
2768+
NOTE: This is experimental and is just an attempt to describe where the design
2769+
is currently for others reading SIL today. It should not be interpreted as
2770+
final.
2771+
2772+
Currently there are two kinds of "move only types" in SIL: pure move only types
2773+
that are always move only and move only wrapped types that are move only
2774+
versions of copyable types. The invariant that values of Move Only type obey is
2775+
that they can only be copied (e.x.: operand to a `copy_value`_, ``copy_addr [init]``) during the
2776+
guaranteed passes when we are in Raw SIL. Once we are in non-Raw SIL though
2777+
(i.e. Canonical and later SIL stages), a program is ill formed if one copies a
2778+
move only type.
2779+
2780+
The reason why we have this special rule for move only types is that this allows
2781+
for SIL code generators to insert copies and then have a later guaranteed
2782+
checker optimization pass recover the underlying move only semantics by
2783+
reconstructing needed copies and removing unneeded copies using Ownership
2784+
SSA. If any such copies are actually needed according to Ownership SSA, the
2785+
checker pass emits a diagnostic stating that move semantics have been
2786+
violated. If such a diagnostic is emitted then the checker pass transforms all
2787+
copies on move only types to their explicit copy forms to ensure that once we
2788+
leave the diagnostic passes and enter canonical SIL, our "copy" invariant is
2789+
maintained.
2790+
27652791
Runtime Failure
27662792
---------------
27672793

@@ -4219,6 +4245,25 @@ operations::
42194245
If ``T`` is a trivial type, then ``copy_addr`` is always equivalent to its
42204246
take-initialization form.
42214247

4248+
It is illegal in non-Raw SIL to apply ``copy_addr [init]`` to a value that is
4249+
move only.
4250+
4251+
explicit_copy_addr
4252+
``````````````````
4253+
::
4254+
4255+
sil-instruction ::= 'explicit_copy_addr' '[take]'? sil-value
4256+
'to' '[initialization]'? sil-operand
4257+
4258+
explicit_copy_addr [take] %0 to [initialization] %1 : $*T
4259+
// %0 and %1 must be of the same $*T address type
4260+
4261+
This instruction is exactly the same as `copy_addr`_ except that it has special
4262+
behavior for move only types. Specifically, an `explicit_copy_addr`_ is viewed
4263+
as a copy_addr that is allowed on values that are move only. This is only used
4264+
by a move checker after it has emitted an error diagnostic to preserve the
4265+
general ``copy_addr [init]`` ban in Canonical SIL on move only types.
4266+
42224267
destroy_addr
42234268
````````````
42244269
::
@@ -5557,6 +5602,8 @@ independent of the operand. In terms of specific types:
55575602
In ownership qualified functions, a ``copy_value`` produces a +1 value that must
55585603
be consumed at most once along any path through the program.
55595604

5605+
It is illegal in non-Raw SIL to `copy_value`_ a value that is "move only".
5606+
55605607
explicit_copy_value
55615608
```````````````````
55625609

@@ -5566,27 +5613,18 @@ explicit_copy_value
55665613

55675614
%1 = explicit_copy_value %0 : $A
55685615

5569-
Performs a copy of a loadable value as if by the value's type lowering and
5570-
returns the copy. The returned copy semantically is a value that is completely
5571-
independent of the operand. In terms of specific types:
5572-
5573-
1. For trivial types, this is equivalent to just propagating through the trivial
5574-
value.
5575-
2. For reference types, this is equivalent to performing a ``strong_retain``
5576-
operation and returning the reference.
5577-
3. For ``@unowned`` types, this is equivalent to performing an
5578-
``unowned_retain`` and returning the operand.
5579-
4. For aggregate types, this is equivalent to recursively performing a
5580-
``copy_value`` on its components, forming a new aggregate from the copied
5581-
components, and then returning the new aggregate.
5582-
5583-
In ownership qualified functions, a ``explicit_copy_value`` produces a +1 value
5584-
that must be consumed at most once along any path through the program.
5585-
5586-
When move only variable checking is performed, ``explicit_copy_value`` is
5616+
This is exactly the same instruction semantically as `copy_value`_ with the
5617+
exception that when move only checking is performed, `explicit_copy_value`_ is
55875618
treated as an explicit copy asked for by the user that should not be rewritten
55885619
and should be treated as a non-consuming use.
55895620

5621+
This is used for two things:
5622+
5623+
1. Implementing a copy builtin for no implicit copy types.
5624+
2. To enable the move checker, once it has emitted an error diagnostic, to still
5625+
produce valid Ownership SSA SIL at the end of the guaranteed optimization
5626+
pipeline when we enter the Canonical SIL stage.
5627+
55905628
move_value
55915629
``````````
55925630

include/swift/AST/ASTContext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,8 +1343,8 @@ class ASTContext final {
13431343
/// particular, the opened archetype signature does not have requirements for
13441344
/// conformances inherited from superclass constraints while existential
13451345
/// values do.
1346-
CanGenericSignature getOpenedArchetypeSignature(Type type,
1347-
GenericSignature parentSig);
1346+
CanGenericSignature getOpenedExistentialSignature(Type type,
1347+
GenericSignature parentSig);
13481348

13491349
GenericSignature getOverrideGenericSignature(const ValueDecl *base,
13501350
const ValueDecl *derived);

include/swift/AST/Attr.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,8 @@ DECL_ATTR(_clangImporterSynthesizedType, ClangImporterSynthesizedType,
456456
74)
457457
SIMPLE_DECL_ATTR(_weakLinked, WeakLinked,
458458
OnNominalType | OnAssociatedType | OnFunc | OnAccessor | OnVar |
459-
OnSubscript | OnConstructor | OnEnumElement | OnExtension | UserInaccessible |
459+
OnSubscript | OnConstructor | OnEnumElement | OnExtension | OnImport |
460+
UserInaccessible |
460461
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
461462
75)
462463
SIMPLE_DECL_ATTR(frozen, Frozen,

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,10 @@ ERROR(recursive_generic_signature,none,
25082508
"%0 %1 has self-referential generic requirements", (DescriptiveDeclKind, DeclBaseName))
25092509
ERROR(recursive_generic_signature_extension,none,
25102510
"extension of %0 %1 has self-referential generic requirements", (DescriptiveDeclKind, DeclBaseName))
2511+
ERROR(recursive_same_type_constraint,none,
2512+
"same-type constraint %0 == %1 is recursive", (Type, Type))
2513+
ERROR(recursive_superclass_constraint,none,
2514+
"superclass constraint %0 : %1 is recursive", (Type, Type))
25112515
ERROR(requires_same_concrete_type,none,
25122516
"generic signature requires types %0 and %1 to be the same", (Type, Type))
25132517
WARNING(redundant_conformance_constraint,none,

include/swift/AST/FileUnit.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,17 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
123123
const ModuleDecl *importedModule,
124124
SmallSetVector<Identifier, 4> &spiGroups) const {};
125125

126+
/// Checks whether this file imports \c module as \c @_weakLinked.
127+
virtual bool importsModuleAsWeakLinked(const ModuleDecl *module) const {
128+
// For source files, this should be overridden to inspect the import
129+
// declarations in the file. Other kinds of file units, like serialized
130+
// modules, can just use this default implementation since the @_weakLinked
131+
// attribute is not transitive. If module C is imported @_weakLinked by
132+
// module B, that does not imply that module A imports module C @_weakLinked
133+
// if it imports module B.
134+
return false;
135+
}
136+
126137
virtual Optional<Fingerprint>
127138
loadFingerprint(const IterableDeclContext *IDC) const { return None; }
128139

include/swift/AST/Import.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ enum class ImportFlags {
8484
/// concurrency.
8585
Preconcurrency = 0x20,
8686

87+
/// The module's symbols are linked weakly.
88+
WeakLinked = 0x40,
89+
8790
/// Used for DenseMap.
8891
Reserved = 0x80
8992
};

include/swift/AST/Module.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,12 +414,11 @@ class ModuleDecl
414414
/// present overlays as if they were part of their underlying module.
415415
std::pair<ModuleDecl *, Identifier> getDeclaringModuleAndBystander();
416416

417+
public:
417418
/// If this is a traditional (non-cross-import) overlay, get its underlying
418419
/// module if one exists.
419420
ModuleDecl *getUnderlyingModuleIfOverlay() const;
420421

421-
public:
422-
423422
/// Returns true if this module is an underscored cross import overlay
424423
/// declared by \p other or its underlying clang module, either directly or
425424
/// transitively (via intermediate cross-import overlays - for cross-imports
@@ -686,6 +685,10 @@ class ModuleDecl
686685
// Is \p spiGroup accessible as an explicitly imported SPI from this module?
687686
bool isImportedAsSPI(Identifier spiGroup, const ModuleDecl *fromModule) const;
688687

688+
/// Is \p targetDecl from a module that is imported as \c @_weakLinked from
689+
/// this module?
690+
bool isImportedAsWeakLinked(const Decl *targetDecl) const;
691+
689692
/// \sa getImportedModules
690693
enum class ImportFilterKind {
691694
/// Include imports declared with `@_exported`.

include/swift/AST/SourceFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,9 @@ class SourceFile final : public FileUnit {
356356
const ModuleDecl *importedModule,
357357
llvm::SmallSetVector<Identifier, 4> &spiGroups) const override;
358358

359+
/// Is \p module imported as \c @_weakLinked by this file?
360+
bool importsModuleAsWeakLinked(const ModuleDecl *module) const override;
361+
359362
// Is \p targetDecl accessible as an explicitly imported SPI from this file?
360363
bool isImportedAsSPI(const ValueDecl *targetDecl) const;
361364

include/swift/AST/Type.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,11 @@ class Type {
282282
/// Transform the given type by recursively applying the user-provided
283283
/// function to each node.
284284
///
285-
/// If the function returns \c None, the transform operation will
286-
///
287285
/// \param fn A function object which accepts a type pointer and returns a
288286
/// transformed type, a null type (which will propagate out the null type),
289287
/// or None (to indicate that the transform operation should recursively
290288
/// transform the children). The function object should use \c dyn_cast rather
291-
/// than \c getAs when the transform is intended to preserve sugar
289+
/// than \c getAs when the transform is intended to preserve sugar.
292290
///
293291
/// \returns the result of transforming the type.
294292
Type transformRec(llvm::function_ref<Optional<Type>(TypeBase *)> fn) const;

include/swift/IRGen/IRABIDetailsProvider.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,15 @@ class IRABIDetailsProvider {
105105
/// access function.
106106
FunctionABISignature getTypeMetadataAccessFunctionSignature();
107107

108+
struct EnumElementInfo {
109+
unsigned tag;
110+
StringRef globalVariableName;
111+
};
112+
108113
/// Returns EnumElementDecls (enum cases) in their declaration order with
109114
/// their tag indices from the given EnumDecl
110-
llvm::MapVector<EnumElementDecl *, unsigned> getEnumTagMapping(EnumDecl *ED);
115+
llvm::MapVector<EnumElementDecl *, EnumElementInfo>
116+
getEnumTagMapping(const EnumDecl *ED);
111117

112118
/// Returns the additional params if they exist after lowering the function.
113119
SmallVector<ABIAdditionalParam, 1>

include/swift/SIL/SILBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,14 @@ class SILBuilder {
10371037
getSILDebugLocation(Loc), srcAddr, destAddr, isTake, isInitialize));
10381038
}
10391039

1040+
ExplicitCopyAddrInst *
1041+
createExplicitCopyAddr(SILLocation Loc, SILValue srcAddr, SILValue destAddr,
1042+
IsTake_t isTake, IsInitialization_t isInitialize) {
1043+
assert(srcAddr->getType() == destAddr->getType());
1044+
return insert(new (getModule()) ExplicitCopyAddrInst(
1045+
getSILDebugLocation(Loc), srcAddr, destAddr, isTake, isInitialize));
1046+
}
1047+
10401048
BindMemoryInst *createBindMemory(SILLocation Loc, SILValue base,
10411049
SILValue index, SILType boundType) {
10421050
return insert(BindMemoryInst::create(getSILDebugLocation(Loc), base, index,

include/swift/SIL/SILCloner.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,17 @@ SILCloner<ImplClass>::visitCopyAddrInst(CopyAddrInst *Inst) {
13831383
Inst->isInitializationOfDest()));
13841384
}
13851385

1386+
template <typename ImplClass>
1387+
void SILCloner<ImplClass>::visitExplicitCopyAddrInst(
1388+
ExplicitCopyAddrInst *Inst) {
1389+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1390+
recordClonedInstruction(
1391+
Inst, getBuilder().createExplicitCopyAddr(
1392+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()),
1393+
getOpValue(Inst->getDest()), Inst->isTakeOfSrc(),
1394+
Inst->isInitializationOfDest()));
1395+
}
1396+
13861397
template <typename ImplClass>
13871398
void SILCloner<ImplClass>::visitMarkUnresolvedMoveAddrInst(
13881399
MarkUnresolvedMoveAddrInst *Inst) {

include/swift/SIL/SILFunction.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ enum IsDistributed_t {
6464
IsNotDistributed,
6565
IsDistributed,
6666
};
67+
enum IsWeakImported_t {
68+
IsNotWeakImported,
69+
IsWeakImportedByModule,
70+
IsAlwaysWeakImported,
71+
};
6772

6873
enum class PerformanceConstraints : uint8_t {
6974
None = 0,
@@ -317,9 +322,8 @@ class SILFunction
317322
/// would indicate.
318323
unsigned HasCReferences : 1;
319324

320-
/// Whether cross-module references to this function should always use
321-
/// weak linking.
322-
unsigned IsWeakImported : 1;
325+
/// Whether cross-module references to this function should use weak linking.
326+
unsigned IsWeakImported : 2;
323327

324328
/// Whether the implementation can be dynamically replaced.
325329
unsigned IsDynamicReplaceable : 1;
@@ -797,12 +801,18 @@ class SILFunction
797801

798802
/// Returns whether this function's symbol must always be weakly referenced
799803
/// across module boundaries.
800-
bool isAlwaysWeakImported() const { return IsWeakImported; }
804+
bool isAlwaysWeakImported() const {
805+
return IsWeakImported == IsWeakImported_t::IsAlwaysWeakImported;
806+
}
801807

802-
void setAlwaysWeakImported(bool value) {
803-
IsWeakImported = value;
808+
/// Returns whether this function's symbol was referenced by a module that
809+
/// imports the defining module \c @_weakLinked.
810+
bool isWeakImportedByModule() const {
811+
return IsWeakImported == IsWeakImported_t::IsWeakImportedByModule;
804812
}
805813

814+
void setIsWeakImported(IsWeakImported_t value) { IsWeakImported = value; }
815+
806816
bool isWeakImported() const;
807817

808818
/// Returns whether this function implementation can be dynamically replaced.

include/swift/SIL/SILInstruction.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5000,6 +5000,48 @@ class CopyAddrInst
50005000
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
50015001
};
50025002

5003+
/// ExplicitCopyAddrInst - A copy_addr that should not be optimized and should
5004+
/// be viewed
5005+
class ExplicitCopyAddrInst
5006+
: public InstructionBase<SILInstructionKind::ExplicitCopyAddrInst,
5007+
NonValueInstruction>,
5008+
public CopyLikeInstruction {
5009+
friend SILBuilder;
5010+
5011+
private:
5012+
FixedOperandList<2> Operands;
5013+
USE_SHARED_UINT8;
5014+
5015+
ExplicitCopyAddrInst(SILDebugLocation DebugLoc, SILValue Src, SILValue Dest,
5016+
IsTake_t isTakeOfSrc,
5017+
IsInitialization_t isInitializationOfDest);
5018+
5019+
public:
5020+
SILValue getSrc() const { return Operands[Src].get(); }
5021+
SILValue getDest() const { return Operands[Dest].get(); }
5022+
5023+
void setSrc(SILValue V) { Operands[Src].set(V); }
5024+
void setDest(SILValue V) { Operands[Dest].set(V); }
5025+
5026+
IsTake_t isTakeOfSrc() const {
5027+
return IsTake_t(sharedUInt8().ExplicitCopyAddrInst.isTakeOfSrc);
5028+
}
5029+
IsInitialization_t isInitializationOfDest() const {
5030+
return IsInitialization_t(
5031+
sharedUInt8().ExplicitCopyAddrInst.isInitializationOfDest);
5032+
}
5033+
5034+
void setIsTakeOfSrc(IsTake_t T) {
5035+
sharedUInt8().ExplicitCopyAddrInst.isTakeOfSrc = (bool)T;
5036+
}
5037+
void setIsInitializationOfDest(IsInitialization_t I) {
5038+
sharedUInt8().ExplicitCopyAddrInst.isInitializationOfDest = (bool)I;
5039+
}
5040+
5041+
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
5042+
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
5043+
};
5044+
50035045
/// "%token = bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $T"
50045046
///
50055047
/// Binds memory at the raw pointer %0 to type $T with enough capacity

include/swift/SIL/SILNode.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ class alignas(8) SILNode :
219219
isTakeOfSrc : 1,
220220
isInitializationOfDest : 1);
221221

222+
SHARED_FIELD(ExplicitCopyAddrInst, uint8_t
223+
isTakeOfSrc : 1,
224+
isInitializationOfDest : 1);
225+
222226
SHARED_FIELD(PointerToAddressInst, uint8_t
223227
isStrict : 1,
224228
isInvariant : 1);

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,8 @@ BRIDGED_NON_VALUE_INST(DebugValueInst, debug_value,
781781
#include "swift/AST/ReferenceStorage.def"
782782
BRIDGED_NON_VALUE_INST(CopyAddrInst, copy_addr,
783783
SILInstruction, MayHaveSideEffects, MayRelease)
784+
BRIDGED_NON_VALUE_INST(ExplicitCopyAddrInst, explicit_copy_addr,
785+
SILInstruction, MayHaveSideEffects, MayRelease)
784786
BRIDGED_NON_VALUE_INST(DestroyAddrInst, destroy_addr,
785787
SILInstruction, MayHaveSideEffects, MayRelease)
786788
NON_VALUE_INST(EndLifetimeInst, end_lifetime,

0 commit comments

Comments
 (0)