Previously even if a type's metadata was optimized away, we would still
emit a field descriptor, which in turn could reference nominal type
descriptors for other types via symbolic references, etc.
Instead of a wholly separate lazyness mechanism for foreign metadata where
the first call to getAddrOfForeignTypeMetadataCandidate() would emit the
metadata, emit it using the lazy metadata mechanism.
This eliminates some code duplication. It also ensures that foreign
metadata is only emitted once per SIL module, and not once per LLVM
module, avoiding duplicate copies that must be ODR'd away in multi-threaded
mode.
This fixes the test case from <rdar://problem/49710077>.
The old logic was confusing. The LazyTypeGlobals map would contain
entries for all referenced types, even those without lazy metadata.
And for a type with lazy metadata, the IsLazy field would begin
with a value of false -- unless it was imported.
When a non-imported type was finally visited in the AST, we would
try to "enable" lazyness for it, which meant queueing up any
metadata that had been requested prior, or immediately emitting
the metadata otherwise.
Instead, let's add a separate map that caches whether a type has
lazy metadata or not. The first time we ask for the metadata of a
type, consult this map. If the type has lazy metadata according to
the map, queue up metadata emission for the type. Otherwise, emit
metadata eagerly when the type is visited in the AST.
This consolidates the various doesClassMetadataRequire*() checks, making
them more managable.
This also adds a forth state, ClassMetadataStrategy::Update. This will be used
when deploying to the new Objective-C runtime. For now it's not plumbed through.
Progress on <rdar://problem/47649465>.
Protocol descriptors for resilient protocols relatively-reference
default witness thunks, so when using -num-threads N with N > 1,
we must ensure the default witness thunk is emitted in the same
LLVM module.
Protocol descriptors for resilient protocols relatively-reference
default witness thunks, so when using -num-threads N with N > 1,
we must ensure the default witness thunk is emitted in the same
LLVM module.
We were wastefully emitting an accessor if a field had a type, for
example if my field type was (() -> (X, Array<Y>>) we would force
the emission of a function to construct (() -> (X, Array<Y>)) even
though all we care about is the type metadata for X and Y.
Conversely, we would skip the field type if it contained an
archetype, even if it otherwise contained metadata that we need
to force to emit, for instance something like (T, X) where T is
a generic parameter and X is a nominal type.
A final side effect is we no longer try to emit type metadata for
one-element tuples when emitting enum payload metadata, which is
something I want to assert against.
This is essentially a long-belated follow-up to Arnold's #12606.
The key observation here is that the enum-tag-single-payload witnesses
are strictly more powerful than the XI witnesses: you can simulate
the XI witnesses by using an extra case count that's <= the XI count.
Of course the result is less efficient than the XI witnesses, but
that's less important than overall code size, and we can work on
fast-paths for that.
The extra inhabitant count is stored in a 32-bit field (always present)
following the ValueWitnessFlags, which now occupy a fixed 32 bits.
This inflates non-XI VWTs on 32-bit targets by a word, but the net effect
on XI VWTs is to shrink them by two words, which is likely to be the
more important change. Also, being able to access the XI count directly
should be a nice win.
- fix code generation for enum types to zext or trunc 32 bit data as appropriate for the platform
- fix IR generation code to use a relative address type of 16 bit width on that platform
- correct order of statements and line up comments
When a (file)private entity occurs inside a generic context, we still need
information about the genericity of the enclosing context to demangle
to metadata. Emit complete context descriptors for parents of anonymous
contexts.
Fixes rdar://problem/46109026.
Extend the key-path pattern with a representation of the generic environment
of the key-path, which includes the generic parameters and generic
requirements of the environment.
Switch key path metadata over to mangled names for each of the places it
refers to either a type metadata accessor or a witness table accessor. For
now, the mangled name is a symbolic reference to the existing accessors.
Part of rdar://problem/38038799.
The current representation of an associated conformance in a witness
tables (e.g., Iterator: IteratorProtocol within a witness table for
Sequence) is a function that the client calls.
Replace this with something more like what we do for associated types:
an associated conformance is either a pointer to the witness table (once
it is known) or a pointer to a mangled name that describes that
conformance. On first access, demangle the mangled name and replace the
entry with the resulting witness table. This will give us a more compact
representation of associated conformances, as well as always caching
them.
For now, the mangled name is a sham: it’s a mangled relative reference to
the existing witness table accessors, not a true mangled name. In time,
we’ll extend the support here to handle proper mangled names.
Part of rdar://problem/38038799.
TargetGenericParamRef is a specialized structure used to describe the
subject of a generic requirement, e.g., the “T.Assoc” in “T.Assoc: P”.
Replace it with a mangled name, for several reasons:
1) Mangled type names are also fairly concise, can often be shared, and
are a well-tested path
2) Mangled type names can express any type, which might be useful in the
future
3) This structure doesn’t accommodate specifically stating where the
conformances come from (to extract associated type witnesses). Neither
can mangled names, but we’d like to do that work in only one place.
This change exposed an existing bug where we improperly calculated the
generic parameter counts for extensions of nested generic types. Fix that
bug here (which broke an execution test).
A dynamically replaceable function calls through a global variable that
holds the function pointer.
struct ChainEntry {
void *(funPtr)();
struct ChainEntry *next;
}
ChainEntry dynamicallyReplaceableVar;
void dynamicallyReplaceableFunction() {
dynamicallyReplaceableVar.funPtr()
}
dynamic replacements will be chainable so the global variable also
functions as the root entry in the chain of replacements.
A dynamic replacement functions can call the previous implementation by
going through its chain entry.
ChainEntry chainEntryOf_dynamic_replacement_for_foo;
void dynamic_replacement_for_foo() {
// call the previous (original) implementation.
chainEntryOf_dynamic_replacement_for_foo.funPtr();
}
Use relative references instead of pointers so that the pattern can be true-const. Instead of trying
to instantiate a constant key path literal in-place, point to a cache variable that we can store
a pointer to the shared instance into when instantiated. Now that the pattern format has diverged
significantly from the instance format, simplify and refactor the instantiation code using a walker
for the pattern format instead of trying to reuse the code for working with instantiated instances.
rdar://problem/42674576
Witness table accessors return a witness table for a given type's
conformance to a protocol. They are called directly from IRGen
(when we need the witness table instance) and from runtime conformance
checking (swift_conformsToProtocol digs the access function out of the
protocol conformance record). They have two interesting functions:
1) For witness tables requiring instantiation, they call
swift_instantiateWitnessTable directly.
2) For synthesized witness tables that might not be unique, they call
swift_getForeignWitnessTable.
Extend swift_instantiateWitnessTable() to handle both runtime
uniquing (for #2) as well as handling witness tables that don't have
a "generic table", i.e., don't need any actual instantiation. Use it
as the universal entry point for "get a witness table given a specific
conformance descriptor and type", eliminating witness table accessors
entirely.
Make a few related simplifications:
* Drop the "pattern" from the generic witness table. Instead, store
the pattern in the main part of the conformance descriptor, always.
* Drop the "conformance kind" from the protocol conformance
descriptor, since it was only there to distinguish between witness
table (pattern) vs. witness table accessor.
* Internalize swift_getForeignWitnessTable(); IRGen no longer needs to
call it.
Reduces the code size of the standard library (+assertions build) by
~149k.
Addresses rdar://problem/45489388.
The “requires instantiation” bit for protocol conformances that
might require runtime instantiation was set for essentially every
resilient conformance, so we would always be forced to create a
copy of the table. Narrow the “requires instantiation” bit to those
cases where there is something in the pattern that needs it to be
copied (for now, only associated type witnesses involving a type
parameter, which need to be cached differently). This optimizes
some narrow cases where we wouldn’t otherwise need a copy.
Simplify calls to getAddrOfLLVMVariableOrGOTEquivalent() and
getAddrOfLLVMVariable() by moving the computation of the alignment and
default type into LinkEntity.
Co-authored-by: Joe Groff <jgroff@apple.com>
Collapse the generic witness table, which was used only as a uniquing
data structure during witness table instantiation, into the protocol
conformance record. This colocates all of the constant protocol conformance
metadata and makes it possible for us to recover the generic witness table
from the conformance descriptor (including looking at the pattern itself).
Rename swift_getGenericWitnessTable() to swift_instantiateWitnessTable()
to make it clearer what its purpose is, and take the conformance descriptor
directly.
Place resilient witnesses in the protocol conformance descriptor,
tail-allocated after the conditional requirements, so they can be found by
reflection. Drop the resilient witness table and protocol descriptor from
the generic witness table.
Addresses rdar://problem/45228582.
The YAML format is the same one produced by the -dump-type-info
frontend mode.
For now this is only enabled if the -read-type-info-path frontend
flag is specified.
Progress on <rdar://problem/17528739>.