externref 0.1.0

Low-cost reference type shims for WASM modules
Documentation
(module
  ;; Corresponds to the following logic:
  ;;
  ;; ```
  ;; extern "C" {
  ;;     fn alloc(arena: &Resource<Arena>, cap: usize)
  ;;         -> Option<Resource<Bytes>>;
  ;; }
  ;;
  ;; pub extern "C" fn test(arena: &Resource<Arena>) {
  ;;     let _bytes = unsafe { alloc(arena, 42) }.unwrap();
  ;; }
  ;; ```
  ;;
  ;; Unlike with the module in `simple.wast`, we don't inline some assignments
  ;; from functions returning `externref`s in order to test that the corresponding
  ;; locals are transformed.

  ;; surrogate imports
  (import "externref" "insert" (func $insert_ref (param i32) (result i32)))
  (import "externref" "get" (func $get_ref (param i32) (result i32)))
  (import "externref" "drop" (func $drop_ref (param i32)))
  ;; real imported fn
  (import "arena" "alloc" (func $alloc (param i32 i32) (result i32)))

  ;; exported fn
  (func (export "test") (param $arena i32)
    (local $bytes i32)
    (local.set $bytes
      (call $alloc
        (call $get_ref
          (local.tee $arena
            (call $insert_ref (local.get $arena))
          )
        )
        (i32.const 42)
      )
    )
    (if (i32.eq
      (local.tee $bytes
        (call $insert_ref (local.get $bytes))
      )
      (i32.const -1))
      (then (unreachable))
      (else (call $drop_ref (local.get $bytes)))
   )
   (call $drop_ref (local.get $arena))
  )

  ;; internal fn; the `ref` local should be transformed as well
  (func (param $index i32)
    (local $ref i32)
    (local.set $ref
      (call $get_ref (local.get $index))
    )
    (call $drop_ref (local.get $ref))
  )
)