Skip to content

Add mangling support for @differentiable function types. #26595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -583,12 +583,16 @@ mangled in to disambiguate.
impl-function-type ::= type* 'I' FUNC-ATTRIBUTES '_'
impl-function-type ::= type* generic-signature 'I' PSEUDO-GENERIC? FUNC-ATTRIBUTES '_'

FUNC-ATTRIBUTES ::= CALLEE-ESCAPE? CALLEE-CONVENTION FUNC-REPRESENTATION? PARAM-CONVENTION* RESULT-CONVENTION* ('z' RESULT-CONVENTION)
FUNC-ATTRIBUTES ::= CALLEE-ESCAPE? DIFFERENTIABILITY-KIND? CALLEE-CONVENTION FUNC-REPRESENTATION? PARAM-CONVENTION* RESULT-CONVENTION* ('z' RESULT-CONVENTION)

PSEUDO-GENERIC ::= 'P'

CALLEE-ESCAPE ::= 'e' // @escaping (inverse of SIL @noescape)

DIFFERENTIABILITY-KIND ::= DIFFERENTIABLE | LINEAR
DIFFERENTIABLE ::= 'd' // @differentiable
LINEAR ::= 'l' // @differentiable(linear)

CALLEE-CONVENTION ::= 'y' // @callee_unowned
CALLEE-CONVENTION ::= 'g' // @callee_guaranteed
CALLEE-CONVENTION ::= 'x' // @callee_owned
Expand Down
4 changes: 4 additions & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ NODE(Identifier)
NODE(Index)
CONTEXT_NODE(IVarInitializer)
CONTEXT_NODE(IVarDestroyer)
// SWIFT_ENABLE_TENSORFLOW
NODE(ImplDifferentiable)
NODE(ImplLinear)
// SWIFT_ENABLE_TENSORFLOW END
NODE(ImplEscaping)
NODE(ImplConvention)
NODE(ImplFunctionAttribute)
Expand Down
12 changes: 12 additions & 0 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,18 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn) {
if (!fn->isNoEscape())
OpArgs.push_back('e');

// SWIFT_ENABLE_TENSORFLOW
switch (fn->getExtInfo().getDifferentiabilityKind()) {
case DifferentiabilityKind::NonDifferentiable:
break;
case DifferentiabilityKind::Normal:
OpArgs.push_back('d');
break;
case DifferentiabilityKind::Linear:
OpArgs.push_back('l');
break;
}

// <impl-callee-convention>
if (fn->getExtInfo().hasContext()) {
OpArgs.push_back(getParamConvention(fn->getCalleeConvention()));
Expand Down
6 changes: 6 additions & 0 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1729,6 +1729,12 @@ NodePointer Demangler::demangleImplFunctionType() {
if (nextIf('e'))
type->addChild(createNode(Node::Kind::ImplEscaping), *this);

// SWIFT_ENABLE_TENSORFLOW
if (nextIf('d'))
type->addChild(createNode(Node::Kind::ImplDifferentiable), *this);
if (nextIf('l'))
type->addChild(createNode(Node::Kind::ImplLinear), *this);

const char *CAttr = nullptr;
switch (nextChar()) {
case 'y': CAttr = "@callee_unowned"; break;
Expand Down
12 changes: 12 additions & 0 deletions lib/Demangling/NodePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,10 @@ class NodePrinter {
case Node::Kind::Index:
case Node::Kind::IVarInitializer:
case Node::Kind::IVarDestroyer:
// SWIFT_ENABLE_TENSORFLOW
case Node::Kind::ImplDifferentiable:
case Node::Kind::ImplLinear:
// SWIFT_ENABLE_TENSORFLOW END
case Node::Kind::ImplEscaping:
case Node::Kind::ImplConvention:
case Node::Kind::ImplFunctionAttribute:
Expand Down Expand Up @@ -2019,6 +2023,14 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
return nullptr;
case Node::Kind::LabelList:
return nullptr;
// SWIFT_ENABLE_TENSORFLOW
case Node::Kind::ImplDifferentiable:
Printer << "@differentiable";
return nullptr;
case Node::Kind::ImplLinear:
Printer << "@differentiable(linear)";
return nullptr;
// SWIFT_ENABLE_TENSORFLOW END
case Node::Kind::ImplEscaping:
Printer << "@escaping";
return nullptr;
Expand Down
12 changes: 12 additions & 0 deletions lib/Demangling/OldRemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,18 @@ void Remangler::mangleImplResult(Node *node) {
mangleChildNodes(node); // impl convention, type
}

// SWIFT_ENABLE_TENSORFLOW
void Remangler::mangleImplDifferentiable(Node *node) {
// The old mangler does not encode `@differentiable` function types.
Buffer << 'd';
}

// SWIFT_ENABLE_TENSORFLOW
void Remangler::mangleImplLinear(Node *node) {
// The old mangler does not encode `@differentiable(linear)` function types.
Buffer << 'l';
}

void Remangler::mangleImplEscaping(Node *node) {
// The old mangler does not encode escaping.
}
Expand Down
18 changes: 18 additions & 0 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,16 @@ void Remangler::mangleIVarDestroyer(Node *node) {
Buffer << "fE";
}

// SWIFT_ENABLE_TENSORFLOW
void Remangler::mangleImplDifferentiable(Node *node) {
Buffer << 'd';
}

// SWIFT_ENABLE_TENSORFLOW
void Remangler::mangleImplLinear(Node *node) {
Buffer << 'l';
}

void Remangler::mangleImplEscaping(Node *node) {
Buffer << 'e';
}
Expand Down Expand Up @@ -1423,6 +1433,14 @@ void Remangler::mangleImplFunctionType(Node *node) {
Buffer << 'I' << PseudoGeneric;
for (NodePointer Child : *node) {
switch (Child->getKind()) {
// SWIFT_ENABLE_TENSORFLOW
case Node::Kind::ImplDifferentiable:
Buffer << 'd';
break;
case Node::Kind::ImplLinear:
Buffer << 'l';
break;
// SWIFT_ENABLE_TENSORFLOW END
case Node::Kind::ImplEscaping:
Buffer << 'e';
break;
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/GenDiffFunc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
using namespace swift;
using namespace irgen;

/// A pair of `@differentiable` function extractee and differentiation order.
using DiffFuncIndex =
std::pair<AutoDiffFunctionExtractInst::Extractee, unsigned>;

Expand Down
37 changes: 37 additions & 0 deletions test/AutoDiff/differentiable_func_debuginfo.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// RUN: %target-swift-frontend -c %s -g -O -parse-stdlib -parse-as-library -module-name Swift

// TF-597: Exact minimal reproducer for IRGenDebugInfo crash.
// Crash occurred only with `-g` and `-O`.
//
// ```
// Assertion failed: (OffsetInBits + SizeInBits <= getSizeInBits(Var) && "pars > totum"),
// function emitVariableDeclaration, file swift/lib/IRGen/IRGenDebugInfo.cpp, line 2216.
// Stack dump:
// 1. Swift version 5.1-dev (LLVM 200186e28b, Swift c09c14dec5)
// 2. While emitting IR SIL function "@$ss8pullback2at2inyx_q_xXFts14DifferentiableRzsADR_r0_lF".
// for 'pullback(at:in:)' (at swift/test/AutoDiff/differentiable_func_debuginfo.swift:21:8)
// ```
//
// The crash was because `IRGenDebugInfoImpl::getOrCreateType` computes
// `llvm::DIType` type debug info by demangling type names.
//
// Since `@differentiable` and `@differentiable(linear)` function types did
// not have mangling support, `getOrCreateType` computed a regular `(A) -> B`
// function type instead of a `@differentiable (A) -> B` function type, leading
// to a type size inconsistency.
//
// Conclusion: mangling coverage is important.

// Minimal dummy compiler-known `Differentiable` protocol.
public protocol Differentiable {
associatedtype TangentVector
}

// This declaration is necessary to reproduce the crash for some reason.
public func blackHole<T, U>(_: (T) -> U) {}

public func pullback<T, R>(
at x: T, in tf597ProblematicVarDecl: @differentiable (T) -> R
) {
let _ = Builtin.autodiffApply_vjp(tf597ProblematicVarDecl, x)
}
3 changes: 3 additions & 0 deletions test/Demangle/Inputs/manglings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,6 @@ $s18keypaths_inlinable13KeypathStructV8computedSSvpACTKq ---> key path getter f
$s18resilient_protocol24ResilientDerivedProtocolPxAA0c4BaseE0Tn --> associated conformance descriptor for resilient_protocol.ResilientDerivedProtocol.A: resilient_protocol.ResilientBaseProtocol
$s3red4testyAA3ResOyxSayq_GAEs5ErrorAAq_sAFHD1__HCg_GADyxq_GsAFR_r0_lF --> red.test<A, B where B: Swift.Error>(red.Res<A, B>) -> red.Res<A, [B]>
$s3red4testyAA7OurTypeOy4them05TheirD0Vy5AssocQzGAjE0F8ProtocolAAxAA0c7DerivedH0HD1_AA0c4BaseH0HI1_AieKHA2__HCg_GxmAaLRzlF ---> red.test<A where A: red.OurDerivedProtocol>(A.Type) -> red.OurType<them.TheirType<A.Assoc>>
// SWIFT_ENABLE_TENSORFLOW
$sxq_Idgnr_D ---> @differentiable @callee_guaranteed (@in_guaranteed A) -> (@out B)
$sxq_Ilgnr_D ---> @differentiable(linear) @callee_guaranteed (@in_guaranteed A) -> (@out B)
8 changes: 8 additions & 0 deletions test/SILGen/mangling.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,11 @@ func varargsVsArray(arr: [Int], n: String) { }

// CHECK-LABEL: sil hidden [ossa] @$s8mangling14varargsVsArray3arr1nySaySiGd_SStF : $@convention(thin) (@guaranteed Array<Array<Int>>, @guaranteed String) -> ()
func varargsVsArray(arr: [Int]..., n: String) { }

// SWIFT_ENABLE_TENSORFLOW
// CHECK-LABEL: sil hidden [ossa] @$s8mangling15funcVsDiffFunc12fnyS2fXE_tF : $@convention(thin) (@noescape @callee_guaranteed (Float) -> Float) -> ()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: these newly added tests actually test @differentiable function mangling logic added in #25804.

That logic is different from the mangling logic added in this patch (mangling modifiers for ImplFunctionType). I'm not sure what's the meaning of ImplFunctionType and why it exists separately from SILFunctionType mangling: why is there ImplEscaping (for ImplFunctionType) in addition to EscapingObjCBlock/EscapingAutoClosureType (for regular SILFunctionType)?

cc @slavapestov, wonder if you can clarify

func funcVsDiffFunc1(fn: (Float) -> Float) {}

// SWIFT_ENABLE_TENSORFLOW
// CHECK-LABEL: sil hidden [ossa] @$s8mangling15funcVsDiffFunc22fnyS2fXF_tF : $@convention(thin) (@differentiable @noescape @callee_guaranteed (Float) -> Float) -> ()
func funcVsDiffFunc2(fn: @differentiable (Float) -> Float) {}
5 changes: 1 addition & 4 deletions utils/build-presets.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2143,10 +2143,7 @@ libcxx
indexstore-db
sourcekit-lsp

# SWIFT_ENABLE_TENSORFLOW
# FIXME(TF-597): IRGenDebugInfo crash for `pullback(at:in:)`.
# release-debuginfo
release
release-debuginfo

lldb-no-debugserver
lldb-use-system-debugserver
Expand Down