I'm considering adding a builtin to support addresses that aren't naturally aligned to their element type. The API change to support this will be proposed separately on Evolution.
func load(from pointer: Builtin.RawPointer,
alignedTo pow2Alignment: UInt) -> Int {
let mustBeAligned =
Builtin.uncheckedAssertAlignment(pointer, pow2Alignment)
return Builtin.loadRaw(mustBeAligned)
}
The builtin would persist in SIL until it can be simplified away. If it can't be simplified away, then IRGen can ignore it.
sil hidden @load : $@(Builtin.RawPointer, Builtin.Int64) -> Int {
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Int64):
%2 = builtin "uncheckedAssertAlignment"
(%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
%3 = pointer_to_address %2 : $Builtin.RawPointer to [align=1] $*Int
%4 = load %3 : $*Int
return %4 : $Int
}
SIL simplifications
1. Literal zero = natural alignment
%1 = integer_literal $Builtin.Int64, 0
%2 = builtin "uncheckedAssertAlignment"
(%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
%3 = pointer_to_address %2 : $Builtin.RawPointer to [align=1] $*Int
Erases the pointer_to_address [align=] attribute:
%3 = pointer_to_address %0 : $Builtin.RawPointer to $*Int
2. Literal nonzero = forced alignment.
%1 = integer_literal $Builtin.Int64, 16
%2 = builtin "uncheckedAssertAlignment"
(%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
%3 = pointer_to_address %2 : $Builtin.RawPointer to [align=16] $*Int
Promotes the pointer_to_address [align=] attribute to a higher value:
%3 = pointer_to_address %0 : $Builtin.RawPointer to [align=8] $*Int
3. Folded dynamic alignment
%1 = builtin "alignof"<T>(%0 : $@thin T.Type) : $Builtin.Word
%2 = builtin "uncheckedAssertAlignment"
(%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
%3 = pointer_to_address %2 : $Builtin.RawPointer to $*T
Erases the pointer_to_address [align=] attribute:
%3 = pointer_to_address %0 : $Builtin.RawPointer to $*T
/cc @glessard @Erik_Eckstein