Skip to content

Commit b4d14c9

Browse files
authored
feat: allow supporting another vm (#94)
1 parent f6b01f5 commit b4d14c9

14 files changed

+778
-429
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,4 @@ jobs:
6666
pushd ./t/testdata/rust && cargo build --target=wasm32-wasi && popd
6767
6868
export PATH=$OPENRESTY_PREFIX/nginx/sbin:$PATH
69-
prove -I. -Itest-nginx/lib -r t/
69+
WASM_VM=wasmtime prove -I. -Itest-nginx/lib -r t/

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ The [Wasm integration of Apache APISIX](https://github.com/apache/apisix/blob/ma
2929
Remember to add the `wasmtime-c-api/lib` to the library search path when you build Nginx, for instance,
3030

3131
```
32-
export wasm_prefix=/path/to/wasm-nginx-module/wasmtime-c-api
32+
export wasmtime_prefix=/path/to/wasm-nginx-module/wasmtime-c-api
3333
./configure ... \
34-
--with-ld-opt="-Wl,-rpath,${wasm_prefix}/lib" \
34+
--with-ld-opt="-Wl,-rpath,${wasmtime_prefix}/lib" \
3535
```
3636

3737
## Directives
@@ -44,8 +44,8 @@ export wasm_prefix=/path/to/wasm-nginx-module/wasmtime-c-api
4444

4545
**context:** *http*
4646

47-
Select the WASM VM. Currently, only wasmtime is supported. If the directive is
48-
not set, the WASM VM won't be enabled.
47+
Select the WASM VM. Currently, only wasmtime is supported.
48+
If the directive is not set, the WASM VM won't be enabled.
4949

5050
## Methods
5151

config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ ngx_module_srcs=" \
2525
$ngx_addon_dir/src/vm/vm.c \
2626
"
2727
ngx_module_deps=" \
28-
$ngx_addon_dir/src/http/ngx_http_wasm_api.h \
28+
$ngx_addon_dir/src/http/ngx_http_wasm_api_def.h \
2929
$ngx_addon_dir/src/vm/vm.h \
3030
"
3131
ngx_module_incs=" \

gen_wasm_host_api.py

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
#!/usr/bin/env python
2+
# Copyright 2022 Shenzhen ZhiLiu Technology Co., Ltd.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
import os
17+
import re
18+
import sys
19+
from string import Template
20+
21+
22+
max_wasm_api_arg = 12
23+
header = """/*
24+
* Copyright 2022 Shenzhen ZhiLiu Technology Co., Ltd.
25+
*
26+
* Licensed under the Apache License, Version 2.0 (the "License");
27+
* you may not use this file except in compliance with the License.
28+
* You may obtain a copy of the License at
29+
*
30+
* http://www.apache.org/licenses/LICENSE-2.0
31+
*
32+
* Unless required by applicable law or agreed to in writing, software
33+
* distributed under the License is distributed on an "AS IS" BASIS,
34+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35+
* See the License for the specific language governing permissions and
36+
* limitations under the License.
37+
*
38+
*/
39+
/* Code generated by `./gen_wasm_host_api.py src/http`. DO NOT EDIT. */"""
40+
41+
api_def_tpl = """
42+
$header
43+
#ifndef NGX_HTTP_WASM_API_DEF_H
44+
#define NGX_HTTP_WASM_API_DEF_H
45+
46+
47+
#include <ngx_core.h>
48+
49+
50+
$host_api_def
51+
52+
53+
#endif
54+
"""
55+
56+
tpl = """
57+
$header
58+
#ifndef $vm_api_header_name
59+
#define $vm_api_header_name
60+
61+
62+
#include <wasm.h>
63+
$vm_header
64+
#include <ngx_core.h>
65+
#include "proxy_wasm/proxy_wasm_types.h"
66+
#include "http/ngx_http_wasm_api_def.h"
67+
68+
69+
#define MAX_WASM_API_ARG $max_wasm_api_arg
70+
71+
$wasm_api_def
72+
73+
74+
#endif
75+
"""
76+
77+
78+
def predefined_macro(vm):
79+
if vm == "wasmtime":
80+
vm_def = """
81+
#define DEFINE_WASM_API(NAME, ARG_CHECK) \\
82+
static wasm_trap_t* wasmtime_##NAME( \\
83+
void *env, \\
84+
wasmtime_caller_t *caller, \\
85+
const wasmtime_val_t *args, \\
86+
size_t nargs, \\
87+
wasmtime_val_t *results, \\
88+
size_t nresults \\
89+
) { \\
90+
ARG_CHECK \\
91+
results[0].kind = WASMTIME_I32; \\
92+
results[0].of.i32 = res; \\
93+
return NULL; \\
94+
}
95+
#define DEFINE_WASM_NAME(NAME, ARG) \\
96+
{ngx_string(#NAME), wasmtime_##NAME, ARG},
97+
98+
99+
typedef struct {
100+
ngx_str_t name;
101+
wasmtime_func_callback_t cb;
102+
int8_t param_num;
103+
wasm_valkind_t param_type[MAX_WASM_API_ARG];
104+
} ngx_wasm_wasmtime_host_api_t;
105+
106+
"""
107+
108+
for i in range(max_wasm_api_arg + 1):
109+
if i == 0:
110+
void_def = """
111+
#define DEFINE_WASM_NAME_ARG_VOID \\
112+
0, {}
113+
#define DEFINE_WASM_API_ARG_CHECK_VOID(NAME) \\
114+
int32_t res = NAME();
115+
"""
116+
vm_def += void_def
117+
else:
118+
param_s = ""
119+
if vm == "wasmtime":
120+
kind = "WASM_I32"
121+
for j in range(1, i + 1):
122+
if j % 5 == 1:
123+
param_s += " "
124+
param_s += kind + ", "
125+
if j % 5 == 0:
126+
param_s += " \\\n"
127+
vm_def += """
128+
#define DEFINE_WASM_NAME_ARG_I32_%d \\
129+
%d, { \\
130+
%s}""" % (i, i, param_s)
131+
vm_def += """
132+
#define DEFINE_WASM_API_ARG_CHECK_I32_%d(NAME) \\\n""" % (i)
133+
for j in range(i):
134+
if vm == "wasmtime":
135+
vm_def += " int32_t p%d = args[%d].of.i32; \\\n" % (j, j)
136+
param_s = ", ".join('p' + str(j) for j in range(i))
137+
vm_def += " int32_t res = NAME(%s);\n" % (param_s)
138+
return vm_def
139+
140+
141+
def get_host_apis(src_dir):
142+
apis = []
143+
with open(os.path.join(src_dir, "ngx_http_wasm_api.c")) as f:
144+
matching = False
145+
api = ""
146+
name = ""
147+
for line in f:
148+
m = re.match(r"^(proxy_\w+)\(", line)
149+
if m is not None:
150+
matching = True
151+
name = m.group(1)
152+
elif line[0] == '{' and matching:
153+
matching = False
154+
n_param = len(api.split(','))
155+
if "(void)" in api:
156+
n_param -= 1
157+
apis.append({
158+
"name": name,
159+
"n_param": n_param
160+
})
161+
api = ""
162+
if matching:
163+
api += line.rstrip()
164+
return apis
165+
166+
167+
if __name__ == '__main__':
168+
host_api_def = ""
169+
api_def = ""
170+
name_def = ""
171+
for i in range(max_wasm_api_arg + 1):
172+
if i == 0:
173+
host_api_def += "#define DEFINE_WASM_API_ARG_VOID void\n"
174+
else:
175+
param_suffix = "I32_%d" % i
176+
param_s = ""
177+
for j in range(1, i + 1):
178+
if j % 8 == 1:
179+
if j != 1:
180+
param_s += ","
181+
param_s += " \\\n "
182+
else:
183+
param_s += ", "
184+
param_s += "int32_t"
185+
host_api_def += "#define DEFINE_WASM_API_ARG_%s%s\n" % (param_suffix, param_s)
186+
host_api_def += "\n\n"
187+
188+
src_dir = sys.argv[1]
189+
apis = get_host_apis(src_dir)
190+
191+
for api in apis:
192+
name = api["name"]
193+
n_param = api["n_param"]
194+
if n_param == 0:
195+
param_suffix = "VOID"
196+
else:
197+
param_suffix = "I32_%d" % n_param
198+
199+
host_api_def += """int32_t %s(DEFINE_WASM_API_ARG_%s);\n""" % (name, param_suffix)
200+
api_def += """
201+
DEFINE_WASM_API(%s,
202+
DEFINE_WASM_API_ARG_CHECK_%s(%s))""" % (name, param_suffix, name)
203+
204+
name_def += " DEFINE_WASM_NAME(%s, DEFINE_WASM_NAME_ARG_%s)\n" % (name, param_suffix)
205+
206+
name_def += " { ngx_null_string, NULL, 0, {} }\n};"
207+
208+
s = Template(api_def_tpl)
209+
with open(os.path.join(src_dir, "ngx_http_wasm_api_def.h"), 'w') as f:
210+
f.write(s.substitute(header=header, host_api_def=host_api_def))
211+
212+
s = Template(tpl)
213+
214+
wasmtime_def = predefined_macro("wasmtime")
215+
wasmtime_def += api_def + "\n\nstatic ngx_wasm_wasmtime_host_api_t host_apis[] = {\n"
216+
wasmtime_def += name_def
217+
with open(os.path.join(src_dir, "ngx_http_wasm_api_wasmtime.h"), 'w') as f:
218+
f.write(s.substitute(
219+
header=header,
220+
vm_header="#include <wasmtime.h>",
221+
vm_api_header_name="NGX_HTTP_WASM_API_WASMTIME_H",
222+
wasm_api_def=wasmtime_def,
223+
max_wasm_api_arg=max_wasm_api_arg,
224+
))

0 commit comments

Comments
 (0)