Skip to content

[pull] swiftwasm from main #3464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Sep 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
78ffd65
[NFC] Remove old comment related to port diagnostics to new framework
LucianoPAlmeida Aug 27, 2021
f97ef0b
[doc] Update SIL.rst to reflect debug_value_addr deprecation
mshockwave Sep 1, 2021
f405364
add warning/note to DiagnosticsSema for SR-4559 (unapplied reference …
jackgmarch Aug 6, 2021
233f4c9
test cases for SR-4559 (unapplied reference to method named "self" ca…
jackgmarch Aug 20, 2021
7e0a7f3
fix SR-4559 (unapplied reference to method named "self" can be used w…
jackgmarch Aug 20, 2021
a80a19b
[Concurrency] Propagate Darwin vouchers across async tasks.
mikeash Aug 27, 2021
c77faaf
[test] When using swift-ide-test specify a resource dir.
gottesmm Sep 2, 2021
62f56d7
RequirementMachine: Skip trivial overlaps
slavapestov Aug 19, 2021
9fac25d
RequirementMachine: Clean up merged associated type algorithm some more
slavapestov Aug 30, 2021
5790c70
Sema: Add recursion guard to AssociatedTypeInference::computeFixedTyp…
slavapestov Aug 30, 2021
9a64e50
Sema: Fix type resolution with invalid nested protocol
slavapestov Sep 2, 2021
32d416a
Merge pull request #39157 from slavapestov/misc-rqm-fixes
slavapestov Sep 3, 2021
c4115cc
Merge pull request #39115 from mikeash/voucher-propagation
mikeash Sep 3, 2021
09f3d99
[Concurrency] Add availability checking when calling voucher_needs_ad…
mikeash Sep 3, 2021
cd7d105
runtime: remove workaround for Windows ARM64
compnerd Sep 3, 2021
0ef4bcd
Merge pull request #39149 from gottesmm/pr-fd7e667165e7ab9b9b96aa08a4…
gottesmm Sep 3, 2021
456f03f
Merge pull request #39123 from mshockwave/dev-debug-inst-doc-update
mshockwave Sep 3, 2021
433215f
Disable test while MikeA fixes it to unblock the builds.
gottesmm Sep 3, 2021
b8fff85
Merge pull request #39165 from gottesmm/pr-17b9d5195c89c1fad251d0b99f…
gottesmm Sep 3, 2021
e2c583e
Merge pull request #39163 from mikeash/voucher-availability
gottesmm Sep 3, 2021
b721488
Merge pull request #37992 from jackgmarch/SR-4559
xedin Sep 3, 2021
a8b95cb
ABIChecker: don't fail when hitting EnumCaseDecl
nkcsgexi Sep 3, 2021
cc8f0bb
Merge pull request #39164 from compnerd/cleanup-arm64
compnerd Sep 3, 2021
e4e2cdd
Merge pull request #39074 from LucianoPAlmeida/minor-fixes
xedin Sep 4, 2021
dd32711
Merge pull request #39167 from nkcsgexi/handle-EnumCaseDecl-abi
nkcsgexi Sep 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 65 additions & 49 deletions docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3493,11 +3493,10 @@ debug_value

debug_value %1 : $Int

This indicates that the value of a declaration with loadable type has changed
value to the specified operand. The declaration in question is identified by
the SILLocation attached to the debug_value instruction.

The operand must have loadable type.
This indicates that the value of a declaration has changed value to the
specified operand. The declaration in question is identified by either the
SILLocation attached to the debug_value instruction or the SILLocation specified
in the advanced debug variable attributes.

::

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

::

advanced-debug-var-attr ::= '(' 'name' string-literal (',' sil-instruction-source-info)? ')'
advanced-debug-var-attr ::= 'type' sil-type

::

debug-info-expr ::= di-expr-operand (':' di-expr-operand)*
di-expr-operand ::= di-expr-operator (':' sil-operand)*
di-expr-operator ::= 'op_fragment'

There are a number of attributes that provide details about the source
variable that is being described, including the name of the
variable. For function and closure arguments ``argno`` is the number
of the function argument starting with 1. A compiler-generated source
variable will be marked ``implicit`` and optimizers are free to remove
it even in -Onone. The advanced debug variable attributes represent source
locations and type of the source variable when it was originally declared.
It is useful when we're indirectly associating the SSA value with the
source variable (via di-expression, for example) in which case SSA value's
type is different from that of source variable.
it even in -Onone.

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

Debug info expression (di-expression) is a powerful method to connect SSA
value with the source variable in an indirect fashion. For example,
we can use the ``op_fragment`` operator to specify that the SSA value
is originated from a struct field inside the source variable (which has
an aggregate data type). Di-expression in SIL works similarly to LLVM's
``!DIExpression`` metadata. Where both of them adopt a stack based
execution model to evaluate the expression. The biggest difference between
them is that LLVM always represent ``!DIExpression`` elements as 64-bit
integers, while SIL's di-expression can have elements with various types,
like AST nodes or strings. Here is an example::
::

advanced-debug-var-attr ::= '(' 'name' string-literal (',' sil-instruction-source-info)? ')'
advanced-debug-var-attr ::= 'type' sil-type

Advanced debug variable attributes represent source locations and the type of
the source variable when it was originally declared. It is useful when
we're indirectly associating the SSA value with the source variable
(via SIL DIExpression, for example) in which case SSA value's type is different
from that of source variable.

::

debug-info-expr ::= di-expr-operand (':' di-expr-operand)*
di-expr-operand ::= di-expr-operator (':' sil-operand)*
di-expr-operator ::= 'op_fragment'
di-expr-operator ::= 'op_deref'

SIL debug info expression (SIL DIExpression) is a powerful method to connect SSA
value with the source variable in an indirect fashion. Di-expression in SIL
uses a stack based execution model to evaluate the expression and apply on
the associated (SIL) SSA value before connecting it with the debug variable.
For instance, given the following SIL code::

debug_value %a : $*Int, name "x", expr op_deref

It means: "You can get the value of source variable 'x' by *dereferencing*
SSA value ``%a``". The ``op_deref`` is a SIL DIExpression operator that represents
"dereference". If there are multiple SIL DIExpression operators (or arguments), they
are evaluated from left to right::

debug_value %b : $**Int, name "y", expr op_deref:op_deref

In the snippet above, two ``op_deref`` operators will be applied on SSA value
``%b`` sequentially.

Note that normally when the SSA value has an address type, there will be a ``op_deref``
in the SIL DIExpression. Because there is no pointer in Swift so you always need to
dereference an address-type SSA value to get the value of a source variable.
However, if the SSA value is a ``alloc_stack``, the ``debug_value`` is used to indicate
the *declaration* of a source variable. Or, you can say, used to specify the location
(memory address) of the source variable. Therefore, we don't need to add a ``op_deref``
in this case::

%a = alloc_stack $Int, ...
debug_value %a : $*Int, name "my_var"


The ``op_fragment`` operator is used to specify the SSA value of a specific
field in an aggregate-type source variable. This SIL DIExpression operator takes
a field declaration -- which references the desired sub-field in source variable
-- as its argument. Here is an example::

struct MyStruct {
var x: Int
Expand All @@ -3556,23 +3582,13 @@ like AST nodes or strings. Here is an example::
...
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

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``.

debug_value_addr
````````````````

::

sil-instruction ::= debug_value_addr sil-operand (',' debug-var-attr)* advanced-debug-var-attr* (',' 'expr' debug-info-expr)?

debug_value_addr %7 : $*SomeProtocol

This indicates that the value of a declaration with address-only type
has changed value to the specified operand. The declaration in
question is identified by the SILLocation attached to the
debug_value_addr instruction.
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".
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``.

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

Accessing Memory
~~~~~~~~~~~~~~~~
Expand Down
32 changes: 25 additions & 7 deletions include/swift/ABI/Task.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "swift/ABI/Metadata.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/Runtime/Config.h"
#include "swift/Runtime/VoucherShims.h"
#include "swift/Basic/STLExtras.h"
#include "bitset"
#include "queue" // TODO: remove and replace with our own mpsc
Expand Down Expand Up @@ -72,7 +73,13 @@ class alignas(2 * alignof(void*)) Job :
// Derived classes can use this to store a Job Id.
uint32_t Id = 0;

void *Reserved[2] = {};
/// The voucher associated with the job. Note: this is currently unused on
/// non-Darwin platforms, with stub implementations of the functions for
/// consistency.
voucher_t Voucher = nullptr;

/// Reserved for future use.
void *Reserved = nullptr;

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

Job(JobFlags flags, TaskContinuationFunction *invoke,
const HeapMetadata *metadata = &jobHeapMetadata)
const HeapMetadata *metadata = &jobHeapMetadata,
bool captureCurrentVoucher = true)
: HeapObject(metadata), Flags(flags), ResumeTask(invoke) {
if (captureCurrentVoucher)
Voucher = voucher_copy();
assert(isAsyncTask() && "wrong constructor for a non-task job");
}

/// Create a job with "immortal" reference counts.
/// Used for async let tasks.
Job(JobFlags flags, TaskContinuationFunction *invoke,
const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal)
const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal,
bool captureCurrentVoucher = true)
: HeapObject(metadata, immortal), Flags(flags), ResumeTask(invoke) {
if (captureCurrentVoucher)
Voucher = voucher_copy();
assert(isAsyncTask() && "wrong constructor for a non-task job");
}

~Job() { swift_voucher_release(Voucher); }

bool isAsyncTask() const {
return Flags.isAsyncTask();
}
Expand Down Expand Up @@ -229,8 +245,9 @@ class AsyncTask : public Job {
/// Private.initialize separately.
AsyncTask(const HeapMetadata *metadata, JobFlags flags,
TaskContinuationFunction *run,
AsyncContext *initialContext)
: Job(flags, run, metadata),
AsyncContext *initialContext,
bool captureCurrentVoucher)
: Job(flags, run, metadata, captureCurrentVoucher),
ResumeContext(initialContext) {
assert(flags.isAsyncTask());
Id = getNextTaskId();
Expand All @@ -243,8 +260,9 @@ class AsyncTask : public Job {
AsyncTask(const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal,
JobFlags flags,
TaskContinuationFunction *run,
AsyncContext *initialContext)
: Job(flags, run, metadata, immortal),
AsyncContext *initialContext,
bool captureCurrentVoucher)
: Job(flags, run, metadata, immortal, captureCurrentVoucher),
ResumeContext(initialContext) {
assert(flags.isAsyncTask());
Id = getNextTaskId();
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3756,8 +3756,13 @@ NOTE(add_self_to_type,none,
WARNING(warn_unqualified_access,none,
"use of %0 treated as a reference to %1 in %2 %3",
(Identifier, DescriptiveDeclKind, DescriptiveDeclKind, DeclName))
WARNING(self_refers_to_method,none,
"'self' refers to the method '%0.self', which may be unexpected",
(StringRef))
NOTE(fix_unqualified_access_member,none,
"use 'self.' to silence this warning", ())
NOTE(fix_unqualified_access_member_named_self,none,
"use '%0.self' to silence this warning", (StringRef))
NOTE(fix_unqualified_access_top_level,none,
"use '%0' to reference the %1",
(StringRef, DescriptiveDeclKind, Identifier))
Expand Down
97 changes: 97 additions & 0 deletions include/swift/Runtime/VoucherShims.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//===--- VoucherShims.h - Shims for OS vouchers --------------------*- C++ -*-//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 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
//
//===----------------------------------------------------------------------===//
//
// Shims for interfacing with OS voucher calls.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_CONCURRENCY_VOUCHERSHIMS_H
#define SWIFT_CONCURRENCY_VOUCHERSHIMS_H

#include "Config.h"

// swift-corelibs-libdispatch has os/voucher_private.h but it doesn't work for
// us yet, so only look for it on Apple platforms.
#if __APPLE__ && __has_include(<os/voucher_private.h>)
#define SWIFT_HAS_VOUCHER_HEADER 1
#include <os/voucher_private.h>
#endif

// A "dead" voucher pointer, indicating that a voucher has been removed from
// a Job, distinct from a NULL voucher that could just mean no voucher was
// present. This allows us to catch problems like adopting a voucher from the
// same Job twice without restoring it.
#define SWIFT_DEAD_VOUCHER ((voucher_t)-1)

// The OS has voucher support if it has the header or if it has ObjC interop.
#if SWIFT_HAS_VOUCHER_HEADER || SWIFT_OBJC_INTEROP
#define SWIFT_HAS_VOUCHERS 1
#endif

#if SWIFT_HAS_VOUCHERS

#if SWIFT_HAS_VOUCHER_HEADER

static inline bool swift_voucher_needs_adopt(voucher_t _Nullable voucher) {
if (__builtin_available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)) {
return voucher_needs_adopt(voucher);
}
return true;
}

#else

// If the header isn't available, declare the necessary calls here.

#include <os/object.h>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
OS_OBJECT_DECL_CLASS(voucher);
#pragma clang diagnostic pop

extern "C" voucher_t _Nullable voucher_copy(void);

// Consumes argument, returns retained value.
extern "C" voucher_t _Nullable voucher_adopt(voucher_t _Nullable voucher);

static inline bool swift_voucher_needs_adopt(voucher_t _Nullable voucher) {
return true;
}

#endif // __has_include(<os/voucher_private.h>)

static inline void swift_voucher_release(voucher_t _Nullable voucher) {
// This NULL check isn't necessary, but NULL vouchers will be common, so
// optimize for that.
if (!voucher)
return;
if (voucher == SWIFT_DEAD_VOUCHER)
return;
os_release(voucher);
}

#else // __APPLE__

// Declare some do-nothing stubs for OSes without voucher support.
typedef void *voucher_t;
static inline voucher_t _Nullable voucher_copy(void) { return nullptr; }
static inline voucher_t _Nullable voucher_adopt(voucher_t _Nullable voucher) {
return nullptr;
}
static inline bool swift_voucher_needs_adopt(voucher_t _Nullable voucher) {
return true;
}
static inline void swift_voucher_release(voucher_t _Nullable voucher) {}
#endif // __APPLE__

#endif
7 changes: 6 additions & 1 deletion lib/APIDigester/ModuleAnalyzerNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1797,12 +1797,17 @@ SwiftDeclCollector::addMembersToRoot(SDKNode *Root, IterableDeclContext *Context
Root->addChild(constructSubscriptDeclNode(SD));
} else if (isa<PatternBindingDecl>(Member)) {
// All containing variables should have been handled.
} else if (isa<EnumCaseDecl>(Member)) {
// All containing variables should have been handled.
} else if (isa<IfConfigDecl>(Member)) {
// All containing members should have been handled.
} else if (isa<DestructorDecl>(Member)) {
// deinit has no impact.
} else if (isa<MissingMemberDecl>(Member)) {
// avoid adding MissingMemberDecl
} else {
llvm_unreachable("unhandled member decl kind.");
llvm::errs() << "Unhandled decl:\n";
Member->dump(llvm::errs());
}
}
}
Expand Down
24 changes: 6 additions & 18 deletions lib/AST/RequirementMachine/RewriteSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
}

unsigned i = Rules.size();
Rules.emplace_back(Term::get(lhs, Context), Term::get(rhs, Context));

auto uniquedLHS = Term::get(lhs, Context);
auto uniquedRHS = Term::get(rhs, Context);
Rules.emplace_back(uniquedLHS, uniquedRHS);

auto oldRuleID = Trie.insert(lhs.begin(), lhs.end(), i);
if (oldRuleID) {
llvm::errs() << "Duplicate rewrite rule!\n";
Expand All @@ -112,23 +116,7 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
abort();
}

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

// Tell the caller that we added a new rule.
return true;
Expand Down
Loading