Commit bbd6780c authored by Kunshan Wang's avatar Kunshan Wang

Python binding generated

parent 80c594ae
......@@ -38,11 +38,16 @@ _primitive_types = {
def type_is_explicit_ptr(ty):
return ty.endswith("*")
r_handle_ty = re.compile(r'^Mu\w*(Value|Node)$')
r_handle_ty = re.compile(r'^Mu\w*Value$')
def type_is_handle(ty):
return r_handle_ty.match(ty) is not None
r_node_ty = re.compile(r'^Mu\w*(Node|Clause)$')
def type_is_node(ty):
return r_node_ty.match(ty) is not None
def type_is_ptr(ty):
return type_is_explicit_ptr(ty) or type_is_handle(ty)
......@@ -54,40 +59,6 @@ def to_basic_type(typedefs, name):
name = typedefs[name]
return name
_no_conversion = {
"MuID", # It's just Int.
"MuTrapHandler", # It is a function pointer. Handle in Scala.
"MuCPtr", # Intended to be raw pointer. Passed directly.
"MuCFP", # ditto
"MuWPID", # Just Int
"MuCommInst", # Only used in new_comminst, and the builder uses opcode directly.
}
_array_converters = {
"char*" : "readCharArray",
"uint64_t*" : "readLongArray",
"MuFlag*" : "readFlagArray",
}
_special_converters = {
"MuBool" : "intToBoolean",
"MuName" : "readCString",
"MuMemOrd" : "toMemoryOrder",
"MuAtomicRMWOptr" : "toAtomicRMWOptr",
"MuBinOptr" : "toBinOptr",
"MuCmpOptr" : "toCmpOptr",
"MuConvOptr" : "toConvOptr",
"MuCallConv" : "toFlag",
"MuDestKind" : "toDestKind",
}
_special_return_converters = {
"MuBool" : "booleanToInt",
"MuName" : "exposeString",
"MuCtx*" : "exposeMuCtx",
"MuVM*" : "exposeMicroVM",
}
_manually_defined_types = [
"MuCFP",
"MuValuesFreer",
......@@ -113,7 +84,7 @@ def generate_ctypes(ast):
_enums = [
("MuTrapHandlerResult", 'MU_'),
("MuDestKind", 'MU_DEST_'),
#("MuDestKind", 'MU_DEST_'), # removed
("MuBinOptr", 'MU_BINOP_'),
("MuCmpOptr", 'MU_CMP_'),
("MuConvOptr", 'MU_CONV_'),
......@@ -143,8 +114,7 @@ def generate_cenums(ast):
comminst_defs = enums_map["MuCommInst"]
lines.append("common_instruction_opcodes = {")
for d in comminst_defs:
dp, dv = d["pragmas"], d["value"]
muname = [pv for pk, pv in (p.split(":") for p in dp) if pk == "muname"][0]
muname, dv = d["muname"], d["value"]
lines.append(" '{}': {},".format(muname, dv))
lines.append("}")
......@@ -192,6 +162,7 @@ _defined_in_python = {k for k,v in _enums} | {
_mu_structs = {
"MuVM*": "MuVM",
"MuCtx*": "MuCtx",
"MuIRBuilder*": "MuIRBuilder",
}
def to_python_ty(cty):
......@@ -247,24 +218,71 @@ _method_blacklist = {
"new_thread_exc",
"dump_keepalives",
},
"MuIRBuilder": {
"gen_sym",
},
}
def need_array_wrapper(params):
return any("array_sz_param" in param for param in params)
def generate_method(typedefs, strname, meth) -> Tuple[str, str]:
name = meth['name']
params = meth['params'][1:]
ret_ty = meth['ret_ty']
pragmas = meth['pragmas']
param_tys = [p["type"] for p in params]
py_param_tys = [to_python_ty(t) for t in param_tys]
py_ret_ty = to_python_ty(ret_ty)
if name in _method_blacklist[strname]:
name = name + "_"
naw = need_array_wrapper(params)
if name in _method_blacklist[strname] or naw:
stub_name = name + "_"
else:
stub_name = name
stub = """('{}', {}, [{}]),""".format(
stub_name, py_ret_ty, ", ".join(py_param_tys))
if naw:
formals = [p for p in params if not p.get("is_sz_param", False)]
formal_names = [p["name"] for p in formals]
actual_names = [p["name"] for p in params]
asgns = []
for f in formals:
fn = f["name"]
fcty = f["type"]
ary_ind = f.get("array_sz_param", None)
is_optional = f.get("is_optional", False)
if ary_ind != None:
assert(fcty.endswith("*"))
fcty_elem = fcty[:-1]
asgns.append("_actual_{}_ty = C{} * len({})".format(fn,
fcty_elem, fn))
asgns.append("_actual_{} = _actual_{}_ty()".format(fn, fn))
asgns.append("for _i,_v in enumerate({}):".format(fn))
if type_is_handle(fcty):
asgns.append(" _actual_{}[_i] = _v.c_mu_value".format(fn))
else:
asgns.append(" _actual_{}[_i] = _v".format(fn))
asgns.append("_actual_{} = len({})".format(ary_ind, fn))
elif is_optional and (type_is_node(fcty) or fcty == "MuID"):
asgns.append("_actual_{} = 0 if {} is None else {}".format(fn, fn, fn))
else:
asgns.append("_actual_{} = {}".format(fn, fn))
wrapper = """\
def {}(self, {}):
{}
return self.{}({})
""".format(name, ", ".join(formal_names), "\n".join(" "*8+ln for ln in asgns),
stub_name, ", ".join("_actual_"+n for n in actual_names))
else:
wrapper = None
return """('{}', {}, [{}]),""".format(
name, py_ret_ty, ", ".join(py_param_tys))
return stub, wrapper
def generate_stubs_for_struct(ast, name) -> str:
st = [s for s in ast["structs"] if s["name"] == name][0]
......@@ -272,13 +290,16 @@ def generate_stubs_for_struct(ast, name) -> str:
typedefs = ast["typedefs"]
results = []
stubs = []
wrappers = []
for meth in methods:
code = generate_method(typedefs, name, meth)
results.append(code)
stub, wrapper = generate_method(typedefs, name, meth)
stubs.append(stub)
if wrapper is not None:
wrappers.append(wrapper)
return "\n".join(results)
return "\n".join(stubs), "\n".join(wrappers)
def main():
with open(muapi_h_path) as f:
......@@ -289,8 +310,9 @@ def main():
c_types = generate_ctypes(ast)
c_enums = generate_cenums(ast)
muvalues = generate_muvalues(ast)
muvm_stubs = generate_stubs_for_struct(ast, "MuVM")
muctx_stubs = generate_stubs_for_struct(ast, "MuCtx")
muvm_stubs, _ = generate_stubs_for_struct(ast, "MuVM")
muctx_stubs, _ = generate_stubs_for_struct(ast, "MuCtx")
muirbuilder_stubs, muirbuilder_wrappers = generate_stubs_for_struct(ast, "MuIRBuilder")
injectable_files["libmu.py"].inject_many({
"CTYPES": c_types,
......@@ -298,6 +320,8 @@ def main():
"MUVALUE": muvalues,
"MuVM": muvm_stubs,
"MuCtx": muctx_stubs,
"MuIRBuilder": muirbuilder_stubs,
"wrp_MuIRBuilder": muirbuilder_wrappers,
})
if __name__=='__main__':
......
......@@ -15,7 +15,8 @@ injectable_files = injecttools.make_injectable_file_set(_refimpl2_root, [
("cStubs.scala", "src/main/scala/uvm/refimpl/nat/cStubs.scala",
["STUBS"]),
("libmu.py", "pythonbinding/libmu.py",
["CTYPES", "CENUMS", "MUVALUE", "MuVM", "MuCtx"]),
["CTYPES", "CENUMS", "MUVALUE", "MuVM", "MuCtx", "MuIRBuilder",
"wrp_MuIRBuilder"]),
("comminsts.scala", "src/main/scala/uvm/comminsts/comminsts.scala",
["IRBUILDER_COMMINSTS"]),
("internals.scala", "src/main/scala/uvm/refimpl/internals.scala",
......
from __future__ import division, absolute_import, print_function, unicode_literals
import sys
import ctypes, ctypes.util
from libmu import *
libc = ctypes.CDLL(ctypes.util.find_library("c"))
libc.write.restype = ctypes.c_ssize_t
libc.write.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_size_t]
dll = MuRefImpl2StartDLL("../cbinding/libmurefimpl2start.so")
mu = dll.mu_refimpl2_new_ex(
dumpBundle=True
#vmLog="DEBUG"
#vmLog="INFO"
)
with mu.new_context() as ctx:
# Perpare the C function pointers:
puts_addr = ctypes.cast(libc.puts, ctypes.c_void_p).value
print("puts = ", puts_addr, hex(puts_addr))
# Building bundle...
b = ctx.new_ir_builder()
i32 = b.gen_sym("@i32")
i8 = b.gen_sym("@i8")
pi8 = b.gen_sym("@pi8")
puts_sig = b.gen_sym("@puts.sig")
puts_fp = b.gen_sym("@puts.fp")
puts = b.gen_sym("@puts")
b.new_type_int(i32, 32)
b.new_type_int(i8, 8)
b.new_type_uptr(pi8, i8)
b.new_funcsig(puts_sig, [pi8], [i32])
b.new_type_ufuncptr(puts_fp, puts_sig)
b.new_const_int(puts, pi8, puts_addr)
buf = ctypes.create_string_buffer("Hello python!".encode("ascii"))
buf_addr = ctypes.cast(buf, ctypes.c_void_p).value
print("buf_addr = ", buf_addr, hex(buf_addr))
msg = b.gen_sym("@msg")
b.new_const_int(msg, pi8, buf_addr)
mumain_sig = b.gen_sym("@mumain.sig")
mumain = b.gen_sym("@mumain")
fv = b.gen_sym("@mumain.v1")
entry = b.gen_sym("@mumain.v1.entry")
ccall = b.gen_sym("@mumain.v1.entry.ccall")
ccall_r = b.gen_sym("@mumain.v1.entry.ccall_r")
threadexit = b.gen_sym("@mumain.v1.entry.threadedit")
b.new_funcsig(mumain_sig, [], [])
b.new_func(mumain, mumain_sig)
b.new_func_ver(fv, mumain, [entry])
b.new_bb(entry, [], [], 0, [ccall, threadexit])
b.new_ccall(ccall, [ccall_r], MuCallConv.DEFAULT, puts_fp, puts_sig, puts, [msg], None, None)
b.new_comminst(threadexit, [], common_instruction_opcodes["@uvm.thread_exit"],
[], [], [], [], None, None)
b.load()
hmumain = ctx.handle_from_func(mumain)
st = ctx.new_stack(hmumain)
th = ctx.new_thread(st, None, PassValues())
mu.execute()
print("Returned from Mu.")
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment