202 lines
4.9 KiB
Python
202 lines
4.9 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
from argparse import ArgumentParser
|
||
|
import json
|
||
|
|
||
|
parser = ArgumentParser(prog='bindgen.py')
|
||
|
parser.add_argument('api')
|
||
|
parser.add_argument('spec')
|
||
|
parser.add_argument('-g', '--guest-stubs')
|
||
|
parser.add_argument('--guest-include')
|
||
|
parser.add_argument('--wasm3-bindings')
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
apiName = args.api
|
||
|
spec = args.spec
|
||
|
guest_stubs_path = args.guest_stubs
|
||
|
if guest_stubs_path == None:
|
||
|
guest_stubs_path = 'bindgen_' + apiName + '_guest_stubs.c'
|
||
|
|
||
|
wasm3_bindings_path = args.wasm3_bindings
|
||
|
if wasm3_bindings_path == None:
|
||
|
wasm3_bindings_path = 'bindgen_' + apiName + '_wasm3_bindings.c'
|
||
|
|
||
|
host_bindings = open(wasm3_bindings_path, 'w')
|
||
|
guest_bindings = None
|
||
|
|
||
|
specFile = open(spec, 'r')
|
||
|
data = json.load(specFile)
|
||
|
|
||
|
def needs_arg_ptr_stub(decl):
|
||
|
res = (decl['ret']['tag'] == 'S')
|
||
|
for arg in decl['args']:
|
||
|
if arg['type']['tag'] == 'S':
|
||
|
res = True
|
||
|
return(res)
|
||
|
|
||
|
for decl in data:
|
||
|
if needs_arg_ptr_stub(decl):
|
||
|
guest_bindings = open(guest_stubs_path, 'w')
|
||
|
if args.guest_include != None:
|
||
|
s = '#include"' + args.guest_include + '"\n\n'
|
||
|
print(s, file=guest_bindings)
|
||
|
break
|
||
|
|
||
|
for decl in data:
|
||
|
|
||
|
name = decl['name']
|
||
|
cname = decl.get('cname', name)
|
||
|
|
||
|
if needs_arg_ptr_stub(decl):
|
||
|
argPtrStubName = name + '_argptr_stub'
|
||
|
# pointer arg stub declaration
|
||
|
s = ''
|
||
|
if decl['ret']['tag'] == 'S':
|
||
|
s += 'void'
|
||
|
else:
|
||
|
s += decl['ret']['name']
|
||
|
|
||
|
s += ' ' + argPtrStubName + '('
|
||
|
|
||
|
if decl['ret']['tag'] == 'S':
|
||
|
s += decl['ret']['name'] + '* __retArg'
|
||
|
if len(decl['args']) > 0:
|
||
|
s += ', '
|
||
|
|
||
|
for i, arg in enumerate(decl['args']):
|
||
|
s += arg['type']['name']
|
||
|
if arg['type']['tag'] == 'S':
|
||
|
s += '*'
|
||
|
s += ' ' + arg['name']
|
||
|
if i+1 < len(decl['args']):
|
||
|
s += ', '
|
||
|
s += ');\n\n'
|
||
|
|
||
|
# forward function to pointer arg stub declaration
|
||
|
s += decl['ret']['name'] + ' ' + name + '('
|
||
|
for i, arg in enumerate(decl['args']):
|
||
|
s += arg['type']['name'] + ' ' + arg['name']
|
||
|
if i+1 < len(decl['args']):
|
||
|
s += ', '
|
||
|
s += ')\n'
|
||
|
s += '{\n'
|
||
|
s += '\t'
|
||
|
if decl['ret']['tag'] == 'S':
|
||
|
s += decl['ret']['name'] + ' __ret;\n\t'
|
||
|
elif decl['ret']['tag'] != 'v':
|
||
|
s += decl['ret']['name']
|
||
|
s += ' __ret = '
|
||
|
s += argPtrStubName + '('
|
||
|
|
||
|
if decl['ret']['tag'] == 'S':
|
||
|
s += '&__ret'
|
||
|
if len(decl['args']) > 0:
|
||
|
s += ', '
|
||
|
|
||
|
for i, arg in enumerate(decl['args']):
|
||
|
if arg['type']['tag'] == 'S':
|
||
|
s += '&'
|
||
|
|
||
|
s += arg['name']
|
||
|
if i+1 < len(decl['args']):
|
||
|
s += ', '
|
||
|
s += ');\n'
|
||
|
if decl['ret']['tag'] != 'v':
|
||
|
s += '\treturn(__ret);\n'
|
||
|
s += '}\n\n'
|
||
|
|
||
|
print(s, file=guest_bindings)
|
||
|
|
||
|
# host-side stub
|
||
|
s = 'const void* ' + cname + '_stub(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t* _sp, void* _mem)'
|
||
|
|
||
|
gen_stub = decl.get('gen_stub', True)
|
||
|
if gen_stub == False:
|
||
|
s += ';\n\n'
|
||
|
else:
|
||
|
s += '\n{\n\t'
|
||
|
retTag = decl['ret']['tag']
|
||
|
|
||
|
if retTag == 'i':
|
||
|
s += '*((i32*)&_sp[0]) = '
|
||
|
elif retTag == 'I':
|
||
|
s += '*((i64*)&_sp[0]) = '
|
||
|
elif retTag == 'f':
|
||
|
s += '*((f32*)&_sp[0]) = '
|
||
|
elif retTag == 'd':
|
||
|
s += '*((f64*)&_sp[0]) = '
|
||
|
elif retTag == 'S':
|
||
|
retTypeName = decl['ret']['name']
|
||
|
retTypeCName = decl['ret'].get('cname', retTypeName)
|
||
|
s += '*(' + retTypeCName + '*)((char*)_mem + *(i32*)&_sp[0]) = '
|
||
|
|
||
|
s += cname + '('
|
||
|
|
||
|
firstArgIndex = 0
|
||
|
if retTag != 'v':
|
||
|
firstArgIndex = 1
|
||
|
|
||
|
for i, arg in enumerate(decl['args']):
|
||
|
typeName = arg['type']['name']
|
||
|
typeCName = arg['type'].get('cname', typeName)
|
||
|
argTag = arg['type']['tag']
|
||
|
if argTag == 'i':
|
||
|
s += '*(i32*)&_sp[' + str(firstArgIndex + i) + ']'
|
||
|
elif argTag == 'I':
|
||
|
s += '*(i64*)&_sp[' + str(firstArgIndex + i) + ']'
|
||
|
elif argTag == 'f':
|
||
|
s += '*(f32*)&_sp[' + str(firstArgIndex + i) + ']'
|
||
|
elif argTag == 'd':
|
||
|
s += '*(f64*)&_sp[' + str(firstArgIndex + i) + ']'
|
||
|
elif argTag == 'p':
|
||
|
s += '(void*)((char*)_mem + *(i32*)&_sp[' + str(firstArgIndex + i) + '])'
|
||
|
elif argTag == 'S':
|
||
|
s += '*(' + typeCName + '*)((char*)_mem + *(i32*)&_sp[' + str(firstArgIndex + i) + '])'
|
||
|
else:
|
||
|
print('unrecognized type ' + c + ' in procedure signature\n')
|
||
|
break
|
||
|
|
||
|
if i+1 < len(decl['args']):
|
||
|
s += ', '
|
||
|
|
||
|
s += ');\n\treturn(0);\n}\n\n'
|
||
|
|
||
|
print(s, file=host_bindings)
|
||
|
|
||
|
# link function
|
||
|
s = 'int bindgen_link_' + apiName + '_api(IM3Module module)\n{\n\t'
|
||
|
s += 'M3Result res;\n'
|
||
|
|
||
|
for decl in data:
|
||
|
name = decl['name']
|
||
|
cname = decl.get('cname', name)
|
||
|
|
||
|
if needs_arg_ptr_stub(decl):
|
||
|
name = name + '_argptr_stub'
|
||
|
|
||
|
m3Sig = ''
|
||
|
if decl['ret']['tag'] == 'S':
|
||
|
m3Sig += 'v'
|
||
|
else:
|
||
|
m3Sig += decl['ret']['tag']
|
||
|
|
||
|
m3Sig += '('
|
||
|
if decl['ret']['tag'] == 'S':
|
||
|
m3Sig += 'i'
|
||
|
for arg in decl['args']:
|
||
|
tag = arg['type']['tag']
|
||
|
if tag == 'p' or tag == 'S':
|
||
|
tag = 'i'
|
||
|
m3Sig += tag
|
||
|
m3Sig += ')'
|
||
|
|
||
|
|
||
|
s += '\tres = m3_LinkRawFunction(module, "*", "' + name + '", "' + m3Sig + '", ' + cname + '_stub);\n'
|
||
|
s += '\tif(res != m3Err_none && res != m3Err_functionLookupFailed) { LOG_ERROR("error: %s\\n", res); return(-1); }\n\n'
|
||
|
|
||
|
|
||
|
s += '\treturn(0);\n}\n'
|
||
|
|
||
|
print(s, file=host_bindings)
|