From 933abb6d7c3868cd70876542427f6ffea3b26fd0 Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Thu, 28 Feb 2019 11:18:49 +0100 Subject: [PATCH] Generate op pretty printer. --- .gitignore | 1 + Makefile | 8 +- src/aeb_fate_asm.erl | 149 +--------------------------------- src/aeb_fate_generate_ops.erl | 105 +++++++++++++++++++++++- 4 files changed, 112 insertions(+), 151 deletions(-) diff --git a/.gitignore b/.gitignore index cccd365..1887839 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ aefateasm include/aeb_fate_opcodes.hrl src/aeb_fate_code.erl src/aeb_fate_opcodes.erl +src/aeb_fate_pp.erl diff --git a/Makefile b/Makefile index bfaadcc..e255d7a 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ REBAR ?= rebar3 all: local -local: src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl src/aeb_fate_asm_scan.xrl +local: src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl src/aeb_fate_asm_scan.xrl src/aeb_fate_pp.erl @$(REBAR) as local release console: local @@ -14,8 +14,12 @@ clean: @$(REBAR) clean rm -f src/aeb_fate_opcodes.erl rm -f src/aeb_fate_code.erl + rm -f src/aeb_fate_asm_scan.xrl + rm -f src/aeb_fate_asm_scan.erl + rm -f src/aeb_fate_pp.erl rm -f include/aeb_fate_opcodes.hrl + dialyzer: local @$(REBAR) as local dialyzer @@ -32,7 +36,7 @@ test: local ebin/aeb_fate_generate_ops.beam: src/aeb_fate_generate_ops.erl ebin erlc -o $(dir $@) $< -src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl src/aeb_fate_asm_scan.xrl: ebin/aeb_fate_generate_ops.beam +src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl src/aeb_fate_asm_scan.xrl src/aeb_fate_pp.erl: ebin/aeb_fate_generate_ops.beam src/aeb_fate_asm_scan.template erl -pa ebin/ -noshell -s aeb_fate_generate_ops gen_and_halt src/ include/ ebin: diff --git a/src/aeb_fate_asm.erl b/src/aeb_fate_asm.erl index 5e320ef..bc96684 100644 --- a/src/aeb_fate_asm.erl +++ b/src/aeb_fate_asm.erl @@ -180,157 +180,10 @@ format_code([], _) -> ""; format_code([Op|Rest], Symbols) -> [" ", - format_op(Op, Symbols), + aeb_fate_pp:format_op(Op, Symbols), "\n", format_code(Rest, Symbols)]. -format_op('RETURN', _) -> "RETURN"; -format_op({'RETURNR', Arg}, _) -> ["RETURNR ", format_arg(Arg)]; -format_op({'CALL', {immediate, Function}}, Symbols) -> - ["CALL ", lookup(Function, Symbols)]; -format_op({'CALL_T', {immediate, Function}}, Symbols) -> - ["CALL_T ", lookup(Function, Symbols)]; -format_op({'CALL_R', {immediate, Contract}, {immediate, Function}}, Symbols) -> - ["CALL_R ", lookup(Contract, Symbols), "." , lookup(Function, Symbols)]; -format_op({'CALL_R', Contract, {immediate, Function}}, Symbols) -> - ["CALL_R ", format_arg(Contract), "." , lookup(Function, Symbols)]; -format_op({'CALL_TR', {immediate, Contract}, {immediate, Function}}, Symbols) -> - ["CALL_TR ", lookup(Contract, Symbols), "." , lookup(Function, Symbols)]; -format_op({'CALL_TR', Contract, {immediate, Function}}, Symbols) -> - ["CALL_TR ", format_arg(Contract), "." , lookup(Function, Symbols)]; -format_op({'JUMP', {immediate, BB}}, _) -> - ["JUMP ", io_lib:format("~p", [BB])]; -format_op({'JUMPIF', Arg, {immediate, BB}}, _) -> - ["JUMPIF ", format_arg(Arg), " ", io_lib:format("~p", [BB])]; -format_op({'SWITCH_V2', Variant, {immediate, BB1}, {immediate, BB2}}, _) -> - ["SWITCH_V2 ", format_arg(Variant), " ", BB1, " ", BB2]; -format_op({'SWITCH_V3', Variant, {immediate, BB1}, {immediate, BB2}, {immediate, BB3}}, _) -> - ["SWITCH_V2 ", format_arg(Variant), " ", BB1, " ", BB2, " ", BB3]; -format_op({'SWITCH_VN', Variant, BBs}, _) -> - ["SWITCH_VN ", format_arg(Variant), [[" ", BB] || {immedate, BB} <- BBs]]; -format_op({'PUSH', Arg0}, _) -> - ["PUSH ", format_arg(Arg0)]; -format_op('INCA', _) -> "INCA"; -format_op({'INC', Name}, _) -> ["INC ", format_arg(Name)]; -format_op({'DEC', Name}, _) -> ["DEC ", format_arg(Name)]; -format_op('DECA', _) -> "DECA"; -format_op({'ADD', Dest, Left, Right}, _) -> - ["ADD ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'SUB', Dest, Left, Right}, _) -> - ["SUB ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'MUL', Dest, Left, Right}, _) -> - ["MUL ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'DIV', Dest, Left, Right}, _) -> - ["DIV ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'MOD', Dest, Left, Right}, _) -> - ["MOD ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'POW', Dest, Left, Right}, _) -> - ["POW ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'LT', Dest, Left, Right}, _) -> - ["LT ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'GT', Dest, Left, Right}, _) -> - ["GT ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'ELT', Dest, Left, Right}, _) -> - ["ELT ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'EGT', Dest, Left, Right}, _) -> - ["EGT ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'EQ', Dest, Left, Right}, _) -> - ["EQ ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'NEQ', Dest, Left, Right}, _) -> - ["NEQ ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'AND', Dest, Left, Right}, _) -> - ["AND ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'OR', Dest, Left, Right}, _) -> - ["OR ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)]; -format_op({'NOT', Dest, Name}, _) -> - ["NOT ", format_arg(Dest), " ", format_arg(Name)]; -format_op({'TUPLE', {immediate, Size}}, _) -> - ["TUPLE ", io_lib:format("~p", [Size])]; -format_op({'ELEMENT', Type, Dest, Which, Tuple}, _) -> - [ "ELEMENT " - , io_lib:format("~p ", [Type]) - , format_arg(Dest), " " - , format_arg(Which), " " - , format_arg(Tuple)]; -format_op({'MAP_EMPTY', Dest}, _) -> - ["MAP_EMPTY ", format_arg(Dest)]; -format_op({'MAP_LOOKUP', Dest, Map, Key}, _) -> - ["MAP_LOOKUP ", format_arg(Dest), " " - , format_arg(Map), " ", format_arg(Key)]; -format_op({'MAP_DELETE', Dest, Map, Key}, _) -> - ["MAP_DELETE ", format_arg(Dest), " " - , format_arg(Map), " ", format_arg(Key)]; -format_op({'MAP_LOOKUPD', Dest, Map, Key, Default}, _) -> - ["MAP_LOOKUPD ", format_arg(Dest), " " - , format_arg(Map), " ", format_arg(Key), " ", format_arg(Default)]; -format_op({'MAP_UPDATE', Dest, Map, Key, Value}, _) -> - ["MAP_UPDATE ", format_arg(Dest), " " - , format_arg(Map), " ", format_arg(Key), " ", format_arg(Value)]; -format_op({'MAP_MEMBER', Dest, Map, Key}, _) -> - ["MAP_MEMBER ", format_arg(Dest), " " - , format_arg(Map), " ", format_arg(Key)]; -format_op({'MAP_FROM_LIST', Dest, List}, _) -> - ["MAP_FROM_LIST ", format_arg(Dest), " ", format_arg(List)]; -format_op({'NIL', Dest}, _) -> - ["NIL ", format_arg(Dest)]; -format_op({'IS_NIL', Dest, List}, _) -> - ["IS_NIL ", format_arg(Dest), " ", format_arg(List)]; -format_op({'CONS', Dest, Hd, Tl}, _) -> - ["CONS ", format_arg(Dest), " ", format_arg(Hd), " ", format_arg(Tl)]; -format_op({'HD', Dest, List}, _) -> - ["HD ", format_arg(Dest), " ", format_arg(List)]; -format_op({'TL', Dest, List}, _) -> - ["TL ", format_arg(Dest), " ", format_arg(List)]; -format_op({'LENGTH', Dest, List}, _) -> - ["LENGTH ", format_arg(Dest), " ", format_arg(List)]; -format_op({'STR_EQ', Dest, Str1, Str2}, _) -> - ["STR_EQ ", format_arg(Dest), " ", format_arg(Str1), format_arg(Str2)]; -format_op({'STR_JOIN', Dest, Str1, Str2}, _) -> - ["STR_JOIN ", format_arg(Dest), " ", format_arg(Str1), format_arg(Str2)]; -format_op({'INT_TO_STR', Dest, Str}, _) -> - ["INT_TO_STR ", format_arg(Dest), " ", format_arg(Str)]; -format_op({'ADDR_TO_STR', Dest, Str}, _) -> - ["ADDR_TO_STR ", format_arg(Dest), " ", format_arg(Str)]; -format_op({'STR_REVERSE', Dest, Str}, _) -> - ["STR_REVERSE ", format_arg(Dest), " ", format_arg(Str)]; -format_op({'INT_TO_ADDR', Dest, Str}, _) -> - ["INT_TO_ADDR ", format_arg(Dest), " ", format_arg(Str)]; -format_op({'VARIANT_TEST', Dest, Variant, Tag}, _) -> - ["VARIANT_TEST ", format_arg(Dest), " ", format_arg(Variant), " ", format_arg(Tag)]; -format_op({'VARIANT_ELEMENT', Dest, Variant, Index}, _) -> - ["VARIANT_ELEMENT ", format_arg(Dest), " ", format_arg(Variant), " ", format_arg(Index)]; -format_op({'VARIANT', Dest, SizeA, TagA, ElementsA}, _) -> - ["VARIANT ", format_arg(Dest), " ", format_arg(SizeA), " " - , format_arg(TagA), " ", format_arg(ElementsA)]; -format_op('BITS_NONEA', _) -> "BITS_NONEA "; -format_op({'BITS_NONE', To}, _) -> ["BITS_NONE ", format_arg(To)]; -format_op('BITS_ALLA', _) -> "BITS_ALLA"; -format_op({'BITS_ALL', To}, _) -> ["BITS_ALL ", format_arg(To)]; -format_op({'BITS_ALL_N', To, N}, _) -> - ["BITS_ALL_N ", format_arg(To), " ", format_arg(N)]; -format_op({'BITS_SET', To, Bits, Bit}, _) -> - ["BITS_SET ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)]; -format_op({'BITS_CLEAR', To, Bits, Bit}, _) -> - ["BITS_CLEAR ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)]; -format_op({'BITS_TEST', To, Bits, Bit}, _) -> - ["BITS_TEST ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)]; -format_op({'BITS_SUM', To, Bits}, _) -> - ["BITS_SUM ", format_arg(To), " ", format_arg(Bits)]; -format_op({'BITS_OR', To, Bits, Bit}, _) -> - ["BITS_OR ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)]; -format_op({'BITS_AND', To, Bits, Bit}, _) -> - ["BITS_AND ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)]; -format_op({'BITS_DIFF', To, Bits, Bit}, _) -> - ["BITS_DIFF ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)]; -format_op('DUPA', _) -> "DUPA"; -format_op({'DUP', {immediate, N}}, _) -> - ["DUP ", io_lib:format("~p", [N])]; -format_op({'POP', Dest}, _) -> - ["POP ", format_arg(Dest)]; -format_op({'STORE', Var, What}, _) -> - ["STORE ", format_arg(Var), " ", format_arg(What)]; -format_op('NOP', _) -> "NOP". - read_file(Filename) -> {ok, File} = file:read_file(Filename), diff --git a/src/aeb_fate_generate_ops.erl b/src/aeb_fate_generate_ops.erl index 5c09d77..432710f 100644 --- a/src/aeb_fate_generate_ops.erl +++ b/src/aeb_fate_generate_ops.erl @@ -18,7 +18,8 @@ generate(Src, Include) -> generate_header_file(HrlFile, Ops), generate_opcodes_ops(aeb_fate_opcodes, HrlFile, Src, Ops), generate_code_ops(aeb_fate_code, Src, Ops), - generate_scanner("aeb_fate_asm_scan.template", "aeb_fate_asm_scan.xrl", Src, Ops). + generate_scanner("aeb_fate_asm_scan.template", "aeb_fate_asm_scan.xrl", Src, Ops), + gen_asm_pp(aeb_fate_pp, Src, Ops). %% TODO: Some real gas numbers... ops_defs() -> @@ -397,3 +398,105 @@ insert_tokens_in_template(<<"###REPLACEWITHNOTE###", Rest/binary >>, Tokens) -> | insert_tokens_in_template(Rest, Tokens)]; insert_tokens_in_template(<>, Tokens) -> [B|insert_tokens_in_template(Rest, Tokens)]. + +gen_asm_pp(Module, Path, Ops) -> + Filename = filename:join(Path, atom_to_list(Module)) ++ ".erl", + {ok, File} = file:open(Filename, [write]), + Formats = lists:flatten([gen_format(Op)++"\n" || Op <- Ops]), + + io:format(File, "~s", [prelude(" Provide pretty printing functuions for " + "Fate instructions.\n")]), + io:format(File, "-module(~w).\n\n", [Module]), + io:format(File, + "-export([format_op/2]).\n\n" + "format_arg(t, T) ->\n" + " io_lib:format(\"~~p \", [T]);\n" + "format_arg(li, List) ->\n" + " [[\" \", E] || {immedate, E} <- List];\n" + "format_arg(_, {immediate, I}) ->\n" + " aeb_fate_data:format(I);\n" + "format_arg(a, {arg, N}) -> io_lib:format(\"arg~~p\", [N]);\n" + "format_arg(a, {var, N}) -> io_lib:format(\"var~~p\", [N]);\n" + "format_arg(a, {stack, 0}) -> \"a\";\n" + "format_arg(a, {stack, N}) -> io_lib:format(\"a~~p\", [N]).\n\n" + "lookup(Name, Symbols) ->\n" + " maps:get(Name, Symbols, Name).\n\n" + "~s" + , [Formats]), + + io:format(File, "format_op(Op, _Symbols) -> io_lib:format(\";; Bad Op: ~~w\\n\", [Op]).\n", []), + file:close(File). + +gen_format(#{opname := Name}) when ('CALL' =:= Name) or (Name =:= 'CALL_T') -> + io_lib:format("format_op({~w, {immediate, Function}}, Symbols) ->\n" + "[\"~s \", lookup(Function, Symbols)];", + [Name, atom_to_list(Name)]); +gen_format(#{opname := Name}) when (Name =:= 'CALL_R') or (Name =:= 'CALL_TR') -> + io_lib:format("format_op({~w, {immediate, Contract}, {immediate, Function}}, Symbols) ->\n" + "[\"~s \", lookup(Contract, Symbols), \".\", lookup(Function, Symbols)];\n" + "format_op({~w, Contract, {immediate, Function}}, Symbols) ->\n" + "[\"~s \", format_arg(a, Contract), \".\", lookup(Function, Symbols)];", + [Name, atom_to_list(Name), Name, atom_to_list(Name)]); +gen_format(#{opname := Name, format := atomic}) -> + io_lib:format("format_op(~w, _) -> [\"~s\"];", [Name, atom_to_list(Name)]); +gen_format(#{opname := Name, format := Args}) -> + NameAsString = atom_to_list(Name), + case Args of + [T0] -> + io_lib:format( + "format_op({~w, Arg0}, _) ->\n" + " [\"~s \", format_arg(~w, Arg0)];", + [Name, NameAsString, T0]); + [T0, T1] -> + io_lib:format( + "format_op({~w, Arg0, Arg1}, _) ->\n" + " [\"~s \", format_arg(~w, Arg0), " + "\" \", format_arg(~w, Arg1)];", + [Name, NameAsString, T0, T1]); + [T0, T1, T2] -> + io_lib:format( + "format_op({~w, Arg0, Arg1, Arg2}, _) ->\n" + " [\"~s \", format_arg(~w, Arg0), " + "\" \", format_arg(~w, Arg1)," + "\" \", format_arg(~w, Arg2)];", + [Name, NameAsString, T0, T1, T2]); + [T0, T1, T2, T3] -> + io_lib:format( + "format_op({~w, Arg0, Arg1, Arg2, Arg3}, _) ->\n" + " [\"~s \", format_arg(~w, Arg0), " + "\" \", format_arg(~w, Arg1)," + "\" \", format_arg(~w, Arg2)," + "\" \", format_arg(~w, Arg3)];", + [Name, NameAsString, T0, T1, T2, T3]); + [T0, T1, T2, T3, T4] -> + io_lib:format( + "format_op({~w, Arg0, Arg1, Arg2, Arg3, Arg4}, _) ->\n" + " [\"~s \", format_arg(~w, Arg0), " + "\" \", format_arg(~w, Arg1)," + "\" \", format_arg(~w, Arg2)," + "\" \", format_arg(~w, Arg3)," + "\" \", format_arg(~w, Arg4)];", + [Name, NameAsString, T0, T1, T2, T3, T4]); + [T0, T1, T2, T3, T4, T5] -> + io_lib:format( + "format_op({~w, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5}, _) ->\n" + " [\"~s \", format_arg(~w, Arg0), " + "\" \", format_arg(~w, Arg1)," + "\" \", format_arg(~w, Arg2)," + "\" \", format_arg(~w, Arg3)," + "\" \", format_arg(~w, Arg4)," + "\" \", format_arg(~w, Arg5)];", + [Name, NameAsString, T0, T1, T2, T3, T4, T5]); + [T0, T1, T2, T3, T4, T5, T6] -> + io_lib:format( + "format_op({~w, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6}, _) ->\n" + " [\"~s \", format_arg(~w, Arg0), " + "\" \", format_arg(~w, Arg1)," + "\" \", format_arg(~w, Arg2)," + "\" \", format_arg(~w, Arg3)," + "\" \", format_arg(~w, Arg4)," + "\" \", format_arg(~w, Arg5)," + "\" \", format_arg(~w, Arg6)];", + [Name, NameAsString, T0, T1, T2, T3, T4, T5, T6]) + end. +