emscripten であそぶ
hello
int main() { puts("hello"); }
生成されたコード
// EMSCRIPTEN_START_FUNCS function _main() { var label = 0; var $1=_puts(((8)|0)); return 0; } Module["_main"] = _main; // EMSCRIPTEN_END_FUNCS
8がだだっぴろいメモリへのインデックスなのはわかるけど、それはどこで定義されてるのかな…と hello で検索しても見つからない。 104 で検索すると見つかった。
STATIC_BASE = 8; STATICTOP = STATIC_BASE + 8; /* memory initializer */ allocate([104,101,108,108,111,0,0,0], "i8", ALLOC_NONE, Rubyntime.GLOBAL_BASE)
sleep
CPS 変換ってやつかなんかしないときつくねー、って気になるものの代表格
#include <unistd.h> int main() { sleep(1); }
えっと…
while (Date.now() - start < msec) { // Do nothing. }
まさかの busy loop! 男らしい!
pthread
<pthread.h> void* thread(void* data) {} int main() { pthread_t th; pthread_create(&th, NULL, &thread, NULL); pthread_join(th, NULL); }
ReferenceError: _pthread_create is not defined
read
#include <unistd.h> int main() { read(0, "foo", 1); perror("read"); }
STDIN は EBADF 。
setjmp
ほとんどイヤガラセみたいな要求ですが
#include <setjmp.h> #include <stdio.h> jmp_buf env; void func() { longjmp(env, 1); } int main() { int ok = 0; if (setjmp(env)) { if (ok) puts("PASS"); } else { ok = 1; func(); } }
意外にも? 動いた! 実装は例外にて。なるほどー。
function _longjmp(env, value) { throw { longjmp: true, id: HEAP32[((env)>>2)], value: value || 1 }; }
メモリ保護
int main() { --*""; char* msg = "hello"; ++*msg; puts(msg); char* p = &main; *p = 42; }
iello 。無し!
mmap
#include <sys/mman.h> int main() { char* p = mmap(0x4000000, 0x1000, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, -1, 0); if (p == MAP_FAILED) perror("mmap"); *p = 'h'; printf("%p %s\n", p, p); }
結果は 0x5000a8 h とかで MAP_FIXED は無視されました。ちなみに
/* FIXME: Since mmap is normally implemented at the kernel level, * this implementation simply uses malloc underneath the call to * mmap. */
とのことで、 mmap が malloc 呼んでて通常と真逆。ちなみにメモリ空間はデフォルトでは 16MB らしい。まあそんなもんですかねえ。
pipe
#include <unistd.h> int main() { int fds[2]; pipe(fds); perror("pipe"); }
pipe は ENOSYS か。ネットワークでも使わない限り blocking call がどうなるかわからない感じか…
connect
#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> int main() { int sock = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(80); addr.sin_addr.s_addr = 0x0100007f; connect(sock, &addr, sizeof(addr)); }
結果は
opening ws://127.0.0.1:80 Error in connect(): ReferenceError: WebSocket is not defined
WebScoket 必須らしい。 sleep 以外の synchronous な関数を呼んでみたいんですけど、どうしたら良いかな。
fork
ENOSYS かなと思ったら EAGAIN
#include <errno.h> #include <unistd.h> int main() { fork(); perror("fork"); printf("%d %d\n", errno, EAGAIN); }
EAGAIN が "No more processes" とかいう見覚えの全く無いメッセージを出したので確認してみました…
qsort
普通に const な領域を sort するのもどうかと思うけど…
#include <stdlib.h> int cmp(const void* a, const void* b) { return *(char*)a-*(char*)b; } int main() { const char* msg = "hoge"; qsort(msg, 4, 1, cmp); puts(msg); }
関数ポインタは FUNCTION_TABLE ってのに入ってて、別の空間にある感じぽい。
var FUNCTION_TABLE = [0,0,_cmp]; // EMSCRIPTEN_START_FUNCS function _cmp($a, $b) {
まとめ
Intel の iOS => HTML5 converter with LLVM 書いた人は今どんな気持ちなんだろうか
http://software.intel.com/en-us/articles/technical-reference-intel-html5-app-porter-tool-beta