To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

Commit bbd6780c authored by Kunshan Wang's avatar Kunshan Wang
Browse files

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