Skip to content

Commit 7fbfbc5

Browse files
authored
[AutoDiff] Fix derivative forwarding thunk linkage. (#31726)
Make derivative forwarding thunks use original function's linkage instead of the derivative function's, stripping external. This is consistent with the linkage of differentiability witnesses. Clarify AutoDiff linkage-related comments. Resolves TF-1160: TBDGen error due to incorrect derivative thunk linkage.
1 parent 58d163b commit 7fbfbc5

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

lib/SILGen/SILGen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -839,8 +839,8 @@ void SILGenModule::emitDifferentiabilityWitness(
839839
SILDifferentiabilityWitnessKey key{originalFunction->getName(), silConfig};
840840
auto *diffWitness = M.lookUpDifferentiabilityWitness(key);
841841
if (!diffWitness) {
842-
// Strip external from linkage of original function.
843-
// Necessary for Clang-imported functions, which have external linkage.
842+
// Differentiability witnesses have the same linkage as the original
843+
// function, stripping external.
844844
auto linkage = stripExternalFromLinkage(originalFunction->getLinkage());
845845
diffWitness = SILDifferentiabilityWitness::createDefinition(
846846
M, linkage, originalFunction, silConfig.parameterIndices,

lib/SILGen/SILGenPoly.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3941,14 +3941,17 @@ SILFunction *SILGenModule::getOrCreateCustomDerivativeThunk(
39413941

39423942
auto loc = customDerivativeFn->getLocation();
39433943
SILGenFunctionBuilder fb(*this);
3944-
// This thunk is publicly exposed and cannot be transparent.
3945-
// Instead, mark it as "always inline" for optimization.
3944+
// Derivative thunks have the same linkage as the original function, stripping
3945+
// external.
3946+
auto linkage = stripExternalFromLinkage(originalFn->getLinkage());
39463947
auto *thunk = fb.getOrCreateFunction(
3947-
loc, name, customDerivativeFn->getLinkage(), thunkFnTy, IsBare,
3948-
IsNotTransparent, customDerivativeFn->isSerialized(),
3948+
loc, name, linkage, thunkFnTy, IsBare, IsNotTransparent,
3949+
customDerivativeFn->isSerialized(),
39493950
customDerivativeFn->isDynamicallyReplaceable(),
39503951
customDerivativeFn->getEntryCount(), IsThunk,
39513952
customDerivativeFn->getClassSubclassScope());
3953+
// This thunk may be publicly exposed and cannot be transparent.
3954+
// Instead, mark it as "always inline" for optimization.
39523955
thunk->setInlineStrategy(AlwaysInline);
39533956
if (!thunk->empty())
39543957
return thunk;

test/AutoDiff/Sema/derivative_attr_type_checking.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,27 @@ fileprivate func _fileprivate_original_fileprivate_derivative(_ x: Float) -> (va
837837
fatalError()
838838
}
839839

840+
func internal_original_usablefrominline_derivative(_ x: Float) -> Float { x }
841+
@usableFromInline
842+
@derivative(of: internal_original_usablefrominline_derivative)
843+
func _internal_original_usablefrominline_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
844+
fatalError()
845+
}
846+
847+
func internal_original_inlinable_derivative(_ x: Float) -> Float { x }
848+
@inlinable
849+
@derivative(of: internal_original_inlinable_derivative)
850+
func _internal_original_inlinable_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
851+
fatalError()
852+
}
853+
854+
func internal_original_alwaysemitintoclient_derivative(_ x: Float) -> Float { x }
855+
@_alwaysEmitIntoClient
856+
@derivative(of: internal_original_alwaysemitintoclient_derivative)
857+
func _internal_original_alwaysemitintoclient_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
858+
fatalError()
859+
}
860+
840861
// MARK: - Original function visibility < derivative function visibility
841862

842863
@usableFromInline
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-frontend -c %s -verify
2+
// REQUIRES: asserts
3+
4+
// TF-1160: Linker error for `@usableFromInline` derivative function but
5+
// non-`@usableFromInline` internal original function.
6+
7+
import _Differentiation
8+
9+
func internalOriginal(_ x: Float) -> Float { x }
10+
11+
@usableFromInline
12+
@derivative(of: internalOriginal)
13+
func usableFromInlineDerivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
14+
(x, { $0 })
15+
}
16+
17+
// Original error: type-checking passes but TBDGen is not consistent with IRGen.
18+
// <unknown>:0: error: symbol 'AD__$s4main16internalOriginalyS2fF__vjp_src_0_wrt_0' (AD__$s4main16internalOriginalyS2fF__vjp_src_0_wrt_0) is in generated IR file, but not in TBD file
19+
// <unknown>:0: error: please file a radar or open a bug on bugs.swift.org with this code, and add -Xfrontend -validate-tbd-against-ir=none to squash the errors

0 commit comments

Comments
 (0)