Skip to content
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

[WASM] Implement thin-to-thick semantic for WebAssembly #186

Merged

Conversation

kateinoigakukun
Copy link
Member

@kateinoigakukun kateinoigakukun commented Feb 17, 2020

Resolve #30

This IRGen change enables us to call thin-to-thicked functions safely on WebAssembly runtime.

For example, the following SIL uses thin_to_thick_function instruction to transform thin function (which means there is no context argument in the last of arguments list) to thick function.

sil @closureToConvert : $@convention(thin) () -> () {
  %99 = tuple ()
  return %99 : $()
}

sil @testConvertFunc : $@convention(thin) () -> () {
bb0:
  %f = function_ref @closureToConvert : $@convention(thin) () -> ()
  %cf = convert_function %f : $@convention(thin) () -> () to $@noescape @convention(thin) () -> ()
  %thick = thin_to_thick_function %cf : $@noescape @convention(thin) () -> () to $@noescape @callee_owned () -> ()
  %apply = apply %thick() : $@noescape @callee_owned () -> ()
  %99 = tuple ()
  return %99 : $()
}

On x86_64 architecture, that SIL is transformed into the following LLVM IR

define swiftcc void @closureToConvert() {
entry:
  ret void
}

define swiftcc void @testConvertFunc() {
entry:
   call swiftcc void @"$closureToConvert"(%swift.refcounted* swiftself null)
   ret void
}

On x86_64, the trailing swiftself is put in r13 register, so it's OK that there is a difference of trailing swiftself parameter between callee and calling signature.
But this IR is invalid on WebAssembly because WebAssembly runtime validation spec requires they should be same signature when calling function indirectly.

So I changed to emit a thunk function to match these function signatures like the following LLVM IR.

define swiftcc void @closureToConvert() {
entry:
  ret void
}

define swiftcc void @testConvertFunc() {
entry:
   call swiftcc void @"$s16closureToConvertTu"(%swift.refcounted* swiftself bitcast (void ()* @closureToConvert to %swift.refcounted*))
   ret void
}

define internal void @"$s16closureToConvertTu"(%swift.refcounted* swiftself %0) {
entry:
  %1 = bitcast %swift.refcounted* %0 to void ()*
  call swiftcc void %1()
  ret void
}

$s16closureToConvertTu just proxy forwards the invocation to actual function which is come from trailing context pointer.

This change makes some failing test cases with optimization passed without indirect function call error.

Add indirect function call test case for WebAssembly and implement
IRGen for thin-to-thick thunk emission
Copy link

@MaxDesiatov MaxDesiatov left a comment

Choose a reason for hiding this comment

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

This seems legit to me, but I'm not an expert in this area 😄 Would probably be best to upstream it sooner rather than later to get more feedback from more people.

@kateinoigakukun kateinoigakukun merged commit 4e01560 into swiftwasm:swiftwasm Feb 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix indirect call type mismatch
2 participants