0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

clang/emscripten + WebAssembly の役に立たない小ネタ

Last updated at Posted at 2024-04-01

WebAssembly Custom Section を書き出す

インラインアセンブリでの、.custom_section で始まるセクションが WebAssembly Custom Section として出力される。
C/C++ ソースコードでは __attribute__((section(".custom_section.(任意の名前)"))) と同等のはずだが、これで修飾したセクションは WebAssembly Data Section に乗ってしまうため、C/C++ の範囲での記述方法はない。

インラインアセンブリ
.section .custom_section.my_data,"",@
    .asciz "Hello, WebAssembly"
出力
(module
  ;; custom section "my_data", size 19
)

WebAssembly ネイティブな setjmp/longjmp

コンパイルフラグに -mllvm -wasm-enable-sjlj を追加することで、setjmp/longjmp を WebAssembly Exception Handling にマッピングするコードを出力できる。
emscripten では JavaScript での例外処理/setjmp/longjmp を無効化する必要があるので、コンパイルフラグに -sSUPPORT_LONGJMP=wasm -sDISABLE_EXCEPTION_THROWING=1 を指定する。

ソース
# include <stdio.h>
# include <setjmp.h>

jmp_buf t;

void test() {
    longjmp(t, 1);
}

int main() {
    if (setjmp(t) == 0) {
        test();
    } else {
        printf("Jumped!\n");
    }
    return 0;
}

参照

extenref/funcref を使う

extenref/funcref はそれぞれ __externref_t__funcref を修飾した関数ポインタにマッピングされている。

externref
__attribute__((import_name("receive_object")))
__externref_t receive_object(void);

__attribute__((import_name("send_object")))
void send_object(__externref_t);

int main() {
    send_object(receive_object());
    return 0;
}
funcref
using main_fp_t = int (*__funcref)();

int main() {
	return 0;
}

__attribute__((used))
extern "C" main_fp_t exportMainAsFuncRef() {
    // WebAssembly での関数ポインタの正体は WebAssembly Table Index
    auto main_fp = &main;

    __asm(R"(
        local.get %0
        table.get __indirect_function_table
        return
    )" 
    : : "r"(main_fp));
}

なお、関数ポインタを直接 funcref に変換することはできない模様。

__attribute__((used))
extern "C" main_fp_t exportMainAsFuncRef() {
 	return (main_fp_t)&main;
}
// Cannot select: 0x2004f5a0ad8: funcref = addrspacecast[0 -> 20]

WebAssembly Table を定義する

C/Cpp
// static で 0 サイズな __externref_t のグローバル変数の配列が WebAssembly Table になる
static __externref_t table[0];

// 組み込み関数も用意されている
__builtin_wasm_table_grow(table, __builtin_wasm_ref_null_extern(), 1);
アセンブリ
subtable:
    .global subtable
    .tabletype subtable, funcref, 1

clang/emscripten を使ってできないこと

  • start function の指定
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?