`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`
The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.
rdar://102362022
In preparation for moving to llvm's opaque pointer representation
replace getPointerElementType and CreateCall/CreateLoad/Store uses that
dependent on the address operand's pointer element type.
This means an `Address` carries the element type and we use
`FunctionPointer` in more places or read the function type off the
`llvm::Function`.
This has a few nice benefits:
1. The splitting happens after LLVM optimizations have run. This ensures that
LLVM will not join these blocks no matter what! The author of this commit has
found that in certain cases LLVM does this even at -Onone. By running this late,
we get the benefit we are looking for: working around the bad SelectionDAG
behavior.
2. This block splitting is just a workaround for the above mentioned unfortunate
SelectionDAG behavior. By doing this when we remove the workaround, we will not
have to update SIL level tests... instead we will just remove a small LLVM pass.
Some additional notes:
1. Only moved values will ever have llvm.dbg.addr emitted today, so we do not
have to worry about this impacting the rest of the language.
2. The pass's behavior is tested at the IR level by move_function_dbginfo.swift.
- 3e1c787b3160bed4146d3b2b5f922aeed3caafd7 `arg_operands` was replaced with `args`.
- 80ea2bb57450a65cc724565ecfc9971ad93a3f15 `get*Attributes` was replaced with `get*Attrs`
In low level LLVMARCOptimizer, during canonicalization we don't rauw the result of RT_Retain with its arg similarly to RT_ObjCRetain and RT_BridgeRetain.
And during performLocalReleaseMotion, we assert that we have canonicalized RT_Retain.
In a release compiler, if we optimize such an RT_Retain with a RT_Release, then this can result in a compiler crash
Similarly not rauw'ing, can cause a crash due to performLocalRetainMotion
Fixes rdar://79238115
Otherwise we set it on all targets/languages in a subdirectory (I forgot if it
propagates up). Regardless, this type of viral stuff is something we want to
move away from since it creates a code that is a "forall" piece of code rather
than a piece of code that only effects a single target.
I also conditionalized the actual definitions being added on the compiled file's
language being C,CXX,OBJC,OBJCXX since as we add Swift sources to the host side
of the compiler, we will not want these flags to propagate to Swift sources.
It breaks withCheckedContinuation.
I have not gotten to the bottom of why. But for now disable the pass for
all async functions until we can fix it.
rdar://77166575
We had a fixed limit of 4 added parameters for merged functions. But if a function is big, it makes sense to allow more parameters to be added.
Now, derived the maximum number of parameters from the function size.
This increases the chances that big functions (which likely require more parameters) are merged.
Add a private scratch context to the ASTContext and allow IntrinsicInfo sole access to it so it can allocate attributes into it. This removes the final dependency on the global context.
A follow-up PR adds a flag to control an inline namespace that allows
symbols in libDemangling to be distinguished between the runtime and
the compiler. These dependencies ensure that the flag is plumbed
through for inclusions of Demangling headers that aren't already
covered by existing `target_link_libraries`.
When backward deploying to an OS that may not have these entry points, weak-link them so that they
can be used conditionally in availability contexts that check for them.
rdar://problem/50731151
I left in the old entrypoint as well that doesn't take the AAQueryInfo by having
it delegate to the AAQueryInfo entrypoint passing a default constructed
AAQueryInfo. This matches how people upstream have handled this.
rdar://49450147
rdar://problem/48833545
From the LLVM Manual regarding tail/musttail : "Both markers imply that the callee does not access allocas from the caller”
Swift’s LLVMARCContract just marks all the calls it creates as tail call without any analysis and/or checking if we are allowed to do that. This created an interesting runtime crash that was a pain to debug - story time:
I traced a runtime crash back to Swift’s LLVMARCContract, but could not grok why the transformation there is wrong: we replaced two consecutive _swift_bridgeObjectRelease(x) calls with _swift_bridgeObjectRelease_n(x, 2), which is a perfectly valid thing to do.
I noticed that the new call is marked as a tail call, disabling that portion of the pass “solved” the runtime crash, but I wanted to understand *why*:
This code worked:
pushq $2
popq %rsi
movq -168(%rbp), %rdi
callq _swift_bridgeObjectRelease_n
leaq -40(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
While this version crashed further on during the run:
movq -168(%rbp), %rdi
leaq -40(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp _swift_bridgeObjectRelease_n
As you can see, the call is the last thing we do before returning, so nothing appeared out of the ordinary at first…
Dumping the heap object at the release basic block looked perfectly fine: the ref count was 2 and all the fields looked valid.
However, when we reached the callee the value was modified / dumping it showed it changed somewhere. Which did not make any sense.
Setting up a memory watchpoint on the heap object and/or its reference count did not get us anywhere: the watchpoint triggered on unrelated code in the entry to the callee..
I then realized what’s going on, here’s a an amusing reproducer that you can checkout in LLDB:
Experiment 1:
Setup a breakpoint at leaq -40(%rbp), %rsp
Dump the heap object - it looks good
Experiment 2:
Rerun the same test with a small modification:
Setup a breakpoint at popq %rbx (the instruction after leaq, do not set a breakpoint at leaq)
Dump the heap object - it looks bad!
So what is going on there? The SIL Optimizer changed an alloc_ref instruction into an alloc_ref [stack], which is a perfectly valid thing to do.
However, this means we allocated the heap object on the stack, and then tail-called into the swift runtime with said object. After having modified the stack pointer in the caller’s epilogue.
So why does experiment 2 show garbage? We’ve updated the stack pointer, and it just so happens that we are after the red zone on the stack. When the breakpoint is hit (the OS passes control back to LLDB), it is perfectly allowed to use the memory where the heap object used to reside.
Note: I then realized something even more concerning, that we were lucky not have hit so far: not only did we not check if we are allowed to mark a call as ’tail’ in this situation, which could have been considered a corner case, we could have if we have not promoted it from heap to stack, but we marked *ALL* the call instructions created in this pass as tail call even if they are not the last thing that occurred in the calling function! Looking at the LVMPasses/contract.ll test case, which is modified in this PR, we see some scary checks that are just wrong: we are checking if a call is marked as ‘tail’ in the middle of the function, then check the rest of the function in CHECK-NEXT lines. Knowing full well that the new ‘tail call’ is not the last thing that should execute in the caller.
We used to represent these just as normal LLVM functions, e.x.:
declare objc_object* @objc_retain(objc_object*)
declare void @objc_release(objc_object*)
Recently, special objc intrinsics were added to LLVM. This pass updates these
small (old) passes to use the new intrinsics.
This turned out to not be too difficult since we never create these
instructions. We only analyze them, move them, and delete them.
rdar://47852297
We used to represent these just as normal LLVM functions, e.x.:
declare objc_object* @objc_retain(objc_object*)
declare void @objc_release(objc_object*)
Recently, special objc intrinsics were added to LLVM. This pass updates these
small (old) passes to use the new intrinsics.
This turned out to not be too difficult since we never create these
instructions. We only analyze them, move them, and delete them.
rdar://47852297