Copy respository files and add rebar.config #118
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,3 +8,4 @@ ebin/*.beam
|
|||||||
rel/example_project
|
rel/example_project
|
||||||
.concrete/DEV_MODE
|
.concrete/DEV_MODE
|
||||||
.rebar
|
.rebar
|
||||||
|
aeb_asm_scan.erl
|
||||||
|
181
include/aeb_opcodes.hrl
Normal file
181
include/aeb_opcodes.hrl
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
|
||||||
|
%% AEVM opcodes
|
||||||
|
-define( 'STOP', 16#00).
|
||||||
|
-define( 'ADD', 16#01).
|
||||||
|
-define( 'MUL', 16#02).
|
||||||
|
-define( 'SUB', 16#03).
|
||||||
|
-define( 'DIV', 16#04).
|
||||||
|
-define( 'SDIV', 16#05).
|
||||||
|
-define( 'MOD', 16#06).
|
||||||
|
-define( 'SMOD', 16#07).
|
||||||
|
-define( 'ADDMOD', 16#08).
|
||||||
|
-define( 'MULMOD', 16#09).
|
||||||
|
-define( 'EXP', 16#0a).
|
||||||
|
-define( 'SIGNEXTEND', 16#0b).
|
||||||
|
|
||||||
|
-define( 'LT', 16#10).
|
||||||
|
-define( 'GT', 16#11).
|
||||||
|
-define( 'SLT', 16#12).
|
||||||
|
-define( 'SGT', 16#13).
|
||||||
|
-define( 'EQ', 16#14).
|
||||||
|
-define( 'ISZERO', 16#15).
|
||||||
|
-define( 'AND', 16#16).
|
||||||
|
-define( 'OR', 16#17).
|
||||||
|
-define( 'XOR', 16#18).
|
||||||
|
-define( 'NOT', 16#19).
|
||||||
|
-define( 'BYTE', 16#1a).
|
||||||
|
|
||||||
|
-define( 'SHA3', 16#20).
|
||||||
|
|
||||||
|
-define( 'ADDRESS', 16#30).
|
||||||
|
-define( 'BALANCE', 16#31).
|
||||||
|
-define( 'ORIGIN', 16#32).
|
||||||
|
-define( 'CALLER', 16#33).
|
||||||
|
-define( 'CALLVALUE', 16#34).
|
||||||
|
-define( 'CALLDATALOAD', 16#35).
|
||||||
|
-define( 'CALLDATASIZE', 16#36).
|
||||||
|
-define( 'CALLDATACOPY', 16#37).
|
||||||
|
-define( 'CODESIZE', 16#38).
|
||||||
|
-define( 'CODECOPY', 16#39).
|
||||||
|
-define( 'GASPRICE', 16#3a).
|
||||||
|
-define( 'EXTCODESIZE', 16#3b).
|
||||||
|
-define( 'EXTCODECOPY', 16#3c).
|
||||||
|
-define( 'RETURNDATASIZE', 16#3d).
|
||||||
|
-define( 'RETURNDATACOPY', 16#3e).
|
||||||
|
|
||||||
|
-define( 'BLOCKHASH', 16#40).
|
||||||
|
-define( 'COINBASE', 16#41).
|
||||||
|
-define( 'TIMESTAMP', 16#42).
|
||||||
|
-define( 'NUMBER', 16#43).
|
||||||
|
-define( 'DIFFICULTY', 16#44).
|
||||||
|
-define( 'GASLIMIT', 16#45).
|
||||||
|
|
||||||
|
-define( 'POP', 16#50).
|
||||||
|
-define( 'MLOAD', 16#51).
|
||||||
|
-define( 'MSTORE', 16#52).
|
||||||
|
-define( 'MSTORE8', 16#53).
|
||||||
|
-define( 'SLOAD', 16#54).
|
||||||
|
-define( 'SSTORE', 16#55).
|
||||||
|
-define( 'JUMP', 16#56).
|
||||||
|
-define( 'JUMPI', 16#57).
|
||||||
|
-define( 'PC', 16#58).
|
||||||
|
-define( 'MSIZE', 16#59).
|
||||||
|
-define( 'GAS', 16#5a).
|
||||||
|
-define( 'JUMPDEST', 16#5b).
|
||||||
|
|
||||||
|
-define( 'PUSH1', 16#60).
|
||||||
|
-define( 'PUSH2', 16#61).
|
||||||
|
-define( 'PUSH3', 16#62).
|
||||||
|
-define( 'PUSH4', 16#63).
|
||||||
|
-define( 'PUSH5', 16#64).
|
||||||
|
-define( 'PUSH6', 16#65).
|
||||||
|
-define( 'PUSH7', 16#66).
|
||||||
|
-define( 'PUSH8', 16#67).
|
||||||
|
-define( 'PUSH9', 16#68).
|
||||||
|
-define( 'PUSH10', 16#69).
|
||||||
|
-define( 'PUSH11', 16#6a).
|
||||||
|
-define( 'PUSH12', 16#6b).
|
||||||
|
-define( 'PUSH13', 16#6c).
|
||||||
|
-define( 'PUSH14', 16#6d).
|
||||||
|
-define( 'PUSH15', 16#6e).
|
||||||
|
-define( 'PUSH16', 16#6f).
|
||||||
|
-define( 'PUSH17', 16#70).
|
||||||
|
-define( 'PUSH18', 16#71).
|
||||||
|
-define( 'PUSH19', 16#72).
|
||||||
|
-define( 'PUSH20', 16#73).
|
||||||
|
-define( 'PUSH21', 16#74).
|
||||||
|
-define( 'PUSH22', 16#75).
|
||||||
|
-define( 'PUSH23', 16#76).
|
||||||
|
-define( 'PUSH24', 16#77).
|
||||||
|
-define( 'PUSH25', 16#78).
|
||||||
|
-define( 'PUSH26', 16#79).
|
||||||
|
-define( 'PUSH27', 16#7a).
|
||||||
|
-define( 'PUSH28', 16#7b).
|
||||||
|
-define( 'PUSH29', 16#7c).
|
||||||
|
-define( 'PUSH30', 16#7d).
|
||||||
|
-define( 'PUSH31', 16#7e).
|
||||||
|
-define( 'PUSH32', 16#7f).
|
||||||
|
-define( 'DUP1', 16#80).
|
||||||
|
-define( 'DUP2', 16#81).
|
||||||
|
-define( 'DUP3', 16#82).
|
||||||
|
-define( 'DUP4', 16#83).
|
||||||
|
-define( 'DUP5', 16#84).
|
||||||
|
-define( 'DUP6', 16#85).
|
||||||
|
-define( 'DUP7', 16#86).
|
||||||
|
-define( 'DUP8', 16#87).
|
||||||
|
-define( 'DUP9', 16#88).
|
||||||
|
-define( 'DUP10', 16#89).
|
||||||
|
-define( 'DUP11', 16#8a).
|
||||||
|
-define( 'DUP12', 16#8b).
|
||||||
|
-define( 'DUP13', 16#8c).
|
||||||
|
-define( 'DUP14', 16#8d).
|
||||||
|
-define( 'DUP15', 16#8e).
|
||||||
|
-define( 'DUP16', 16#8f).
|
||||||
|
-define( 'SWAP1', 16#90).
|
||||||
|
-define( 'SWAP2', 16#91).
|
||||||
|
-define( 'SWAP3', 16#92).
|
||||||
|
-define( 'SWAP4', 16#93).
|
||||||
|
-define( 'SWAP5', 16#94).
|
||||||
|
-define( 'SWAP6', 16#95).
|
||||||
|
-define( 'SWAP7', 16#96).
|
||||||
|
-define( 'SWAP8', 16#97).
|
||||||
|
-define( 'SWAP9', 16#98).
|
||||||
|
-define( 'SWAP10', 16#99).
|
||||||
|
-define( 'SWAP11', 16#9a).
|
||||||
|
-define( 'SWAP12', 16#9b).
|
||||||
|
-define( 'SWAP13', 16#9c).
|
||||||
|
-define( 'SWAP14', 16#9d).
|
||||||
|
-define( 'SWAP15', 16#9e).
|
||||||
|
-define( 'SWAP16', 16#9f).
|
||||||
|
-define( 'LOG0', 16#a0).
|
||||||
|
-define( 'LOG1', 16#a1).
|
||||||
|
-define( 'LOG2', 16#a2).
|
||||||
|
-define( 'LOG3', 16#a3).
|
||||||
|
-define( 'LOG4', 16#a4).
|
||||||
|
|
||||||
|
-define( 'CREATE', 16#f0).
|
||||||
|
-define( 'CALL', 16#f1).
|
||||||
|
-define( 'CALLCODE', 16#f2).
|
||||||
|
-define( 'RETURN', 16#f3).
|
||||||
|
-define( 'DELEGATECALL', 16#f4).
|
||||||
|
|
||||||
|
-define( 'STATICCALL', 16#fa).
|
||||||
|
|
||||||
|
-define( 'REVERT', 16#fd).
|
||||||
|
-define( 'INVALID', 16#fe).
|
||||||
|
-define( 'SUICIDE', 16#ff).
|
||||||
|
|
||||||
|
-define( COMMENT(X), {comment, X}).
|
||||||
|
|
||||||
|
%% Transactions are implemented as contract calls to address zero, with the
|
||||||
|
%% first argument encoding the transaction type according to the below.
|
||||||
|
|
||||||
|
-define(PRIM_CALLS_CONTRACT, 0).
|
||||||
|
|
||||||
|
-define(PRIM_CALL_SPEND, 1).
|
||||||
|
|
||||||
|
-define(PRIM_CALL_IN_ORACLE_RANGE(__TTYPE__), (((__TTYPE__) > 99) andalso ((__TTYPE__) < 200))).
|
||||||
|
-define(PRIM_CALL_ORACLE_REGISTER, 100).
|
||||||
|
-define(PRIM_CALL_ORACLE_QUERY, 101).
|
||||||
|
-define(PRIM_CALL_ORACLE_RESPOND, 102).
|
||||||
|
-define(PRIM_CALL_ORACLE_EXTEND, 103).
|
||||||
|
-define(PRIM_CALL_ORACLE_GET_ANSWER, 104).
|
||||||
|
-define(PRIM_CALL_ORACLE_GET_QUESTION, 105).
|
||||||
|
-define(PRIM_CALL_ORACLE_QUERY_FEE, 106).
|
||||||
|
|
||||||
|
-define(PRIM_CALL_IN_AENS_RANGE(__TTYPE__), (((__TTYPE__) > 199) andalso ((__TTYPE__) < 300))).
|
||||||
|
-define(PRIM_CALL_AENS_RESOLVE, 200).
|
||||||
|
-define(PRIM_CALL_AENS_PRECLAIM, 201).
|
||||||
|
-define(PRIM_CALL_AENS_CLAIM, 202).
|
||||||
|
-define(PRIM_CALL_AENS_UPDATE, 203).
|
||||||
|
-define(PRIM_CALL_AENS_TRANSFER, 204).
|
||||||
|
-define(PRIM_CALL_AENS_REVOKE, 205).
|
||||||
|
|
||||||
|
-define(PRIM_CALL_IN_MAP_RANGE(__TTYPE__), (((__TTYPE__) > 299) andalso ((__TTYPE__) < 400))).
|
||||||
|
-define(PRIM_CALL_MAP_EMPTY, 300).
|
||||||
|
-define(PRIM_CALL_MAP_GET, 301).
|
||||||
|
-define(PRIM_CALL_MAP_PUT, 302).
|
||||||
|
-define(PRIM_CALL_MAP_DELETE, 303).
|
||||||
|
-define(PRIM_CALL_MAP_SIZE, 304).
|
||||||
|
-define(PRIM_CALL_MAP_TOLIST, 305).
|
||||||
|
|
1
rebar.lock
Normal file
1
rebar.lock
Normal file
@ -0,0 +1 @@
|
|||||||
|
[].
|
147
src/aeb_asm.erl
Normal file
147
src/aeb_asm.erl
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
|
%%% @doc Assembler for aevm machine code.
|
||||||
|
%%%
|
||||||
|
%%% Assembler code can be read from a file.
|
||||||
|
%%% The assembler has the following format
|
||||||
|
%%% Comments start with 2 semicolons and runs till end of line
|
||||||
|
%%% ;; This is a comment
|
||||||
|
%%% Opcode mnemonics start with an upper case letter.
|
||||||
|
%%% DUP1
|
||||||
|
%%% Identifiers start with a lower case letter
|
||||||
|
%%% an_identifier
|
||||||
|
%%% All identifiers has to be decleard with a label.
|
||||||
|
%%% A label is an identifier that ends with a colon.
|
||||||
|
%%% The label is the byte code address of the next instruction.
|
||||||
|
%%% a_label:
|
||||||
|
%%% Immediates can be of four types:
|
||||||
|
%%% 1. integers
|
||||||
|
%%% 42
|
||||||
|
%%% 2. hexadecimal integers starting with 0x
|
||||||
|
%%% 0x0deadbeef0
|
||||||
|
%%% 3. 256-bit hash strings starting with #
|
||||||
|
%%% followed by up to 64 hex chars
|
||||||
|
%%% #00000deadbeef
|
||||||
|
%%% 4. labels as descibed above.
|
||||||
|
%%%
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 21 Dec 2017
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(aeb_asm).
|
||||||
|
|
||||||
|
-export([ file/2
|
||||||
|
, pp/1
|
||||||
|
, to_hexstring/1
|
||||||
|
]).
|
||||||
|
|
||||||
|
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
||||||
|
|
||||||
|
|
||||||
|
pp(Asm) ->
|
||||||
|
Listing = format(Asm),
|
||||||
|
io:format("~s~n", [Listing]).
|
||||||
|
|
||||||
|
format(Asm) -> format(Asm, 0).
|
||||||
|
|
||||||
|
format([{comment, Comment} | Rest], Address) ->
|
||||||
|
";; " ++ Comment ++ "\n" ++ format(Rest, Address);
|
||||||
|
format([Mnemonic | Rest], Address) ->
|
||||||
|
Op = aeb_opcodes:m_to_op(Mnemonic),
|
||||||
|
case (Op >= ?PUSH1) andalso (Op =< ?PUSH32) of
|
||||||
|
true ->
|
||||||
|
Arity = aeb_opcodes:op_size(Op) - 1,
|
||||||
|
{Args, Code} = get_args(Arity, Rest),
|
||||||
|
" " ++ atom_to_list(Mnemonic)
|
||||||
|
++ " " ++ Args ++ "\n"
|
||||||
|
++ format(Code, Address + Arity + 1);
|
||||||
|
false ->
|
||||||
|
" " ++ atom_to_list(Mnemonic) ++ "\n"
|
||||||
|
++ format(Rest, Address + 1)
|
||||||
|
end;
|
||||||
|
format([],_) -> [].
|
||||||
|
|
||||||
|
%% TODO: Are args encoded as one list element or as a number of bytes...
|
||||||
|
get_args(1, [Arg|Code]) ->
|
||||||
|
{integer_to_list(Arg), Code};
|
||||||
|
get_args(N, [Arg|Code]) ->
|
||||||
|
{Args, Rest} = get_args(N-1, Code),
|
||||||
|
{integer_to_list(Arg) ++ ", " ++ Args, Rest}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
file(Filename, Options) ->
|
||||||
|
{ok, File} = file:read_file(Filename),
|
||||||
|
{ok, Tokens, _} = aeb_asm_scan:scan(binary_to_list(File)),
|
||||||
|
|
||||||
|
case proplists:lookup(pp_tokens, Options) of
|
||||||
|
{pp_tokens, true} ->
|
||||||
|
io:format("Tokens ~p~n",[Tokens]);
|
||||||
|
none ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
|
||||||
|
ByteList = to_bytecode(Tokens, 0, #{}, [], Options),
|
||||||
|
|
||||||
|
case proplists:lookup(pp_hex_string, Options) of
|
||||||
|
{pp_hex_string, true} ->
|
||||||
|
io:format("Code: ~s~n",[to_hexstring(ByteList)]);
|
||||||
|
none ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
|
||||||
|
|
||||||
|
list_to_binary(ByteList).
|
||||||
|
|
||||||
|
to_hexstring(ByteList) ->
|
||||||
|
"0x" ++ lists:flatten(
|
||||||
|
[io_lib:format("~2.16.0b", [X])
|
||||||
|
|| X <- ByteList]).
|
||||||
|
|
||||||
|
|
||||||
|
to_bytecode([{mnemonic,_line, Op}|Rest], Address, Env, Code, Opts) ->
|
||||||
|
OpCode = aeb_opcodes:m_to_op(Op),
|
||||||
|
OpSize = aeb_opcodes:op_size(OpCode),
|
||||||
|
to_bytecode(Rest, Address + OpSize, Env, [OpCode|Code], Opts);
|
||||||
|
to_bytecode([{int,_line, Int}|Rest], Address, Env, Code, Opts) ->
|
||||||
|
to_bytecode(Rest, Address, Env, [Int|Code], Opts);
|
||||||
|
to_bytecode([{hash,_line, Hash}|Rest], Address, Env, Code, Opts) ->
|
||||||
|
to_bytecode(Rest, Address, Env, [Hash|Code], Opts);
|
||||||
|
to_bytecode([{id,_line, ID}|Rest], Address, Env, Code, Opts) ->
|
||||||
|
to_bytecode(Rest, Address, Env, [{ref, ID}|Code], Opts);
|
||||||
|
to_bytecode([{label,_line, Label}|Rest], Address, Env, Code, Opts) ->
|
||||||
|
to_bytecode(Rest, Address, Env#{Label => Address}, Code, Opts);
|
||||||
|
to_bytecode([], _Address, Env, Code, Opts) ->
|
||||||
|
case proplists:lookup(pp_opcodes, Opts) of
|
||||||
|
{pp_opcodes, true} ->
|
||||||
|
io:format("opcodes ~p~n", [lists:reverse(Code)]);
|
||||||
|
none ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
|
||||||
|
PatchedCode = resolve_refs(Code, Env, []),
|
||||||
|
case proplists:lookup(pp_patched_code, Opts) of
|
||||||
|
{pp_patched_code, true} ->
|
||||||
|
io:format("Patched Code: ~p~n", [PatchedCode]);
|
||||||
|
none ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
|
||||||
|
expand_args(PatchedCode).
|
||||||
|
|
||||||
|
%% Also reverses the code (back to unreversed state).
|
||||||
|
resolve_refs([{ref, ID} | Rest], Env, Code) ->
|
||||||
|
Address = maps:get(ID, Env),
|
||||||
|
resolve_refs(Rest, Env, [Address | Code]);
|
||||||
|
resolve_refs([Op | Rest], Env, Code) ->
|
||||||
|
resolve_refs(Rest, Env, [Op | Code]);
|
||||||
|
resolve_refs([],_Env, Code) -> Code.
|
||||||
|
|
||||||
|
expand_args([OP, Arg | Rest]) when OP >= ?PUSH1 andalso OP =< ?PUSH32 ->
|
||||||
|
BitSize = (aeb_opcodes:op_size(OP) - 1) * 8,
|
||||||
|
Bin = << << X:BitSize>> || X <- [Arg] >>,
|
||||||
|
ArgByteList = binary_to_list(Bin),
|
||||||
|
[OP | ArgByteList] ++ expand_args(Rest);
|
||||||
|
expand_args([OP | Rest]) ->
|
||||||
|
[OP | expand_args(Rest)];
|
||||||
|
expand_args([]) -> [].
|
211
src/aeb_asm_scan.xrl
Normal file
211
src/aeb_asm_scan.xrl
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
|
%%% @doc Assembler lexer.
|
||||||
|
%%%
|
||||||
|
%%% @end
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
|
Definitions.
|
||||||
|
DIGIT = [0-9]
|
||||||
|
HEXDIGIT = [0-9a-fA-F]
|
||||||
|
LOWER = [a-z_]
|
||||||
|
UPPER = [A-Z]
|
||||||
|
INT = {DIGIT}+
|
||||||
|
HEX = 0x{HEXDIGIT}+
|
||||||
|
HASH = #{HEXDIGIT}+
|
||||||
|
WS = [\000-\s]
|
||||||
|
ID = {LOWER}[a-zA-Z0-9_]*
|
||||||
|
LABEL = {ID}:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Rules.
|
||||||
|
{LABEL} : {token, {label, TokenLine, TokenChars -- ":"}}.
|
||||||
|
STOP : {token, {mnemonic, TokenLine, 'STOP'}}.
|
||||||
|
ADD : {token, {mnemonic, TokenLine, 'ADD'}}.
|
||||||
|
MUL : {token, {mnemonic, TokenLine, 'MUL'}}.
|
||||||
|
SUB : {token, {mnemonic, TokenLine, 'SUB'}}.
|
||||||
|
DIV : {token, {mnemonic, TokenLine, 'DIV'}}.
|
||||||
|
SDIV : {token, {mnemonic, TokenLine, 'SDIV'}}.
|
||||||
|
MOD : {token, {mnemonic, TokenLine, 'MOD'}}.
|
||||||
|
SMOD : {token, {mnemonic, TokenLine, 'SMOD'}}.
|
||||||
|
ADDMOD : {token, {mnemonic, TokenLine, 'ADDMOD'}}.
|
||||||
|
MULMOD : {token, {mnemonic, TokenLine, 'MULMOD'}}.
|
||||||
|
EXP : {token, {mnemonic, TokenLine, 'EXP'}}.
|
||||||
|
SIGNEXTEND : {token, {mnemonic, TokenLine, 'SIGNEXTEND'}}.
|
||||||
|
LT : {token, {mnemonic, TokenLine, 'LT'}}.
|
||||||
|
GT : {token, {mnemonic, TokenLine, 'GT'}}.
|
||||||
|
SLT : {token, {mnemonic, TokenLine, 'SLT'}}.
|
||||||
|
SGT : {token, {mnemonic, TokenLine, 'SGT'}}.
|
||||||
|
EQ : {token, {mnemonic, TokenLine, 'EQ'}}.
|
||||||
|
ISZERO : {token, {mnemonic, TokenLine, 'ISZERO'}}.
|
||||||
|
AND : {token, {mnemonic, TokenLine, 'AND'}}.
|
||||||
|
OR : {token, {mnemonic, TokenLine, 'OR'}}.
|
||||||
|
XOR : {token, {mnemonic, TokenLine, 'XOR'}}.
|
||||||
|
NOT : {token, {mnemonic, TokenLine, 'NOT'}}.
|
||||||
|
BYTE : {token, {mnemonic, TokenLine, 'BYTE'}}.
|
||||||
|
SHA3 : {token, {mnemonic, TokenLine, 'SHA3'}}.
|
||||||
|
ADDRESS : {token, {mnemonic, TokenLine, 'ADDRESS'}}.
|
||||||
|
BALANCE : {token, {mnemonic, TokenLine, 'BALANCE'}}.
|
||||||
|
ORIGIN : {token, {mnemonic, TokenLine, 'ORIGIN'}}.
|
||||||
|
CALLER : {token, {mnemonic, TokenLine, 'CALLER'}}.
|
||||||
|
CALLVALUE : {token, {mnemonic, TokenLine, 'CALLVALUE'}}.
|
||||||
|
CALLDATALOAD : {token, {mnemonic, TokenLine, 'CALLDATALOAD'}}.
|
||||||
|
CALLDATASIZE : {token, {mnemonic, TokenLine, 'CALLDATASIZE'}}.
|
||||||
|
CALLDATACOPY : {token, {mnemonic, TokenLine, 'CALLDATACOPY'}}.
|
||||||
|
CODESIZE : {token, {mnemonic, TokenLine, 'CODESIZE'}}.
|
||||||
|
CODECOPY : {token, {mnemonic, TokenLine, 'CODECOPY'}}.
|
||||||
|
GASPRICE : {token, {mnemonic, TokenLine, 'GASPRICE'}}.
|
||||||
|
EXTCODESIZE : {token, {mnemonic, TokenLine, 'EXTCODESIZE'}}.
|
||||||
|
EXTCODECOPY : {token, {mnemonic, TokenLine, 'EXTCODECOPY'}}.
|
||||||
|
RETURNDATASIZE : {token, {mnemonic, TokenLine, 'RETURNDATASIZE'}}.
|
||||||
|
RETURNDATACOPY : {token, {mnemonic, TokenLine, 'RETURNDATACOPY'}}.
|
||||||
|
BLOCKHASH : {token, {mnemonic, TokenLine, 'BLOCKHASH'}}.
|
||||||
|
COINBASE : {token, {mnemonic, TokenLine, 'COINBASE'}}.
|
||||||
|
TIMESTAMP : {token, {mnemonic, TokenLine, 'TIMESTAMP'}}.
|
||||||
|
NUMBER : {token, {mnemonic, TokenLine, 'NUMBER'}}.
|
||||||
|
DIFFICULTY : {token, {mnemonic, TokenLine, 'DIFFICULTY'}}.
|
||||||
|
GASLIMIT : {token, {mnemonic, TokenLine, 'GASLIMIT'}}.
|
||||||
|
POP : {token, {mnemonic, TokenLine, 'POP'}}.
|
||||||
|
MLOAD : {token, {mnemonic, TokenLine, 'MLOAD'}}.
|
||||||
|
MSTORE : {token, {mnemonic, TokenLine, 'MSTORE'}}.
|
||||||
|
MSTORE8 : {token, {mnemonic, TokenLine, 'MSTORE8'}}.
|
||||||
|
SLOAD : {token, {mnemonic, TokenLine, 'SLOAD'}}.
|
||||||
|
SSTORE : {token, {mnemonic, TokenLine, 'SSTORE'}}.
|
||||||
|
JUMP : {token, {mnemonic, TokenLine, 'JUMP'}}.
|
||||||
|
JUMPI : {token, {mnemonic, TokenLine, 'JUMPI'}}.
|
||||||
|
PC : {token, {mnemonic, TokenLine, 'PC'}}.
|
||||||
|
MSIZE : {token, {mnemonic, TokenLine, 'MSIZE'}}.
|
||||||
|
GAS : {token, {mnemonic, TokenLine, 'GAS'}}.
|
||||||
|
JUMPDEST : {token, {mnemonic, TokenLine, 'JUMPDEST'}}.
|
||||||
|
PUSH1 : {token, {mnemonic, TokenLine, 'PUSH1'}}.
|
||||||
|
PUSH2 : {token, {mnemonic, TokenLine, 'PUSH2'}}.
|
||||||
|
PUSH3 : {token, {mnemonic, TokenLine, 'PUSH3'}}.
|
||||||
|
PUSH4 : {token, {mnemonic, TokenLine, 'PUSH4'}}.
|
||||||
|
PUSH5 : {token, {mnemonic, TokenLine, 'PUSH5'}}.
|
||||||
|
PUSH6 : {token, {mnemonic, TokenLine, 'PUSH6'}}.
|
||||||
|
PUSH7 : {token, {mnemonic, TokenLine, 'PUSH7'}}.
|
||||||
|
PUSH8 : {token, {mnemonic, TokenLine, 'PUSH8'}}.
|
||||||
|
PUSH9 : {token, {mnemonic, TokenLine, 'PUSH9'}}.
|
||||||
|
PUSH10 : {token, {mnemonic, TokenLine, 'PUSH10'}}.
|
||||||
|
PUSH11 : {token, {mnemonic, TokenLine, 'PUSH11'}}.
|
||||||
|
PUSH12 : {token, {mnemonic, TokenLine, 'PUSH12'}}.
|
||||||
|
PUSH13 : {token, {mnemonic, TokenLine, 'PUSH13'}}.
|
||||||
|
PUSH14 : {token, {mnemonic, TokenLine, 'PUSH14'}}.
|
||||||
|
PUSH15 : {token, {mnemonic, TokenLine, 'PUSH15'}}.
|
||||||
|
PUSH16 : {token, {mnemonic, TokenLine, 'PUSH16'}}.
|
||||||
|
PUSH17 : {token, {mnemonic, TokenLine, 'PUSH17'}}.
|
||||||
|
PUSH18 : {token, {mnemonic, TokenLine, 'PUSH18'}}.
|
||||||
|
PUSH19 : {token, {mnemonic, TokenLine, 'PUSH19'}}.
|
||||||
|
PUSH20 : {token, {mnemonic, TokenLine, 'PUSH20'}}.
|
||||||
|
PUSH21 : {token, {mnemonic, TokenLine, 'PUSH21'}}.
|
||||||
|
PUSH22 : {token, {mnemonic, TokenLine, 'PUSH22'}}.
|
||||||
|
PUSH23 : {token, {mnemonic, TokenLine, 'PUSH23'}}.
|
||||||
|
PUSH24 : {token, {mnemonic, TokenLine, 'PUSH24'}}.
|
||||||
|
PUSH25 : {token, {mnemonic, TokenLine, 'PUSH25'}}.
|
||||||
|
PUSH26 : {token, {mnemonic, TokenLine, 'PUSH26'}}.
|
||||||
|
PUSH27 : {token, {mnemonic, TokenLine, 'PUSH27'}}.
|
||||||
|
PUSH28 : {token, {mnemonic, TokenLine, 'PUSH28'}}.
|
||||||
|
PUSH29 : {token, {mnemonic, TokenLine, 'PUSH29'}}.
|
||||||
|
PUSH30 : {token, {mnemonic, TokenLine, 'PUSH30'}}.
|
||||||
|
PUSH31 : {token, {mnemonic, TokenLine, 'PUSH31'}}.
|
||||||
|
PUSH32 : {token, {mnemonic, TokenLine, 'PUSH32'}}.
|
||||||
|
DUP1 : {token, {mnemonic, TokenLine, 'DUP1'}}.
|
||||||
|
DUP2 : {token, {mnemonic, TokenLine, 'DUP2'}}.
|
||||||
|
DUP3 : {token, {mnemonic, TokenLine, 'DUP3'}}.
|
||||||
|
DUP4 : {token, {mnemonic, TokenLine, 'DUP4'}}.
|
||||||
|
DUP5 : {token, {mnemonic, TokenLine, 'DUP5'}}.
|
||||||
|
DUP6 : {token, {mnemonic, TokenLine, 'DUP6'}}.
|
||||||
|
DUP7 : {token, {mnemonic, TokenLine, 'DUP7'}}.
|
||||||
|
DUP8 : {token, {mnemonic, TokenLine, 'DUP8'}}.
|
||||||
|
DUP9 : {token, {mnemonic, TokenLine, 'DUP9'}}.
|
||||||
|
DUP10 : {token, {mnemonic, TokenLine, 'DUP10'}}.
|
||||||
|
DUP11 : {token, {mnemonic, TokenLine, 'DUP11'}}.
|
||||||
|
DUP12 : {token, {mnemonic, TokenLine, 'DUP12'}}.
|
||||||
|
DUP13 : {token, {mnemonic, TokenLine, 'DUP13'}}.
|
||||||
|
DUP14 : {token, {mnemonic, TokenLine, 'DUP14'}}.
|
||||||
|
DUP15 : {token, {mnemonic, TokenLine, 'DUP15'}}.
|
||||||
|
DUP16 : {token, {mnemonic, TokenLine, 'DUP16'}}.
|
||||||
|
SWAP1 : {token, {mnemonic, TokenLine, 'SWAP1'}}.
|
||||||
|
SWAP2 : {token, {mnemonic, TokenLine, 'SWAP2'}}.
|
||||||
|
SWAP3 : {token, {mnemonic, TokenLine, 'SWAP3'}}.
|
||||||
|
SWAP4 : {token, {mnemonic, TokenLine, 'SWAP4'}}.
|
||||||
|
SWAP5 : {token, {mnemonic, TokenLine, 'SWAP5'}}.
|
||||||
|
SWAP6 : {token, {mnemonic, TokenLine, 'SWAP6'}}.
|
||||||
|
SWAP7 : {token, {mnemonic, TokenLine, 'SWAP7'}}.
|
||||||
|
SWAP8 : {token, {mnemonic, TokenLine, 'SWAP8'}}.
|
||||||
|
SWAP9 : {token, {mnemonic, TokenLine, 'SWAP9'}}.
|
||||||
|
SWAP10 : {token, {mnemonic, TokenLine, 'SWAP10'}}.
|
||||||
|
SWAP11 : {token, {mnemonic, TokenLine, 'SWAP11'}}.
|
||||||
|
SWAP12 : {token, {mnemonic, TokenLine, 'SWAP12'}}.
|
||||||
|
SWAP13 : {token, {mnemonic, TokenLine, 'SWAP13'}}.
|
||||||
|
SWAP14 : {token, {mnemonic, TokenLine, 'SWAP14'}}.
|
||||||
|
SWAP15 : {token, {mnemonic, TokenLine, 'SWAP15'}}.
|
||||||
|
SWAP16 : {token, {mnemonic, TokenLine, 'SWAP16'}}.
|
||||||
|
LOG0 : {token, {mnemonic, TokenLine, 'LOG0'}}.
|
||||||
|
LOG1 : {token, {mnemonic, TokenLine, 'LOG1'}}.
|
||||||
|
LOG2 : {token, {mnemonic, TokenLine, 'LOG2'}}.
|
||||||
|
LOG3 : {token, {mnemonic, TokenLine, 'LOG3'}}.
|
||||||
|
LOG4 : {token, {mnemonic, TokenLine, 'LOG4'}}.
|
||||||
|
CREATE : {token, {mnemonic, TokenLine, 'CREATE'}}.
|
||||||
|
CALL : {token, {mnemonic, TokenLine, 'CALL'}}.
|
||||||
|
CALLCODE : {token, {mnemonic, TokenLine, 'CALLCODE'}}.
|
||||||
|
RETURN : {token, {mnemonic, TokenLine, 'RETURN'}}.
|
||||||
|
DELEGATECALL : {token, {mnemonic, TokenLine, 'DELEGATECALL'}}.
|
||||||
|
STATICCALL : {token, {mnemonic, TokenLine, 'STATICCALL'}}.
|
||||||
|
REVERT : {token, {mnemonic, TokenLine, 'REVERT'}}.
|
||||||
|
INVALID : {token, {mnemonic, TokenLine, 'INVALID'}}.
|
||||||
|
SUICIDE : {token, {mnemonic, TokenLine, 'SUICIDE'}}.
|
||||||
|
COMMENT : {token, {mnemonic, TokenLine, 'COMMENT'}}.
|
||||||
|
{ID} :
|
||||||
|
{token, {id, TokenLine, TokenChars}}.
|
||||||
|
{HEX} :
|
||||||
|
{token, {int, TokenLine, parse_hex(TokenChars)}}.
|
||||||
|
{INT} :
|
||||||
|
{token, {int, TokenLine, parse_int(TokenChars)}}.
|
||||||
|
{HASH} :
|
||||||
|
{token, {hash, TokenLine, parse_hash(TokenChars)}}.
|
||||||
|
|
||||||
|
|
||||||
|
%% Symbols
|
||||||
|
, : {token, {',', TokenLine}}.
|
||||||
|
\. : {token, {'.', TokenLine}}.
|
||||||
|
\( : {token, {'(', TokenLine}}.
|
||||||
|
\) : {token, {')', TokenLine}}.
|
||||||
|
\[ : {token, {'[', TokenLine}}.
|
||||||
|
\] : {token, {']', TokenLine}}.
|
||||||
|
{ : {token, {'{', TokenLine}}.
|
||||||
|
} : {token, {'}', TokenLine}}.
|
||||||
|
|
||||||
|
|
||||||
|
%% Whitespace ignore
|
||||||
|
{WS} : skip_token.
|
||||||
|
|
||||||
|
%% Comments (TODO: nested comments)
|
||||||
|
;;.* : skip_token.
|
||||||
|
|
||||||
|
. : {error, "Unexpected token: " ++ TokenChars}.
|
||||||
|
|
||||||
|
Erlang code.
|
||||||
|
|
||||||
|
-export([scan/1]).
|
||||||
|
|
||||||
|
-dialyzer({nowarn_function, yyrev/2}).
|
||||||
|
|
||||||
|
-ignore_xref([format_error/1, string/2, token/2, token/3, tokens/2, tokens/3]).
|
||||||
|
|
||||||
|
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
||||||
|
|
||||||
|
|
||||||
|
parse_hex("0x" ++ Chars) -> list_to_integer(Chars, 16).
|
||||||
|
|
||||||
|
parse_int(Chars) -> list_to_integer(Chars).
|
||||||
|
|
||||||
|
parse_hash("#" ++ Chars) ->
|
||||||
|
N = list_to_integer(Chars, 16),
|
||||||
|
<<N:256>>.
|
||||||
|
|
||||||
|
scan(S) ->
|
||||||
|
string(S).
|
||||||
|
|
102
src/aeb_disassemble.erl
Normal file
102
src/aeb_disassemble.erl
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
|
%%% @doc
|
||||||
|
%%% Prettyprint aevm machine code
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 2 Oct 2017
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(aeb_disassemble).
|
||||||
|
|
||||||
|
-export([ pp/1,
|
||||||
|
format/2,
|
||||||
|
format_address/1
|
||||||
|
]).
|
||||||
|
|
||||||
|
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
||||||
|
|
||||||
|
|
||||||
|
pp(Binary) ->
|
||||||
|
Listing = format(Binary, fun io:format/2),
|
||||||
|
io:format("~s~n", [Listing]).
|
||||||
|
|
||||||
|
format(Binary, ErrFormatFun) ->
|
||||||
|
pp(0, binary:bin_to_list(Binary), [], ErrFormatFun).
|
||||||
|
|
||||||
|
pp(Address, [Op|Ops], Assembly, ErrFormatFun) ->
|
||||||
|
case Op of
|
||||||
|
X when (X >= ?STOP) andalso (X =< ?SIGNEXTEND) ->
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||||
|
X when (X >= ?LT) andalso (X =< ?BYTE) ->
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||||
|
X when (X >= ?SHA3) andalso (X =< ?SHA3) ->
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||||
|
X when (X >= ?ADDRESS) andalso (X =< ?EXTCODECOPY) ->
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||||
|
X when (X >= ?BLOCKHASH) andalso (X =< ?GASLIMIT) ->
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||||
|
X when (X >= ?POP) andalso (X =< ?JUMPDEST) ->
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||||
|
X when (X >= ?PUSH1) andalso (X =< ?PUSH32) ->
|
||||||
|
Bytes = X-?PUSH1+1,
|
||||||
|
{ArgList, NextOps} = lists:split(Bytes, Ops),
|
||||||
|
Arg = arglist_to_arg(ArgList),
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), [{Arg,8*Bytes}]),
|
||||||
|
next(Address+Bytes, NextOps, Instr, Assembly, ErrFormatFun);
|
||||||
|
X when (X >= ?DUP1) andalso (X =< ?LOG4) ->
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||||
|
X when (X >= ?CREATE) andalso (X =< ?DELEGATECALL) ->
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||||
|
X when (X >= ?INVALID) andalso (X =< ?SUICIDE) ->
|
||||||
|
Instr = pp_instruction(Address, aeb_opcodes:mnemonic(Op), []),
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun);
|
||||||
|
_ ->
|
||||||
|
ErrFormatFun("unhandled op ~p at ~p",[Op, Address]),
|
||||||
|
next(Address, Ops, "", Assembly, ErrFormatFun)
|
||||||
|
end;
|
||||||
|
pp(_, [], Assembly, _) -> lists:reverse(Assembly).
|
||||||
|
|
||||||
|
|
||||||
|
arglist_to_arg([B|Bs]) ->
|
||||||
|
arglist_to_arg(Bs, B).
|
||||||
|
|
||||||
|
arglist_to_arg([B|Bs], Acc) ->
|
||||||
|
arglist_to_arg(Bs, Acc*256 + B);
|
||||||
|
arglist_to_arg([], Acc) -> Acc.
|
||||||
|
|
||||||
|
pp_instruction(Address, Op, Args) ->
|
||||||
|
[format_address(Address), " ",
|
||||||
|
pad_op(atom_to_list(Op)),
|
||||||
|
pp_args(Args),
|
||||||
|
"\n"].
|
||||||
|
|
||||||
|
format_address(Address) ->
|
||||||
|
io_lib:format("0x~8.16.0B",[Address]).
|
||||||
|
|
||||||
|
pad_op(Op) ->
|
||||||
|
N = length(Op),
|
||||||
|
Pad = 17 - N,
|
||||||
|
[Op,lists:duplicate(Pad, 32)].
|
||||||
|
|
||||||
|
pp_args([]) -> [];
|
||||||
|
pp_args([{Arg, Size}]) ->
|
||||||
|
case Size of
|
||||||
|
8 -> io_lib:format("0x~2.16.0B",[Arg]);
|
||||||
|
160 -> io_lib:format("0x~64.16.0B",[Arg]);
|
||||||
|
232 -> io_lib:format("0x~64.16.0B",[Arg]);
|
||||||
|
256 -> io_lib:format("0x~64.16.0B",[Arg]);
|
||||||
|
_ -> io_lib:format("0x~64.16.0B",[Arg])
|
||||||
|
end;
|
||||||
|
pp_args([{Arg, Size}|Args]) ->
|
||||||
|
[pp_args([{Arg, Size}]), " ", pp_args(Args)].
|
||||||
|
|
||||||
|
next(Address, Ops, Instr, Assembly, ErrFormatFun) ->
|
||||||
|
pp(Address+1, Ops, [Instr|Assembly], ErrFormatFun).
|
448
src/aeb_opcodes.erl
Normal file
448
src/aeb_opcodes.erl
Normal file
@ -0,0 +1,448 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2017, Aeternity Anstalt
|
||||||
|
%%% @doc
|
||||||
|
%%% Opcodes
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 2 Oct 2017
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(aeb_opcodes).
|
||||||
|
|
||||||
|
-export([ dup/1
|
||||||
|
, mnemonic/1
|
||||||
|
, m_to_op/1
|
||||||
|
, opcode/1
|
||||||
|
, op_size/1
|
||||||
|
, push/1
|
||||||
|
, swap/1
|
||||||
|
]).
|
||||||
|
|
||||||
|
-include_lib("aebytecode/include/aeb_opcodes.hrl").
|
||||||
|
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% API
|
||||||
|
%%====================================================================
|
||||||
|
|
||||||
|
opcode(?STOP) -> ?STOP;
|
||||||
|
opcode(?ADD) -> ?ADD;
|
||||||
|
opcode(?MUL) -> ?MUL;
|
||||||
|
opcode(?SUB) -> ?SUB;
|
||||||
|
opcode(?DIV) -> ?DIV;
|
||||||
|
opcode(?SDIV) -> ?SDIV;
|
||||||
|
opcode(?MOD) -> ?MOD;
|
||||||
|
opcode(?SMOD) -> ?SMOD;
|
||||||
|
opcode(?ADDMOD) -> ?ADDMOD;
|
||||||
|
opcode(?MULMOD) -> ?MULMOD;
|
||||||
|
opcode(?EXP) -> ?EXP;
|
||||||
|
opcode(?SIGNEXTEND) -> ?SIGNEXTEND;
|
||||||
|
opcode(?LT) -> ?LT;
|
||||||
|
opcode(?GT) -> ?GT;
|
||||||
|
opcode(?SLT) -> ?SLT;
|
||||||
|
opcode(?SGT) -> ?SGT;
|
||||||
|
opcode(?EQ) -> ?EQ;
|
||||||
|
opcode(?ISZERO) -> ?ISZERO;
|
||||||
|
opcode(?AND) -> ?AND;
|
||||||
|
opcode(?OR) -> ?OR;
|
||||||
|
opcode(?XOR) -> ?XOR;
|
||||||
|
opcode(?NOT) -> ?NOT;
|
||||||
|
opcode(?BYTE) -> ?BYTE;
|
||||||
|
opcode(?SHA3) -> ?SHA3;
|
||||||
|
opcode(?ADDRESS) -> ?ADDRESS;
|
||||||
|
opcode(?BALANCE) -> ?BALANCE;
|
||||||
|
opcode(?ORIGIN) -> ?ORIGIN;
|
||||||
|
opcode(?CALLER) -> ?CALLER;
|
||||||
|
opcode(?CALLVALUE) -> ?CALLVALUE;
|
||||||
|
opcode(?CALLDATALOAD) -> ?CALLDATALOAD;
|
||||||
|
opcode(?CALLDATASIZE) -> ?CALLDATASIZE;
|
||||||
|
opcode(?CALLDATACOPY) -> ?CALLDATACOPY;
|
||||||
|
opcode(?CODESIZE) -> ?CODESIZE;
|
||||||
|
opcode(?CODECOPY) -> ?CODECOPY;
|
||||||
|
opcode(?GASPRICE) -> ?GASPRICE;
|
||||||
|
opcode(?EXTCODESIZE) -> ?EXTCODESIZE;
|
||||||
|
opcode(?EXTCODECOPY) -> ?EXTCODECOPY;
|
||||||
|
opcode(?RETURNDATASIZE) -> ?RETURNDATASIZE; %% TODO
|
||||||
|
opcode(?RETURNDATACOPY) -> ?RETURNDATACOPY; %% TODO
|
||||||
|
opcode(?BLOCKHASH) -> ?BLOCKHASH;
|
||||||
|
opcode(?COINBASE) -> ?COINBASE;
|
||||||
|
opcode(?TIMESTAMP) -> ?TIMESTAMP;
|
||||||
|
opcode(?NUMBER) -> ?NUMBER;
|
||||||
|
opcode(?DIFFICULTY) -> ?DIFFICULTY;
|
||||||
|
opcode(?GASLIMIT) -> ?GASLIMIT;
|
||||||
|
opcode(?POP) -> ?POP;
|
||||||
|
opcode(?MLOAD) -> ?MLOAD;
|
||||||
|
opcode(?MSTORE) -> ?MSTORE;
|
||||||
|
opcode(?MSTORE8) -> ?MSTORE8;
|
||||||
|
opcode(?SLOAD) -> ?SLOAD;
|
||||||
|
opcode(?SSTORE) -> ?SSTORE;
|
||||||
|
opcode(?JUMP) -> ?JUMP;
|
||||||
|
opcode(?JUMPI) -> ?JUMPI;
|
||||||
|
opcode(?PC) -> ?PC;
|
||||||
|
opcode(?MSIZE) -> ?MSIZE;
|
||||||
|
opcode(?GAS) -> ?GAS;
|
||||||
|
opcode(?JUMPDEST) -> ?JUMPDEST;
|
||||||
|
opcode(?PUSH1) -> ?PUSH1;
|
||||||
|
opcode(?PUSH2) -> ?PUSH2;
|
||||||
|
opcode(?PUSH3) -> ?PUSH3;
|
||||||
|
opcode(?PUSH4) -> ?PUSH4;
|
||||||
|
opcode(?PUSH5) -> ?PUSH5;
|
||||||
|
opcode(?PUSH6) -> ?PUSH6;
|
||||||
|
opcode(?PUSH7) -> ?PUSH7;
|
||||||
|
opcode(?PUSH8) -> ?PUSH8;
|
||||||
|
opcode(?PUSH9) -> ?PUSH9;
|
||||||
|
opcode(?PUSH10) -> ?PUSH10;
|
||||||
|
opcode(?PUSH11) -> ?PUSH11;
|
||||||
|
opcode(?PUSH12) -> ?PUSH12;
|
||||||
|
opcode(?PUSH13) -> ?PUSH13;
|
||||||
|
opcode(?PUSH14) -> ?PUSH14;
|
||||||
|
opcode(?PUSH15) -> ?PUSH15;
|
||||||
|
opcode(?PUSH16) -> ?PUSH16;
|
||||||
|
opcode(?PUSH17) -> ?PUSH17;
|
||||||
|
opcode(?PUSH18) -> ?PUSH18;
|
||||||
|
opcode(?PUSH19) -> ?PUSH19;
|
||||||
|
opcode(?PUSH20) -> ?PUSH20;
|
||||||
|
opcode(?PUSH21) -> ?PUSH21;
|
||||||
|
opcode(?PUSH22) -> ?PUSH22;
|
||||||
|
opcode(?PUSH23) -> ?PUSH23;
|
||||||
|
opcode(?PUSH24) -> ?PUSH24;
|
||||||
|
opcode(?PUSH25) -> ?PUSH25;
|
||||||
|
opcode(?PUSH26) -> ?PUSH26;
|
||||||
|
opcode(?PUSH27) -> ?PUSH27;
|
||||||
|
opcode(?PUSH28) -> ?PUSH28;
|
||||||
|
opcode(?PUSH29) -> ?PUSH29;
|
||||||
|
opcode(?PUSH30) -> ?PUSH30;
|
||||||
|
opcode(?PUSH31) -> ?PUSH31;
|
||||||
|
opcode(?PUSH32) -> ?PUSH32;
|
||||||
|
opcode(?DUP1) -> ?DUP1;
|
||||||
|
opcode(?DUP2) -> ?DUP2;
|
||||||
|
opcode(?DUP3) -> ?DUP3;
|
||||||
|
opcode(?DUP4) -> ?DUP4;
|
||||||
|
opcode(?DUP5) -> ?DUP5;
|
||||||
|
opcode(?DUP6) -> ?DUP6;
|
||||||
|
opcode(?DUP7) -> ?DUP7;
|
||||||
|
opcode(?DUP8) -> ?DUP8;
|
||||||
|
opcode(?DUP9) -> ?DUP9;
|
||||||
|
opcode(?DUP10) -> ?DUP10;
|
||||||
|
opcode(?DUP11) -> ?DUP11;
|
||||||
|
opcode(?DUP12) -> ?DUP12;
|
||||||
|
opcode(?DUP13) -> ?DUP13;
|
||||||
|
opcode(?DUP14) -> ?DUP14;
|
||||||
|
opcode(?DUP15) -> ?DUP15;
|
||||||
|
opcode(?DUP16) -> ?DUP16;
|
||||||
|
opcode(?SWAP1) -> ?SWAP1;
|
||||||
|
opcode(?SWAP2) -> ?SWAP2;
|
||||||
|
opcode(?SWAP3) -> ?SWAP3;
|
||||||
|
opcode(?SWAP4) -> ?SWAP4;
|
||||||
|
opcode(?SWAP5) -> ?SWAP5;
|
||||||
|
opcode(?SWAP6) -> ?SWAP6;
|
||||||
|
opcode(?SWAP7) -> ?SWAP7;
|
||||||
|
opcode(?SWAP8) -> ?SWAP8;
|
||||||
|
opcode(?SWAP9) -> ?SWAP9;
|
||||||
|
opcode(?SWAP10) -> ?SWAP10;
|
||||||
|
opcode(?SWAP11) -> ?SWAP11;
|
||||||
|
opcode(?SWAP12) -> ?SWAP12;
|
||||||
|
opcode(?SWAP13) -> ?SWAP13;
|
||||||
|
opcode(?SWAP14) -> ?SWAP14;
|
||||||
|
opcode(?SWAP15) -> ?SWAP15;
|
||||||
|
opcode(?SWAP16) -> ?SWAP16;
|
||||||
|
opcode(?LOG0) -> ?LOG0;
|
||||||
|
opcode(?LOG1) -> ?LOG1;
|
||||||
|
opcode(?LOG2) -> ?LOG2;
|
||||||
|
opcode(?LOG3) -> ?LOG3;
|
||||||
|
opcode(?LOG4) -> ?LOG4;
|
||||||
|
opcode(?CREATE) -> ?CREATE;
|
||||||
|
opcode(?CALL) -> ?CALL;
|
||||||
|
opcode(?CALLCODE) -> ?CALLCODE;
|
||||||
|
opcode(?RETURN) -> ?RETURN;
|
||||||
|
opcode(?DELEGATECALL) -> ?DELEGATECALL;
|
||||||
|
opcode(?STATICCALL) -> ?STATICCALL; %% TODO
|
||||||
|
opcode(?REVERT) -> ?REVERT;
|
||||||
|
opcode({comment,X}) -> ?COMMENT(X);
|
||||||
|
opcode(?SUICIDE) -> ?SUICIDE.
|
||||||
|
|
||||||
|
|
||||||
|
mnemonic(?STOP) -> 'STOP' ;
|
||||||
|
mnemonic(?ADD) -> 'ADD' ;
|
||||||
|
mnemonic(?MUL) -> 'MUL' ;
|
||||||
|
mnemonic(?SUB) -> 'SUB' ;
|
||||||
|
mnemonic(?DIV) -> 'DIV' ;
|
||||||
|
mnemonic(?SDIV) -> 'SDIV' ;
|
||||||
|
mnemonic(?MOD) -> 'MOD' ;
|
||||||
|
mnemonic(?SMOD) -> 'SMOD' ;
|
||||||
|
mnemonic(?ADDMOD) -> 'ADDMOD' ;
|
||||||
|
mnemonic(?MULMOD) -> 'MULMOD' ;
|
||||||
|
mnemonic(?EXP) -> 'EXP' ;
|
||||||
|
mnemonic(?SIGNEXTEND) -> 'SIGNEXTEND' ;
|
||||||
|
mnemonic(?LT) -> 'LT' ;
|
||||||
|
mnemonic(?GT) -> 'GT' ;
|
||||||
|
mnemonic(?SLT) -> 'SLT' ;
|
||||||
|
mnemonic(?SGT) -> 'SGT' ;
|
||||||
|
mnemonic(?EQ) -> 'EQ' ;
|
||||||
|
mnemonic(?ISZERO) -> 'ISZERO' ;
|
||||||
|
mnemonic(?AND) -> 'AND' ;
|
||||||
|
mnemonic(?OR) -> 'OR' ;
|
||||||
|
mnemonic(?XOR) -> 'XOR' ;
|
||||||
|
mnemonic(?NOT) -> 'NOT' ;
|
||||||
|
mnemonic(?BYTE) -> 'BYTE' ;
|
||||||
|
mnemonic(?SHA3) -> 'SHA3' ;
|
||||||
|
mnemonic(?ADDRESS) -> 'ADDRESS' ;
|
||||||
|
mnemonic(?BALANCE) -> 'BALANCE' ;
|
||||||
|
mnemonic(?ORIGIN) -> 'ORIGIN' ;
|
||||||
|
mnemonic(?CALLER) -> 'CALLER' ;
|
||||||
|
mnemonic(?CALLVALUE) -> 'CALLVALUE' ;
|
||||||
|
mnemonic(?CALLDATALOAD) -> 'CALLDATALOAD' ;
|
||||||
|
mnemonic(?CALLDATASIZE) -> 'CALLDATASIZE' ;
|
||||||
|
mnemonic(?CALLDATACOPY) -> 'CALLDATACOPY' ;
|
||||||
|
mnemonic(?CODESIZE) -> 'CODESIZE' ;
|
||||||
|
mnemonic(?CODECOPY) -> 'CODECOPY' ;
|
||||||
|
mnemonic(?GASPRICE) -> 'GASPRICE' ;
|
||||||
|
mnemonic(?EXTCODESIZE) -> 'EXTCODESIZE' ;
|
||||||
|
mnemonic(?EXTCODECOPY) -> 'EXTCODECOPY' ;
|
||||||
|
mnemonic(?RETURNDATASIZE) -> 'RETURNDATASIZE' ;
|
||||||
|
mnemonic(?RETURNDATACOPY) -> 'RETURNDATACOPY' ;
|
||||||
|
mnemonic(?BLOCKHASH) -> 'BLOCKHASH' ;
|
||||||
|
mnemonic(?COINBASE) -> 'COINBASE' ;
|
||||||
|
mnemonic(?TIMESTAMP) -> 'TIMESTAMP' ;
|
||||||
|
mnemonic(?NUMBER) -> 'NUMBER' ;
|
||||||
|
mnemonic(?DIFFICULTY) -> 'DIFFICULTY' ;
|
||||||
|
mnemonic(?GASLIMIT) -> 'GASLIMIT' ;
|
||||||
|
mnemonic(?POP) -> 'POP' ;
|
||||||
|
mnemonic(?MLOAD) -> 'MLOAD' ;
|
||||||
|
mnemonic(?MSTORE) -> 'MSTORE' ;
|
||||||
|
mnemonic(?MSTORE8) -> 'MSTORE8' ;
|
||||||
|
mnemonic(?SLOAD) -> 'SLOAD' ;
|
||||||
|
mnemonic(?SSTORE) -> 'SSTORE' ;
|
||||||
|
mnemonic(?JUMP) -> 'JUMP' ;
|
||||||
|
mnemonic(?JUMPI) -> 'JUMPI' ;
|
||||||
|
mnemonic(?PC) -> 'PC' ;
|
||||||
|
mnemonic(?MSIZE) -> 'MSIZE' ;
|
||||||
|
mnemonic(?GAS) -> 'GAS' ;
|
||||||
|
mnemonic(?JUMPDEST) -> 'JUMPDEST' ;
|
||||||
|
mnemonic(?PUSH1) -> 'PUSH1' ;
|
||||||
|
mnemonic(?PUSH2) -> 'PUSH2' ;
|
||||||
|
mnemonic(?PUSH3) -> 'PUSH3' ;
|
||||||
|
mnemonic(?PUSH4) -> 'PUSH4' ;
|
||||||
|
mnemonic(?PUSH5) -> 'PUSH5' ;
|
||||||
|
mnemonic(?PUSH6) -> 'PUSH6' ;
|
||||||
|
mnemonic(?PUSH7) -> 'PUSH7' ;
|
||||||
|
mnemonic(?PUSH8) -> 'PUSH8' ;
|
||||||
|
mnemonic(?PUSH9) -> 'PUSH9' ;
|
||||||
|
mnemonic(?PUSH10) -> 'PUSH10' ;
|
||||||
|
mnemonic(?PUSH11) -> 'PUSH11' ;
|
||||||
|
mnemonic(?PUSH12) -> 'PUSH12' ;
|
||||||
|
mnemonic(?PUSH13) -> 'PUSH13' ;
|
||||||
|
mnemonic(?PUSH14) -> 'PUSH14' ;
|
||||||
|
mnemonic(?PUSH15) -> 'PUSH15' ;
|
||||||
|
mnemonic(?PUSH16) -> 'PUSH16' ;
|
||||||
|
mnemonic(?PUSH17) -> 'PUSH17' ;
|
||||||
|
mnemonic(?PUSH18) -> 'PUSH18' ;
|
||||||
|
mnemonic(?PUSH19) -> 'PUSH19' ;
|
||||||
|
mnemonic(?PUSH20) -> 'PUSH20' ;
|
||||||
|
mnemonic(?PUSH21) -> 'PUSH21' ;
|
||||||
|
mnemonic(?PUSH22) -> 'PUSH22' ;
|
||||||
|
mnemonic(?PUSH23) -> 'PUSH23' ;
|
||||||
|
mnemonic(?PUSH24) -> 'PUSH24' ;
|
||||||
|
mnemonic(?PUSH25) -> 'PUSH25' ;
|
||||||
|
mnemonic(?PUSH26) -> 'PUSH26' ;
|
||||||
|
mnemonic(?PUSH27) -> 'PUSH27' ;
|
||||||
|
mnemonic(?PUSH28) -> 'PUSH28' ;
|
||||||
|
mnemonic(?PUSH29) -> 'PUSH29' ;
|
||||||
|
mnemonic(?PUSH30) -> 'PUSH30' ;
|
||||||
|
mnemonic(?PUSH31) -> 'PUSH31' ;
|
||||||
|
mnemonic(?PUSH32) -> 'PUSH32' ;
|
||||||
|
mnemonic(?DUP1) -> 'DUP1' ;
|
||||||
|
mnemonic(?DUP2) -> 'DUP2' ;
|
||||||
|
mnemonic(?DUP3) -> 'DUP3' ;
|
||||||
|
mnemonic(?DUP4) -> 'DUP4' ;
|
||||||
|
mnemonic(?DUP5) -> 'DUP5' ;
|
||||||
|
mnemonic(?DUP6) -> 'DUP6' ;
|
||||||
|
mnemonic(?DUP7) -> 'DUP7' ;
|
||||||
|
mnemonic(?DUP8) -> 'DUP8' ;
|
||||||
|
mnemonic(?DUP9) -> 'DUP9' ;
|
||||||
|
mnemonic(?DUP10) -> 'DUP10' ;
|
||||||
|
mnemonic(?DUP11) -> 'DUP11' ;
|
||||||
|
mnemonic(?DUP12) -> 'DUP12' ;
|
||||||
|
mnemonic(?DUP13) -> 'DUP13' ;
|
||||||
|
mnemonic(?DUP14) -> 'DUP14' ;
|
||||||
|
mnemonic(?DUP15) -> 'DUP15' ;
|
||||||
|
mnemonic(?DUP16) -> 'DUP16' ;
|
||||||
|
mnemonic(?SWAP1) -> 'SWAP1' ;
|
||||||
|
mnemonic(?SWAP2) -> 'SWAP2' ;
|
||||||
|
mnemonic(?SWAP3) -> 'SWAP3' ;
|
||||||
|
mnemonic(?SWAP4) -> 'SWAP4' ;
|
||||||
|
mnemonic(?SWAP5) -> 'SWAP5' ;
|
||||||
|
mnemonic(?SWAP6) -> 'SWAP6' ;
|
||||||
|
mnemonic(?SWAP7) -> 'SWAP7' ;
|
||||||
|
mnemonic(?SWAP8) -> 'SWAP8' ;
|
||||||
|
mnemonic(?SWAP9) -> 'SWAP9' ;
|
||||||
|
mnemonic(?SWAP10) -> 'SWAP10' ;
|
||||||
|
mnemonic(?SWAP11) -> 'SWAP11' ;
|
||||||
|
mnemonic(?SWAP12) -> 'SWAP12' ;
|
||||||
|
mnemonic(?SWAP13) -> 'SWAP13' ;
|
||||||
|
mnemonic(?SWAP14) -> 'SWAP14' ;
|
||||||
|
mnemonic(?SWAP15) -> 'SWAP15' ;
|
||||||
|
mnemonic(?SWAP16) -> 'SWAP16' ;
|
||||||
|
mnemonic(?LOG0) -> 'LOG0' ;
|
||||||
|
mnemonic(?LOG1) -> 'LOG1' ;
|
||||||
|
mnemonic(?LOG2) -> 'LOG2' ;
|
||||||
|
mnemonic(?LOG3) -> 'LOG3' ;
|
||||||
|
mnemonic(?LOG4) -> 'LOG4' ;
|
||||||
|
mnemonic(?CREATE) -> 'CREATE' ;
|
||||||
|
mnemonic(?CALL) -> 'CALL' ;
|
||||||
|
mnemonic(?CALLCODE) -> 'CALLCODE' ;
|
||||||
|
mnemonic(?RETURN) -> 'RETURN' ;
|
||||||
|
mnemonic(?DELEGATECALL) -> 'DELEGATECALL' ;
|
||||||
|
mnemonic(?STATICCALL) -> 'STATICCALL' ;
|
||||||
|
mnemonic(?REVERT) -> 'REVERT' ;
|
||||||
|
mnemonic({comment,_}) -> 'COMMENT' ;
|
||||||
|
mnemonic(?SUICIDE) -> 'SUICIDE' .
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
m_to_op('STOP') -> ?STOP ;
|
||||||
|
m_to_op('ADD') -> ?ADD ;
|
||||||
|
m_to_op('MUL') -> ?MUL ;
|
||||||
|
m_to_op('SUB') -> ?SUB ;
|
||||||
|
m_to_op('DIV') -> ?DIV ;
|
||||||
|
m_to_op('SDIV') -> ?SDIV ;
|
||||||
|
m_to_op('MOD') -> ?MOD ;
|
||||||
|
m_to_op('SMOD') -> ?SMOD ;
|
||||||
|
m_to_op('ADDMOD') -> ?ADDMOD ;
|
||||||
|
m_to_op('MULMOD') -> ?MULMOD ;
|
||||||
|
m_to_op('EXP') -> ?EXP ;
|
||||||
|
m_to_op('SIGNEXTEND') -> ?SIGNEXTEND ;
|
||||||
|
m_to_op('LT') -> ?LT ;
|
||||||
|
m_to_op('GT') -> ?GT ;
|
||||||
|
m_to_op('SLT') -> ?SLT ;
|
||||||
|
m_to_op('SGT') -> ?SGT ;
|
||||||
|
m_to_op('EQ') -> ?EQ ;
|
||||||
|
m_to_op('ISZERO') -> ?ISZERO ;
|
||||||
|
m_to_op('AND') -> ?AND ;
|
||||||
|
m_to_op('OR') -> ?OR ;
|
||||||
|
m_to_op('XOR') -> ?XOR ;
|
||||||
|
m_to_op('NOT') -> ?NOT ;
|
||||||
|
m_to_op('BYTE') -> ?BYTE ;
|
||||||
|
m_to_op('SHA3') -> ?SHA3 ;
|
||||||
|
m_to_op('ADDRESS') -> ?ADDRESS ;
|
||||||
|
m_to_op('BALANCE') -> ?BALANCE ;
|
||||||
|
m_to_op('ORIGIN') -> ?ORIGIN ;
|
||||||
|
m_to_op('CALLER') -> ?CALLER ;
|
||||||
|
m_to_op('CALLVALUE') -> ?CALLVALUE ;
|
||||||
|
m_to_op('CALLDATALOAD') -> ?CALLDATALOAD ;
|
||||||
|
m_to_op('CALLDATASIZE') -> ?CALLDATASIZE ;
|
||||||
|
m_to_op('CALLDATACOPY') -> ?CALLDATACOPY ;
|
||||||
|
m_to_op('CODESIZE') -> ?CODESIZE ;
|
||||||
|
m_to_op('CODECOPY') -> ?CODECOPY ;
|
||||||
|
m_to_op('GASPRICE') -> ?GASPRICE ;
|
||||||
|
m_to_op('EXTCODESIZE') -> ?EXTCODESIZE ;
|
||||||
|
m_to_op('EXTCODECOPY') -> ?EXTCODECOPY ;
|
||||||
|
m_to_op('RETURNDATASIZE') -> ?RETURNDATASIZE ;
|
||||||
|
m_to_op('RETURNDATACOPY') -> ?RETURNDATACOPY ;
|
||||||
|
m_to_op('BLOCKHASH') -> ?BLOCKHASH ;
|
||||||
|
m_to_op('COINBASE') -> ?COINBASE ;
|
||||||
|
m_to_op('TIMESTAMP') -> ?TIMESTAMP ;
|
||||||
|
m_to_op('NUMBER') -> ?NUMBER ;
|
||||||
|
m_to_op('DIFFICULTY') -> ?DIFFICULTY ;
|
||||||
|
m_to_op('GASLIMIT') -> ?GASLIMIT ;
|
||||||
|
m_to_op('POP') -> ?POP ;
|
||||||
|
m_to_op('MLOAD') -> ?MLOAD ;
|
||||||
|
m_to_op('MSTORE') -> ?MSTORE ;
|
||||||
|
m_to_op('MSTORE8') -> ?MSTORE8 ;
|
||||||
|
m_to_op('SLOAD') -> ?SLOAD ;
|
||||||
|
m_to_op('SSTORE') -> ?SSTORE ;
|
||||||
|
m_to_op('JUMP') -> ?JUMP ;
|
||||||
|
m_to_op('JUMPI') -> ?JUMPI ;
|
||||||
|
m_to_op('PC') -> ?PC ;
|
||||||
|
m_to_op('MSIZE') -> ?MSIZE ;
|
||||||
|
m_to_op('GAS') -> ?GAS ;
|
||||||
|
m_to_op('JUMPDEST') -> ?JUMPDEST ;
|
||||||
|
m_to_op('PUSH1') -> ?PUSH1 ;
|
||||||
|
m_to_op('PUSH2') -> ?PUSH2 ;
|
||||||
|
m_to_op('PUSH3') -> ?PUSH3 ;
|
||||||
|
m_to_op('PUSH4') -> ?PUSH4 ;
|
||||||
|
m_to_op('PUSH5') -> ?PUSH5 ;
|
||||||
|
m_to_op('PUSH6') -> ?PUSH6 ;
|
||||||
|
m_to_op('PUSH7') -> ?PUSH7 ;
|
||||||
|
m_to_op('PUSH8') -> ?PUSH8 ;
|
||||||
|
m_to_op('PUSH9') -> ?PUSH9 ;
|
||||||
|
m_to_op('PUSH10') -> ?PUSH10 ;
|
||||||
|
m_to_op('PUSH11') -> ?PUSH11 ;
|
||||||
|
m_to_op('PUSH12') -> ?PUSH12 ;
|
||||||
|
m_to_op('PUSH13') -> ?PUSH13 ;
|
||||||
|
m_to_op('PUSH14') -> ?PUSH14 ;
|
||||||
|
m_to_op('PUSH15') -> ?PUSH15 ;
|
||||||
|
m_to_op('PUSH16') -> ?PUSH16 ;
|
||||||
|
m_to_op('PUSH17') -> ?PUSH17 ;
|
||||||
|
m_to_op('PUSH18') -> ?PUSH18 ;
|
||||||
|
m_to_op('PUSH19') -> ?PUSH19 ;
|
||||||
|
m_to_op('PUSH20') -> ?PUSH20 ;
|
||||||
|
m_to_op('PUSH21') -> ?PUSH21 ;
|
||||||
|
m_to_op('PUSH22') -> ?PUSH22 ;
|
||||||
|
m_to_op('PUSH23') -> ?PUSH23 ;
|
||||||
|
m_to_op('PUSH24') -> ?PUSH24 ;
|
||||||
|
m_to_op('PUSH25') -> ?PUSH25 ;
|
||||||
|
m_to_op('PUSH26') -> ?PUSH26 ;
|
||||||
|
m_to_op('PUSH27') -> ?PUSH27 ;
|
||||||
|
m_to_op('PUSH28') -> ?PUSH28 ;
|
||||||
|
m_to_op('PUSH29') -> ?PUSH29 ;
|
||||||
|
m_to_op('PUSH30') -> ?PUSH30 ;
|
||||||
|
m_to_op('PUSH31') -> ?PUSH31 ;
|
||||||
|
m_to_op('PUSH32') -> ?PUSH32 ;
|
||||||
|
m_to_op('DUP1') -> ?DUP1 ;
|
||||||
|
m_to_op('DUP2') -> ?DUP2 ;
|
||||||
|
m_to_op('DUP3') -> ?DUP3 ;
|
||||||
|
m_to_op('DUP4') -> ?DUP4 ;
|
||||||
|
m_to_op('DUP5') -> ?DUP5 ;
|
||||||
|
m_to_op('DUP6') -> ?DUP6 ;
|
||||||
|
m_to_op('DUP7') -> ?DUP7 ;
|
||||||
|
m_to_op('DUP8') -> ?DUP8 ;
|
||||||
|
m_to_op('DUP9') -> ?DUP9 ;
|
||||||
|
m_to_op('DUP10') -> ?DUP10 ;
|
||||||
|
m_to_op('DUP11') -> ?DUP11 ;
|
||||||
|
m_to_op('DUP12') -> ?DUP12 ;
|
||||||
|
m_to_op('DUP13') -> ?DUP13 ;
|
||||||
|
m_to_op('DUP14') -> ?DUP14 ;
|
||||||
|
m_to_op('DUP15') -> ?DUP15 ;
|
||||||
|
m_to_op('DUP16') -> ?DUP16 ;
|
||||||
|
m_to_op('SWAP1') -> ?SWAP1 ;
|
||||||
|
m_to_op('SWAP2') -> ?SWAP2 ;
|
||||||
|
m_to_op('SWAP3') -> ?SWAP3 ;
|
||||||
|
m_to_op('SWAP4') -> ?SWAP4 ;
|
||||||
|
m_to_op('SWAP5') -> ?SWAP5 ;
|
||||||
|
m_to_op('SWAP6') -> ?SWAP6 ;
|
||||||
|
m_to_op('SWAP7') -> ?SWAP7 ;
|
||||||
|
m_to_op('SWAP8') -> ?SWAP8 ;
|
||||||
|
m_to_op('SWAP9') -> ?SWAP9 ;
|
||||||
|
m_to_op('SWAP10') -> ?SWAP10 ;
|
||||||
|
m_to_op('SWAP11') -> ?SWAP11 ;
|
||||||
|
m_to_op('SWAP12') -> ?SWAP12 ;
|
||||||
|
m_to_op('SWAP13') -> ?SWAP13 ;
|
||||||
|
m_to_op('SWAP14') -> ?SWAP14 ;
|
||||||
|
m_to_op('SWAP15') -> ?SWAP15 ;
|
||||||
|
m_to_op('SWAP16') -> ?SWAP16 ;
|
||||||
|
m_to_op('LOG0') -> ?LOG0 ;
|
||||||
|
m_to_op('LOG1') -> ?LOG1 ;
|
||||||
|
m_to_op('LOG2') -> ?LOG2 ;
|
||||||
|
m_to_op('LOG3') -> ?LOG3 ;
|
||||||
|
m_to_op('LOG4') -> ?LOG4 ;
|
||||||
|
m_to_op('CREATE') -> ?CREATE ;
|
||||||
|
m_to_op('CALL') -> ?CALL ;
|
||||||
|
m_to_op('CALLCODE') -> ?CALLCODE ;
|
||||||
|
m_to_op('RETURN') -> ?RETURN ;
|
||||||
|
m_to_op('DELEGATECALL') -> ?DELEGATECALL ;
|
||||||
|
m_to_op('STATICCALL') -> ?STATICCALL ;
|
||||||
|
m_to_op('REVERT') -> ?REVERT ;
|
||||||
|
m_to_op('COMMENT') -> ?COMMENT("") ;
|
||||||
|
m_to_op('SUICIDE') -> ?SUICIDE ;
|
||||||
|
m_to_op(Data) when 0=<Data, Data=<255
|
||||||
|
-> Data .
|
||||||
|
|
||||||
|
push(N) when N >= 1, N =< 32 -> ?PUSH1 + N - 1.
|
||||||
|
dup(N) when N >= 1, N =< 16 -> ?DUP1 + N - 1.
|
||||||
|
swap(N) when N >= 1, N =< 16 -> ?SWAP1 + N - 1.
|
||||||
|
|
||||||
|
op_size(OP) when OP >= ?PUSH1 andalso OP =< ?PUSH32 ->
|
||||||
|
(OP - ?PUSH1) + 2;
|
||||||
|
op_size({comment, _}) -> 0;
|
||||||
|
op_size(_) -> 1.
|
||||||
|
|
31
src/aeb_primops.erl
Normal file
31
src/aeb_primops.erl
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @copyright (C) 2018, Aeternity Anstalt
|
||||||
|
%%% @doc
|
||||||
|
%%% Handle interaction with the aeternity chain
|
||||||
|
%%% through calls to AEternity primitive operations at address 0.
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 18 Dec 2018
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(aeb_primops).
|
||||||
|
-export([ is_local_primop_op/1
|
||||||
|
, op_needs_type_check/1
|
||||||
|
]).
|
||||||
|
|
||||||
|
-include("aeb_opcodes.hrl").
|
||||||
|
|
||||||
|
is_local_primop_op(Op) when ?PRIM_CALL_IN_MAP_RANGE(Op) -> true;
|
||||||
|
is_local_primop_op(Op) when is_integer(Op) -> false.
|
||||||
|
|
||||||
|
op_needs_type_check(Op) ->
|
||||||
|
(not is_local_primop_op(Op)) andalso op_has_dynamic_type(Op).
|
||||||
|
|
||||||
|
op_has_dynamic_type(?PRIM_CALL_ORACLE_QUERY) -> true;
|
||||||
|
op_has_dynamic_type(?PRIM_CALL_ORACLE_RESPOND) -> true;
|
||||||
|
op_has_dynamic_type(?PRIM_CALL_ORACLE_GET_QUESTION) -> true;
|
||||||
|
op_has_dynamic_type(?PRIM_CALL_ORACLE_GET_ANSWER) -> true;
|
||||||
|
op_has_dynamic_type(?PRIM_CALL_MAP_GET) -> true;
|
||||||
|
op_has_dynamic_type(?PRIM_CALL_MAP_PUT) -> true;
|
||||||
|
op_has_dynamic_type(?PRIM_CALL_MAP_TOLIST) -> true;
|
||||||
|
op_has_dynamic_type(?PRIM_CALL_AENS_RESOLVE) -> true;
|
||||||
|
op_has_dynamic_type(_) -> false.
|
14
src/aebytecode.app.src
Normal file
14
src/aebytecode.app.src
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{application, aebytecode,
|
||||||
|
[{description, "Bytecode definitions for AEthernity VM shared with compiler."},
|
||||||
|
{vsn, "1.0.0"},
|
||||||
|
{registered, []},
|
||||||
|
{applications,
|
||||||
|
[kernel,
|
||||||
|
stdlib
|
||||||
|
]},
|
||||||
|
{env,[]},
|
||||||
|
{modules, []},
|
||||||
|
{maintainers, []},
|
||||||
|
{licenses, []},
|
||||||
|
{links, []}
|
||||||
|
]}.
|
19
test/aebytecode_SUITE.erl
Normal file
19
test/aebytecode_SUITE.erl
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
-module(aebytecode_SUITE).
|
||||||
|
|
||||||
|
%% common_test exports
|
||||||
|
-export([ all/0 ]).
|
||||||
|
|
||||||
|
%% test case exports
|
||||||
|
-export([ roundtrip_identy/1 ]).
|
||||||
|
|
||||||
|
-include_lib("common_test/include/ct.hrl").
|
||||||
|
|
||||||
|
all() ->
|
||||||
|
[ roundtrip_identy ].
|
||||||
|
|
||||||
|
roundtrip_identy(_Cfg) ->
|
||||||
|
CodeDir = code:lib_dir(aebytecode, test),
|
||||||
|
FileName = filename:join(CodeDir, "asm_code/identity.aesm"),
|
||||||
|
Code = aeb_asm:file(FileName, []),
|
||||||
|
ct:log("Code ~p:~n~s~n", [FileName, aeb_disassemble:format(Code, fun io:format/2)]),
|
||||||
|
ok.
|
74
test/asm_code/identity.aesm
Normal file
74
test/asm_code/identity.aesm
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
;; CONTRACT: Identity
|
||||||
|
|
||||||
|
PUSH1 0
|
||||||
|
CALLDATALOAD
|
||||||
|
|
||||||
|
DUP1
|
||||||
|
;; Should be the hash of
|
||||||
|
;; the signature of the
|
||||||
|
;; first function (use 0 as placeholder)
|
||||||
|
PUSH32 0x0000000000000000000000000000
|
||||||
|
EQ
|
||||||
|
PUSH32 id_entry
|
||||||
|
JUMPI
|
||||||
|
|
||||||
|
STOP
|
||||||
|
|
||||||
|
id_entry: JUMPDEST
|
||||||
|
;; Skip the function name in the calldata
|
||||||
|
PUSH1 32
|
||||||
|
;; Load argument on stack
|
||||||
|
CALLDATALOAD
|
||||||
|
;; This function only takes one immidiate as argument.
|
||||||
|
|
||||||
|
;; Call the local version of the function
|
||||||
|
;; Get return address
|
||||||
|
PC
|
||||||
|
PUSH1 39
|
||||||
|
ADD
|
||||||
|
;; Get Argument
|
||||||
|
SWAP1
|
||||||
|
PUSH32 id_local
|
||||||
|
JUMP
|
||||||
|
|
||||||
|
|
||||||
|
;; return here from local call
|
||||||
|
;; Store top of stack at mem[0]
|
||||||
|
JUMPDEST
|
||||||
|
PUSH1 0
|
||||||
|
MSTORE
|
||||||
|
;; Return mem[0]-mem[32]
|
||||||
|
PUSH1 32
|
||||||
|
PUSH1 0
|
||||||
|
RETURN
|
||||||
|
|
||||||
|
;; for local calls
|
||||||
|
;; Stack:
|
||||||
|
;; | |
|
||||||
|
;; | Arg | <- SP
|
||||||
|
;; | RetAdr |
|
||||||
|
;; ...
|
||||||
|
|
||||||
|
id_local: JUMPDEST
|
||||||
|
|
||||||
|
;; Just return the argument
|
||||||
|
SWAP1
|
||||||
|
;; Stack:
|
||||||
|
;; | |
|
||||||
|
;; | RetAdr | <- SP
|
||||||
|
;; | RetVal | (Arg in this case)
|
||||||
|
;; ...
|
||||||
|
|
||||||
|
JUMP
|
||||||
|
|
||||||
|
;; Test the code from the shell
|
||||||
|
;; aevm_eeevm:eval(aevm_eeevm_state:init(#{ exec => #{ code => list_to_binary(aeb_asm:file("apps/aesophia/test/contracts/identity.aesm", [])), address => 0, caller => 0, data => <<0:256, 42:256>>, gas => 1000000, gasPrice => 1, origin => 0, value => 0 }, env => #{currentCoinbase => 0, currentDifficulty => 0, currentGasLimit => 10000, currentNumber => 0, currentTimestamp => 0}, pre => #{}}, #{})).
|
||||||
|
|
||||||
|
;; Test the code from the shell with tracing.
|
||||||
|
;; aevm_eeevm:eval(aevm_eeevm_state:init(#{ exec => #{ code => aeb_asm:file("apps/aesophia/test/contracts/identity.aesm", []), address => 0, caller => 0, data => <<0:256, 42:256>>, gas => 1000000, gasPrice => 1, origin => 0, value => 0 }, env => #{currentCoinbase => 0, currentDifficulty => 0, currentGasLimit => 10000, currentNumber => 0, currentTimestamp => 0}, pre => #{}}, #{ trace => true})).
|
||||||
|
|
||||||
|
|
||||||
|
;; Test the code from the shell with tracing.
|
||||||
|
;; aevm_eeevm:eval(aevm_eeevm_state:init(#{ exec => #{ code => aeb_asm:file("apps/aesophia/test/contracts/identity.aesm", [pp_tokens, pp_opcodes, pp_patched_code, pp_hex_string]), address => 0, caller => 0, data => <<0:256, 42:256>>, gas => 1000000, gasPrice => 1, origin => 0, value => 0}, env => #{currentCoinbase => 0, currentDifficulty => 0, currentGasLimit => 10000, currentNumber => 0, currentTimestamp => 0}, pre => #{}}, #{ trace => true})).
|
||||||
|
|
||||||
|
;; aec_conductor:stop_mining().
|
Loading…
x
Reference in New Issue
Block a user