Skip to content

Commit

Permalink
WASM: Add support for visit_WASMInstsAssembler()
Browse files Browse the repository at this point in the history
  • Loading branch information
Shaikh-Ubaid committed Apr 4, 2023
1 parent 3317fec commit ed0fdae
Showing 1 changed file with 36 additions and 16 deletions.
52 changes: 36 additions & 16 deletions src/libasr/wasm_instructions_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(self, stream, data):
self.stream = stream
self.data = data

def visitWASMInstructions(self, mod, *args):
def visit_BaseWASMVisitor(self, mod, *args):
self.emit("template <class Struct>", 0)
self.emit("class BaseWASMVisitor {", 0)
self.emit("private:", 0)
Expand All @@ -47,7 +47,7 @@ def visitWASMInstructions(self, mod, *args):
self.emit( "BaseWASMVisitor(Vec<uint8_t> &code, uint32_t offset): code(code), offset(offset) {}", 1)

for inst in mod["instructions"]:
self.emit("void visit_%s(%s) {throw LCompilersException(\"visit_%s() not implemented\");}\n" % (inst["func"], make_param_list(inst["params"]), inst["func"]), 1)
self.emit("void visit_%s(%s) {throw LCompilersException(\"visit_%s() not implemented\");}\n" % (inst["func_read"], make_param_list(inst["params"], comment_out=True), inst["func_read"]), 1)

self.emit( "void decode_instructions() {", 1)
self.emit( "uint8_t cur_byte = wasm::read_b8(code, offset);", 2)
Expand All @@ -57,7 +57,7 @@ def visitWASMInstructions(self, mod, *args):
self.emit( "case %s: {" % (inst["opcode"]), 4)
for param in inst["params"]:
self.emit( "%s %s = %s(code, offset);" % (param["type"], param["name"], param["read_func"]), 5)
self.emit( "self().visit_%s(%s);" % (inst["func"], make_param_list(inst["params"], call=True)), 5)
self.emit( "self().visit_%s(%s);" % (inst["func_read"], make_param_list(inst["params"], call=True)), 5)
self.emit( "break;", 5)
self.emit( "}", 4)

Expand All @@ -68,7 +68,7 @@ def visitWASMInstructions(self, mod, *args):
self.emit( "case %sU: {" % (inst["params"][0]["val"]), 6)
for param in inst["params"][1:]: # first param is already read right at the start of case 0xFC
self.emit( "%s %s = %s(code, offset);" % (param["type"], param["name"], param["read_func"]), 7)
self.emit( "self().visit_%s(%s);" % (inst["func"], make_param_list(inst["params"], call=True)), 7)
self.emit( "self().visit_%s(%s);" % (inst["func_read"], make_param_list(inst["params"], call=True)), 7)
self.emit( "break;", 7)
self.emit( "}", 6)
self.emit( "default: {", 6)
Expand All @@ -85,7 +85,7 @@ def visitWASMInstructions(self, mod, *args):
self.emit( "case %sU: {" % (inst["params"][0]["val"]), 6)
for param in inst["params"][1:]: # first param is already read right at the start of case 0xFD
self.emit( "%s %s = %s(code, offset);" % (param["type"], param["name"], param["read_func"]), 7)
self.emit( "self().visit_%s(%s);" % (inst["func"], make_param_list(inst["params"], call=True)), 7)
self.emit( "self().visit_%s(%s);" % (inst["func_read"], make_param_list(inst["params"], call=True)), 7)
self.emit( "break;", 7)
self.emit( "}", 6)
self.emit( "default: {", 6)
Expand All @@ -102,18 +102,23 @@ def visitWASMInstructions(self, mod, *args):
self.emit( "cur_byte = wasm::read_b8(code, offset);", 3)
self.emit( "}", 2)
self.emit( "}", 1)
self.emit("};", 0)

self.emit("};\n", 0)

def emit(self, line, level=0):
indent = " "*level
self.stream.write(indent + line + "\n")

def make_param_list(params, call = False):
params = list(filter(lambda param: param["val"] != "0x00" and param["name"] != "num", params))
def filter_params(params):
return list(filter(lambda param: param["val"] != "0x00" and param["name"] != "num", params))

def make_param_list(params, comment_out = False, call = False):
params = filter_params(params)
if call:
return ", ".join(map(lambda param: param["name"], params))
return ", ".join(map(lambda param: param["type"] + " /*" + param["name"] + "*/", params))
return ", ".join(map(lambda p: p["name"], params))
if comment_out:
return ", ".join(map(lambda p: p["type"] + " /*" + p["name"] + "*/", params))
return ", ".join(map(lambda p: p["type"] + " " + p["name"], params))


def read_file(path):
with open(path, encoding="utf-8") as fp:
Expand All @@ -130,8 +135,10 @@ def process_raw_instructions(instructions_raw):
instructions.append(line.strip())
return instructions

def get_func_name(func):
def get_func_name(func, emit = False):
splitted_name = re.split("[\._]", func)
if emit:
return "_".join(splitted_name)
return "".join(map(lambda name_sub_part: name_sub_part.capitalize(), splitted_name))

param_read_function = {
Expand All @@ -143,6 +150,15 @@ def get_func_name(func):
"double": "wasm::read_f64"
}

param_emit_function = {
"uint8_t": "wasm::emit_b8",
"uint32_t": "wasm::emit_u32",
"int32_t": "wasm::emit_i32",
"int64_t": "wasm::emit_i64",
"float": "wasm::emit_f32",
"double": "wasm::emit_f64"
}

param_type = {
"u8": "uint8_t",
"u32": "uint32_t",
Expand All @@ -156,7 +172,9 @@ def parse_param_info(param_info):
type_info, name, val = param_info.split(":")
type = param_type[type_info]
read_func = param_read_function[type]
return {"type": type, "read_func": read_func, "name": name, "val": val}
emit_func = param_emit_function[type]
return {"type": type, "read_func": read_func, "emit_func": emit_func,
"name": name, "val": val}

def parse_instructions(instructions):
instructions_info = []
Expand All @@ -166,10 +184,12 @@ def parse_instructions(instructions):
opcode = binary_info[0]
params_info = binary_info[1:]
text_info = text_info.strip().split(" ")
func = get_func_name(text_info[0]) # first parameter is the function name
func_read = get_func_name(text_info[0]) # first parameter is the function name
func_emit = get_func_name(text_info[0], emit=True) # first parameter is the function name
text_params = text_info[1:] # text_params are currently not needed and hence not used further
params = list(map(lambda param_info: parse_param_info(param_info), params_info))
instructions_info.append({"opcode": opcode, "func": func, "params": params})
instructions_info.append({"opcode": opcode, "func_read": func_read,
"func_emit": func_emit, "params": params})
return instructions_info

def main(argv):
Expand All @@ -191,7 +211,7 @@ def main(argv):
try:
fp.write(HEAD % subs)
wasm_instructions_visitor = WASMInstructionsVisitor(fp, None)
wasm_instructions_visitor.visitWASMInstructions({"instructions": instructions_info})
wasm_instructions_visitor.visit_BaseWASMVisitor({"instructions": instructions_info})
fp.write(FOOT % subs)
finally:
fp.close()
Expand Down

0 comments on commit ed0fdae

Please sign in to comment.