Commit 89f15c67 authored by Kunshan Wang's avatar Kunshan Wang

Replace new_inst_res with get_inst_res.

Given all arguments (including all type arguments, signature arguments
and value arguments), the micro VM always knows how many results an
instruction has.
parent f9f5b52c
This diff is collapsed.
...@@ -204,20 +204,22 @@ defining it. ...@@ -204,20 +204,22 @@ defining it.
MuNorParam p0 = ctx->new_nor_param(ctx, entry, i32); MuNorParam p0 = ctx->new_nor_param(ctx, entry, i32);
MuNorParam p1 = ctx->new_nor_param(ctx, entry, i32); MuNorParam p1 = ctx->new_nor_param(ctx, entry, i32);
**Instructions** can be added to basic blocks. NOTE that the **results of **Instructions** can be added to basic blocks. Each instruction may have zero or
instructions are separate IR nodes**! They have to be added separately:: more results. **Instruction results** are IR nodes, too. They are created when
the instruction is created. Their handles can be obtained by the
``get_inst_res`` function::
// The ADD instruction produces one result. // The ADD instruction produces one result.
MuInstNode add = ctx->new_binop(ctx, entry, MU_BINOP_ADD, i32, p0, p1); MuInstNode add = ctx->new_binop(ctx, entry, MU_BINOP_ADD, i32, p0, p1);
MuInstResNode add_r = ctx->new_inst_res(ctx, add); MuInstResNode add_r = ctx->get_inst_res(ctx, add, 0);
// Mu functions may return multiple return values. // Mu functions may return multiple return values.
MuVarNode args[] = { xxx, xxx, xxx }; MuVarNode args[] = { xxx, xxx, xxx };
MuInstNode call = ctx->new_call(ctx, entry, some_sig, some_func, args, 3); MuInstNode call = ctx->new_call(ctx, entry, some_sig, some_func, args, 3);
MuInstResNode call_r0 = ctx->new_inst_res(ctx, call); MuInstResNode call_r0 = ctx->get_inst_res(ctx, call, 0);
MuInstResNode call_r1 = ctx->new_inst_res(ctx, call); MuInstResNode call_r1 = ctx->get_inst_res(ctx, call, 1);
MuInstResNode call_r2 = ctx->new_inst_res(ctx, call); MuInstResNode call_r2 = ctx->get_inst_res(ctx, call, 2);
MuInstResNode call_r3 = ctx->new_inst_res(ctx, call); MuInstResNode call_r3 = ctx->get_inst_res(ctx, call, 3);
Unlike the text form, the **exception clauses** are just destinations. For Unlike the text form, the **exception clauses** are just destinations. For
instructions that may have exception clauses, if you set the normal destination, instructions that may have exception clauses, if you set the normal destination,
...@@ -502,11 +504,15 @@ function, or redefine an existing function, the client should use the ...@@ -502,11 +504,15 @@ function, or redefine an existing function, the client should use the
:: ::
MuInstResNode (*new_inst_res )(MuCtx *ctx, MuInstNode inst); MuInstResNode (*get_inst_res )(MuCtx *ctx, MuInstNode inst, int index);
int (*get_num_inst_res)(MuCtx *ctx, MuInstNode inst);
``new_inst_res`` creates an instruction result node and adds it to the ``get_inst_res`` gets the ``index``-th instruction result node from the
instruction ``inst``. Each instruction must have **exactly** as many result instruction ``inst``. ``index`` starts from 0. This function returns a new
nodes as the number of results it produces. handle for each call (but refers to the same *IR node*), so they need to be
disposed (``delete_value``) separately, or just close the ``MuCtx``.
``get_num_inst_res`` gets the number of results of the instruction ``inst``.
.. _add_dest: .. _add_dest:
......
This diff is collapsed.
#/usr/bin/env python3
"""
Extract comminst definitions from common-insts.rst into C macros.
USAGE: python3 script/comminsts-to-muapi.py
"""
import re
import sys
from muspecinjectablefiles import injectable_files, common_insts_path
pat = re.compile(r'\[(0x[0-9a-f]+)\]@([a-zA-Z0-9_.]+)', re.MULTILINE)
def main():
defs = []
longest = 0
with open(common_insts_path) as f:
text = f.read()
for opcode, name in pat.findall(text):
macro_name = "MU_CI_" + name.upper().replace(".", "_")
opcode = opcode.lower()
defs.append((name, macro_name, opcode))
longest = max(longest, len(macro_name))
lines = []
for name, macro_name, opcode in defs:
lines.append("#define {} ((MuCommInst){}) /// MUAPIPARSER muname:@{}".format(
macro_name.ljust(longest), opcode, name))
outtext = "\n".join(lines)
injectable_files["muapi.h"].inject_many({
"COMMINSTS": outtext,
})
if __name__=="__main__":
main()
#/usr/bin/env python3
"""
Extract comminst definitions from common-insts.rest into C macros.
USAGE: python3 script/extract_comminst_macros.py < common-inst.rest
"""
import re
import sys
pat = re.compile(r'\[(0x[0-9a-f]+)\]@([a-zA-Z0-9_.]+)', re.MULTILINE)
defs = []
longest = 0
text = sys.stdin.read()
for opcode, name in pat.findall(text):
macro_name = "MU_CI_" + name.upper().replace(".", "_")
opcode = opcode.lower()
defs.append((name, macro_name, opcode))
longest = max(longest, len(macro_name))
for name, macro_name, opcode in defs:
print("#define {} ((MuCommInst){}) /// MUAPIPARSER muname:@{}".format(
macro_name.ljust(longest), opcode, name))
import re import re
from typing import List, Union, Tuple, Any, Callable, TypeVar from typing import List, Union, Tuple, Any, Callable, TypeVar, Mapping
from typing.re import Pattern from typing.re import Pattern
import tempfile, os.path
Predicate = Union[str, Predicate = Union[str,
Tuple[Pattern, ...], Tuple[Pattern, ...],
Callable[[Any], bool]] Callable[[Any], bool]]
...@@ -62,3 +64,56 @@ def inject_lines(parent: str, begin: Predicate, end: Predicate, generated: str) ...@@ -62,3 +64,56 @@ def inject_lines(parent: str, begin: Predicate, end: Predicate, generated: str)
new_lines = lines[:begin_line+1] + generated.splitlines() + lines[end_line:] new_lines = lines[:begin_line+1] + generated.splitlines() + lines[end_line:]
return "\n".join(new_lines) return "\n".join(new_lines)
STANDARD_PREFIX_BEGIN = "GEN:BEGIN:"
STANDARD_PREFIX_END = "GEN:END:"
class StandardInjectableFile(object):
def __init__(self, path: str, injection_points: List[str] = None):
self.path = path
if injection_points is None:
injection_points = []
self.injection_points = injection_points
def inject_many(self, m: Mapping[str, str], force=False):
with open(self.path) as f:
orig_txt = f.read()
txt = orig_txt
for inj_point, inj_content in m.items():
if inj_point not in self.injection_points and not force:
raise Exception("Unknown injection point '{}'".format(inj_point))
inj_begin = STANDARD_PREFIX_BEGIN + inj_point
inj_end = STANDARD_PREFIX_END + inj_point
new_txt = inject_lines(txt, inj_begin, inj_end, inj_content)
txt = new_txt
if not txt.endswith("\n"):
txt += "\n"
with tempfile.NamedTemporaryFile("w", delete=False) as f:
print("Backup to temporary file: {} -> {}".format(self.path, f.name))
f.write(orig_txt)
with open(self.path, "w") as f:
print("Writing to file: {}".format(self.path))
f.write(txt)
def make_injectable_file_set(
root_path: str,
items : List[Tuple[str, str, List[str]]],
) -> Mapping[str, StandardInjectableFile]:
m = InjectableFileSet()
for name, path, inj_points in items:
full_path = os.path.join(root_path, path)
sif = StandardInjectableFile(full_path, inj_points)
m[name] = sif
return m
class InjectableFileSet(dict):
def inject_many(self, m: Mapping[str, Mapping[str, str]]):
for name, mm in m.items():
self[name].inject_many(mm)
...@@ -9,6 +9,8 @@ Then paste into common-insts.rst ...@@ -9,6 +9,8 @@ Then paste into common-insts.rst
import muapiparser import muapiparser
import sys import sys
from muspecinjectablefiles import injectable_files, muapi_h_path
start_id_comminst = 0x300 start_id_comminst = 0x300
start_id_constant = 0x400 start_id_constant = 0x400
...@@ -16,6 +18,7 @@ _type_map = { ...@@ -16,6 +18,7 @@ _type_map = {
"void" : "", "void" : "",
"MuID" : "int<32>", "MuID" : "int<32>",
"MuName" : "iref<int<8>>", "MuName" : "iref<int<8>>",
"MuCString" : "iref<int<8>>",
"MuBool" : "int<32>", "MuBool" : "int<32>",
"MuWPID" : "int<32>", "MuWPID" : "int<32>",
"MuArraySize" : "int<64>", "MuArraySize" : "int<64>",
...@@ -54,7 +57,7 @@ def to_mu_ty(cty): ...@@ -54,7 +57,7 @@ def to_mu_ty(cty):
else: else:
raise Exception("I don't know how to translate: {}".format(cty)) raise Exception("I don't know how to translate: {}".format(cty))
def print_comminsts(ast): def get_comminst_defs(ast):
muctx_methods = [s["methods"] for s in ast["structs"] muctx_methods = [s["methods"] for s in ast["structs"]
if s["name"] == "MuCtx"][0] if s["name"] == "MuCtx"][0]
...@@ -64,6 +67,8 @@ def print_comminsts(ast): ...@@ -64,6 +67,8 @@ def print_comminsts(ast):
next_id = start_id_comminst next_id = start_id_comminst
lines = ["", "::", ""] # start reStructuredText block
for i in range(index_new_bundle, len(muctx_methods)): for i in range(index_new_bundle, len(muctx_methods)):
meth = muctx_methods[i] meth = muctx_methods[i]
name = meth["name"] name = meth["name"]
...@@ -83,11 +88,16 @@ def print_comminsts(ast): ...@@ -83,11 +88,16 @@ def print_comminsts(ast):
mu_params_joined = ", ".join(mu_params) mu_params_joined = ", ".join(mu_params)
mu_ret_ty = to_mu_ty(ret_ty) mu_ret_ty = to_mu_ty(ret_ty)
print(" [0x{:x}]@uvm.irbuilder.{} ({}) -> ({})".format( lines.append(" [0x{:x}]@uvm.irbuilder.{} ({}) -> ({})".format(
next_id, name, mu_params_joined, mu_ret_ty)) next_id, name, mu_params_joined, mu_ret_ty))
next_id += 1 next_id += 1
lines.append("")
lines.append("")
return "\n".join(lines)
_enums = [ _enums = [
"MuDestKind", "MuDestKind",
"MuBinOptr", "MuBinOptr",
...@@ -99,43 +109,17 @@ _enums = [ ...@@ -99,43 +109,17 @@ _enums = [
"MuCommInst", "MuCommInst",
] ]
def print_constants(ast):
""" NOT USED """
enums = ast["enums"]
next_id = start_id_constant
enums_map = {}
for enum in enums:
enums_map[enum["name"]] = enum["defs"]
print(" .typedef @uvm.irbuilder.MuFlag = int<32> // Private. Not available for the client.")
for enum_name in _enums:
defs = enums_map[enum_name]
for def_ in defs:
cn = def_["name"]
cv = def_["value"]
mcn = "@uvm.irbuilder." + cn
mcv = cv
print(" .const {} <@uvm.irbuilder.MuFlag> = {} // ID: 0x{:x}".format(
mcn, mcv, next_id))
next_id += 1
def main(): def main():
txt = sys.stdin.read() with open(muapi_h_path) as f:
txt = f.read()
ast = muapiparser.parse_muapi(txt) ast = muapiparser.parse_muapi(txt)
print_comminsts(ast) outtext = get_comminst_defs(ast)
#print()
#print_constants(ast) # Do not print. This merely pollutes the pre-loaded injectable_files["common-insts.rst"].inject_many({
# space with more constants, and not profitable. "IRBUILDER_COMMINSTS": outtext,
# We keep muapi.h as the canonical definition. })
# Clients should define their own constants.
if __name__=='__main__': if __name__=='__main__':
main() main()
import injecttools
import os.path
_my_dir = os.path.dirname(__file__)
_mu_spec_root = os.path.join(_my_dir, "..")
def _make_injectable_file_set(m):
m2 = {os.path.join(_mu_spec_root, k): v for k,v in m.items()}
return InjectableFileSet(m2)
muapi_h_path = os.path.join(_mu_spec_root, "muapi.h")
common_insts_path = os.path.join(_mu_spec_root, "common-insts.rst")
injectable_files = injecttools.make_injectable_file_set(_mu_spec_root, [
("common-insts.rst", "common-insts.rst",
["IRBUILDER_COMMINSTS"]),
("muapi.h", "muapi.h",
["COMMINSTS"]),
])
python3 muapi-irbuilder-to-comminsts.py
python3 comminsts-to-muapi.py
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