Skip to content

Instantly share code, notes, and snippets.

@Azoy
Last active March 1, 2020 20:43
Show Gist options
  • Save Azoy/9e60a74eb990b67497cce4531b95be43 to your computer and use it in GitHub Desktop.
Save Azoy/9e60a74eb990b67497cce4531b95be43 to your computer and use it in GitHub Desktop.
Demangle Function

Demangle Function

Introduction

Introduce a new function, demangle, that takes a mangled Swift symbol, like $sSS7cStringSSSPys4Int8VG_tcfC, and output the human readable Swift symbol, like Swift.String.init(cString: Swift.UnsafePointer<Swift.Int8>) -> Swift.String. Along with the introduction of this function, we're also going to introduce a new module LowLevel that provides similar functionality to Swift.

Swift-evolution thread: Demangle Function

Motivation

Currently in Swift, if a user is given an unreadable mangled symbol, they're most likely to use the swift-demangle tool to get the demangled version. However, this is a little awkward when you want to demangle a symbol in-process in Swift. One could create a new Process from Foundation and set it up to launch a new process within the process to use swift-demangle, but we can certainly make this a lot easier.

Proposed solution

LowLevel Module

Demangle Function

The LowLevel module will add the following function:

// Given a mangled Swift symbol, return the demangled symbol.
public func demangle(
  _ mangledName: String,
  isSimplified: Bool = false
) -> String?

Examples:

import LowLevel

print(demangle("$s8Demangle3FooV")!) // Demangle.Foo
print(demangle("$sSi")!) // Swift.Int
print(demangle("Hello World!") ?? "Not a valid symbol!") // Not a valid symbol!

Detailed design

If one were to pass a string that wasn't a valid Swift mangled symbol, like abc123, then the (String) -> String? would simply return nil to indicate failure.

This implementation relies on the Swift runtime function swift_demangle which accepts symbols that start with _T, _T0, $S, and $s.

Source compatibility

These are completely new standard library functions, thus source compatibility is unaffected.

Effect on ABI stability

These are completely new standard library functions, thus ABI compatibility is unaffected.

Effect on API resilience

These are completely new standard library functions, thus API resilience is unaffected.

Alternatives considered

We could choose to only provide one of the proposed functions, but each of these brings unique purposes. The trivial take a string and return a string version is a very simplistic version in cases where maybe you're not worried about allocating new memory, and the buffer variants where you don't want to alloc new memory and want to pass in some memory you've already allocated.

Future Directions

The swift_demangle runtime function has an extra flags parameter, but currently it is not being used for anything. In the future if that function ever supports any flags, it would make sense to introduce new overloads or something similar to expose those flags to the standard library as well. E.g.

public func demangle(_ input: String, flags: DemangleFlags) -> String

public func demangle(
  _ input: String,
  into buffer: UnsafeMutableBufferPointer<Int8>,
  flags: DemangleFlags
) -> Int?

where DemangleFlags could be an enum, OptionSet, [DemangleFlag], etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment