Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift fun(ctions)

Swift fun(ctions)

Lightning talk at dotSwift 2014. Shows how we can utilise knowledge of the memory layout for functions to dynamically call into C and call Swift from C.

Boris Bügling

February 06, 2015
Tweet

More Decks by Boris Bügling

Other Decks in Technology

Transcript

  1. WHAT IS A FUNCTION? func add(a: Int, b: Int) ->

    Int { return a + b } let f = add f(1, 2) // $R0: Int = 3 println(f) // (Function)
  2. NAME MANGLING $ xcrun swiftc func.swift $ nm -g func

    0000000100000f10 T __TF4func3addFTSiSi_Si [...] $ xcrun swift-demangle __TF4func3addFTSiSi_Si _TF4func3addFTSiSi_Si ---> func.add (Swift.Int, Swift.Int) -> Swift.Int
  3. MEMORY LAYOUT ▸ 8 bytes => Pointer to _TPA__TTRXFo_dSidSi_dSi_XFo_iTSiSi__iSi_ ▸

    8 bytes => Pointer to struct _TPA__TTRXFo_dSidSi_dSi_XFo_iTSiSi__iSi_ ---> partial apply forwarder for reabstraction thunk helper [...]
  4. MEMORY LAYOUT ▸ 16 bytes => Swift object ▸ 8

    bytes => Pointer to _TF6memory3addFTSiSi_Si Function pointer !
  5. import Darwin @asmname("floor") func my_floor(dbl: Double) -> Double println(my_floor(6.7)) let

    handle = dlopen(nil, RTLD_NOW) let pointer = COpaquePointer(dlsym(handle, "ceil")) typealias FunctionType = (Double) -> Double
  6. struct f_trampoline { [...] } struct function_obj { [...] }

    let orig = unsafeBitCast(my_floor, f_trampoline.self) let new = f_trampoline(prototype: orig, new_fp: pointer) let my_ceil = unsafeBitCast(new, FunctionType.self) println(my_ceil(6.7))