* Add UnsafeRawPointer type and API.
As proposed in SE-0107: UnsafeRawPointer.
https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md
The fundamental difference between Unsafe[Mutable]RawPointer and
Unsafe[Mutable]Pointer<Pointee> is simply that the former is used for "untyped"
memory access, and the later is used for "typed" memory access. Let's refer to
these as "raw pointers" and "typed pointers". Because operations on raw pointers
access untyped memory, the compiler cannot make assumptions about the underlying
type of memory and must be conservative. With operations on typed pointers, the
compiler may make strict assumptions about the type of the underlying memory,
which allows more aggressive optimization.
Memory can only be accessed by a typed pointer when it is currently
bound to the Pointee type. Memory can be bound to type `T` via:
- `UnsafePointer<T>.allocate(capacity: n)`
- `UnsafePointer<Pointee>.withMemoryRebound(to: T.self, capacity: n) {...}`
- `UnsafeMutableRawPointer.initializeMemory(as: T.self, at: i, count: n, to: x)`
- `UnsafeMutableRawPointer.initializeMemory(as: T.self, from: p, count: n)`
- `UnsafeMutableRawPointer.moveInitializeMemory(as: T.self, from: p, count: n)`
- `UnsafeMutableRawPointer.bindMemory(to: T.self, capacity: n)`
Mangle UnsafeRawPointer as predefined substitution 'Sv' for Swift void
pointer ([urp] are taken).
* UnsafeRawPointer minor improvements.
Incorporate Dmitri's feedback.
Properly use a _memmove helper.
Add load/storeBytes alignment precondition checks.
Reword comments.
Demangler tests.
* Fix name mangling test cases.
* Fix bind_memory specialization.
(in preparation for the private/fileprivate split)
An "access scope" is the outermost DeclContext where a particular
declaration may be referenced: for a 'fileprivate' declaration it's
the enclosing file, and for an 'internal' declaration it's the module.
'public' corresponds to a scope of "everything", represented by a null
DeclContext.
This model extends naturally to the (not-yet-implemented) SE-0025
notion of 'private', where the access scope is a declaration's
immediately enclosing DeclContext.
Complicating this model is the revised rules that allow, e.g., a public
declaration to be declared within an internal type. The access scope
for this declaration is still just the module, not "everything".
This commit reworks formal access control checking in terms of this
model, including tightening up some of the handling for '@testable'.
This implements the rule that you must be able to access a declaration's
type everywhere you can reference the declaration.
This was not intended to change compiler behavior, but in practice it
has made cross-file dependency tracking a bit more conservative
(unnecessarily), caught a mistake in diagnosing access violations,
and fixed a fuzzer-based crasher (see test changes).
Progress on SE-0025 ('private' and 'fileprivate')
Change the 'G' mangling to include generic parameters from
all levels of nested nominal types, and not just the innermost.
Note that the raw mangling syntax is something like this for
a nested type 'A<Int>.B<String>':
- bound_generic
- struct 'B'
- struct 'A'
- module 'M'
- args
- Int
- args
- String
However, the actual mangling tree is more along the lines of:
- bound_generic_struct 'B'
- bound_generic_struct 'A'
- module 'M'
- args
- Int
- args
- String
This arrangement improves the quality of substitutions (we are
more likely to have a substitution for the entire unbound
generic type name 'A.B' around), and simplifies a few other
details.
Unfortunately, the remangling logic becomes slightly grotesque.
A simple SILGen test for nested generics exercises the mangling,
and ensures that Sema and SILGen do not crash with nested generics.
More detailed SILGen tests, as well as IRGen support for nested
generics is next.
Consider this code:
struct A<T> {
struct B {}
struct C<U> {}
}
Previously:
- getDeclaredType() of 'A.B' would give 'A<T>.B'
- getDeclaredTypeInContext() of 'A.B' would give 'A<T>.B'
- getDeclaredType() of 'A.C' would give 'A<T>.C'
- getDeclaredTypeInContext() of 'A.C' would give 'A<T>.C<U>'
This was causing problems for nested generics. Now, with this change,
- getDeclaredType() of 'A.B' gives 'A.B' (*)
- getDeclaredTypeInContext() of 'A.B' gives 'A<T>.B'
- getDeclaredType() of 'A.C' gives 'A.C' (*)
- getDeclaredTypeInContext() of 'A.C' gives 'A<T>.C<U>'
(Differences marked with (*)).
Also, this change makes these accessors fully lazy. Previously,
only getDeclaredTypeInContext() and getDeclaredIterfaceType()
were lazy, whereas getDeclaredType() was built from validateDecl().
Fix a few spots where the return value wasn't being checked
properly.
These functions return ErrorType if a circularity was detected via
the generic parameter list, or if the extension did not resolve.
They return Type() if the extension cannot be resolved *yet*.
This is pretty subtle, and I'll need to do another pass over
callers of these functions at some point. Many of them should be
moved over to use getSelfInContext(), getSelfOfContext() and
getSelfInterfaceType() instead.
Finally, this patch consolidates logic for diagnosting invalid
nesting of types.
The parser had some code for protocols in bad places and bad things
inside protocols, and Sema had several different bail-outs for
bad things in protocols, nested generic types, and stuff nested
inside protocol extensions.
Combine all of these into a single set of checks in Sema. Note
that we no longer give up early if we find invalid nesting.
Leaving decls unvalidated and un-type-checked only leads to
further problems. Now that all the preliminary crap has been
fixed, we can go ahead and start validating these funny nested
decls, actually fixing some crashers in the process.
If a behavior has storage that can be initialized out-of-line, generate code in SILGen that uses stores to mark_uninitialized_behavior for eventual analysis by DI.
This is incomplete, particularly, it's missing code generation of glue thunks for accessors that require reabstraction, but I wanted to make sure the progress here didn't bitrot.
Now that we have ArchetypeBuilder::mapTypeOutOfContext(), we can
delete some tricky hand-crafted logic for getting the depth and
index of archetypes.
Notice that the depth of an archetype is now the same as generic
parameters, where depth 0 is the outermost generic context.
Previously it was backwards.
Mostly NFC, except that a few IDE crashers are now fixed because
of asserts firing in removed code, and also the change to depth
mangling (which I think makes sense, and it matches what's written
in docs/ABI.rst).
not have access to their type arguments at runtime. Use this to
fix the emission of native thunks for imported ObjC-generic
initializers, since they may need to perform bridging.
For now, pseudo-genericity is all-or-nothing, but we may want to
make it apply only to certain type arguments.
Also, clean up some code that was using dead mangling nodes.
...by mangling them the same as any other value decl. This is important for debug info to
preserve and recover a private typealias.
rdar://problem/24921067
This reorganization allows adding attributes that refer to types.
I need this for a @_specialize attribute with a type list.
PrintOptions.h and other headers depend on these enums. But Attr.h
defines a lot of classes that almost never need to be included.
Fix some interface type/context type confusion in the AST synthesis from the previous patch, add a unique private mangling for behavior protocol conformances, and set up SILGen to emit the conformances when property declarations with behaviors are visited. Disable synthesis of the struct memberwise initializer if any instance properties use behaviors; codegen will need to be redesigned here.
Similarly to how we've always handled parameter types, we
now recursively expand tuples in result types and separately
determine a result convention for each result.
The most important code-generation change here is that
indirect results are now returned separately from each
other and from any direct results. It is generally far
better, when receiving an indirect result, to receive it
as an independent result; the caller is much more likely
to be able to directly receive the result in the address
they want to initialize, rather than having to receive it
in temporary memory and then copy parts of it into the
target.
The most important conceptual change here that clients and
producers of SIL must be aware of is the new distinction
between a SILFunctionType's *parameters* and its *argument
list*. The former is just the formal parameters, derived
purely from the parameter types of the original function;
indirect results are no longer in this list. The latter
includes the indirect result arguments; as always, all
the indirect results strictly precede the parameters.
Apply instructions and entry block arguments follow the
argument list, not the parameter list.
A relatively minor change is that there can now be multiple
direct results, each with its own result convention.
This is a minor change because I've chosen to leave
return instructions as taking a single operand and
apply instructions as producing a single result; when
the type describes multiple results, they are implicitly
bound up in a tuple. It might make sense to split these
up and allow e.g. return instructions to take a list
of operands; however, it's not clear what to do on the
caller side, and this would be a major change that can
be separated out from this already over-large patch.
Unsurprisingly, the most invasive changes here are in
SILGen; this requires substantial reworking of both call
emission and reabstraction. It also proved important
to switch several SILGen operations over to work with
RValue instead of ManagedValue, since otherwise they
would be forced to spuriously "implode" buffers.
As part of this, use a different enum for parsed generic requirements.
NFC except that I noticed that ASTWalker wasn't visiting the second
type in a conformance constraint; fixing this seems to have no effect
beyond producing better IDE annotations.
This is necessary for some other work I'm doing, which really wants
paramdecls to have reasonable declcontexts. It is also a small step
towards generic subscripts.
This commit is related to the work of encoding mangled names more efficiently by
compressing them. This commit adds two new methods to the mangler that allows it
to identify requests to mangle strings that are already mangled. Right now the
mangler does not do anything with this information.
This API is needed in all of the places in the compiler where we compose mangled
names. For example, when the optimizer is cloning functions it adds a prefix to
an existing name.
I verified that this change is correct by adding a compress/decompress methods
that add a prefix to the mangled names with assertions to catch compression of
already compressed symbols or decompression of non-compressed named. I plan to
commit the verification code together with the compression implementation later
on.
This commit changes the Swift mangler from a utility that writes tokens into a
stream into a name-builder that has two phases: "building a name", and "ready".
This clear separation is needed for the implementation of the compression layer.
Users of the mangler can continue to build the name using the mangleXXX methods,
but to access the results the users of the mangler need to call the finalize()
method. This method can write the result into a stream, like before, or return
an std::string.
to make sure we are not accessing the buffer before the output is ready. The Mangler is going to be buffered (for compression), and accessing the underlying buffer is a bug.
Use 'XH' rather than 'H' for SIL box types to keep SIL-specific concepts
under 'X' rather than claiming more of the top-level mangling namespace.
Suggested by @jckarter.
The SIL optimizer's closure specialization pass clones functions that
take closures as arguments and generates a new function with a direct
call to the closure function. The cloned function has new arguments
added for the values that are captured by the closure.
In the cases where the closure takes a @box argument, we were hitting an
assert attempting to mangle the name of the newly generated function,
since it now has a @box argument as a parameter. We don't normally
expect @box arguments during mangling because they do not exist prior to
SILGen, but since we generate new manglings throughout the optimizer we
need to be able to mangle (and demangle) these types.
Fixes rdar://problem/23893290.
Modeling nonescaping captures as @inout parameters is wrong, because captures are allowed to share state, unlike 'inout' parameters, which are allowed to assume to some degree that there are no aliases during the parameter's scope. To model this, introduce a new @inout_aliasable parameter convention to indicate an indirect parameter that can be written to, not only by the current function, but by well-typed, well-synchronized aliasing accesses too. (This is unrelated to our discussions of adding a "type-unsafe-aliasable" annotation to pointer_to_address to allow for safe pointer punning.)
And include some supplementary mangling changes:
- Give the first generic param (depth=0, index=0) a single character mangling. Even after removing the self type from method declaration types, 'Self' still shows up very frequently in protocol requirement signatures.
- Fix the mangling of generic parameter counts to elide the count when there's only one parameter at the starting depth of the mangling.
Together these carve another 154KB out of a debug standard library. There's some awkwardness in demangled strings that I'll clean up in subsequent commits; since decl types now only mangle the number of generic params at their own depth, it's context-dependent what depths those represent, which we get wrong now. Currying markers are also wrong, but since free function currying is going away, we can mangle the partial application thunks in different ways.
Swift SVN r32896
Canonical dependent member types are always based from a generic parameter, so we can use a more optimal mangling that assumes this. We can also introduce substitutions for AssociatedTypeDecls, and when a generic parameter in a signature is constrained by a single protocol, we can leave that protocol qualification out of the unsubstituted associated type mangling. These optimizations together shrink the standard library by 117KB, and bring the length of the longest Swift symbol in the stdlib down from 578 to 334 characters, shorter than the longest C++ symbol in the stdlib.
Swift SVN r32786
A microoptimization; since the module is likely to come up often in the subsequent mangling, we want to make it more likely to get the coveted S_ substitution.
Swift SVN r32784
Together, UnsafePointer, UnsafeMutablePointer, UnsafeBufferPointer, and UnsafeMutableBufferPointer appear in standard library manglings over 1000 times, and they're fairly long names. Giving them standard substitutions shrinks the stdlib by 44KB.
Swift SVN r32410
'Ss' appears in manglings tens of thousands of times in the standard library and is also incredibly frequent in other modules. This alone is enough to shrink the standard library by 59KB.
Swift SVN r32409
When -disable-self-type-mangling is set, mangle the decl type of methods without the encoding of the self type or any generic requirements from the context, since these are implied by the context mangling and aren't needed to uniquely identify the method. Doing this saves 150KB in the standard library. Before:
$ ls -l lib/swift/macosx/libswiftCore.dylib
-rwxr-xr-x 1 jgroff staff 9358140 Oct 1 11:14 lib/swift/macosx/libswiftCore.dylib
$ nm lib/swift/macosx/libswiftCore.dylib | wc -c
1475338
After:
$ ls -l lib/swift/macosx/libswiftCore.dylib
-rwxr-xr-x 1 jgroff staff 9204428 Oct 1 13:59 lib/swift/macosx/libswiftCore.dylib
$ nm lib/swift/macosx/libswiftCore.dylib | wc -c
1421702
This is hidden behind a flag because it doesn't yet have de/remangling support, and because we'll need to make sure the debugger and other clients can recover declaration types reasonably without help from the mangling.
Swift SVN r32399
This is more resilient, since we want to be able to add more information behind the address point of type objects. The start of the metadata object is now an internal "full metadata" symbol.
Note that we can't do this for known opaque metadata from the C++ runtime, since clang doesn't have a good way to emit offset symbol aliases, so for non-nominal metadata objects we still emit an adjustment inline. We also aren't able to generate references to aliases within the same module due to an MC bug with alias refs on i386 and armv7 (rdar://problem/22450593).
Swift SVN r31523