kubo39's blog

ただの雑記です。

LDCでwasmのmultivalue拡張できないか軽く試す (2)

前回の続き。

構造体は静的初期化にしたらうまくいくかも?と思い以下のようにコードを変更してみた。

extern (C):
nothrow:
@nogc:

struct TwoI32
{
    int aa;
    int bb;
};

export TwoI32 return_two_i32()
{
    TwoI32 s = { aa: 1, bb: 2 };
    return s;
}

が結果は変わらず。

$ wasm-validate multivalue.wasm
000000e: error: invalid function result count 2, only 1 bytes left in section

このエラーメッセージだけだとちょっとわかりにくいが、型定義の部分がおかしいようだ。

$ wasm-objdump -x -j Type multivalue.wasm

multivalue.wasm:    file format wasm 0x1
000000e: error: invalid function result count 2, only 1 bytes left in section

Section Details:

Type[1]:

本来であれば

() -> (i32, i32)

のような型が出現してほしい。

スタック参照してるのが悪いのかな?と思い、-Ozで最適化+ついでにコードサイズ小さくしてみる。

ldc2 -mtriple=wasm32-unknown-unknown \
    -mattr=+multivalue \
    -betterC \
    -fvisibility=hidden \
    --frame-pointer=none \
    -L=-no-entry \
    -Oz \
    --output-ll \
    -vv \
    multivalue.d

LLVM IRもなんか小奇麗になった。

(...)
%multivalue.TwoI32 = type { i32, i32 }

; [#uses = 0]
; Function Attrs: norecurse nounwind readnone
define %multivalue.TwoI32 @return_two_i32() local_unnamed_addr #0 {
  ret %multivalue.TwoI32 { i32 1, i32 2 }
}

attributes #0 = { norecurse nounwind readnone "frame-pointer"="none" "target-cpu"="generic" "target-features"="+multivalue" }
(...)

しかし--output-ll外してwasm生成すると同じエラーになる。

$ wasm-validate multivalue.wasm
000000e: error: invalid function result count 2, only 1 bytes left in section

同じようにTypeが壊れているということのはずなので、%multivalue.TwoI32ではだめということか。

本体が

ret { i32, i32 } { i32 1, i32 2 }

のようになる必要がある?

ただLDC側でArgInfo::getDirect()のような新し目のAPIを使えるようにするのは今の時点だとなかなか大変な作業なので、なんか簡単に試せる方法がないか考えよう。