As the optimizer uses more and more AST stuff, it's now time to create an "AST" module.
Initially it defines following AST datastructures:
* declarations: `Decl` + derived classes
* `Conformance`
* `SubstitutionMap`
* `Type` and `CanonicalType`
Some of those were already defined in the SIL module and are now moved to the AST module.
This change also cleans up a few things:
* proper definition of `NominalTypeDecl`-related APIs in `SIL.Type`
* rename `ProtocolConformance` to `Conformance`
* use `AST.Type`/`AST.CanonicalType` instead of `BridgedASTType` in SIL and the Optimizer
Make SILLInkage available in SIL as `SIL.Linkage`.
Also, rename the misleading Function and GlobalVariable ABI `isAvailableExternally` to `isDefinedExternally`
The buffer of global arrays could already be statically initialized.
The missing piece was the array itself, which is basically a reference to the array buffer.
For example:
```
var a = [1, 2, 3]
```
ends up in two statically initialized globals:
1. the array buffer, which contains the elements
2. the variable `a` which is a single reference (= pointer) of the array buffer
This optimization removes the need for lazy initialization of such variables.
rdar://127757554
* `alloc_vector`: allocates an uninitialized vector of elements on the stack or in a statically initialized global
* `vector`: creates an initialized vector in a statically initialized global
Introduce two modes of bridging:
* inline mode: this is basically how it worked so far. Using full C++ interop which allows bridging functions to be inlined.
* pure mode: bridging functions are not inlined but compiled in a cpp file. This allows to reduce the C++ interop requirements to a minimum. No std/llvm/swift headers are imported.
This change requires a major refactoring of bridging sources. The implementation of bridging functions go to two separate files: SILBridgingImpl.h and OptimizerBridgingImpl.h.
Depending on the mode, those files are either included in the corresponding header files (inline mode), or included in the c++ file (pure mode).
The mode can be selected with the BRIDGING_MODE cmake variable. By default it is set to the inline mode (= existing behavior). The pure mode is only selected in certain configurations to work around C++ interop issues:
* In debug builds, to workaround a problem with LLDB's `po` command (rdar://115770255).
* On windows to workaround a build problem.
For example:
```
var p = Point(x: 10, y: 20)
let o = UnsafePointer(&p)
```
Also support outlined arrays with pointers to other globals. For example:
```
var g1 = 1
var g2 = 2
func f() -> [UnsafePointer<Int>] {
return [UnsafePointer(&g1), UnsafePointer(&g2)]
}
```
* add `GlobalVariable.staticInitializerInstructions` to access all initializer instructions of a global
* implement `GlobalVariable.staticInitValue` with `GlobalVariable.staticInitializerInstructions`
* this requires that `InstructionList.reversed()` works without accessing the parent block of the iterator instruction
* allow `Context.erase(instruction:)` to delete instructions from a global's initializer list, which means to handle the case where a deleted instruction has no parent function.
Before this change, if a global variable is required to be statically initialized (e.g. due to @_section attribute), we don't allow its type to be a struct, only a scalar type works. This change improves on that by teaching MandatoryPerformanceOptimizations pass to inline struct initializer calls into initializer of globals, as long as they are simple enough so that we can be sure that we don't trigger recursive/infinite inlining.
The main change here is in IRGen which needs to be able to emit constant enum values.
Use `emitValueInjection` to create the enum constant.
Usually this method creates code in the current function.
But if all arguments to the enum are constant, the builder never has to emit an instruction.
Instead it can constant fold everything and just returns the final constant.
Also, create statically initialized let-globals as constant global (`constant` instead of `global`).
* add the StaticInitCloner utility
* remove bridging of `copyStaticInitializer` and `createStaticInitializer`
* add `Context.mangleOutlinedVariable` and `Context.createGlobalVariable`
* add new create-functions for instructions
* allow the Builder to build static initializer instructions for global variables
* some refactoring to simplify the implementation
While I was using the new AccessUtils for a new optimization pass I discovered some areas for improvements. Also I found some bugs.
Changes:
* AccessBase: remove the unhealthy redundancy between `kind` and `baseAddress` types. Now AccessBase is single enum with the relevant base objects/addresses as payloads.
* AccessBase: for `global`, store the `GlobalValue` and not a `global_address` instruction, which is more accurate (because there can be multiple `global_addr`s for a single global variable)
* AccessBase: drop the support for function argument "pointers". The `pointer` is now always a `pointer_to_address` instruction. This also simplifies `PointerIdentification`: either it finds a matching `address_to_pointer` or it bails.
* AccessBase: improve `func isDistinct(from:)`. There are more possibilities to prove that two access bases do not alias.
* AccessBase: replace `var isUniquelyIdentified` with `var hasKnownStorageKind` which is more useful for aliasing checking.
* AccessPath: fix `func isDistinct(from:)`. `SmallProjectionPath.matches` is the wrong way to check if two expression paths may overlap. Instead use the new `SmallProjectionPath.mayOverlap`.
* AccessStoragePathWalker: rename `getAccessStorage` -> `visitAccessStorageRoots` and let it return false if it's not a class/reference AccessBase.
* add tests for `AccessPath.isDistinct(from:)`
This fixes a dangling pointer issue when creating a `Swift.String` from `std::string`.
Also fixes a warning:
```
warning: variable 's' was never mutated; consider changing to 'let' constant
var s = SILBasicBlock_debugDescription(bridged)
~~~ ^
let
```
rdar://92963081
rdar://93053488
and introduce the StringRef struct.
It's more efficient.
Also, rename the `HasName` protocol to `HasShortDescription`, which introduces the new requirement `shortDescription`. This is need because `name` now has `StringRef` type and not `String` anymore
Improve block/instruction lists and similar collections
* pretty print collections in the form “[a, b, c]”
* also do this for lazy sequences
* define a custom Mirror
* in a collection, only print the name of blocks, functions and globals (instead of the full object)
* replace `BasicBlock.reverseInstructions` with `BasicBlock.instructions.reversed()` - in an efficient way