2017-04-26 3 views
0

残念ながら私はwasmファイルにC/C++をコンパイルするために動作するツールチェーンを手に入れることができませんが、ここで親切な魂が私を助けてくれることを望んでいました。与えられたプログラムの断片:ローカル構造へのポインタはどのようにwebassemblyに変換されますか?

struct foo { 
    int a; 
    float b; 
}; 

void function(foo * p); 

void my_program() { 
    struct foo my_foo; 
    my_foo.a = 1; 
    my_foo.b = -3.0F; 
    foo(&my_foo); 
} 

my_programのwasmコードはどのように見えるのですか?

答えて

2

私は、無駄なテキスト形式の外観はどういう意味だろうと思いますか?

それがコンパイルなるように、私はあなたのコード内のカップルの事を調整する:

struct foo { 
    int a; 
    float b; 
}; 

extern void bar(struct foo * p); 

void my_program() { 
    struct foo my_foo; 
    my_foo.a = 1; 
    my_foo.b = -3.0F; 
    bar(&my_foo); 
} 

はemscripten/binaryenを使用して、wasm2wastを使用してそれをコンパイル:

emcc -s WASM=1 -s SIDE_MODULE=1 -O2 str.c -o str.js 
wasm-dis str.wasm -o str.wast 

注意を-s SIDE_MODULE=1 -O2せず、emscriptenこと標準ライブラリ(mallocなど)の束を引っ張り出し、wastファイルは10,000行長くなります。私はおそらく、あなたはおそらく、すべてのリンケージ/封入物がなくてもかなり単純なwasm/wast結果を望んでいると仮定しています。 memoryBasetableBase__post_instantiate、およびrunPostSetsはプラットフォームのメモリの統合/初期化のための追加をemscriptenしていることを

(module 
(type $0 (func (param i32))) 
(type $1 (func)) 
(import "env" "memoryBase" (global $import$0 i32)) 
(import "env" "_bar" (func $import$1 (param i32))) 
(import "env" "memory" (memory $0 256)) 
(import "env" "table" (table 0 anyfunc)) 
(import "env" "tableBase" (global $import$4 i32)) 
(global $global$0 (mut i32) (i32.const 0)) 
(global $global$1 (mut i32) (i32.const 0)) 
(export "_my_program" (func $0)) 
(export "__post_instantiate" (func $2)) 
(export "runPostSets" (func $1)) 
(func $0 (type $1) 
    (local $var$0 i32) 
    (local $var$1 i32) 
    (block $label$0 
    (set_local $var$0 
    (get_global $global$0) 
    ) 
    (set_global $global$0 
    (i32.add 
    (get_global $global$0) 
    (i32.const 16) 
    ) 
    ) 
    (i32.store 
    (tee_local $var$1 
    (get_local $var$0) 
    ) 
    (i32.const 1) 
    ) 
    (f32.store offset=4 
    (get_local $var$1) 
    (f32.const -3) 
    ) 
    (call $import$1 
    (get_local $var$1) 
    ) 
    (set_global $global$0 
    (get_local $var$0) 
    ) 
) 
) 
(func $1 (type $1) 
    (nop) 
) 
(func $2 (type $1) 
    (block $label$0 
    (set_global $global$0 
    (get_global $import$0) 
    ) 
    (set_global $global$1 
    (i32.add 
    (get_global $global$0) 
    (i32.const 5242880) 
    ) 
    ) 
    (call $1) 
) 
) 
;; custom section "dylink", size 5 
) 

注:以下ワストファイルになり

memoryBaseは基本的にCスタックの先頭であり、値は__post_instantiateによって$global$0にコピーされます(これはこのモジュールのすべての機能に共通です)。 my_programが最初に呼び出されると、スタック上のmy_foo構造体に "割り当てられた"スペースがあるところを指すように、スタックポインタを16で調整します。 foo内のフィールドを更新するために、offset=Xを使用して、i32.storeオペレーションを実行します。関数が返ってきたら、スタックポインタ($global$0)を、関数を入力したときの位置に復元します。

+0

私が理解しようとしているのは、ローカルストレージがどのように構造体のための領域を確保するために割り当てられているかです。グローバル2はある種の明示的なスタックポインタのように動作しているようです。ローカル0にコピーされ、16( 'sizeof foo')だけインクリメントされ、プロシージャの終了時にローカル0の値にリセットされます。環境がグローバルポインタとして「スタックポインタ」を提供すると仮定するのは正しいでしょうか? –

+0

@JohnKällénはい、それは私の理解です。よりインテリジェントな分解と注釈が追加されているので、バイステンからwasm-disを使用して廃棄物を更新しました。私はそれを説明するコードの説明文を追加しました。 – kanaka

関連する問題