diff --git a/examples/cfg/example/intrinsics.yml b/examples/cfg/example/intrinsics.yml new file mode 100644 index 00000000..17333aa3 --- /dev/null +++ b/examples/cfg/example/intrinsics.yml @@ -0,0 +1,13 @@ +--- +intrinsics: + intrinsics: + - args: + - arg_name: rd + arg_type: i32 + - arg_name: rs1 + arg_type: i32 + - arg_name: rs2 + arg_type: i32 + instr_name: xexample.subincacc + intrinsic_name: subincacc + ret_type: i32 diff --git a/examples/demo.py b/examples/demo.py index c913a4fb..44ecb476 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -94,6 +94,7 @@ EXAMPLES_DIR / "cfg" / "tests.yml", EXAMPLES_DIR / "cfg" / "passes.yml", EXAMPLES_DIR / "cfg" / "git.yml", + EXAMPLES_DIR / "cfg" / "example/intrinsics.yml", ] seal5_flow.load(cfg_files, verbose=VERBOSE, overwrite=False) diff --git a/examples/tests/example/test_subincacc.c b/examples/tests/example/test_subincacc.c index fc7f699a..063bceb3 100644 --- a/examples/tests/example/test_subincacc.c +++ b/examples/tests/example/test_subincacc.c @@ -23,3 +23,13 @@ __attribute__((naked)) void test_subincacc() { // CHECK: ab ba b5 51 xexample.subincacc x21, x11, x27 asm("xexample.subincacc x21, x11, x27"); } + +void test_intrinsic() { + // CHECK: + int a = 3; + int b = 7; + int c = 4; + // Can't rely upon specific registers being used but at least instruction should have been used + // CHECK: example.subincacc + c = __builtin_xexample_subincacc(a, b, c); +} diff --git a/seal5/backends/riscv_instr_info/writer.py b/seal5/backends/riscv_instr_info/writer.py index 765cd8e1..59941892 100644 --- a/seal5/backends/riscv_instr_info/writer.py +++ b/seal5/backends/riscv_instr_info/writer.py @@ -241,7 +241,7 @@ def main(): parser.add_argument("--metrics", default=None, help="Output metrics to file") parser.add_argument("--index", default=None, help="Output index to file") parser.add_argument("--ext", type=str, default="td", help="Default file extension (if using --splitted)") - parser.add_argument("--add-intrinsics", type=bool, default=True, action=argparse.BooleanOptionalAction, help="Include patterns for intrinsic functions") + parser.add_argument("--no-add-intrinsics", dest='add_intrinsics', default=True, action='store_false', help="Suppress patterns for intrinsic functions") args = parser.parse_args() # initialize logging diff --git a/seal5/backends/riscv_intrinsics/writer.py b/seal5/backends/riscv_intrinsics/writer.py index f620307d..95d8d91d 100644 --- a/seal5/backends/riscv_intrinsics/writer.py +++ b/seal5/backends/riscv_intrinsics/writer.py @@ -45,16 +45,16 @@ def build_target(arch: str, intrinsic: IntrinsicDefn): target = f'TARGET_BUILTIN(__builtin_{arch}_{intrinsic.intrinsic_name}, "{arg_str}", "nc", "{arch}")' return target + def ir_type_to_pattern(ir_type: str): # needs fleshing out with all likely types - match ir_type: - case 'i32': - return 'llvm_i32_ty' + if ir_type == 'i32': + return 'llvm_i32_ty' raise NotImplementedError(f'Unhandled ir_type "{ir_type}"') + def build_attr(arch: str, intrinsic: IntrinsicDefn): - uses_mem = False #@todo - ret_types = '(unsupported)' # how to spec void intrinsic? + uses_mem = False # @todo attr = f' def int_riscv_{intrinsic.intrinsic_name} : Intrinsic<\n [' if intrinsic.ret_type: attr += f'{ir_type_to_pattern(intrinsic.ret_type)}' @@ -77,9 +77,11 @@ def build_emit(arch: str, intrinsic: IntrinsicDefn): @dataclass class PatchFrag: - patchee: str - tag: str - contents: str = "" + """Pairs patch contents to location to apply it""" + patchee: str + tag: str + contents: str = "" + def main(): """Main app entrypoint.""" @@ -113,7 +115,7 @@ def main(): else: out_path = pathlib.Path(args.output) - logger.info("loading models") + logger.info("intrinsics/writer - loading models") if not is_seal5_model: raise NotImplementedError @@ -157,7 +159,7 @@ def main(): if llvm_settings: llvm_state = llvm_settings.state if llvm_state: - llvm_version = llvm_state.version + llvm_version = llvm_state.version # unused today, but needed very soon patch_frags = { 'target': PatchFrag(patchee='clang/include/clang/Basic/BuiltinsRISCV.def', tag='builtins_riscv'), 'attr': PatchFrag(patchee='llvm/include/llvm/IR/IntrinsicsRISCV.td', tag='intrinsics_riscv'), diff --git a/seal5/flow.py b/seal5/flow.py index a4797180..c8919290 100644 --- a/seal5/flow.py +++ b/seal5/flow.py @@ -81,6 +81,7 @@ # ("riscv_instr_formats", passes.gen_riscv_instr_formats_patch, {}), ("riscv_register_info", passes.gen_riscv_register_info_patch, {}), ("riscv_instr_info", passes.gen_riscv_instr_info_patch, {}), + ("riscv_intrinsics", passes.gen_riscv_intrinsics, {}), # subtarget_tests # register_types # operand_types diff --git a/seal5/pass_list.py b/seal5/pass_list.py index fbdd3ba0..3fed3f22 100644 --- a/seal5/pass_list.py +++ b/seal5/pass_list.py @@ -1076,7 +1076,6 @@ def gen_riscv_isa_info_patch( print_func=logger.info if verbose else logger.debug, live=True, ) -# breakpoint() if gen_index_file: if index_file.is_file(): patch_name = f"riscv_isa_info_{input_file.stem}" @@ -1138,7 +1137,6 @@ def gen_riscv_intrinsics( print_func=logger.info if verbose else logger.debug, live=True, ) -# breakpoint() if gen_index_file: if index_file.is_file(): patch_base = f"riscv_intrinsics_target_{input_file.stem}" @@ -1166,7 +1164,6 @@ def gen_riscv_instr_info_patch( **_kwargs, ): # assert not split, "TODO" -# breakpoint() assert split, "TODO" # formats = True gen_metrics_file = True diff --git a/seal5/settings.py b/seal5/settings.py index 5135b6ea..a3a1073e 100644 --- a/seal5/settings.py +++ b/seal5/settings.py @@ -157,7 +157,7 @@ "clone_depth": 1, "sparse_checkout": False, }, - }, + }, "intrinsics": { }, } @@ -572,11 +572,13 @@ class ToolsSettings(YAMLSettings): pattern_gen: Optional[PatternGenSettings] = None + @dataclass class IntrinsicArg(YAMLSettings): arg_name: str arg_type: str + @dataclass class IntrinsicDefn(YAMLSettings): instr_name: str @@ -584,6 +586,7 @@ class IntrinsicDefn(YAMLSettings): ret_type: Optional[str] = None args: Optional[List[IntrinsicArg]] = None + @dataclass class IntrinsicsSettings(YAMLSettings): intrinsics: Optional[List[IntrinsicDefn]] = None