From fd55b58125de227b7344bd5f09efebc2b141baa7 Mon Sep 17 00:00:00 2001 From: Tobias Lindahl Date: Tue, 21 May 2019 17:11:41 +0200 Subject: [PATCH] Break out fate code to separate adt module --- src/aeb_fate_asm.erl | 594 +++---------------------------------- src/aeb_fate_code.erl | 573 +++++++++++++++++++++++++++++++++++ test/aeb_fate_asm_test.erl | 17 +- 3 files changed, 614 insertions(+), 570 deletions(-) create mode 100644 src/aeb_fate_code.erl diff --git a/src/aeb_fate_asm.erl b/src/aeb_fate_asm.erl index 96c459e..f0cea24 100644 --- a/src/aeb_fate_asm.erl +++ b/src/aeb_fate_asm.erl @@ -89,13 +89,11 @@ -export([ assemble_file/3 , asm_to_bytecode/2 - , bytecode_to_fate_code/2 , function_call/1 , pp/1 , read_file/1 , strip/1 , to_asm/1 - , to_hexstring/1 ]). -include_lib("aebytecode/include/aeb_fate_opcodes.hrl"). @@ -132,9 +130,10 @@ pp(FateCode) -> io_lib:format("~ts~n",[Listing]). -to_asm(#{ functions := Functions - , symbols := Symbols - , annotations := Annotations} = _FateCode) -> +to_asm(FateCode) -> + Functions = aeb_fate_code:functions(FateCode), + Symbols = aeb_fate_code:symbols(FateCode), + Annotations = aeb_fate_code:annotations(FateCode), insert_comments(get_comments(Annotations), 1, lists:flatten( io_lib:format("~s", @@ -150,12 +149,6 @@ insert_comments([],_,[]) -> []; insert_comments([{L,C}|Rest], _, []) -> ";; " ++ C ++ "\n" ++ insert_comments(Rest, L + 1, []). - - - - - - format_functions(Functions, Symbols) -> [format(lookup(Name, Symbols), Sig, @@ -218,521 +211,22 @@ asm_to_bytecode(AssemblerCode, Options) -> none -> ok end, + Env = #{ fate_code => aeb_fate_code:new() + , functions => #{} + }, - Env = to_bytecode(Tokens, none, #{ functions => #{} - , symbols => #{} - , annotations => #{} - }, [], Options), - - ByteList = serialize(Env), - Signatures = serialize_sigs(Env), - SymbolTable = serialize_symbol_table(Env), - Annotatations = serialize_annotations(Env), - ByteCode = << (aeser_rlp:encode(list_to_binary(ByteList)))/binary, - (aeser_rlp:encode(list_to_binary(Signatures)))/binary, - (aeser_rlp:encode(SymbolTable))/binary, - (aeser_rlp:encode(Annotatations))/binary - >>, - - case proplists:lookup(pp_hex_string, Options) of - {pp_hex_string, true} -> - io:format("Code: ~s~n",[to_hexstring(ByteList)]); - none -> - ok - end, - + Env1 = to_bytecode(Tokens, none, Env, [], Options), + FateCode = maps:get(fate_code, Env1), + FunctionsMap = maps:get(functions, Env1), + Functions = [X || {_, X} <- lists:sort(maps:to_list(FunctionsMap))], + FunctionsBin = iolist_to_binary(Functions), + ByteCode = aeb_fate_code:serialize(FateCode, FunctionsBin, Options), {Env, ByteCode}. strip(ByteCode) -> {Code, _Rest} = aeser_rlp:decode_one(ByteCode), Code. -bytecode_to_fate_code(Bytes, _Options) -> - {ByteCode, Rest1} = aeser_rlp:decode_one(Bytes), - {Signatures, Rest2} = aeser_rlp:decode_one(Rest1), - {SymbolTable, Rest3} = aeser_rlp:decode_one(Rest2), - {Annotations, <<>>} = aeser_rlp:decode_one(Rest3), - - Env1 = deserialize(ByteCode, #{ function => none - , bb => 0 - , current_bb_code => [] - , functions => #{} - , code => #{} - }), - Env2 = deserialize_signatures(Signatures, Env1), - Env3 = deserialize_symbols(SymbolTable, Env2), - Env4 = deserialize_annotations(Annotations, Env3), - Env4. - - -deserialize(<>, - #{ function := none - , bb := 0 - , current_bb_code := [] - } = Env) -> - {Sig, Rest2} = deserialize_signature(Rest), - Env2 = Env#{function => {<>, Sig}}, - deserialize(Rest2, Env2); -deserialize(<>, - #{ function := {F, Sig} - , bb := BB - , current_bb_code := Code - , code := Program - , functions := Funs} = Env) -> - {NewSig, Rest2} = deserialize_signature(Rest), - case Code of - [] -> - Env2 = Env#{ bb => 0 - , current_bb_code => [] - , function => {<>, NewSig} - , code => #{} - , functions => Funs#{F => {Sig, Program}}}, - deserialize(Rest2, Env2); - _ -> - Env2 = Env#{ bb => 0 - , current_bb_code => [] - , function => {<>, NewSig} - , code => #{} - , functions => - Funs#{F => {Sig, - Program#{ BB => lists:reverse(Code)}}}}, - deserialize(Rest2, Env2) - end; -deserialize(<>, - #{ bb := BB - , current_bb_code := Code - , code := Program} = Env) -> - {Rest2, OpCode} = deserialize_op(Op, Rest, Code), - case aeb_fate_opcodes:end_bb(Op) of - true -> - deserialize(Rest2, Env#{ bb => BB+1 - , current_bb_code => [] - , code => Program#{BB => - lists:reverse(OpCode)}}); - false -> - deserialize(Rest2, Env#{ current_bb_code => OpCode}) - end; -deserialize(<<>>, #{ function := {F, Sig} - , bb := BB - , current_bb_code := Code - , code := Program - , functions := Funs} = Env) -> - FunctionCode = - case Code of - [] -> Program; - _ -> Program#{ BB => lists:reverse(Code)} - end, - Env#{ bb => 0 - , current_bb_code => [] - , function => none - , code => #{} - , functions => Funs#{F => {Sig, FunctionCode}}}. - -deserialize_op(?SWITCH_VN, Rest, Code) -> - <> = Rest, - {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), - case aeb_fate_encoding:deserialize_one(Rest3) of - {L, Rest4} when is_list(L) -> - Modifier0 = bits_to_modifier(ArgType band 2#11), - immediate = bits_to_modifier((ArgType bsr 2) band 2#11), - {Rest4, [{aeb_fate_opcodes:mnemonic(?SWITCH_VN) - , {Modifier0, Arg0} - , {immediate, L} - } - | Code]}; - _ -> exit(bad_argument_to_switch_vn) - end; -deserialize_op(Op, Rest, Code) -> - OpName = aeb_fate_opcodes:mnemonic(Op), - case aeb_fate_opcodes:args(Op) of - 0 -> {Rest, [OpName | Code]}; - 1 -> - <> = Rest, - {Arg, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), - Modifier = bits_to_modifier(ArgType), - {Rest3, [{OpName, {Modifier, Arg}} | Code]}; - 2 -> - <> = Rest, - {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), - {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), - Modifier0 = bits_to_modifier(ArgType band 2#11), - Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), - {Rest4, [{OpName, {Modifier0, Arg0}, - {Modifier1, Arg1}} | Code]}; - 3 -> - <> = Rest, - {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), - {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), - {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), - Modifier0 = bits_to_modifier(ArgType band 2#11), - Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), - Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), - {Rest5, [{ OpName - , {Modifier0, Arg0} - , {Modifier1, Arg1} - , {Modifier2, Arg2}} - | Code]}; - 4 -> - <> = Rest, - {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), - {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), - {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), - {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), - Modifier0 = bits_to_modifier(ArgType band 2#11), - Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), - Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), - Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), - {Rest6, [{ OpName - , {Modifier0, Arg0} - , {Modifier1, Arg1} - , {Modifier2, Arg2} - , {Modifier3, Arg3}} - | Code]}; - 5 -> - <> = Rest, - {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), - {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), - {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), - {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), - {Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6), - Modifier0 = bits_to_modifier(ArgType band 2#11), - Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), - Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), - Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), - Modifier4 = bits_to_modifier(ArgType2 band 2#11), - {Rest7, [{ OpName - , {Modifier0, Arg0} - , {Modifier1, Arg1} - , {Modifier2, Arg2} - , {Modifier3, Arg3} - , {Modifier4, Arg4} - } - | Code]}; - 6 -> - <> = Rest, - {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), - {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), - {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), - {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), - {Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6), - {Arg5, Rest8} = aeb_fate_encoding:deserialize_one(Rest7), - Modifier0 = bits_to_modifier(ArgType band 2#11), - Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), - Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), - Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), - Modifier4 = bits_to_modifier(ArgType2 band 2#11), - Modifier5 = bits_to_modifier((ArgType2 bsr 2) band 2#11), - {Rest8, [{ OpName - , {Modifier0, Arg0} - , {Modifier1, Arg1} - , {Modifier2, Arg2} - , {Modifier3, Arg3} - , {Modifier4, Arg4} - , {Modifier5, Arg5} - } - | Code]}; - 7 -> - <> = Rest, - {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), - {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), - {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), - {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), - {Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6), - {Arg5, Rest8} = aeb_fate_encoding:deserialize_one(Rest7), - {Arg6, Rest9} = aeb_fate_encoding:deserialize_one(Rest8), - Modifier0 = bits_to_modifier(ArgType band 2#11), - Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), - Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), - Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), - Modifier4 = bits_to_modifier(ArgType2 band 2#11), - Modifier5 = bits_to_modifier((ArgType2 bsr 2) band 2#11), - Modifier6 = bits_to_modifier((ArgType2 bsr 4) band 2#11), - {Rest9, [{ OpName - , {Modifier0, Arg0} - , {Modifier1, Arg1} - , {Modifier2, Arg2} - , {Modifier3, Arg3} - , {Modifier4, Arg4} - , {Modifier5, Arg5} - , {Modifier6, Arg6} - } - | Code]}; - 8 -> - <> = Rest, - {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), - {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), - {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), - {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), - {Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6), - {Arg5, Rest8} = aeb_fate_encoding:deserialize_one(Rest7), - {Arg6, Rest9} = aeb_fate_encoding:deserialize_one(Rest8), - {Arg7, Rest10} = aeb_fate_encoding:deserialize_one(Rest9), - Modifier0 = bits_to_modifier(ArgType band 2#11), - Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), - Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), - Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), - Modifier4 = bits_to_modifier(ArgType2 band 2#11), - Modifier5 = bits_to_modifier((ArgType2 bsr 2) band 2#11), - Modifier6 = bits_to_modifier((ArgType2 bsr 4) band 2#11), - Modifier7 = bits_to_modifier((ArgType2 bsr 6) band 2#11), - {Rest10, [{ OpName - , {Modifier0, Arg0} - , {Modifier1, Arg1} - , {Modifier2, Arg2} - , {Modifier3, Arg3} - , {Modifier4, Arg4} - , {Modifier5, Arg5} - , {Modifier6, Arg6} - , {Modifier7, Arg7} - } - | Code]} - end. - - - - -deserialize_signatures(_Signatures, Env) -> Env. - -deserialize_symbols(Table, Env) -> - ?FATE_MAP_VALUE(SymbolTable) = aeb_fate_encoding:deserialize(Table), - Env#{symbols => SymbolTable}. - -deserialize_annotations(AnnotationsBin, Env) -> - ?FATE_MAP_VALUE(Annotations) = aeb_fate_encoding:deserialize(AnnotationsBin), - Env#{annotations => Annotations}. - - - -serialize_sigs(_Env) -> []. - -serialize_symbol_table(#{ symbols := Symbols }) -> - aeb_fate_encoding:serialize(aeb_fate_data:make_map(Symbols)). - -serialize_annotations(#{ annotations := Annotations}) -> - aeb_fate_encoding:serialize(aeb_fate_data:make_map(Annotations)). - - - - - -serialize(#{functions := Functions} =_Env) -> - %% Sort the functions oon name to get a canonical serialisation. - Code = [[?FUNCTION, Name, serialize_signature(Sig), C] || - {Name, {Sig, C}} <- lists:sort(maps:to_list(Functions))], - serialize_code(lists:flatten(Code)). - - -%% Argument encoding -%% Agument Specification Byte -%% bitpos: 6 4 2 0 -%% xx xx xx xx -%% Arg3 Arg2 Arg1 Arg0 -%% For 5-8 args another Argument Spec Byte is used -%% Bit pattern -%% 00 : stack/unused (depending on instruction) -%% 01 : argN -%% 10 : varN -%% 11 : immediate -serialize_code([ {Arg0Type, Arg0} - , {Arg1Type, Arg1} - , {Arg2Type, Arg2} - , {Arg3Type, Arg3} - , {Arg4Type, Arg4} - , {Arg5Type, Arg5} - , {Arg6Type, Arg6} - , {Arg7Type, Arg7} - | Rest]) -> - ArgSpec1 = - modifier_bits(Arg0Type) bor - (modifier_bits(Arg1Type) bsl 2) bor - (modifier_bits(Arg2Type) bsl 4) bor - (modifier_bits(Arg3Type) bsl 6), - ArgSpec2 = - modifier_bits(Arg4Type) bor - (modifier_bits(Arg5Type) bsl 2) bor - (modifier_bits(Arg6Type) bsl 4) bor - (modifier_bits(Arg7Type) bsl 6), - [ ArgSpec1 - , ArgSpec2 - , serialize_data(Arg0Type, Arg0) - , serialize_data(Arg1Type, Arg1) - , serialize_data(Arg2Type, Arg2) - , serialize_data(Arg3Type, Arg3) - , serialize_data(Arg4Type, Arg4) - , serialize_data(Arg5Type, Arg5) - , serialize_data(Arg6Type, Arg6) - , serialize_data(Arg7Type, Arg7) - | serialize_code(Rest)]; -serialize_code([ {Arg0Type, Arg0} - , {Arg1Type, Arg1} - , {Arg2Type, Arg2} - , {Arg3Type, Arg3} - , {Arg4Type, Arg4} - , {Arg5Type, Arg5} - , {Arg6Type, Arg6} - | Rest]) -> - ArgSpec1 = - modifier_bits(Arg0Type) bor - (modifier_bits(Arg1Type) bsl 2) bor - (modifier_bits(Arg2Type) bsl 4) bor - (modifier_bits(Arg3Type) bsl 6), - ArgSpec2 = - modifier_bits(Arg4Type) bor - (modifier_bits(Arg5Type) bsl 2) bor - (modifier_bits(Arg6Type) bsl 4), - [ ArgSpec1 - , ArgSpec2 - , serialize_data(Arg0Type, Arg0) - , serialize_data(Arg1Type, Arg1) - , serialize_data(Arg2Type, Arg2) - , serialize_data(Arg3Type, Arg3) - , serialize_data(Arg4Type, Arg4) - , serialize_data(Arg5Type, Arg5) - , serialize_data(Arg6Type, Arg6) - | serialize_code(Rest)]; -serialize_code([ {Arg0Type, Arg0} - , {Arg1Type, Arg1} - , {Arg2Type, Arg2} - , {Arg3Type, Arg3} - , {Arg4Type, Arg4} - , {Arg5Type, Arg5} - | Rest]) -> - ArgSpec1 = - modifier_bits(Arg0Type) bor - (modifier_bits(Arg1Type) bsl 2) bor - (modifier_bits(Arg2Type) bsl 4) bor - (modifier_bits(Arg3Type) bsl 6), - ArgSpec2 = - modifier_bits(Arg4Type) bor - (modifier_bits(Arg5Type) bsl 2), - [ ArgSpec1 - , ArgSpec2 - , serialize_data(Arg0Type, Arg0) - , serialize_data(Arg1Type, Arg1) - , serialize_data(Arg2Type, Arg2) - , serialize_data(Arg3Type, Arg3) - , serialize_data(Arg4Type, Arg4) - , serialize_data(Arg5Type, Arg5) - | serialize_code(Rest)]; -serialize_code([ {Arg0Type, Arg0} - , {Arg1Type, Arg1} - , {Arg2Type, Arg2} - , {Arg3Type, Arg3} - , {Arg4Type, Arg4} - | Rest]) -> - ArgSpec1 = - modifier_bits(Arg0Type) bor - (modifier_bits(Arg1Type) bsl 2) bor - (modifier_bits(Arg2Type) bsl 4) bor - (modifier_bits(Arg3Type) bsl 6), - ArgSpec2 = - modifier_bits(Arg4Type), - [ ArgSpec1 - , ArgSpec2 - , serialize_data(Arg0Type, Arg0) - , serialize_data(Arg1Type, Arg1) - , serialize_data(Arg2Type, Arg2) - , serialize_data(Arg3Type, Arg3) - , serialize_data(Arg4Type, Arg4) - | serialize_code(Rest)]; - -serialize_code([ {Arg0Type, Arg0} - , {Arg1Type, Arg1} - , {Arg2Type, Arg2} - , {Arg3Type, Arg3}| Rest]) -> - ArgSpec = - modifier_bits(Arg0Type) bor - (modifier_bits(Arg1Type) bsl 2) bor - (modifier_bits(Arg2Type) bsl 4) bor - (modifier_bits(Arg3Type) bsl 6), - [ ArgSpec - , serialize_data(Arg0Type, Arg0) - , serialize_data(Arg1Type, Arg1) - , serialize_data(Arg2Type, Arg2) - , serialize_data(Arg3Type, Arg3) - | serialize_code(Rest)]; -serialize_code([ {Arg0Type, Arg0} - , {Arg1Type, Arg1} - , {Arg2Type, Arg2} - | Rest]) -> - ArgSpec = - modifier_bits(Arg0Type) bor - (modifier_bits(Arg1Type) bsl 2) bor - (modifier_bits(Arg2Type) bsl 4), - [ArgSpec - , serialize_data(Arg0Type, Arg0) - , serialize_data(Arg1Type, Arg1) - , serialize_data(Arg2Type, Arg2) - | serialize_code(Rest)]; -serialize_code([ {Arg0Type, Arg0} - , {Arg1Type, Arg1} - | Rest]) -> - ArgSpec = - modifier_bits(Arg0Type) bor - (modifier_bits(Arg1Type) bsl 2), - [ArgSpec - , serialize_data(Arg0Type, Arg0) - , serialize_data(Arg1Type, Arg1) - | serialize_code(Rest)]; -serialize_code([ {Arg0Type, Arg0} | Rest]) -> - ArgSpec = - modifier_bits(Arg0Type), - [ArgSpec - , serialize_data(Arg0Type, Arg0) - | serialize_code(Rest)]; -serialize_code([ ?SWITCH_VN - , {Arg0Type, Arg0} - , {immediate, L} - | Rest]) -> - ArgSpec = - modifier_bits(Arg0Type) bor - (modifier_bits(immediate) bsl 2), - [?SWITCH_VN - , ArgSpec - , serialize_data(Arg0Type, Arg0) - , serialize_data(immediate, L)] ++ serialize_code(Rest); -serialize_code([B|Rest]) -> - [B | serialize_code(Rest)]; -serialize_code([]) -> []. - - -%% 00 : stack/unused (depending on instruction) -%% 01 : argN -%% 10 : varN -%% 11 : immediate -modifier_bits(immediate) -> 2#11; -modifier_bits(var) -> 2#10; -modifier_bits(arg) -> 2#01; -modifier_bits(stack) -> 2#00. - -bits_to_modifier(2#11) -> immediate; -bits_to_modifier(2#10) -> var; -bits_to_modifier(2#01) -> arg; -bits_to_modifier(2#00) -> stack. - -serialize_data(_, Data) -> - aeb_fate_encoding:serialize(Data). - -serialize_signature({Args, RetType}) -> - [aeb_fate_encoding:serialize_type({tuple, Args}) | - aeb_fate_encoding:serialize_type(RetType)]. - - - -deserialize_signature(Binary) -> - {{tuple, Args}, Rest} = aeb_fate_encoding:deserialize_type(Binary), - {RetType, Rest2} = aeb_fate_encoding:deserialize_type(Rest), - {{Args, RetType}, Rest2}. - - - -to_hexstring(ByteList) -> - "0x" ++ lists:flatten( - [io_lib:format("~2.16.0b", [X]) - || X <- ByteList]). - - - %% ------------------------------------------------------------------- %% Parser %% Asm tokens -> Fate code env @@ -795,8 +289,8 @@ to_bytecode([{signature,_line, {signature, Value}}|Rest], [{immediate, aeb_fate_data:make_signature(Value)}|Code], Opts); to_bytecode([{id,_line, ID}|Rest], Address, Env, Code, Opts) -> - {Hash, Env2} = insert_symbol(ID, Env), - to_bytecode(Rest, Address, Env2, [{immediate, Hash}|Code], Opts); + {Env2, Id} = insert_symbol(list_to_binary(ID), Env), + to_bytecode(Rest, Address, Env2, [{immediate, Id}|Code], Opts); to_bytecode([{'{',_line}|Rest], Address, Env, Code, Opts) -> {Map, Rest2} = parse_map(Rest), to_bytecode(Rest2, Address, Env, [{immediate, Map}|Code], Opts); @@ -819,17 +313,8 @@ to_bytecode([{comment, Line, Comment}|Rest], Address, Env, Code, Opts) -> Env2 = insert_annotation(comment, Line, Comment, Env), to_bytecode(Rest, Address, Env2, Code, Opts); -to_bytecode([], Address, Env, Code, Opts) -> - Env2 = insert_fun(Address, Code, Env), - #{functions := Funs} = Env2, - case proplists:lookup(pp_opcodes, Opts) of - {pp_opcodes, true} -> - Ops = [C || {_Name, {_Sig, C}} <- maps:to_list(Funs)], - io:format("opcodes ~p~n", [Ops]); - none -> - ok - end, - Env2. +to_bytecode([], Address, Env, Code,_Opts) -> + insert_fun(Address, Code, Env). parse_map([{'}',_line}|Rest]) -> {#{}, Rest}; @@ -990,11 +475,24 @@ to_list_of_types(Tokens) -> %% State handling insert_fun(none, [], Env) -> Env; -insert_fun({Name, Type, RetType}, Code, #{functions := Functions} = Env) -> - {Hash, Env2} = insert_symbol(Name, Env), - Env2#{ - functions => Functions#{Hash => {{Type, RetType}, lists:reverse(Code)}} - }. +insert_fun({NameString, ArgType, RetType}, Code, #{ fate_code := FateCode + , functions := Funs} = Env) -> + Name = list_to_binary(NameString), + {FateCode1, Id} = aeb_fate_code:insert_symbol(Name, FateCode), + BodyByteCode = aeb_fate_code:serialize_code(lists:reverse(Code)), + SigByteCode = aeb_fate_code:serialize_signature({ArgType, RetType}), + FunByteCode = [?FUNCTION, Id, SigByteCode, BodyByteCode], + Env#{ functions => Funs#{ Id => FunByteCode } + , fate_code => FateCode1}. + +insert_symbol(Name, #{ fate_code := FateCode } = Env) -> + {FateCode1, Id} = aeb_fate_code:insert_symbol(Name, FateCode), + { Env#{ fate_code => FateCode1 } + , Id}. + +insert_annotation(comment, Line, Comment, #{ fate_code := FateCode } = Env) -> + FateCode1 = aeb_fate_code:insert_annotation(comment, Line, Comment, FateCode), + Env#{ fate_code => FateCode1}. mk_hash(Id) -> %% Use first 4 bytes of blake hash @@ -1003,33 +501,11 @@ mk_hash(Id) -> %% Handle annotations -insert_annotation(comment, Line, Comment, #{annotations := A} = Env) -> - Key = aeb_fate_data:make_tuple({aeb_fate_data:make_string("comment"), Line}), - Value = aeb_fate_data:make_string(Comment), - Env#{annotations => A#{ Key => Value}}. - get_comments(Annotations) -> [ {Line, Comment} || {?FATE_TUPLE({?FATE_STRING_VALUE("comment"), Line}), ?FATE_STRING_VALUE(Comment)} <- maps:to_list(Annotations)]. -%% Symbols handling - -insert_symbol(Id, Env) -> - Hash = mk_hash(Id), - insert_symbol(Id, Hash, Env). - -insert_symbol(Id, Hash, #{symbols := Symbols} = Env) -> - case maps:find(Hash, Symbols) of - {ok, Id} -> {Hash, Env}; - {ok, Id2} -> - %% Very unlikely... - exit({two_symbols_with_same_hash, Id, Id2}); - error -> - {Hash, Env#{symbols => Symbols#{ Id => Hash - , Hash => Id}}} - end. - %% Symbol table handling lookup(Name, Symbols) -> diff --git a/src/aeb_fate_code.erl b/src/aeb_fate_code.erl new file mode 100644 index 0000000..d09caca --- /dev/null +++ b/src/aeb_fate_code.erl @@ -0,0 +1,573 @@ +%%%------------------------------------------------------------------- +%%% @copyright (C) 2019, Aeternity Anstalt +%%% @doc +%%% ADT for fate byte code/fate code +%%% @end +%%% +%%%------------------------------------------------------------------- +-module(aeb_fate_code). + +-export([ annotations/1 + , deserialize/1 + , functions/1 + , insert_annotation/4 + , insert_fun/4 + , insert_symbol/2 + , new/0 + , serialize/1 + , serialize/2 + , serialize/3 + , serialize_code/1 + , serialize_signature/1 + , symbol_identifier/1 + , symbols/1 + ]). + +-include("../include/aeb_fate_opcodes.hrl"). +-include("../include/aeb_fate_data.hrl"). + + +-record(fcode, { functions = #{} :: map() + , symbols = #{} :: map() + , annotations = #{} :: map() + }). + +-define(HASH_BYTES, 32). + +%%%=================================================================== +%%% API +%%%=================================================================== + +new() -> + #fcode{}. + +annotations(#fcode{ annotations = As }) -> + As. + +functions(#fcode{ functions = Fs }) -> + Fs. + +symbols(#fcode{ symbols = Ss}) -> + Ss. + +symbol_identifier(Bin) -> + %% First 4 bytes of blake hash + {ok, <> } = eblake2:blake2b(?HASH_BYTES, Bin), + X. + +insert_fun(Name, {ArgType, RetType}, #{} = BBs, #fcode{ functions = Funs } = F) -> + {F1, ID} = insert_symbol(Name, F), + F1#fcode{ functions = Funs#{ ID => {{ArgType, RetType}, BBs}} }. + +insert_symbol(Name, #fcode{ symbols = Syms } = F) -> + ID = symbol_identifier(Name), + case maps:find(ID, Syms) of + {ok, Name} -> + {F, ID}; + {ok, X} -> + error({two_symbols_with_same_hash, Name, X}); + error -> + {F#fcode{symbols = Syms#{ ID => Name}}, ID} + end. + +insert_annotation(comment =_Type, Line, Comment, #fcode{ annotations = Anns} = F) -> + Key = aeb_fate_data:make_tuple({aeb_fate_data:make_string("comment"), Line}), + Value = aeb_fate_data:make_string(Comment), + F#fcode{ annotations = Anns#{ Key => Value}}. + +%%%=================================================================== +%%% Serialization +%%%=================================================================== + +serialize(#fcode{} = F) -> + serialize(F, []). + +serialize(#fcode{} = F, Options) -> + serialize(F, iolist_to_binary(serialize_functions(F)), Options). + +serialize(#fcode{} = F, Functions, Options) -> + SymbolTable = serialize_symbol_table(F), + Annotatations = serialize_annotations(F), + ByteCode = << (aeser_rlp:encode(Functions))/binary, + (aeser_rlp:encode(SymbolTable))/binary, + (aeser_rlp:encode(Annotatations))/binary + >>, + + case proplists:lookup(pp_hex_string, Options) of + {pp_hex_string, true} -> + io:format("Code: ~s~n",[to_hexstring(Functions)]); + none -> + ok + end, + ByteCode. + +to_hexstring(ByteList) -> + "0x" ++ lists:flatten( + [io_lib:format("~2.16.0b", [X]) + || X <- ByteList]). + + +serialize_functions(#fcode{ functions = Functions }) -> + %% Sort the functions on name to get a canonical serialisation. + Code = [[?FUNCTION, Name, serialize_signature(Sig), serialize_bbs(C)] || + {Name, {Sig, C}} <- lists:sort(maps:to_list(Functions))], + lists:flatten(Code). + +serialize_signature({Args, RetType}) -> + [aeb_fate_encoding:serialize_type({tuple, Args}) | + aeb_fate_encoding:serialize_type(RetType)]. + +serialize_symbol_table(#fcode{ symbols = Symbols }) -> + aeb_fate_encoding:serialize(aeb_fate_data:make_map(Symbols)). + +serialize_annotations(#fcode{ annotations = Annotations}) -> + aeb_fate_encoding:serialize(aeb_fate_data:make_map(Annotations)). + +serialize_bbs(#{} = BBs) -> + serialize_bbs(BBs, 0, []). + +serialize_bbs(BBs, N, Acc) -> + case maps:get(N, BBs, none) of + none -> + %% Assert that the BBs were contiguous + Size = maps:size(BBs), + case Size =:= N of + true -> + lists:reverse(Acc); + false -> + error({not_contiguous_labels, lists:sort(maps:keys(BBs))}) + end; + BB -> + serialize_bbs(BBs, N + 1, [serialize_bb(BB, [])|Acc]) + end. + +serialize_bb([Op|Rest], Acc) -> + serialize_bb(Rest, [serialize_op(Op)|Acc]); +serialize_bb([], Acc) -> + lists:reverse(Acc). + +serialize_op(Op) when is_tuple(Op) -> + [Opcode|Args] = tuple_to_list(Op), + [aeb_fate_opcodes:m_to_op(Opcode)|serialize_code(Args)]; +serialize_op(Opcode) -> + [aeb_fate_opcodes:m_to_op(Opcode)]. + +%% Argument encoding +%% Agument Specification Byte +%% bitpos: 6 4 2 0 +%% xx xx xx xx +%% Arg3 Arg2 Arg1 Arg0 +%% For 5-8 args another Argument Spec Byte is used +%% Bit pattern +%% 00 : stack/unused (depending on instruction) +%% 01 : argN +%% 10 : varN +%% 11 : immediate +serialize_code([ {Arg0Type, Arg0} + , {Arg1Type, Arg1} + , {Arg2Type, Arg2} + , {Arg3Type, Arg3} + , {Arg4Type, Arg4} + , {Arg5Type, Arg5} + , {Arg6Type, Arg6} + , {Arg7Type, Arg7} + | Rest]) -> + ArgSpec1 = + modifier_bits(Arg0Type) bor + (modifier_bits(Arg1Type) bsl 2) bor + (modifier_bits(Arg2Type) bsl 4) bor + (modifier_bits(Arg3Type) bsl 6), + ArgSpec2 = + modifier_bits(Arg4Type) bor + (modifier_bits(Arg5Type) bsl 2) bor + (modifier_bits(Arg6Type) bsl 4) bor + (modifier_bits(Arg7Type) bsl 6), + [ ArgSpec1 + , ArgSpec2 + , serialize_data(Arg0Type, Arg0) + , serialize_data(Arg1Type, Arg1) + , serialize_data(Arg2Type, Arg2) + , serialize_data(Arg3Type, Arg3) + , serialize_data(Arg4Type, Arg4) + , serialize_data(Arg5Type, Arg5) + , serialize_data(Arg6Type, Arg6) + , serialize_data(Arg7Type, Arg7) + | serialize_code(Rest)]; +serialize_code([ {Arg0Type, Arg0} + , {Arg1Type, Arg1} + , {Arg2Type, Arg2} + , {Arg3Type, Arg3} + , {Arg4Type, Arg4} + , {Arg5Type, Arg5} + , {Arg6Type, Arg6} + | Rest]) -> + ArgSpec1 = + modifier_bits(Arg0Type) bor + (modifier_bits(Arg1Type) bsl 2) bor + (modifier_bits(Arg2Type) bsl 4) bor + (modifier_bits(Arg3Type) bsl 6), + ArgSpec2 = + modifier_bits(Arg4Type) bor + (modifier_bits(Arg5Type) bsl 2) bor + (modifier_bits(Arg6Type) bsl 4), + [ ArgSpec1 + , ArgSpec2 + , serialize_data(Arg0Type, Arg0) + , serialize_data(Arg1Type, Arg1) + , serialize_data(Arg2Type, Arg2) + , serialize_data(Arg3Type, Arg3) + , serialize_data(Arg4Type, Arg4) + , serialize_data(Arg5Type, Arg5) + , serialize_data(Arg6Type, Arg6) + | serialize_code(Rest)]; +serialize_code([ {Arg0Type, Arg0} + , {Arg1Type, Arg1} + , {Arg2Type, Arg2} + , {Arg3Type, Arg3} + , {Arg4Type, Arg4} + , {Arg5Type, Arg5} + | Rest]) -> + ArgSpec1 = + modifier_bits(Arg0Type) bor + (modifier_bits(Arg1Type) bsl 2) bor + (modifier_bits(Arg2Type) bsl 4) bor + (modifier_bits(Arg3Type) bsl 6), + ArgSpec2 = + modifier_bits(Arg4Type) bor + (modifier_bits(Arg5Type) bsl 2), + [ ArgSpec1 + , ArgSpec2 + , serialize_data(Arg0Type, Arg0) + , serialize_data(Arg1Type, Arg1) + , serialize_data(Arg2Type, Arg2) + , serialize_data(Arg3Type, Arg3) + , serialize_data(Arg4Type, Arg4) + , serialize_data(Arg5Type, Arg5) + | serialize_code(Rest)]; +serialize_code([ {Arg0Type, Arg0} + , {Arg1Type, Arg1} + , {Arg2Type, Arg2} + , {Arg3Type, Arg3} + , {Arg4Type, Arg4} + | Rest]) -> + ArgSpec1 = + modifier_bits(Arg0Type) bor + (modifier_bits(Arg1Type) bsl 2) bor + (modifier_bits(Arg2Type) bsl 4) bor + (modifier_bits(Arg3Type) bsl 6), + ArgSpec2 = + modifier_bits(Arg4Type), + [ ArgSpec1 + , ArgSpec2 + , serialize_data(Arg0Type, Arg0) + , serialize_data(Arg1Type, Arg1) + , serialize_data(Arg2Type, Arg2) + , serialize_data(Arg3Type, Arg3) + , serialize_data(Arg4Type, Arg4) + | serialize_code(Rest)]; + +serialize_code([ {Arg0Type, Arg0} + , {Arg1Type, Arg1} + , {Arg2Type, Arg2} + , {Arg3Type, Arg3}| Rest]) -> + ArgSpec = + modifier_bits(Arg0Type) bor + (modifier_bits(Arg1Type) bsl 2) bor + (modifier_bits(Arg2Type) bsl 4) bor + (modifier_bits(Arg3Type) bsl 6), + [ ArgSpec + , serialize_data(Arg0Type, Arg0) + , serialize_data(Arg1Type, Arg1) + , serialize_data(Arg2Type, Arg2) + , serialize_data(Arg3Type, Arg3) + | serialize_code(Rest)]; +serialize_code([ {Arg0Type, Arg0} + , {Arg1Type, Arg1} + , {Arg2Type, Arg2} + | Rest]) -> + ArgSpec = + modifier_bits(Arg0Type) bor + (modifier_bits(Arg1Type) bsl 2) bor + (modifier_bits(Arg2Type) bsl 4), + [ArgSpec + , serialize_data(Arg0Type, Arg0) + , serialize_data(Arg1Type, Arg1) + , serialize_data(Arg2Type, Arg2) + | serialize_code(Rest)]; +serialize_code([ {Arg0Type, Arg0} + , {Arg1Type, Arg1} + | Rest]) -> + ArgSpec = + modifier_bits(Arg0Type) bor + (modifier_bits(Arg1Type) bsl 2), + [ArgSpec + , serialize_data(Arg0Type, Arg0) + , serialize_data(Arg1Type, Arg1) + | serialize_code(Rest)]; +serialize_code([ {Arg0Type, Arg0} | Rest]) -> + ArgSpec = + modifier_bits(Arg0Type), + [ArgSpec + , serialize_data(Arg0Type, Arg0) + | serialize_code(Rest)]; +serialize_code([B|Rest]) -> + [B | serialize_code(Rest)]; +serialize_code([]) -> []. + +serialize_data(_, Data) -> + aeb_fate_encoding:serialize(Data). + +%% 00 : stack/unused (depending on instruction) +%% 01 : argN +%% 10 : varN +%% 11 : immediate +modifier_bits(immediate) -> 2#11; +modifier_bits(var) -> 2#10; +modifier_bits(arg) -> 2#01; +modifier_bits(stack) -> 2#00. + +bits_to_modifier(2#11) -> immediate; +bits_to_modifier(2#10) -> var; +bits_to_modifier(2#01) -> arg; +bits_to_modifier(2#00) -> stack. + +%%%=================================================================== +%%% Deserialization +%%%=================================================================== + +deserialize(Bytes) -> + {ByteCode, Rest1} = aeser_rlp:decode_one(Bytes), + {SymbolTable, Rest2} = aeser_rlp:decode_one(Rest1), + {Annotations, <<>>} = aeser_rlp:decode_one(Rest2), + + Env = #{ function => none + , bb => 0 + , current_bb_code => [] + , functions => #{} + , code => #{} + }, + #fcode{ functions = deserialize_functions(ByteCode, Env) + , annotations = deserialize_annotations(Annotations) + , symbols = deserialize_symbols(SymbolTable) + }. + + +deserialize_functions(<>, + #{ function := none + , bb := 0 + , current_bb_code := [] + } = Env) -> + {Sig, Rest2} = deserialize_signature(Rest), + Env2 = Env#{function => {<>, Sig}}, + deserialize_functions(Rest2, Env2); +deserialize_functions(<>, + #{ function := {F, Sig} + , bb := BB + , current_bb_code := Code + , code := Program + , functions := Funs} = Env) -> + {NewSig, Rest2} = deserialize_signature(Rest), + case Code of + [] -> + Env2 = Env#{ bb => 0 + , current_bb_code => [] + , function => {<>, NewSig} + , code => #{} + , functions => Funs#{F => {Sig, Program}}}, + deserialize_functions(Rest2, Env2); + _ -> + Env2 = Env#{ bb => 0 + , current_bb_code => [] + , function => {<>, NewSig} + , code => #{} + , functions => + Funs#{F => {Sig, + Program#{ BB => lists:reverse(Code)}}}}, + deserialize_functions(Rest2, Env2) + end; +deserialize_functions(<>, + #{ bb := BB + , current_bb_code := Code + , code := Program} = Env) -> + {Rest2, OpCode} = deserialize_op(Op, Rest, Code), + case aeb_fate_opcodes:end_bb(Op) of + true -> + deserialize_functions(Rest2, Env#{ bb => BB+1 + , current_bb_code => [] + , code => Program#{BB => + lists:reverse(OpCode)}}); + false -> + deserialize_functions(Rest2, Env#{ current_bb_code => OpCode}) + end; +deserialize_functions(<<>>, #{ function := {F, Sig} + , bb := BB + , current_bb_code := Code + , code := Program + , functions := Funs}) -> + FunctionCode = + case Code of + [] -> Program; + _ -> Program#{ BB => lists:reverse(Code)} + end, + Funs#{F => {Sig, FunctionCode}}. + +deserialize_op(Op, Rest, Code) -> + OpName = aeb_fate_opcodes:mnemonic(Op), + case aeb_fate_opcodes:args(Op) of + 0 -> {Rest, [OpName | Code]}; + 1 -> + <> = Rest, + {Arg, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), + Modifier = bits_to_modifier(ArgType), + {Rest3, [{OpName, {Modifier, Arg}} | Code]}; + 2 -> + <> = Rest, + {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), + {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), + Modifier0 = bits_to_modifier(ArgType band 2#11), + Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), + {Rest4, [{OpName, {Modifier0, Arg0}, + {Modifier1, Arg1}} | Code]}; + 3 -> + <> = Rest, + {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), + {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), + {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), + Modifier0 = bits_to_modifier(ArgType band 2#11), + Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), + Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), + {Rest5, [{ OpName + , {Modifier0, Arg0} + , {Modifier1, Arg1} + , {Modifier2, Arg2}} + | Code]}; + 4 -> + <> = Rest, + {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), + {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), + {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), + {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), + Modifier0 = bits_to_modifier(ArgType band 2#11), + Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), + Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), + Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), + {Rest6, [{ OpName + , {Modifier0, Arg0} + , {Modifier1, Arg1} + , {Modifier2, Arg2} + , {Modifier3, Arg3}} + | Code]}; + 5 -> + <> = Rest, + {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), + {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), + {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), + {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), + {Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6), + Modifier0 = bits_to_modifier(ArgType band 2#11), + Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), + Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), + Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), + Modifier4 = bits_to_modifier(ArgType2 band 2#11), + {Rest7, [{ OpName + , {Modifier0, Arg0} + , {Modifier1, Arg1} + , {Modifier2, Arg2} + , {Modifier3, Arg3} + , {Modifier4, Arg4} + } + | Code]}; + 6 -> + <> = Rest, + {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), + {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), + {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), + {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), + {Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6), + {Arg5, Rest8} = aeb_fate_encoding:deserialize_one(Rest7), + Modifier0 = bits_to_modifier(ArgType band 2#11), + Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), + Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), + Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), + Modifier4 = bits_to_modifier(ArgType2 band 2#11), + Modifier5 = bits_to_modifier((ArgType2 bsr 2) band 2#11), + {Rest8, [{ OpName + , {Modifier0, Arg0} + , {Modifier1, Arg1} + , {Modifier2, Arg2} + , {Modifier3, Arg3} + , {Modifier4, Arg4} + , {Modifier5, Arg5} + } + | Code]}; + 7 -> + <> = Rest, + {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), + {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), + {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), + {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), + {Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6), + {Arg5, Rest8} = aeb_fate_encoding:deserialize_one(Rest7), + {Arg6, Rest9} = aeb_fate_encoding:deserialize_one(Rest8), + Modifier0 = bits_to_modifier(ArgType band 2#11), + Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), + Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), + Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), + Modifier4 = bits_to_modifier(ArgType2 band 2#11), + Modifier5 = bits_to_modifier((ArgType2 bsr 2) band 2#11), + Modifier6 = bits_to_modifier((ArgType2 bsr 4) band 2#11), + {Rest9, [{ OpName + , {Modifier0, Arg0} + , {Modifier1, Arg1} + , {Modifier2, Arg2} + , {Modifier3, Arg3} + , {Modifier4, Arg4} + , {Modifier5, Arg5} + , {Modifier6, Arg6} + } + | Code]}; + 8 -> + <> = Rest, + {Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2), + {Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3), + {Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4), + {Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5), + {Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6), + {Arg5, Rest8} = aeb_fate_encoding:deserialize_one(Rest7), + {Arg6, Rest9} = aeb_fate_encoding:deserialize_one(Rest8), + {Arg7, Rest10} = aeb_fate_encoding:deserialize_one(Rest9), + Modifier0 = bits_to_modifier(ArgType band 2#11), + Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11), + Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11), + Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11), + Modifier4 = bits_to_modifier(ArgType2 band 2#11), + Modifier5 = bits_to_modifier((ArgType2 bsr 2) band 2#11), + Modifier6 = bits_to_modifier((ArgType2 bsr 4) band 2#11), + Modifier7 = bits_to_modifier((ArgType2 bsr 6) band 2#11), + {Rest10, [{ OpName + , {Modifier0, Arg0} + , {Modifier1, Arg1} + , {Modifier2, Arg2} + , {Modifier3, Arg3} + , {Modifier4, Arg4} + , {Modifier5, Arg5} + , {Modifier6, Arg6} + , {Modifier7, Arg7} + } + | Code]} + end. + + + +deserialize_signature(Binary) -> + {{tuple, Args}, Rest} = aeb_fate_encoding:deserialize_type(Binary), + {RetType, Rest2} = aeb_fate_encoding:deserialize_type(Rest), + {{Args, RetType}, Rest2}. + +deserialize_symbols(Table) -> + ?FATE_MAP_VALUE(SymbolTable) = aeb_fate_encoding:deserialize(Table), + SymbolTable. + +deserialize_annotations(AnnotationsBin) -> + ?FATE_MAP_VALUE(Annotations) = aeb_fate_encoding:deserialize(AnnotationsBin), + Annotations. diff --git a/test/aeb_fate_asm_test.erl b/test/aeb_fate_asm_test.erl index 33b3989..bebacf6 100644 --- a/test/aeb_fate_asm_test.erl +++ b/test/aeb_fate_asm_test.erl @@ -25,12 +25,7 @@ read_file(File) -> Asm. assemble(Asm) -> - {Env, BC} = aeb_fate_asm:asm_to_bytecode(Asm, []), - {Env, BC}. - -disassemble(BC) -> - aeb_fate_asm:bytecode_to_fate_code(BC, []). - + aeb_fate_asm:asm_to_bytecode(Asm, []). asm_disasm_idenity_test() -> check_roundtrip(identity). @@ -58,12 +53,12 @@ sources() -> check_roundtrip(File) -> AssemblerCode = read_file(File), {_Env, ByteCode} = assemble(AssemblerCode), - FateCode = disassemble(ByteCode), + FateCode = aeb_fate_code:deserialize(ByteCode), DissasmCode = aeb_fate_asm:to_asm(FateCode), - io:format("~s~n", [AssemblerCode]), - io:format("~s~n", [DissasmCode]), {_Env2, ByteCode2} = assemble(DissasmCode), + ByteCode3 = aeb_fate_code:serialize(FateCode), Code1 = aeb_fate_asm:strip(ByteCode), Code2 = aeb_fate_asm:strip(ByteCode2), - io:format("~s~n", [aeb_fate_asm:to_asm(disassemble(ByteCode2))]), - ?assertEqual(Code1, Code2). + Code3 = aeb_fate_asm:strip(ByteCode3), + ?assertEqual(Code1, Code2), + ?assertEqual(Code1, Code3).