emscriptenでgotoって使えるの?
A. 使えます。というか clang -> LLVM bitcode -> JavaScriptという変換なのでwhileなどのループもすべてgotoで表現されたあとJSに変換するので、gotoを表現できないとループすらできません。
中身を見てみると、たとえば以下のCのコード
#include <stdio.h> int main(int argc, const char** argv) { int i = (argc > 0) ? 42 : 0; if (i == 42) goto p; ++i; p: printf("i: %d\n", i); return 0; }
emcc(1) でコンパイルすると3600行ほどのJavaScriptになります。main()部分は以下のとおり。
function _main($argc, $argv) { var label = 0; var tempVarArgs = 0; var sp = STACKTOP; (assert((STACKTOP|0) < (STACK_MAX|0))|0); label = 1; while(1) switch(label) { case 1: // main()関数の先頭 var $retval; var $argc_addr; var $argv_addr; var $i; // iの宣言 $retval=0; $argc_addr=$argc; $argv_addr=$argv; var $0=$argc_addr; var $cmp=(($0)|(0)) > 0; var $cond=$cmp ? 42 : 0; $i=$cond; // i への代入(42が入る) var $1=$i; var $cmp1=(($1)|(0))==42; // i == 42 // ifで分岐して case 2 or 3 にジャンプ // label変数へジャンプ先のcase idを入れるようだ if ($cmp1) { label = 2; break; } else { label = 3; break; } case 2: // gotoする場合 label = 4; break; case 3: // gotoしない場合(今回は通過しない) var $2=$i; var $inc=((($2)+(1))|0); $i=$inc; label = 4; break; case 4: // case 2, 3いずれもここにくる var $3=$i; var $call=_printf(((8)|0), (tempVarArgs=STACKTOP,STACKTOP = (STACKTOP + 8)|0,(assert((STACKTOP|0) < (STACK_MAX|0))|0),HEAP32[((tempVarArgs)>>2)]=$3,tempVarArgs)); STACKTOP=tempVarArgs; STACKTOP = sp; return 0; default: assert(0, "bad label: " + label); } }
非常に読みにくいですが、もとのプログラムの変数 i は $i と表現されているようなので、それを追うとなんとなく処理はわかります。どうやらgoto文やラベル付き文でコードを分割し、while(1) switch (label) { ... }
で囲ってジャンプを表現しているようですね。
printf()の呼び出しが恐ろしいことになってますが、それはまたいずれ。