Commit Graph

56 Commits

Author SHA1 Message Date
Erik Eckstein
6ff2f09796 [SIL] Let alloc_stack return a single value.
Having a separate address and container value returned from alloc_stack is not really needed in SIL.
Even if they differ we have both addresses available during IRGen, because a dealloc_stack is always dominated by the corresponding alloc_stack in the same function.

Although this commit quite large, most changes are trivial. The largest non-trivial change is in IRGenSIL.

This commit is a NFC regarding the generated code. Even the generated SIL is the same (except removed #0, #1 and @local_storage).
2016-01-06 17:35:27 -08:00
Slava Pestov
a7a9e16298 SILGen: Open code calls of enum case constructors
Sema models enum case constructors as ApplyExprs. Formerly SILGen
would emit a case constructor function for each enum case,
constructing the enum value in the constructor body. ApplyExprs
of case constructors were lowered like any other call.

This is nice and straightforward but has several downsides:

1) Case constructor functions are very repetitive and trivial,
   in particular for no-payload cases. They were declared
   @_transparent and so were inlined at call sites, but for
   public enums they still had to be emitted into the final
   object file.

2) If the enum is generic, the substituted type may be loadable
   even if the unsubstituted type is not, but since the case
   constructor is polymorphic we had to allocate stack buffers
   anyway, to pass the payload and result at the right abstration
   level. This meant that for example Optional.Some(foo)
   generated less-efficient SIL than the equivalent implicit
   conversion.

3) We were missing out on peephole optimization opportunities when
   the payload of an indirect case or address-only enum could be
   emitted directly into the destination buffer, avoiding a copy.
   One example would be when an enum payload is the result of
   calling a function that returns an address-only value indirectly.
   It appears we had unnecessary copies and takes even with -O.
   Again, optional implicit conversions special-cased this.

This patch implements a new approach where a fully-formed call to
a element constructor is handled via a special code path where
the 'enum' or 'init_enum_data_addr' / 'inject_enum_addr'
instructions are emitted directly. These always work on the
substituted type, avoiding stack allocations unless needed.
An additional optimization is that the ArgumentSource abstraction
is used to delay evaluation of the payload argument until the
indirect box or address-only payload was set up.

If a element constructor is partially applied, we still emit a
reference to the constant as before.

It may seem like case constructor functions are at least useful
for resilience, but case constructors are transparent, so making
them resilient would require a new "transparent but only in this
module, and don't serialize the SIL body" declaration.
@inline(always) is almost what we need here, but this affect
mandatory inlining, only the optimizer, so it would be a
regression for non-resilient enums, or usages of resilient enums
in the current module.

A better approach is to construct resilient enums with a new
destructiveInjectEnumTag value witness function, which is
coming soon, and the general improvement from that approach
is what prompted this patch.
2015-12-05 01:44:44 -08:00
Joe Groff
2368ce774b Remove self types from mangling by default.
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
2015-10-26 22:05:20 +00:00
Joe Groff
5cabb04f46 SILGen: Handle indirect payloads in if/guard case patterns.
Reported externally by AirspeedVelocity, don't have an rdar handy yet.

Swift SVN r30499
2015-07-22 19:55:15 +00:00
Joe Groff
729e599ffc SILGen: Project boxed payloads when switching indirect enums.
And fix some bugs in the switch implementation I ran into on the way:

- Make getManagedSubobject(CopyOnSuccess) really produce a CopyOnSuccess ConsumableManagedValue;
- Avoid invalidating address-only enums when they can't be unconditionally taken by copying the enum before projecting it. Ideally there'd be a copy_enum_data_addr instruction to do this more efficiently.

Swift SVN r29817
2015-06-30 23:10:38 +00:00
Joe Groff
2ff79e87e0 SILGen: Box indirect payloads in enum constructors.
Swift SVN r29794
2015-06-29 22:25:25 +00:00