<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/139630>139630</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [WebAssembly][Clang] Add intrinsics to make and test for an externref sentinel
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          hoodmane
      </td>
    </tr>
</table>

<pre>
    #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:
```C
  if (error_condition) {
     return __builtin_wasm_ref_sentinel_extern();
 }
```
and then check like:
```C
  __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 
```wat
(type $sentinel (struct)) ;; 0x5f, 0x00
```
Then `__builtin_wasm_ref_sentinel_extern()` would translate to:
```wat
 struct.new $sentinel ;; 0xfb, 0x00, <type index of $sentinel>
 extern.convert_any   ;; 0xfb, 27
```
and `__builtin_wasm_ref_is_sentinel_extern()` translates to:
```wat
 any.convert_extern ;; 0xfb, 26
    ref.test $sentinel ;; 0xfb, 20, <type index of $sentinel>
```

It's also worth noting that 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.

</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyMVs1u4zwSfBr60ohBU5Z_Dj4oyQbYuewhs5ijQYktizsU6SVbdvz2H5qSPYmTGQwQIEhEsquqq4vUKdmDR9yJ8lGUzzM9UBfirgvB9NrjrA7mshOqWBTbciNBG5OAOgRdW2fpAhSAMBGcO6QOI2gPYiXxjTD6iK1YSbAJ_OAchAg-0By-dzZBo72QVY0wJDTQhgjWP9TaG8AYQwRGpZ2z_iDUE9QDgSXeBA61yVVjGGqHUGOjh4SQQo9CVt_0Sb820R4J2sE3ZIPnYpERh4EydmPbFiP6hnfTGdGPALn64A221qPhstobISvbwjnjHFdRmMCNSBN_ZDZqTdBpbxyChojajctP2g3IpJExRMaY8IRROziGlCxzSMENGakoKiGrxRyeOu0PCP3lHQvqNEFEGqKfZN7vb0LviaWm8Onf0Aq1sZ6ErABAqCqRpiExPVE8hbFp8ZBE8S-htqJ45HOE2uQumYBpZBbx_4NlBv4CzQiOAjRO-8Oc98lKzeE19NiFMzik8RMY1uFsqXvHI__ZD47s0eGVUJYp5RYc7AnBToA1HLWNENpPCz_5jPdqGOnxR1sosZJCVsUcXm1vnY4uG1Yx-V7_xOyG9-fyfusPDuGsU_9waCBRHBrK2gu1ThMeIavlHP6b8oZxRWblA7QWnUmgeWlCT9ajE5LbmhVtwxCpg0YnhCYMzoAL4Sc4-xPH5jPk_POUBbAtNyM7bd8EbyxrKNQWxPpxVAiuDPb7erCOrN8z-D13_wpgMoRQm6nHsgKxfn5fTsiKBaQOPTQdNn_A9NFfEROI4jkP4J67_KHKROALbDZ9AS9i4r0f-Qn1ItTLdbi4Z1mPXyRuS_7Ddj7bxP6BiMeIXCK7RTc0aAffXqeJvOMuZPUD4Zw70ukTN5YuR8wiwPu1Z83OFGqTPwu1vJJgmqMXrgyKR1E8gnwrWzacfJPyruh3FjsP7F92biUniBS1T04TT-Fdj0aAky3nHs8fQV5BtfUN1BgFmY_1Bt942t7t4WSQFYxA5k3wJ4y05yCA--PU-gtLfU3wy_ZPHG_s0m_paX-5QRm3f8KymvwTsZ3nO-oPOqi_VOHOMv-eQsGlAOcQcwKQ9Ycxq8eLwyMa5CuLK5yvU5_jhxOChxqCx4cxgHJ9zpI72l97bvHLdJCnpx0vHR-ukm6vZvzcl3TLxPrCFzvj7kNEbtjvDlvJa8DdMUnQsyOMTWR9wy0aYT3Umi_4MVUpeBBK3SRVKvPNaXnmzPXEczkzu8Jsi62e4W6xXq7lptysV7NupxQuVgpRbZZmrdBsVtsFbop2WSzXy1KVM7tTUpWyXCi1KNblai6X622xabFZbk1ZLluxlNhr6-bOnfp5iIeZTWnA3aLYrgo5c7pGl_JbSKl8gwml-FkUd7zhoR4OSSyls4nSryPIkssPqB9YVylhX7uLKJ9F-fiUjyifoTIGrKdofbINu3qSjROXrckPIO3hlqu3q2M2RLfriI75bZBT7mCpG-p5E3qhXhjE9OvhGMP_kOPnJZNKQr1MvE479U8AAAD__3rgMac">