Skip to content

Commit fa52ea4

Browse files
Merge pull request #3464 from swiftwasm/main
[pull] swiftwasm from main
2 parents 73738f0 + dd32711 commit fa52ea4

24 files changed

+1013
-190
lines changed

docs/SIL.rst

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3493,11 +3493,10 @@ debug_value
34933493

34943494
debug_value %1 : $Int
34953495

3496-
This indicates that the value of a declaration with loadable type has changed
3497-
value to the specified operand. The declaration in question is identified by
3498-
the SILLocation attached to the debug_value instruction.
3499-
3500-
The operand must have loadable type.
3496+
This indicates that the value of a declaration has changed value to the
3497+
specified operand. The declaration in question is identified by either the
3498+
SILLocation attached to the debug_value instruction or the SILLocation specified
3499+
in the advanced debug variable attributes.
35013500

35023501
::
35033502

@@ -3507,47 +3506,74 @@ The operand must have loadable type.
35073506
debug-var-attr ::= 'argno' integer-literal
35083507
debug-var-attr ::= 'implicit'
35093508

3510-
::
3511-
3512-
advanced-debug-var-attr ::= '(' 'name' string-literal (',' sil-instruction-source-info)? ')'
3513-
advanced-debug-var-attr ::= 'type' sil-type
3514-
3515-
::
3516-
3517-
debug-info-expr ::= di-expr-operand (':' di-expr-operand)*
3518-
di-expr-operand ::= di-expr-operator (':' sil-operand)*
3519-
di-expr-operator ::= 'op_fragment'
3520-
35213509
There are a number of attributes that provide details about the source
35223510
variable that is being described, including the name of the
35233511
variable. For function and closure arguments ``argno`` is the number
35243512
of the function argument starting with 1. A compiler-generated source
35253513
variable will be marked ``implicit`` and optimizers are free to remove
3526-
it even in -Onone. The advanced debug variable attributes represent source
3527-
locations and type of the source variable when it was originally declared.
3528-
It is useful when we're indirectly associating the SSA value with the
3529-
source variable (via di-expression, for example) in which case SSA value's
3530-
type is different from that of source variable.
3514+
it even in -Onone.
35313515

35323516
If the '[poison]' flag is set, then all references within this debug
35333517
value will be overwritten with a sentinel at this point in the
35343518
program. This is used in debug builds when shortening non-trivial
35353519
value lifetimes to ensure the debugger cannot inspect invalid
3536-
memory. `debug_value` instructions with the poison flag are not
3537-
generated until OSSA islowered. They are not expected to be serialized
3520+
memory. ``debug_value`` instructions with the poison flag are not
3521+
generated until OSSA is lowered. They are not expected to be serialized
35383522
within the module, and the pipeline is not expected to do any
35393523
significant code motion after lowering.
35403524

3541-
Debug info expression (di-expression) is a powerful method to connect SSA
3542-
value with the source variable in an indirect fashion. For example,
3543-
we can use the ``op_fragment`` operator to specify that the SSA value
3544-
is originated from a struct field inside the source variable (which has
3545-
an aggregate data type). Di-expression in SIL works similarly to LLVM's
3546-
``!DIExpression`` metadata. Where both of them adopt a stack based
3547-
execution model to evaluate the expression. The biggest difference between
3548-
them is that LLVM always represent ``!DIExpression`` elements as 64-bit
3549-
integers, while SIL's di-expression can have elements with various types,
3550-
like AST nodes or strings. Here is an example::
3525+
::
3526+
3527+
advanced-debug-var-attr ::= '(' 'name' string-literal (',' sil-instruction-source-info)? ')'
3528+
advanced-debug-var-attr ::= 'type' sil-type
3529+
3530+
Advanced debug variable attributes represent source locations and the type of
3531+
the source variable when it was originally declared. It is useful when
3532+
we're indirectly associating the SSA value with the source variable
3533+
(via SIL DIExpression, for example) in which case SSA value's type is different
3534+
from that of source variable.
3535+
3536+
::
3537+
3538+
debug-info-expr ::= di-expr-operand (':' di-expr-operand)*
3539+
di-expr-operand ::= di-expr-operator (':' sil-operand)*
3540+
di-expr-operator ::= 'op_fragment'
3541+
di-expr-operator ::= 'op_deref'
3542+
3543+
SIL debug info expression (SIL DIExpression) is a powerful method to connect SSA
3544+
value with the source variable in an indirect fashion. Di-expression in SIL
3545+
uses a stack based execution model to evaluate the expression and apply on
3546+
the associated (SIL) SSA value before connecting it with the debug variable.
3547+
For instance, given the following SIL code::
3548+
3549+
debug_value %a : $*Int, name "x", expr op_deref
3550+
3551+
It means: "You can get the value of source variable 'x' by *dereferencing*
3552+
SSA value ``%a``". The ``op_deref`` is a SIL DIExpression operator that represents
3553+
"dereference". If there are multiple SIL DIExpression operators (or arguments), they
3554+
are evaluated from left to right::
3555+
3556+
debug_value %b : $**Int, name "y", expr op_deref:op_deref
3557+
3558+
In the snippet above, two ``op_deref`` operators will be applied on SSA value
3559+
``%b`` sequentially.
3560+
3561+
Note that normally when the SSA value has an address type, there will be a ``op_deref``
3562+
in the SIL DIExpression. Because there is no pointer in Swift so you always need to
3563+
dereference an address-type SSA value to get the value of a source variable.
3564+
However, if the SSA value is a ``alloc_stack``, the ``debug_value`` is used to indicate
3565+
the *declaration* of a source variable. Or, you can say, used to specify the location
3566+
(memory address) of the source variable. Therefore, we don't need to add a ``op_deref``
3567+
in this case::
3568+
3569+
%a = alloc_stack $Int, ...
3570+
debug_value %a : $*Int, name "my_var"
3571+
3572+
3573+
The ``op_fragment`` operator is used to specify the SSA value of a specific
3574+
field in an aggregate-type source variable. This SIL DIExpression operator takes
3575+
a field declaration -- which references the desired sub-field in source variable
3576+
-- as its argument. Here is an example::
35513577

35523578
struct MyStruct {
35533579
var x: Int
@@ -3556,23 +3582,13 @@ like AST nodes or strings. Here is an example::
35563582
...
35573583
debug_value %1 : $Int, var, (name "the_struct", loc "file.swift":8:7), type $MyStruct, expr op_fragment:#MyStruct.y, loc "file.swift":9:4
35583584

3559-
In the snippet above, source variable "the_struct" has an aggregate type ``$MyStruct`` and we use di-expression with ``op_fragment`` operator to associate ``%1`` to the ``y`` member variable inside "the_struct". Note that the extra source location directive follows rigt after ``name "the_struct"`` indicate that "the_struct" was originally declared in line 8, but not until line 9, the current ``debug_value`` instruction's source location, does member ``y`` got updated with SSA value ``%1``.
3560-
3561-
debug_value_addr
3562-
````````````````
3563-
3564-
::
3565-
3566-
sil-instruction ::= debug_value_addr sil-operand (',' debug-var-attr)* advanced-debug-var-attr* (',' 'expr' debug-info-expr)?
3567-
3568-
debug_value_addr %7 : $*SomeProtocol
3569-
3570-
This indicates that the value of a declaration with address-only type
3571-
has changed value to the specified operand. The declaration in
3572-
question is identified by the SILLocation attached to the
3573-
debug_value_addr instruction.
3585+
In the snippet above, source variable "the_struct" has an aggregate type ``$MyStruct`` and we use a SIL DIExpression with ``op_fragment`` operator to associate ``%1`` to the ``y`` member variable (via the ``#MyStruct.y`` directive) inside "the_struct".
3586+
Note that the extra source location directive follows rigt after ``name "the_struct"`` indicate that "the_struct" was originally declared in line 8, but not until line 9 -- the current ``debug_value`` instruction's source location -- does member ``y`` got updated with SSA value ``%1``.
35743587

3575-
Note that this instruction can be replaced by ``debug_value`` + di-expression operator that is equivalent to LLVM's ``DW_OP_deref``.
3588+
It is worth noting that a SIL DIExpression is similar to
3589+
`!DIExpression <https://www.llvm.org/docs/LangRef.html#diexpression>`_ in LLVM debug
3590+
info metadata. While LLVM represents ``!DIExpression`` are a list of 64-bit integers,
3591+
SIL DIExpression can have elements with various types, like AST nodes or strings.
35763592

35773593
Accessing Memory
35783594
~~~~~~~~~~~~~~~~

include/swift/ABI/Task.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/ABI/Metadata.h"
2424
#include "swift/ABI/MetadataValues.h"
2525
#include "swift/Runtime/Config.h"
26+
#include "swift/Runtime/VoucherShims.h"
2627
#include "swift/Basic/STLExtras.h"
2728
#include "bitset"
2829
#include "queue" // TODO: remove and replace with our own mpsc
@@ -72,7 +73,13 @@ class alignas(2 * alignof(void*)) Job :
7273
// Derived classes can use this to store a Job Id.
7374
uint32_t Id = 0;
7475

75-
void *Reserved[2] = {};
76+
/// The voucher associated with the job. Note: this is currently unused on
77+
/// non-Darwin platforms, with stub implementations of the functions for
78+
/// consistency.
79+
voucher_t Voucher = nullptr;
80+
81+
/// Reserved for future use.
82+
void *Reserved = nullptr;
7683

7784
// We use this union to avoid having to do a second indirect branch
7885
// when resuming an asynchronous task, which we expect will be the
@@ -88,23 +95,32 @@ class alignas(2 * alignof(void*)) Job :
8895
Job(JobFlags flags, JobInvokeFunction *invoke,
8996
const HeapMetadata *metadata = &jobHeapMetadata)
9097
: HeapObject(metadata), Flags(flags), RunJob(invoke) {
98+
Voucher = voucher_copy();
9199
assert(!isAsyncTask() && "wrong constructor for a task");
92100
}
93101

94102
Job(JobFlags flags, TaskContinuationFunction *invoke,
95-
const HeapMetadata *metadata = &jobHeapMetadata)
103+
const HeapMetadata *metadata = &jobHeapMetadata,
104+
bool captureCurrentVoucher = true)
96105
: HeapObject(metadata), Flags(flags), ResumeTask(invoke) {
106+
if (captureCurrentVoucher)
107+
Voucher = voucher_copy();
97108
assert(isAsyncTask() && "wrong constructor for a non-task job");
98109
}
99110

100111
/// Create a job with "immortal" reference counts.
101112
/// Used for async let tasks.
102113
Job(JobFlags flags, TaskContinuationFunction *invoke,
103-
const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal)
114+
const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal,
115+
bool captureCurrentVoucher = true)
104116
: HeapObject(metadata, immortal), Flags(flags), ResumeTask(invoke) {
117+
if (captureCurrentVoucher)
118+
Voucher = voucher_copy();
105119
assert(isAsyncTask() && "wrong constructor for a non-task job");
106120
}
107121

122+
~Job() { swift_voucher_release(Voucher); }
123+
108124
bool isAsyncTask() const {
109125
return Flags.isAsyncTask();
110126
}
@@ -229,8 +245,9 @@ class AsyncTask : public Job {
229245
/// Private.initialize separately.
230246
AsyncTask(const HeapMetadata *metadata, JobFlags flags,
231247
TaskContinuationFunction *run,
232-
AsyncContext *initialContext)
233-
: Job(flags, run, metadata),
248+
AsyncContext *initialContext,
249+
bool captureCurrentVoucher)
250+
: Job(flags, run, metadata, captureCurrentVoucher),
234251
ResumeContext(initialContext) {
235252
assert(flags.isAsyncTask());
236253
Id = getNextTaskId();
@@ -243,8 +260,9 @@ class AsyncTask : public Job {
243260
AsyncTask(const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal,
244261
JobFlags flags,
245262
TaskContinuationFunction *run,
246-
AsyncContext *initialContext)
247-
: Job(flags, run, metadata, immortal),
263+
AsyncContext *initialContext,
264+
bool captureCurrentVoucher)
265+
: Job(flags, run, metadata, immortal, captureCurrentVoucher),
248266
ResumeContext(initialContext) {
249267
assert(flags.isAsyncTask());
250268
Id = getNextTaskId();

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3756,8 +3756,13 @@ NOTE(add_self_to_type,none,
37563756
WARNING(warn_unqualified_access,none,
37573757
"use of %0 treated as a reference to %1 in %2 %3",
37583758
(Identifier, DescriptiveDeclKind, DescriptiveDeclKind, DeclName))
3759+
WARNING(self_refers_to_method,none,
3760+
"'self' refers to the method '%0.self', which may be unexpected",
3761+
(StringRef))
37593762
NOTE(fix_unqualified_access_member,none,
37603763
"use 'self.' to silence this warning", ())
3764+
NOTE(fix_unqualified_access_member_named_self,none,
3765+
"use '%0.self' to silence this warning", (StringRef))
37613766
NOTE(fix_unqualified_access_top_level,none,
37623767
"use '%0' to reference the %1",
37633768
(StringRef, DescriptiveDeclKind, Identifier))

include/swift/Runtime/VoucherShims.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//===--- VoucherShims.h - Shims for OS vouchers --------------------*- C++ -*-//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Shims for interfacing with OS voucher calls.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_CONCURRENCY_VOUCHERSHIMS_H
18+
#define SWIFT_CONCURRENCY_VOUCHERSHIMS_H
19+
20+
#include "Config.h"
21+
22+
// swift-corelibs-libdispatch has os/voucher_private.h but it doesn't work for
23+
// us yet, so only look for it on Apple platforms.
24+
#if __APPLE__ && __has_include(<os/voucher_private.h>)
25+
#define SWIFT_HAS_VOUCHER_HEADER 1
26+
#include <os/voucher_private.h>
27+
#endif
28+
29+
// A "dead" voucher pointer, indicating that a voucher has been removed from
30+
// a Job, distinct from a NULL voucher that could just mean no voucher was
31+
// present. This allows us to catch problems like adopting a voucher from the
32+
// same Job twice without restoring it.
33+
#define SWIFT_DEAD_VOUCHER ((voucher_t)-1)
34+
35+
// The OS has voucher support if it has the header or if it has ObjC interop.
36+
#if SWIFT_HAS_VOUCHER_HEADER || SWIFT_OBJC_INTEROP
37+
#define SWIFT_HAS_VOUCHERS 1
38+
#endif
39+
40+
#if SWIFT_HAS_VOUCHERS
41+
42+
#if SWIFT_HAS_VOUCHER_HEADER
43+
44+
static inline bool swift_voucher_needs_adopt(voucher_t _Nullable voucher) {
45+
if (__builtin_available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)) {
46+
return voucher_needs_adopt(voucher);
47+
}
48+
return true;
49+
}
50+
51+
#else
52+
53+
// If the header isn't available, declare the necessary calls here.
54+
55+
#include <os/object.h>
56+
57+
#pragma clang diagnostic push
58+
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
59+
OS_OBJECT_DECL_CLASS(voucher);
60+
#pragma clang diagnostic pop
61+
62+
extern "C" voucher_t _Nullable voucher_copy(void);
63+
64+
// Consumes argument, returns retained value.
65+
extern "C" voucher_t _Nullable voucher_adopt(voucher_t _Nullable voucher);
66+
67+
static inline bool swift_voucher_needs_adopt(voucher_t _Nullable voucher) {
68+
return true;
69+
}
70+
71+
#endif // __has_include(<os/voucher_private.h>)
72+
73+
static inline void swift_voucher_release(voucher_t _Nullable voucher) {
74+
// This NULL check isn't necessary, but NULL vouchers will be common, so
75+
// optimize for that.
76+
if (!voucher)
77+
return;
78+
if (voucher == SWIFT_DEAD_VOUCHER)
79+
return;
80+
os_release(voucher);
81+
}
82+
83+
#else // __APPLE__
84+
85+
// Declare some do-nothing stubs for OSes without voucher support.
86+
typedef void *voucher_t;
87+
static inline voucher_t _Nullable voucher_copy(void) { return nullptr; }
88+
static inline voucher_t _Nullable voucher_adopt(voucher_t _Nullable voucher) {
89+
return nullptr;
90+
}
91+
static inline bool swift_voucher_needs_adopt(voucher_t _Nullable voucher) {
92+
return true;
93+
}
94+
static inline void swift_voucher_release(voucher_t _Nullable voucher) {}
95+
#endif // __APPLE__
96+
97+
#endif

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1797,12 +1797,17 @@ SwiftDeclCollector::addMembersToRoot(SDKNode *Root, IterableDeclContext *Context
17971797
Root->addChild(constructSubscriptDeclNode(SD));
17981798
} else if (isa<PatternBindingDecl>(Member)) {
17991799
// All containing variables should have been handled.
1800+
} else if (isa<EnumCaseDecl>(Member)) {
1801+
// All containing variables should have been handled.
1802+
} else if (isa<IfConfigDecl>(Member)) {
1803+
// All containing members should have been handled.
18001804
} else if (isa<DestructorDecl>(Member)) {
18011805
// deinit has no impact.
18021806
} else if (isa<MissingMemberDecl>(Member)) {
18031807
// avoid adding MissingMemberDecl
18041808
} else {
1805-
llvm_unreachable("unhandled member decl kind.");
1809+
llvm::errs() << "Unhandled decl:\n";
1810+
Member->dump(llvm::errs());
18061811
}
18071812
}
18081813
}

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,11 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
9797
}
9898

9999
unsigned i = Rules.size();
100-
Rules.emplace_back(Term::get(lhs, Context), Term::get(rhs, Context));
100+
101+
auto uniquedLHS = Term::get(lhs, Context);
102+
auto uniquedRHS = Term::get(rhs, Context);
103+
Rules.emplace_back(uniquedLHS, uniquedRHS);
104+
101105
auto oldRuleID = Trie.insert(lhs.begin(), lhs.end(), i);
102106
if (oldRuleID) {
103107
llvm::errs() << "Duplicate rewrite rule!\n";
@@ -112,23 +116,7 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
112116
abort();
113117
}
114118

115-
// Check if we have a rule of the form
116-
//
117-
// X.[P1:T] => X.[P2:T]
118-
//
119-
// If so, record this rule for later. We'll try to merge the associated
120-
// types in RewriteSystem::processMergedAssociatedTypes().
121-
if (lhs.size() == rhs.size() &&
122-
std::equal(lhs.begin(), lhs.end() - 1, rhs.begin()) &&
123-
lhs.back().getKind() == Symbol::Kind::AssociatedType &&
124-
rhs.back().getKind() == Symbol::Kind::AssociatedType &&
125-
lhs.back().getName() == rhs.back().getName()) {
126-
if (Debug.contains(DebugFlags::Merge)) {
127-
llvm::dbgs() << "## Associated type merge candidate ";
128-
llvm::dbgs() << lhs << " => " << rhs << "\n\n";
129-
}
130-
MergedAssociatedTypes.emplace_back(lhs, rhs);
131-
}
119+
checkMergedAssociatedType(uniquedLHS, uniquedRHS);
132120

133121
// Tell the caller that we added a new rule.
134122
return true;

0 commit comments

Comments
 (0)