Commit Graph

1223 Commits

Author SHA1 Message Date
Hamish Knight
c667d2b361 Use DefaultArgumentExpr for caller-side defaults
This commit changes how we represent caller-side
default arguments within the AST. Instead of
directly inserting them into the call-site, use
a DefaultArgumentExpr to refer to them indirectly.

The main goal of this change is to make it such
that the expression type-checker no longer cares
about the difference between caller-side and
callee-side default arguments. In particular, it
no longer cares about whether a caller-side
default argument is well-formed when type-checking
an apply. This is important because any
conversions introduced by the default argument
shouldn't affect the score of the resulting
solution.

Instead, caller-side defaults are now lazily
type-checked when we want to emit them in SILGen.
This is done through introducing a request, and
adjusting the logic in SILGen to be more lenient
with ErrorExprs. Caller-side defaults in primary
files are still also currently checked as a part
of the declaration by `checkDefaultArguments`.

Resolves SR-11085.
Resolves rdar://problem/56144412.
2019-11-20 15:07:32 -08:00
Slava Pestov
7c145fb7be Merge pull request #27951 from zoecarver/key-path-default-arg
Fix KeyPath with default arg
2019-11-19 00:04:51 -05:00
zoecarver
a8953b1f6d Format with clang-format 2019-11-17 14:29:26 -08:00
zoecarver
3a98452295 Add FileCheck tests 2019-11-12 18:12:43 -08:00
zoecarver
800feda1d7 Fix spacing 2019-11-12 13:36:22 -08:00
zoecarver
08244697d1 Format properly 2019-11-12 13:24:49 -08:00
zoecarver
0f3dd52972 Use correct function type to prevent conflicting argument types 2019-11-12 13:23:31 -08:00
zoecarver
51dc7c8535 Create emitKeyPathSubscriptOperands to lower all the args properly (including the default ones) 2019-11-11 19:35:47 -08:00
zoecarver
e385439e6e Use ArgEmitter 2019-11-11 16:10:48 -08:00
Arnold Schwaighofer
33f4f57cc4 SILGen: Add TypeExpansionContext to SILGen 2019-11-11 14:21:52 -08:00
Robert Widmann
3e1a61f425 [NFC] Fold The Tri-State In Optional<ProtocolConformanceRef>
ProtocolConformanceRef already has an invalid state.  Drop all of the
uses of Optional<ProtocolConformanceRef> and just use
ProtocolConformanceRef::forInvalid() to represent it.  Mechanically
translate all of the callers and callsites to use this new
representation.
2019-10-29 16:55:56 -07:00
Joe Groff
03c7919b4a SIL: Add fields to SILFunctionType for substituted function types.
https://forums.swift.org/t/improving-the-representation-of-polymorphic-interfaces-in-sil-with-substituted-function-types/29711

This prepares SIL to be able to more accurately preserve the calling convention of
polymorphic generic interfaces by letting the type system represent "substituted function types".
We add a couple of fields to SILFunctionType to support this:

- A substitution map, accessed by `getSubstitutions()`, which maps the generic signature
  of the function to its concrete implementation. This will allow, for instance, a protocol
  witness for a requirement of type `<Self: P> (Self, ...) -> ...` for a concrete conforming
  type `Foo` to express its type as `<Self: P> (Self, ...) -> ... for <Foo>`, preserving the relation
  to the protocol interface without relying on the pile of hacks that is the `witness_method`
  protocol.

- A bool for whether the generic signature of the function is "implied" by the substitutions.
  If true, the generic signature isn't really part of the calling convention of the function.
  This will allow closure types to distinguish a closure being passed to a generic function, like
  `<T, U> in (*T, *U) -> T for <Int, String>`, from the concrete type `(*Int, *String) -> Int`,
  which will make it easier for us to differentiate the representation of those as types, for
  instance by giving them different pointer authentication discriminators to harden arm64e
  code.

This patch is currently NFC, it just introduces the new APIs and takes a first pass at updating
code to use them. Much more work will need to be done once we start exercising these new
fields.

This does bifurcate some existing APIs:

- SILFunctionType now has two accessors to get its generic signature.
  `getSubstGenericSignature` gets the generic signature that is used to apply its
  substitution map, if any. `getInvocationGenericSignature` gets the generic signature
  used to invoke the function at apply sites. These differ if the generic signature is
  implied.
- SILParameterInfo and SILResultInfo values carry the unsubstituted types of the parameters
  and results of the function. They now have two APIs to get that type. `getInterfaceType`
  returns the unsubstituted type of the generic interface, and
  `getArgumentType`/`getReturnValueType` produce the substituted type that is used at
  apply sites.
2019-10-25 13:38:51 -07:00
Brent Royal-Gordon
f44077b5c5 Merge pull request #27619 from brentdax/epic-wrap-battles-of-property
Fix property wrapper crasher
2019-10-11 19:23:13 -07:00
Brent Royal-Gordon
f27a58c757 Fix property wrapper crasher
Due to insufficiently robust argument emission code, certain combinations of language features could cause a call to a property wrapper backing initalizer to have mismatched argument types, causing an assertion failure in SILGenApply. This commit moves SILGenFunction::emitApplyOfPropertyWrapperBackingInitializer() into SILGenApply so it can use CallEmission and PreparedArguments to emit the call with full generality. Fixes rdar://problem/55995892.
2019-10-10 22:07:11 -07:00
Jordan Rose
171ff440fc Remove swift::reversed in favor of llvm::reverse (#27610)
The former predates the latter, but we don't need it anymore! The
latter has more features anyway.

No functionality change.
2019-10-10 17:16:09 -07:00
Robert Widmann
5a8d0744c3 [NFC] Adopt TypeBase-isms for GenericSignature
Structurally prevent a number of common anti-patterns involving generic
signatures by separating the interface into GenericSignature and the
implementation into GenericSignatureBase.  In particular, this allows
the comparison operators to be deleted which forces callers to
canonicalize the signature or ask to compare pointers explicitly.
2019-09-30 14:04:36 -07:00
Doug Gregor
8613b05445 [DI] Support definite initialization for composed property wrappers.
Use the newly-introduced property wrapper backing initializer function
in definite initialization (DI) to form the assign_by_wrapper
instruction, rather than forming a reference to the (only) property
wrapper's `init(wrappedValue:)`. This allows DI to work on properties
that have multiple, composed property wrappers applied to them.
2019-09-24 09:11:53 -07:00
Michael Gottesman
20c5dff4b5 [builtin] Implement polymorphic builtins for all BUILTIN_BINARY_OPERATIONs.
TLDR: This patch introduces a new kind of builtin, "a polymorphic builtin". One
calls it like any other builtin, e.x.:

```
Builtin.generic_add(x, y)
```

but it has a contract: it must be specialized to a concrete builtin by the time
we hit Lowered SIL. In this commit, I add support for the following generic
operations:

Type           | Op
------------------------
FloatOrVector  |FAdd
FloatOrVector  |FDiv
FloatOrVector  |FMul
FloatOrVector  |FRem
FloatOrVector  |FSub
IntegerOrVector|AShr
IntegerOrVector|Add
IntegerOrVector|And
IntegerOrVector|ExactSDiv
IntegerOrVector|ExactUDiv
IntegerOrVector|LShr
IntegerOrVector|Mul
IntegerOrVector|Or
IntegerOrVector|SDiv
IntegerOrVector|SRem
IntegerOrVector|Shl
IntegerOrVector|Sub
IntegerOrVector|UDiv
IntegerOrVector|Xor
Integer        |URem

NOTE: I only implemented support for the builtins in SIL and in SILGen. I am
going to implement the optimizer parts of this in a separate series of commits.

DISCUSSION
----------

Today there are polymorphic like instructions in LLVM-IR. Yet, at the
swift and SIL level we represent these operations instead as Builtins whose
names are resolved by splatting the builtin into the name. For example, adding
two things in LLVM:

```
  %2 = add i64 %0, %1
  %2 = add <2 x i64> %0, %1
  %2 = add <4 x i64> %0, %1
  %2 = add <8 x i64> %0, %1
```

Each of the add operations are done by the same polymorphic instruction. In
constrast, we splat out these Builtins in swift today, i.e.:

```
let x, y: Builtin.Int32
Builtin.add_Int32(x, y)
let x, y: Builtin.Vec4xInt32
Builtin.add_Vec4xInt32(x, y)
...
```

In SIL, we translate these verbatim and then IRGen just lowers them to the
appropriate polymorphic instruction. Beyond being verbose, these prevent these
Builtins (which need static types) from being used in polymorphic contexts where
we can guarantee that eventually a static type will be provided.

In contrast, the polymorphic builtins introduced in this commit can be passed
any type, with the proviso that the expert user using this feature can guarantee
that before we reach Lowered SIL, the generic_add has been eliminated. This is
enforced by IRGen asserting if passed such a builtin and by the SILVerifier
checking that the underlying builtin is never called once the module is in
Lowered SIL.

In forthcoming commits, I am going to add two optimizations that give the stdlib
tool writer the tools needed to use this builtin:

1. I am going to add an optimization to constant propagation that changes a
"generic_*" op to the type of its argument if the argument is a type that is
valid for the builtin (i.e. integer or vector).

2. I am going to teach the SILCloner how to specialize these as it inlines. This
ensures that when we transparent inline, we specialize the builtin automatically
and can then form SSA at -Onone using predictable memory access operations.

The main implication around these polymorphic builtins are that if an author is
not able to specialize the builtin, they need to ensure that after constant
propagation, the generic builtin has been DCEed. The general rules are that the
-Onone optimizer will constant fold branches with constant integer operands. So
if one can use a bool of some sort to trigger the operation, one can be
guaranteed that the code will not codegen. I am considering putting in some sort
of diagnostic to ensure that the stdlib writer has a good experience (e.x. get
an error instead of crashing the compiler).
2019-09-19 11:42:10 -07:00
Slava Pestov
533d41d0db SIL: Compute lowered local captures of SILDeclRefs and not AnyFunctionRefs
Unfortuantely this commit is bigger than I would like but I couldn't think
of any reasonable ways to split it up.

The general idea here is that capture computation is now done for a
SILDeclRef and not an AnyFunctionRef. This allows SIL to represent the
captures of a default argument generator.
2019-09-18 14:26:01 -04:00
Slava Pestov
b8642b0965 SILGen: Fix crash when immediately-applied closure transitively captures generic parameters 2019-09-18 14:26:01 -04:00
Slava Pestov
d434188157 SIL: Refactor TypeConverter to not require a SILModule
This mostly requires changing various entry points to pass around a
TypeConverter instead of a SILModule. I've left behind entry points
that take a SILModule for a few methods like SILType::subst() to
avoid creating even more churn.
2019-09-06 21:50:15 -04:00
Slava Pestov
75f4625bee AST: Peel off ClangModuleLoader.h from ASTContext.h 2019-09-03 22:39:35 -04:00
Jordan Rose
94d1e5efe6 Avoid reserved names in C++ code: "__Consuming" (#26720)
Double-underscored names are reserved for the C++ "implementation"
(language and standard library). Even though "__Consuming" isn't
likely to be part of the C++ standard any time soon, we should follow
the rules.

Note that the API digester will continue to use the string
"__Consuming" for now, even though the underscores aren't really
significant, to avoid invalidating existing dumps.

No functionality change.
2019-08-19 13:06:53 -07:00
Slava Pestov
0c5d52d860 AST: Introduce AbstractStorageDecl::get{Parsed,Opaque}Accessor()
Also, change visitOpaqueAccessors() to call getOpaqueAccessor() instead of
asserting if the expected accessor does not exist.
2019-08-02 19:34:43 -04:00
Slava Pestov
64c32c695b AST: Remove a few utility methods from AbstractStorageDecl
Since the return value of getAccessor() depends on mutable state, it
does not make sense in the request evaluator world. Let's begin by
removing some utility methods derived from getAccessor(), replacing
calls to them with calls to getAccessor().
2019-08-01 18:31:58 -04:00
Jordan Rose
844ae38722 Remove some Swift STLExtras that LLVM now provides (#26443)
No functionality change.
2019-07-31 18:34:52 -07:00
Slava Pestov
83c90b6b2a AST: Turn NominalTypeDecl::getStoredProperties() into a request
This improves on the previous situation:

- The request ensures that the backing storage for lazy properties
  and property wrappers gets synthesized first; previously it was
  only somewhat guaranteed by callers.

- Instead of returning a range this just returns an ArrayRef,
  which simplifies clients.

- Indexing into the ArrayRef is O(1), which addresses some FIXMEs
  in the SIL optimizer.
2019-07-16 16:38:38 -04:00
Ravi Kandhadai
5430aa0b17 [Builtin][SILGen][IRGen] Create a new builtin "globalStringTablePointer":
String -> Builtin.RawPointer that given a string constructed from a
literal, returns the address of the string literal in the global string
table of the compiled binary as a pointer.
2019-07-03 16:47:34 -07:00
Slava Pestov
b735e25373 Merge pull request #25775 from pschuh/s-9
Convert ForEachStmt to not use tc.callWitness().
2019-06-28 22:09:29 -04:00
Parker Schuh
687ff25157 Convert ForEachStmt to not use tc.callWitness().
For reference, everything else except string interpolation has been converted
not to call this method.
2019-06-28 14:20:42 -07:00
Slava Pestov
5826db5d56 AST: Add AbstractFunctionDecl::hasDynamicSelfResult() and use it
This calculates a result directly from the function's result type
instead of checking a bit that was previously set by the type
checker. Also, always returns true for constructors to simplify
some callers.
2019-06-26 01:10:12 -04:00
Doug Gregor
c02ecf9859 [SE-0258] Rename to Property Wrappers 2019-05-29 22:17:50 -07:00
Arnold Schwaighofer
7e646847c7 SILGen: Add an option to disable the previous implementation inside of dynamic replacement thunks
@_dynamicReplacement(for: selfRec(x: acc:))
  func selfRec_r(x: Int, acc: Int) -> Int {
    if x <= 0 {
      return acc
    }
    // Normally, this will call selfRec(x: acc:)'s implementation.
    // With the option, this will call to selfRec_r(x: acc:).
    return selfRec(x: x - 1, acc: acc + 1)
  }

rdar://51229650
2019-05-29 11:31:27 -07:00
Slava Pestov
9587a3a1f6 Merge pull request #23170 from slavapestov/enable-sil-resilience-expansion
Start using the best resilience expansion in SIL
2019-04-27 07:07:24 -04:00
Slava Pestov
16d5716e71 SIL: Use the best resilience expansion when lowering types
This is a large patch; I couldn't split it up further while still
keeping things working. There are four things being changed at
once here:

- Places that call SILType::isAddressOnly()/isLoadable() now call
  the SILFunction overload and not the SILModule one.

- SILFunction's overloads of getTypeLowering() and getLoweredType()
  now pass the function's resilience expansion down, instead of
  hardcoding ResilienceExpansion::Minimal.

- Various other places with '// FIXME: Expansion' now use a better
  resilience expansion.

- A few tests were updated to reflect SILGen's improved code
  generation, and some new tests are added to cover more code paths
  that previously were uncovered and only manifested themselves as
  standard library build failures while I was working on this change.
2019-04-26 22:47:59 -04:00
Slava Pestov
1f37941b26 SILGen: Always reference allocating entry points when calling class constructors
Previously we would emit an alloc_ref_dynamic followed by a call
of the initializing entry point when calling an @objc dynamic
initializer in a class.

However this is unnecessary now that the allocating entry point
does the right alloc_ref_dynamic.
2019-04-26 18:53:21 -04:00
Slava Pestov
472787bab7 SIL: isNonThrowing parameter of SILBuilder::create{Begin,}Apply() defaults to false
Also remove the overload of createApply() that does not take a SubstitutionMap.
It accomplishes nothing except creating ambiguity.
2019-04-25 22:27:38 -04:00
Slava Pestov
9a1abf705a SILGen: Remove SILGenSILBuilder
This reverts commit 59cc3c1216fbb1719e5357dcef3f8b249528fc74.
2019-04-25 02:06:14 -04:00
Erik Eckstein
573a82ba93 SILGen: generate assign_by_delegate for property delegates 2019-04-23 11:32:28 -07:00
Azoy
588e82f52b Emit default arg generator for stored property kind 2019-03-31 11:53:31 -05:00
Slava Pestov
89758758f0 Merge pull request #23672 from slavapestov/kill-argument-shuffle-expr
Kill ArgumentShuffleExpr
2019-03-31 11:20:30 -04:00
Slava Pestov
1467f554f5 AST: Remove ArgumentShuffleExpr 2019-03-31 01:36:19 -04:00
Slava Pestov
e212d4567f Sema: Collect varargs into an ArrayExpr and use DefaultArgumentExpr
Instead of building ArgumentShuffleExprs, lets just build a TupleExpr,
with explicit representation of collected varargs and default
arguments.

This isn't quite as elegant as it should be, because when re-typechecking,
SanitizeExpr needs to restore the 'old' parameter list by stripping out
the nodes inserted by type checking. However that hackery is all isolated
in one place and will go away soon.

Note that there's a minor change the generated SIL. Caller default
arguments (#file, #line, etc) are no longer delayed and are instead
evaluated in their usual argument position. I don't believe this actually
results in an observable change in behavior, but if it turns out to be
a problem, we can pretty easily change it back to the old behavior with a
bit of extra work.
2019-03-31 01:36:19 -04:00
Saleem Abdulrasool
e71d03cbdc SILGen: explicitly state the constructor in use (NFC)
MSVC found the constructor to be ambiguous here:

	error C2668: 'swift::Lowering::PreparedArguments::PreparedArguments': ambiguous call to overloaded function
	note: could be 'swift::Lowering::PreparedArguments::PreparedArguments(swift::Lowering::PreparedArguments &&)'
	note: or       'swift::Lowering::PreparedArguments::PreparedArguments(llvm::ArrayRef<swift::AnyFunctionType::Param>)'
	note: while trying to match the argument list '(initializer list)'

Explicitly state the constructor in use.
2019-03-29 14:25:23 -07:00
Slava Pestov
1417647a69 SILGen: (Almost) remove "scalar" PreparedArguments
They still exist when an ArgumentShuffleExpr is decomposed, but that's
about to go away.
2019-03-28 23:24:02 -04:00
Slava Pestov
50b24429c9 SILGen: Stop using "scalar" PreparedArguments except for ArgumentShuffleExpr
For anything else, we can decompose the argument list on the spot.

Note that builtins that are implemented as EarlyEmitters now take a
the argument list as a PreparedArguments instead of a single Expr.

Since the PreparedArguments can still be a scalar with an
ArgumentShuffleExpr, we have to jump through some hoops to turn
it into a list of argument Exprs. This will all go away soon.
2019-03-28 23:23:58 -04:00
Slava Pestov
d7ba72fbca SILGen: Refactor emitApplyAllocatingInitializer() to take PreparedArguments
This eliminates another place where we built "scalar" PreparedArguments.
2019-03-28 23:23:58 -04:00
Slava Pestov
6bfffae2b4 SILGen: More uniform construction of CallSites
This introduces a bit of repetition for now, but I'm going to factor
it out a different way later.
2019-03-28 23:23:58 -04:00
Slava Pestov
9e8acbe892 SILGen: ArgEmitter::forward() should return PreparedArguments and not an ArgumentSource 2019-03-28 23:23:58 -04:00
Slava Pestov
b9ef5708e2 Sema: Simplify representation of vararg forwarding
VarargExpansionExpr shows up in call argument lists in synthesized
initializers and modify accessors when we need to forward arguments
to a call taking varargs.

Previously we would say that the type of VarargExpansionExpr is
$T when its subexpression type is [$T]. matchCallArguments() would
then 'collect' the single VarargExpansionExpr into a variadic
argument list with a single element, and build an ArgumentShuffleExpr
for the argument list.

In turn, SILGen would peephole vararg emission of a variadic
argument list with a single entry that happens to be a
VarargExpansionExpr, by returning the subexpression's value,
which happened to be an array of the right element type,
instead of building a new array containing the elements of the
variadic argument list.

This was all too complicated. Instead, let's say that the type of
a VarargExpansionExpr is [$T], except that when it appears in a
TupleExpr, the variadic bit of the corresponding element is set.

Then, matchCallArguments() needs to support a case where both
the parameter and argument list have a matching vararg element.
In this case, instead of collecting multiple arguments into a
single variadic argument list, we treat the variadic argument like
an ordinary parameter, bypassing construction of the
ArgumentShuffleExpr altogether.

Finally, SILGen now needs to be able to emit a VarargExpansionExpr
in ordinary rvalue position, since it now appears as a child of a
TupleExpr; it can do this by simply emitting the sub-expression
to produce an array value.
2019-03-28 23:23:58 -04:00