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.
MuNorParam p0 = 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 are separate IR nodes**! They have to be added separately::
**Instructions** can be added to basic blocks. Each instruction may have zero or
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.
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.
MuVarNode args[] = { xxx, xxx, xxx };
MuInstNode call = ctx->new_call(ctx, entry, some_sig, some_func, args, 3);
MuInstResNode call_r0 = ctx->new_inst_res(ctx, call);
MuInstResNode call_r1 = ctx->new_inst_res(ctx, call);
MuInstResNode call_r2 = ctx->new_inst_res(ctx, call);
MuInstResNode call_r3 = ctx->new_inst_res(ctx, call);
MuInstResNode call_r0 = ctx->get_inst_res(ctx, call, 0);
MuInstResNode call_r1 = ctx->get_inst_res(ctx, call, 1);
MuInstResNode call_r2 = ctx->get_inst_res(ctx, call, 2);
MuInstResNode call_r3 = ctx->get_inst_res(ctx, call, 3);
Unlike the text form, the **exception clauses** are just destinations. For
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
::
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
instruction ``inst``. Each instruction must have **exactly** as many result
nodes as the number of results it produces.
``get_inst_res`` gets the ``index``-th instruction result node from the
instruction ``inst``. ``index`` starts from 0. This function returns a new
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:
......
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
from typing import List, Union, Tuple, Any, Callable, TypeVar
from typing import List, Union, Tuple, Any, Callable, TypeVar, Mapping
from typing.re import Pattern
import tempfile, os.path
Predicate = Union[str,
Tuple[Pattern, ...],
Callable[[Any], bool]]
......@@ -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:]
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
import muapiparser
import sys
from muspecinjectablefiles import injectable_files, muapi_h_path
start_id_comminst = 0x300
start_id_constant = 0x400
......@@ -16,6 +18,7 @@ _type_map = {
"void" : "",
"MuID" : "int<32>",
"MuName" : "iref<int<8>>",
"MuCString" : "iref<int<8>>",
"MuBool" : "int<32>",
"MuWPID" : "int<32>",
"MuArraySize" : "int<64>",
......@@ -54,7 +57,7 @@ def to_mu_ty(cty):
else:
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"]
if s["name"] == "MuCtx"][0]
......@@ -64,6 +67,8 @@ def print_comminsts(ast):
next_id = start_id_comminst
lines = ["", "::", ""] # start reStructuredText block
for i in range(index_new_bundle, len(muctx_methods)):
meth = muctx_methods[i]
name = meth["name"]
......@@ -83,11 +88,16 @@ def print_comminsts(ast):
mu_params_joined = ", ".join(mu_params)
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 += 1
lines.append("")
lines.append("")
return "\n".join(lines)
_enums = [
"MuDestKind",
"MuBinOptr",
......@@ -99,43 +109,17 @@ _enums = [
"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():
txt = sys.stdin.read()
with open(muapi_h_path) as f:
txt = f.read()
ast = muapiparser.parse_muapi(txt)
print_comminsts(ast)
#print()
#print_constants(ast) # Do not print. This merely pollutes the pre-loaded
# space with more constants, and not profitable.
# We keep muapi.h as the canonical definition.
# Clients should define their own constants.
outtext = get_comminst_defs(ast)
injectable_files["common-insts.rst"].inject_many({
"IRBUILDER_COMMINSTS": outtext,
})
if __name__=='__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