[Solved] Help needed with differentiable attribute serialization

Hello serialization experts,

Serialization for the @differentiable attribute isn't working properly. Below is a reproducer: I test whether @differentiable attributes are serialized correctly and show up where referenced from another module during SILGen.

// fail.swift
Float(1) + 1
["", ""].joined()

When I emit SILGen for the program, the SIL [differentiable] attribute doesn't show up, but the [_specialize] attribute does.

$ swiftc -emit-silgen fail.swift

...

// static Float.+ infix(_:_:)
// BUG: 'differentiable' attribute doesn't show up.
sil [transparent] [serialized] @$sSf1poiyS2f_SftFZ : $@convention(method) (Float, Float, @thin Float.Type) -> Float

// BidirectionalCollection<>.joined(separator:)
// 'specialize' attribute shows up.
sil [_specialize exported: false, kind: full, where τ_0_0 == Array<String>] @$sSKsSS7ElementRtzrlE6joined9separatorS2S_tF : $@convention(method) <τ_0_0 where τ_0_0 : BidirectionalCollection, τ_0_0.Element == String> (@guaranteed String, @in_guaranteed τ_0_0) -> @owned String

Here are some relevant code paths regarding @differentaible attribute serialization. (The implementations were copied from serialization for other attributes.)

There are two serialization tests for @differentiable, but they don't catch this bug.

Does anyone know what might be causing this? I imagine the bug is likely that @differentiable attribute isn't getting (de)serialized at all, rather than one part of (de)serialization being missing.

Any tips would be greatly appreciated!

cc @rxwei @jrose @Joe_Groff

A more pointed question: what part of SILGen is responsible for "loading" functions from other modules?

sil_stage raw

import Builtin
import Swift
import SwiftShims

// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
  ...
} // end sil function 'main'

// QUESTION: What part of SILGen loads these functions below?

// static Float.+ infix(_:_:)
sil [transparent] [serialized] @$sSf1poiyS2f_SftFZ : $@convention(method) (Float, Float, @thin Float.Type) -> Float

// BidirectionalCollection<>.joined(separator:)
sil [_specialize exported: false, kind: full, where τ_0_0 == Array<String>] @$sSKsSS7ElementRtzrlE6joined9separatorS2S_tF : $@convention(method) <τ_0_0 where τ_0_0 : BidirectionalCollection, τ_0_0.Element == String> (@guaranteed String, @in_guaranteed τ_0_0) -> @owned String

Aha, I found the issue. Code is missing from lib/SIL/SILFunctionBuilder.cpp.

addFunctionAttributes is responsible for propagating function attributes like @_specialize. @differentiable attributes need to be propagated there.

1 Like