Skip to content

[WebAssembly][Clang] Add intrinsics to make and test for an externref sentinel #139630

Open
@hoodmane

Description

@hoodmane

#139580 adds the ability to test whether an externref is null or not. This can
be used for in-band error signalling, but it can lead to trouble because some
JavaScript functions care about the difference between null and undefined, and
if we use null to signal errors we can't handle a real null value. There are
several possible solutions:

  1. Change my functions that return an __externref_t to __externref_t f(int *status, <other args>); (This doesn't require any change to clang.)
  2. Somehow let clang deal with functions with multiple return values and give it
    a pair of return values an externref and a status i32
  3. Similarly to 2, make the return value a single wasm-gc struct that's a pair
  4. Use a struct with no fields as a sentinel

This fourth case could look like:

  if (error_condition) {
     return __builtin_wasm_ref_sentinel_extern();
  }

and then check like:

  __externref_t res = some_func();
  if (__builtin_wasm_ref_is_sentinel_extern(res)) {
     // handle the error
  }
  // Otherwise it represents an actual JS value.

We would have a type like

(type $sentinel (struct)) ;; 0x5f, 0x00

Then __builtin_wasm_ref_sentinel_extern() would translate to:

    struct.new $sentinel ;; 0xfb, 0x00, <type index of $sentinel>
    extern.convert_any   ;; 0xfb, 27

and __builtin_wasm_ref_is_sentinel_extern() would translate to:

    any.convert_extern ;; 0xfb, 26
    ref.test $sentinel ;; 0xfb, 20, <type index of $sentinel>

If we needed to, we could make a second one-value type with:

(type $sentinel1 (struct (ref null noextern))) 

and similarly by adding more (ref null noextern) fields we could make as many distinct
struct-based singleton "sentinel" types as we want.

cc @sbc100 @tlively @pmatos

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions