swift icon indicating copy to clipboard operation
swift copied to clipboard

Centralize KeyPath accessor calling convention logic to IRGen

Open kateinoigakukun opened this issue 2 years ago • 1 comments

Motivation

KeyPath's getter/setter/hash/equals functions have their own calling convention, which receives generic arguments and embedded indices from a given KeyPath argument buffer. The convention was previously implemented by:

  1. Accepting an argument buffer as an UnsafeRawPointer and casting it to indices tuple pointer in SIL.
struct S {
  subscript<T>(x: Int) -> Int { get }
}

// keypath getter accessor for `\S.[x]`
sil hidden @testGetter : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out Int {
bb0(%0 : $*Int, %1 : $*S, %2 : $UnsafeRawPointer):
  %3 = load %1 : $*S
  %4 = pointer_to_address %2 : $UnsafeRawPointer to $*(Int)
}
  1. Bind generic arguments info from the given argument buffer while emitting prologue in IRGen by creating a new forwarding thunk.
; Accessor generated at SILGen
define swiftcc void @testGetter(%TSi* noalias nocapture sret(%TSi) %0, %T3bar4YeahV* noalias nocapture %1, i8* %2) {
  ...
}
; Thunk generated at IRGen
define swiftcc void @keypath_get(%TSi* noalias nocapture sret(%TSi) %0, %T3bar4YeahV* noalias nocapture %1, i8* %2, i64 %3) {
  ...
  ; forward arguments (also unpack witness tables from the buffer if needed)
  call swiftcc void @testGetter(%0, %1, %2)
}

This 2-phase lowering approach was not ideal, as it blocked KeyPath projection optimization ^1, and also required having a target arch specific signature lowering logic in SIL-level ^2.

Description

This patch centralizes the KeyPath accessor calling convention logic to IRGen, by introducing @convention(keypath_accessor_XXX) convention in SIL and lowering it in IRGen. The accessor functions now accept indices as tuple instead of UnsafeRawPointer in SIL level.

// keypath getter accessor for `\S.[x]`
sil hidden @testGetter : $@convention(thin) (@in_guaranteed S, @in_guaranteed (Int)) -> @out Int {
bb0(%0 : $*Int, %1 : $*S, %2 : $*(Int)):
   ...
}

This change unblocks the KeyPath projection optimization while capturing subscript indices, and also makes it easier to support WebAssembly target.

ABI concerns

  • The layout of the KeyPath argument buffer itself is not changed
  • Thunk functions generation is now skipped except for referencing external property descriptors to make relative pointers, but the thunk function symbols are hidden, so doesn't break ABI
  • Accessor functions now always have argument buffer pointer and its size integer in parameter list even the keypath doesn't have indices or generic parameter captures. But caller sites unconditionally pass them and works well, so the new form should be more strict and has no effect.

Merge plan

TBD

kateinoigakukun avatar Jun 01 '23 14:06 kateinoigakukun

CC: @atrick @meg-gupta @nate-chandler

tbkka avatar Jun 05 '23 16:06 tbkka

I think we need something marker to propagate hasIndices info. I'd like to hear your thoughts and which direction we should go (four conventions or parameter attribute or other)

~~I think you can have an attribute on the function rather than parameter attribute. The reason why I would not want a new parameter attribute is that the SIL optimizer would have to understand its semantics. The function attribute it can ignore.~~ (edit: see below)

aschwaighofer avatar Aug 11 '23 14:08 aschwaighofer

Thinking about this more, using a function attribute would be kinda unfortunate -- the signature of a function should be all that is needed to determine its ABI. Using a function attribute would require to look at the function declaration to get the final ABI that would be very unfortunate. Ignore my above suggestion.

aschwaighofer avatar Aug 11 '23 14:08 aschwaighofer

@swift-ci Please smoke test

kateinoigakukun avatar Sep 14 '23 15:09 kateinoigakukun

@swift-ci Please smoke test

kateinoigakukun avatar Sep 14 '23 18:09 kateinoigakukun

@swift-ci build toolchain

MaxDesiatov avatar Sep 14 '23 18:09 MaxDesiatov

preset=buildbot_incremental_linux_crosscompile_wasm @swift-ci Please test with preset Linux Platform

MaxDesiatov avatar Sep 14 '23 18:09 MaxDesiatov

@swift-ci Please smoke test Windows platform

kateinoigakukun avatar Sep 14 '23 23:09 kateinoigakukun

@swift-ci build toolchain Windows platform

kateinoigakukun avatar Sep 14 '23 23:09 kateinoigakukun

The preset CI job is failing due to completely unrelated issue (will be fixed by https://github.com/apple/swift/pull/68527), so it's now ready for review!

kateinoigakukun avatar Sep 15 '23 16:09 kateinoigakukun

preset=buildbot_incremental_linux_crosscompile_wasm @swift-ci Please test with preset Linux Platform

kateinoigakukun avatar Sep 17 '23 20:09 kateinoigakukun

@swift-ci Please smoke test and merge

kateinoigakukun avatar Sep 20 '23 15:09 kateinoigakukun

@swift-ci Please smoke test and merge

kateinoigakukun avatar Sep 20 '23 18:09 kateinoigakukun