|
| 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