When accessing global variables defined in the REPL, lldb does not consult
debug info, so it does not see that the DW_OP_deref was emitted.
So instead, set a special bit on globals defined in the REPL which bypasses
resilience for them altogether.
Part of the fix <rdar://problem/39722386>.
The major important thing here is that by using copy_unowned_value we can
guarantee that the non-ownership SIL ARC optimizer will treat the release
associated with the strong_retain_unowned as on a distinc rc-identity from its
argument. As an example of this problem consider the following SILGen like
output:
----
%1 = copy_value %0 : $Builtin.NativeObject
%2 = ref_to_unowned %1
%3 = copy_unowned_value %2
destroy_value %1
...
destroy_value %3
----
In this case, we are converting a strong reference to an unowned value and then
lifetime extending the value past the original value. After eliminating
ownership this lowers to:
----
strong_retain %0 : $Builtin.NativeObject
%1 = ref_to_unowned %0
strong_retain_unowned %1
strong_release %0
...
strong_release %0
----
From an RC identity perspective, we have now blurred the lines in between %3 and
%1 in the previous example. This can then result in the following miscompile:
----
%1 = ref_to_unowned %0
strong_retain_unowned %1
...
strong_release %0
----
In this case, it is possible that we created a lifetime gap that will then cause
strong_retain_unowned to assert. By not lowering copy_unowned_value throughout
the SIL pipeline, we instead get this after lowering:
----
strong_retain %0 : $Builtin.NativeObject
%1 = ref_to_unowned %0
%2 = copy_unowned_value %1
strong_release %0
...
strong_release %2
----
And we do not miscompile since we preserved the high level rc identity
pairing.
There shouldn't be any performance impact since we do not really optimize
strong_retain_unowned at the SIL level. I went through all of the places that
strong_retain_unowned was referenced and added appropriate handling for
copy_unowned_value.
rdar://41328987
**NOTE** I am going to remove strong_retain_unowned in a forthcoming commit. I
just want something more minimal for cherry-picking purposes.
It hass been a longstanding principle in LLVM that the presence of
debug info shall not affect code generation. This patch brings the
Swift frontend closer to this ideal:
- unconditionally emit shadow copies
- unconditionally bind type metadata
The extra allocas, bitcasts, geps, and stores being emitted get
optimized away when compiling at anything but -Onone. There are few
use-cases for compiling at -Onone without -g, so this shouldn't affect
performance for any real-world use-cases.
In the majority of the use-cases transparent functions are inlined by
the mandatory inliner which by design drops all debug info and
pretends the inlined instructions were always part of the
caller. Since an outlined copy of the function is often still
generated, attaching debug locations to it is inconsistent and can
create the false impression that it were possible to set a breakpoint
in such a function when in reality these functions are only there for
very few edge cases.
<rdar://problem/40258813>
We already zero init AllocStack, and here's the same.
The debugger's variable view shows up variables on the line
where they're declared (before they've been initialized).
In some cases, we just print garbage. In some others, it's
dangerous (imagine an array which we believe has 2^32 elements
because we ended up reusing a stack slot). This way it's always
consistent, as lldb uses the first word to understand whether
an object is initialized or not here.
Fixes <rdar://problem/39883298>
Modify IRGen to emit builtin access markers with an error flag in
Swift 3 mode.
KeyPath enforcement is required by user code in Swift 4+ mode, but is
implemented within the standard library. A [builtin] flag marks the
special case for access generated by Builtins so that they are
always enforced as an error regardless of the language mode.
This is necessary for Swift 4.2 because the standard library continues
to build in Swift 3 mode. Once the standard library build migrates,
this is all irrelevant.
This does not actually affect existing Swift 3 code, since the KeyPath
feature wasn't introduced until Swift 4.
<rdar://problem/40115738> [Exclusivity] Enforce Keypath access as an error, not a warning in 4.2.
This is in some code to initialize variables for the debugger.
From the original commit
"Zero-initialize uninitialized Dictionary variables for the debugger.
To avoid the debugger displaying garbage or having expressions crash
when inspecting an uninitialized dictionary variable, zero-initialize
the first word of the alloca at -Onone.
"
Unfortunately, we are comparing different quantities in that code.
rdar://40043512
Mandatory pass will clean it up and replace it by a copy_block and
is_escaping/cond_fail/release combination on the %closure in follow-up
patches.
The instruction marks the dependence of a block on a closure that is
used as an 'withoutActuallyEscaping' sentinel.
rdar://39682865
To avoid the debugger displaying garbage or having expressions crash
when inspecting an uninitialized dictionary variable, zero-initialize
the first word of the alloca at -Onone.
<rdar://problem/36619561>
IRGenDebugInfo expects to see an autogenerated bit before allowing reuse
of the last seen debug location for a new instruction.
rdar://28544248
(cherry picked from commit 5f6d8e8c8c)
When we use type(of: x) on a class in an ObjC bridged context, the optimizer turns this into a SIL `value_metatype @objc` operation, which is supposed to get the dynamic type of the object as an ObjC class. This was previously lowered by IRGen into a `object_getClass` call, which extracts the isa pointer from the object, but is inconsistent with the `-class` method in ObjC or with the Swift-native behavior, which both look through artificial subclasses, proxies, and so on. This inconsistency led to observably different behavior between debug and release builds and between ObjC-bridged and native entry points, so provide an alternative runtime entry point that replicates the behavior of getting a native Swift class. Fixes SR-7258.
The current approach has several problems:
- Types that are not inout types but loadable may incorrectly get
marked as inout types.
- When inout arguments get inlined or otherwise optimized LLDB cannot
rely on the type to decide to dereference that value.
- One argument may get represented by different types in the same
function depending on what code is generated for it.
Fixes rdar://problem/rdar://problem/39023374
Most of the work of this patch is just propagating metadata states
throughout the system, especially local-type-data caching and
metadata-path resolution. It took a few design revisions to get both
DynamicMetadataRequest and MetadataResponse to a shape that felt
right and seemed to make everything easier.
The design is laid out pretty clearly (I hope) in the comments on
DynamicMetadataRequest and MetadataResponse, so I'm not going to
belabor it again here. Instead, I'll list out the work that's still
outstanding:
- I'm sure there are places we're asking for complete metadata where
we could be asking for something weaker.
- I need to actually test the runtime behavior to verify that it's
breaking the cycles it's supposed to, instead of just not regressing
anything else.
- I need to add something to the runtime to actually force all the
generic arguments of a generic type to be complete before reporting
completion. I think we can get away with this for now because all
existing types construct themselves completely on the first request,
but there might be a race condition there if another asks for the
type argument, gets an abstract metadata, and constructs a type with
it without ever needing it to be completed.
- Non-generic resilient types need to be switched over to an IRGen
pattern that supports initialization suspension.
- We should probably space out the MetadataStates so that there's some
space between Abstract and Complete.
- The runtime just calmly sits there, never making progress and
permanently blocking any waiting threads, if you actually form an
unresolvable metadata dependency cycle. It is possible to set up such
a thing in a way that Sema can't diagnose, and we should detect it at
runtime. I've set up some infrastructure so that it should be
straightforward to diagnose this, but I haven't actually implemented
the diagnostic yet.
- It's not clear to me that swift_checkMetadataState is really cheap
enough that it doesn't make sense to use a cache for type-fulfilled
metadata in associated type access functions. Fortunately this is not
ABI-affecting, so we can evaluate it anytime.
- Type layout really seems like a lot of code now that we sometimes
need to call swift_checkMetadataState for generic arguments. Maybe
we can have the runtime do this by marking low bits or something, so
that a TypeLayoutRef is actually either (1) a TypeLayout, (2) a known
layout-complete metadata, or (3) a metadata of unknown state. We could
do that later with a flag, but we'll need to at least future-proof by
allowing the runtime functions to return a MetadataDependency.
At -Onone, we may opt to extend the liverange of a value by inserting
fake uses of the value in blocks which postdominate its def. This keeps
values available throughout the entirety of a function when stepping
through it in a debugger.
This patch makes it so that we also insert a fake use at the start of a
value's lifetime. This forces early materialization of the value, i.e it
becomes available for inspection in a debugger as soon as it's defined.
This is useful when a value has no uses except fake uses. In such cases,
ISel may (correctly!) decide to materialize the value at the end of its
scope. This is really unintuitive and unhelpful for users, because you
need to be done stepping through the value's scope before you can
inspect it.
For the same reasons, forcing early materialization is also useful when
a value *does* have uses. Consider:
let d = ...
print("Here is the value of d: \(d)")
Without early materialization, if you set a breakpoint on the line
containing the print, you would not be able to inspect "d". That's
because "d" would be materialized right before string interpolation
happens, which is *after* the breakpoint PC.
rdar://38465084
Abstract type/heap metadata access goes into MetadataRequest.
Metadata access starting from a heap object goes into GenHeap.
Accessing various components of class metadata goes into GenClass
or MetadataLayout.
SIL functions might be associated with decls from other source files whose symbols we can't necessarily locally link to. The module should be associated with the SourceFile that was compiled.
This makes it more likely we'll do optimizations that are currently scoped to same-SourceFile references, such as direct relative references or symbolic references in mangling, in codegen that gets triggered on behalf of a SILFunction. Should be NFC, aside from some tiny code size improvement.
Will be used to verify that withoutActuallyEscaping's block does not
escape the closure.
``%escaping = is_escaping_closure %closure`` tests the reference count. If the
closure is not uniquely referenced it prints out and error message and
returns true. Otherwise, it returns false. The returned result can be
used with a ``cond_fail %escaping`` instruction to abort the program.
rdar://35525730
This patch both makes debug variable information it optional on
alloc_stack and alloc_box instructions, and forced variable
information on debug_value and debug_value_addr instructions. The
change of the interface uncovered a plethora of bugs in SILGen,
SILTransform, and IRGen's LoadableByAddress pass.
Most importantly this fixes the previously commented part of the
DebugInfo/local-vars.swift.gyb testcase.
rdar://problem/37720555
Factor out and reuse logic in the lowering of CondFailInst to emit
non-mergeable traps, everywhere we emit traps. This should address a
debugging quality issue with ambiguous ud2 instructions.
rdar://32772768
Whan an alloca is dynamic, all FastISel can do is describe the
register in which the address of of the dynamic alloca is kept, and if
the value isn't used it will get kicked out by regalloc.
rdar://problem/36663932
- make @noescape function types trivial
- think_to_thick_function with @noescape result type
- Fix for getSwiftFunctionPointerCallee
Part of:
SR-5441
rdar://36116691