Generate the code from the makefile. Remove generated files.

This commit is contained in:
Erik Stenman 2019-02-27 11:55:53 +01:00
parent c85af9e7f3
commit ab150ce7f8
7 changed files with 69 additions and 911 deletions

View File

@ -19,7 +19,7 @@ jobs:
- dialyzer-cache-v1- - dialyzer-cache-v1-
- run: - run:
name: Build name: Build
command: rebar3 compile command: make
- run: - run:
name: Static Analysis name: Static Analysis
command: rebar3 dialyzer command: rebar3 dialyzer

3
.gitignore vendored
View File

@ -12,3 +12,6 @@ aeb_asm_scan.erl
aeb_fate_asm_scan.erl aeb_fate_asm_scan.erl
_build/ _build/
aefateasm aefateasm
include/aeb_fate_opcodes.hrl
src/aeb_fate_code.erl
src/aeb_fate_opcodes.erl

View File

@ -4,17 +4,29 @@ REBAR ?= rebar3
all: local all: local
local: local: src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl
@$(REBAR) as local release @$(REBAR) as local release
console: console: src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl
@$(REBAR) as local shell @$(REBAR) as local shell
clean: clean:
@$(REBAR) clean @$(REBAR) clean
rm -f src/aeb_fate_opcodes.erl
rm -f src/aeb_fate_code.erl
rm -f include/aeb_fate_opcodes.hrl
distclean: clean distclean: clean
@rm -rf _build/ @rm -rf _build/
test: local test: local
@$(REBAR) as local eunit @$(REBAR) as local eunit
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: ebin/aeb_fate_generate_ops.beam
erl -pa ebin/ -noshell -s aeb_fate_generate_ops gen_and_halt src/ include/
ebin:
mkdir ebin

View File

@ -1,121 +0,0 @@
%% FATE opcodes
-define('NOP' , 16#00).
-define('RETURN' , 16#01).
-define('CALL' , 16#02).
-define('CALL_R' , 16#03).
-define('CALL_T' , 16#04).
-define('CALL_TR' , 16#05).
-define('JUMP' , 16#06).
-define('JUMPIF' , 16#07).
-define('SWITCH' , 16#08).
-define('PUSH' , 16#09).
-define('DUP' , 16#0a).
-define('POP' , 16#0b).
-define('STORE' , 16#10).
-define('ADD' , 16#11).
-define('MUL' , 16#12).
-define('SUB' , 16#13).
-define('DIV' , 16#14).
-define('MOD' , 16#15).
-define('POW' , 16#16).
-define('LT' , 16#17).
-define('GT' , 16#18).
-define('EQ' , 16#19).
-define('ELT' , 16#1a).
-define('EGT' , 16#1b).
-define('NEQ' , 16#1c).
-define('AND' , 16#1d).
-define('OR' , 16#1e).
-define('NOT' , 16#1f).
-define('TUPLE' , 16#20).
-define('ELEMENT' , 16#21).
-define('MAP_EMPTY' , 16#22).
-define('MAP_LOOKUP' , 16#23).
-define('MAP_UPDATE' , 16#24).
-define('MAP_DELETE' , 16#25).
-define('MAP_MEMBER' , 16#26).
-define('MAP_FROM_LIST' , 16#27).
-define('NIL' , 16#28).
-define('IS_NIL' , 16#29).
-define('CONS' , 16#2a).
-define('HD' , 16#2b).
-define('TL' , 16#2c).
-define('LENGTH' , 16#2d).
-define('STR_EQ' , 16#2e).
-define('STR_JOIN' , 16#2f).
-define('ADDR_TO_STR' , 16#30).
-define('STR_REVERSE' , 16#31).
-define('INT_TO_ADDR' , 16#32).
-define('VARIANT' , 16#33).
-define('VARIANT_TEST' , 16#34).
-define('VARIANT_ELEMENT', 16#35).
-define('BITS_NONE' , 16#36).
-define('BITS_ALL' , 16#37).
-define('BITS_SET' , 16#38).
-define('BITS_CLEAR' , 16#39).
-define('BITS_TEST' , 16#3a).
-define('BITS_SUM' , 16#3b).
-define('BITS_OR' , 16#3c).
-define('BITS_AND' , 16#3d).
-define('BITS_DIFF' , 16#3e).
-define('ADDRESS' , 16#3f).
-define('BALANCE' , 16#40).
-define('ORIGIN' , 16#41).
-define('CALLER' , 16#42).
-define('GASPRICE' , 16#43).
-define('BLOCKHASH' , 16#44).
-define('BENEFICIARY' , 16#45).
-define('TIMESTAMP' , 16#46).
-define('NUMBER' , 16#47).
-define('DIFFICULTY' , 16#48).
-define('GASLIMIT' , 16#49).
-define('GAS' , 16#4a).
-define('LOG0' , 16#4b).
-define('LOG1' , 16#4c).
-define('LOG2' , 16#4d).
-define('LOG3' , 16#4e).
-define('LOG4' , 16#4f).
-define('ABORT' , 16#50).
-define('EXIT' , 16#51).
-define('DEACTIVATE' , 16#52).
-define('INC' , 16#53).
-define('DEC' , 16#54).
-define('INT_TO_STR' , 16#55).
-define('SPEND' , 16#56).
-define('ORACLE_REGISTER', 16#57).
-define('ORACLE_QUERY' , 16#58).
-define('ORACLE_RESPOND' , 16#59).
-define('ORACLE_EXTEND' , 16#5a).
-define('ORACLE_GET_ANSWER', 16#5b).
-define('ORACLE_GET_QUESTION', 16#5c).
-define('ORACLE_QUERY_FEE', 16#5d).
-define('AENS_RESOLVE' , 16#5e).
-define('AENS_PRECLAIM' , 16#5f).
-define('AENS_CLAIM' , 16#60).
-define('AENS_UPDATE' , 16#61).
-define('AENS_TRANSFER' , 16#62).
-define('AENS_REVOKE' , 16#63).
-define('ECVERIFY' , 16#64).
-define('SHA3' , 16#65).
-define('SHA256' , 16#66).
-define('BLAKE2B' , 16#67).
-define('RETURNR' , 16#68).
-define('MAP_LOOKUPD' , 16#69).
-define('SWITCH_V2' , 16#6a).
-define('SWITCH_V3' , 16#6b).
-define('SWITCH_VN' , 16#6c).
-define('BITS_ALL_N' , 16#6d).
-define('BITS_NONEA' , 16#6e).
-define('BITS_ALLA' , 16#6f).
-define('DUPA' , 16#70).
-define('INCA' , 16#71).
-define('DECA' , 16#72).
-define('POPA' , 16#73).
-define('FUNCTION' , 16#fe).
-define('EXTEND' , 16#ff).
-define( COMMENT(X), {comment, X}).

View File

@ -1,389 +0,0 @@
%% Provide constructor functuions for Fate instructions.
%% Provide types and documentation for Fate instructions.
-module(aeb_fate_code).
-include_lib("aebytecode/include/aeb_fate_data.hrl").
-type fate_arg_immediate(T) :: {immediate, T}.
-type fate_arg_var() :: {var, integer()}.
-type fate_arg_arg() :: {arg, integer()}.
-type fate_arg_stack() :: {stack, integer()}.
-type fate_arg() :: fate_arg_immediate()
| fate_arg_var()
| fate_arg_arg()
| fate_arg_stack().
-type fate_arg_immediate() :: {immediate, aeb_fate_data:fate_type()}.
-type fate_return() :: 'RETURN'.
-type fate_returnr() :: {'RETURNR', fate_arg()}.
-type fate_call() :: {'CALL',
fate_arg_immediate(aeb_fate_data:fate_string())}.
-type fate_call_t() :: {'CALL_T',
fate_arg_immediate(aeb_fate_data:fate_string())}.
-type fate_call_r() :: {'CALL_R', fate_arg(),
fate_arg_immediate(aeb_fate_data:fate_string())}.
-type fate_call_tr() :: {'CALL_TR', fate_arg(),
fate_arg_immediate(aeb_fate_data:fate_string())}.
-type fate_jump() :: {'JUMP',
fate_arg_immediate(aeb_fate_data:fate_integer())}.
-type fate_jumpif() :: {'JUMPIF', fate_arg(),
fate_arg_immediate(aeb_fate_data:fate_integer())}.
-type fate_switch_v2() :: {'SWITCH_V2', fate_arg(),
fate_arg_immediate(aeb_fate_data:fate_integer()),
fate_arg_immediate(aeb_fate_data:fate_integer())}.
-type fate_switch_v3() :: {'SWITCH_V3', fate_arg(),
fate_arg_immediate(aeb_fate_data:fate_integer()),
fate_arg_immediate(aeb_fate_data:fate_integer()),
fate_arg_immediate(aeb_fate_data:fate_integer())}.
-type fate_switch_vn() :: {'SWITCH_VN', fate_arg(),
fate_arg_immediate(aeb_fate_data:fate_integer()),
[fate_arg_immediate(aeb_fate_data:fate_integer())]}.
-type fate_push() :: {'PUSH', fate_arg()}.
-type fate_inca() :: 'INCA'.
-type fate_inc() :: {'INC', fate_arg()}.
-type fate_deca() :: 'DECA'.
-type fate_dec() :: {'DEC', fate_arg()}.
-type fate_code() :: fate_return()
| fate_returnr()
| fate_call()
| fate_call_t()
| fate_call_r()
| fate_call_tr()
| fate_jump()
| fate_jumpif()
| fate_switch_v2()
| fate_switch_v3()
| fate_switch_vn()
| fate_push()
| fate_inca()
| fate_inc()
| fate_deca()
| fate_dec()
.
-export_type([ fate_code/0
, fate_arg/0
]).
-export([ return/0
, return/1
, call/1
, call_t/1
, call_r/2
, call_tr/2
, jump/1
, jumpif/2
, switch/3
, switch/4
, switch_n/2
, push/1
, inc/0
, inc/1
, dec/0
, dec/1
, add/3
, sub/3
, mul/3
, divide/3
, modulo/3
, pow/3
, lt/3
, gt/3
, elt/3
, egt/3
, eq/3
, neq/3
, and_op/3
, or_op/3
, not_op/2
, tuple/1
, element_op/4
, map_empty/1
, map_lookup/3
, map_lookup/4
, map_update/4
, map_member/3
, map_from_list/2
, nil/1
, is_nil/2
, cons/3
, hd/2
, tl/2
, length/2
, str_eq/3
, str_join/3
, int_to_str/2
, addr_to_str/2
, str_reverse/2
, int_to_addr/2
, variant_test/3
, variant_element/3
, variant/4
, bits_none/0
, bits_none/1
, bits_all/0
, bits_all/1
, bits_all_n/2
, bits_set/3
, bits_clear/3
, bits_test/3
, bits_sum/2
, bits_or/3
, bits_and/3
, bits_diff/3
, dup/0
, dup/1
, pop/0
, store/2
, nop/0
]).
-define(i(__X__), {immediate, __X__ }).
-spec return() -> fate_return().
return() ->
'RETURN'.
-spec return(fate_arg()) -> fate_returnr().
return(Arg) ->
{'RETURNR', Arg}.
-spec call(aeb_fate_data:fate_string()) -> fate_call().
call(Function) when ?IS_FATE_STRING(Function)->
{'CALL', ?i(Function) }.
-spec call_t(aeb_fate_data:fate_string()) -> fate_call_t().
call_t(Function) when ?IS_FATE_STRING(Function) ->
{'CALL_T', ?i(Function)}.
-spec call_r(fate_arg(), aeb_fate_data:fate_string()) -> fate_call_r().
call_r(Contract, Function) when ?IS_FATE_STRING(Function) ->
{'CALL_R', Contract, ?i(Function)}.
-spec call_tr(fate_arg(), aeb_fate_data:fate_string()) -> fate_call_tr().
call_tr(Contract, Function) when ?IS_FATE_STRING(Function) ->
{'CALL_TR', Contract, ?i(Function)}.
-spec jump(aeb_fate_data:fate_integer()) -> fate_jump().
jump(BB) when ?IS_FATE_INTEGER(BB) ->
{'JUMP', ?i(BB)}.
-spec jumpif(fate_arg(), aeb_fate_data:fate_integer()) -> fate_jumpif().
jumpif(Arg, BB) when ?IS_FATE_INTEGER(BB) ->
{'JUMPIF', Arg, ?i(BB)}.
-spec switch(fate_arg(),
aeb_fate_data:fate_integer(),
aeb_fate_data:fate_integer())
-> fate_switch_v2().
switch(Arg, BB1, BB2) when ?IS_FATE_INTEGER(BB1),
?IS_FATE_INTEGER(BB2) ->
{'SWITCH_V2', Arg, ?i(BB1), ?i(BB2)}.
-spec switch(fate_arg(),
aeb_fate_data:fate_integer(),
aeb_fate_data:fate_integer(),
aeb_fate_data:fate_integer())
-> fate_switch_v3().
switch(Arg, BB1, BB2, BB3) when ?IS_FATE_INTEGER(BB1),
?IS_FATE_INTEGER(BB2),
?IS_FATE_INTEGER(BB3) ->
{'SWITCH_V3', Arg, ?i(BB1), ?i(BB2), ?i(BB3)}.
-spec switch_n(fate_arg(),
[aeb_fate_data:fate_integer()])
-> fate_switch_vn().
switch_n(Arg, BBS) when is_list(BBS) ->
N = length(BBS),
{'SWITCH_VN', Arg, ?i(N), [?i(BB) || BB <- BBS]}.
-spec push(fate_arg()) -> fate_push().
push(Arg) ->
{'PUSH', Arg}.
-spec inc() -> fate_inca().
inc() ->
'INCA'.
-spec inc(fate_arg()) -> fate_inc().
inc(Arg) ->
{'INC', Arg}.
-spec dec() -> fate_deca().
dec() ->
'DECA'.
-spec dec(fate_arg()) -> fate_dec().
dec(Arg) ->
{'DEC', Arg}.
add(Dest, Left, Right) ->
{'ADD', Dest, Left, Right}.
sub(Dest, Left, Right) ->
{'SUB', Dest, Left, Right}.
mul(Dest, Left, Right) ->
{'MUL', Dest, Left, Right}.
divide(Dest, Left, Right) ->
{'DIV', Dest, Left, Right}.
modulo(Dest, Left, Right) ->
{'MOD', Dest, Left, Right}.
pow(Dest, Left, Right) ->
{'POW', Dest, Left, Right}.
lt(Dest, Left, Right) ->
{'LT', Dest, Left, Right}.
gt(Dest, Left, Right) ->
{'GT', Dest, Left, Right}.
elt(Dest, Left, Right) ->
{'ELT', Dest, Left, Right}.
egt(Dest, Left, Right) ->
{'EGT', Dest, Left, Right}.
eq(Dest, Left, Right) ->
{'EQ', Dest, Left, Right}.
neq(Dest, Left, Right) ->
{'NEQ', Dest, Left, Right}.
and_op(Dest, Left, Right) ->
{'AND', Dest, Left, Right}.
or_op(Dest, Left, Right) ->
{'OR', Dest, Left, Right}.
not_op(Dest, Arg) ->
{'NOT', Dest, Arg}.
tuple(Size) when ?IS_FATE_INTEGER(Size) ->
{'TUPLE', ?i(Size)}.
element_op(Type, Dest, N, T) ->
{'ELEMENT', Type, Dest, N, T}.
map_empty(Dest) ->
{'MAP_EMPTY', Dest}.
map_lookup(Dest, Map, Key) ->
{'MAP_LOOKUP', Dest, Map, Key}.
map_lookup(Dest, Map, Key, Default) ->
{'MAP_LOOKUPD', Dest, Map, Key, Default}.
map_update(Dest, Map, Key, Value) ->
{'MAP_UPDATE', Dest, Map, Key, Value}.
map_member(Dest, Map, Key) ->
{'MAP_MEMBER', Dest, Map, Key}.
map_from_list(Dest, List) ->
{'MAP_MEMBER', Dest, List}.
nil(Dest) ->
{'NIL', Dest}.
is_nil(Dest, List) ->
{'IS_NIL', Dest, List}.
cons(Dest, Hd, Tl) ->
{'CONS', Dest, Hd, Tl}.
hd(Dest, List) ->
{'HD', Dest, List}.
tl(Dest, List) ->
{'TL', Dest, List}.
length(Dest, List) ->
{'LENGTH', Dest, List}.
str_eq(Dest, Str1, Str2) ->
{'STR_EQ', Dest, Str1, Str2}.
str_join(Dest, Str1, Str2) ->
{'STR_JOIN', Dest, Str1, Str2}.
int_to_str(Dest, Str) ->
{'INT_TO_STR', Dest, Str}.
addr_to_str(Dest, Str) ->
{'ADDR_TO_STR', Dest, Str}.
str_reverse(Dest, Str) ->
{'STR_REVERSE', Dest, Str}.
int_to_addr(Dest, Str) ->
{'INT_TO_ADDR', Dest, Str}.
variant_test(Dest, Variant, Tag) ->
{'VARIANT_TEST', Dest, Variant, Tag}.
variant_element( Dest, Variant, Index) ->
{'VARIANT_ELEMENT', Dest, Variant, Index}.
variant(Dest, SizeA, TagA, ElementsA) ->
{'VARIANT', Dest, SizeA, TagA, ElementsA}.
bits_none() ->
'BITS_NONEA'.
bits_none(To) ->
{'BITS_NONE', To}.
bits_all() ->
'BITS_ALLA'.
bits_all(To) ->
{'BITS_ALL', To}.
bits_all_n(To, N) ->
{'BITS_ALL_N', To, N}.
bits_set(To, Bits, Bit) ->
{'BITS_SET', To, Bits, Bit}.
bits_clear(To, Bits, Bit) ->
{'BITS_CLEAR', To, Bits, Bit}.
bits_test(To, Bits, Bit) ->
{'BITS_TEST', To, Bits, Bit}.
bits_sum(To, Bits) ->
{'BITS_SUM', To, Bits}.
bits_or(To, Bits, Bit) ->
{'BITS_OR', To, Bits, Bit}.
bits_and(To, Bits, Bit) ->
{'BITS_AND', To, Bits, Bit}.
bits_diff(To, Bits, Bit) ->
{'BITS_DIFF', To, Bits, Bit}.
dup() ->
'DUPA'.
dup(N) when ?IS_FATE_INTEGER(N) ->
{'DUP', ?i(N)}.
pop() ->
'POP'.
store(Var, What) ->
{'STORE', Var, What}.
nop() ->
'NOP'.

View File

@ -1,34 +1,33 @@
-module(aeb_fate_generate_ops). -module(aeb_fate_generate_ops).
-export([generate/0]). -export([ gen_and_halt/1
, generate/0]).
-define(ati(__X__), {immediate, __X__}). gen_and_halt([SrcDirArg, IncludeDirArg]) ->
-define(atv(__X__), {var, __X__}). generate(atom_to_list(SrcDirArg),
-define(ata(__X__), {arg, __X__}). atom_to_list(IncludeDirArg)),
-define(ats(__X__), {stack, __X__}). halt().
-define(ta(), "fate_arg()").
-define(ti(__X__), "fate_arg_immediate(" __X__ ")").
-define(ts, "aeb_fate_data:fate_string()").
generate() -> generate() ->
generate("src/", "include/").
generate(Src, Include) ->
Ops = gen(ops_defs()), Ops = gen(ops_defs()),
io:format("ops: ~p\n", [Ops]), %% io:format("ops: ~p\n", [Ops]),
HrlFile = "aeb_new_fate_opcodes.hrl", HrlFile = Include ++ "aeb_fate_opcodes.hrl",
generate_header_file(HrlFile, Ops), generate_header_file(HrlFile, Ops),
generate_opcodes_ops(aeb_new_fate_opcodes, HrlFile, Ops), generate_opcodes_ops(aeb_fate_opcodes, HrlFile, Src, Ops),
generate_code_ops(aeb_new_fate_code, Ops). generate_code_ops(aeb_fate_code, Src, Ops).
ops_defs() -> ops_defs() ->
%% Opname, Opcode, args, end_bb, gas, format, Constructor, Documentation %% Opname, Opcode, args, end_bb, gas, format, Constructor, Documentation
[ { 'NOP', 16#00, 0, false, 1, atomic, nop, "The no op. does nothing."} [ { 'NOP', 16#f0, 0, false, 1, atomic, nop, "The no op. does nothing."}
, { 'RETURN', 16#01, 0, true, 2, atomic, return, "Return from function call pop stack to arg0."} , { 'RETURN', 16#00, 0, true, 2, atomic, return, "Return from function call pop stack to arg0."}
, { 'RETURNR', 16#68, 1, true, 2, [a], returnr, "Return from function call pop stack to arg0."} , { 'RETURNR', 16#01, 1, true, 2, [a], returnr, "Return from function call pop stack to arg0."}
, { 'CALL', 16#02, 1, true, 4, [is], call, "Call given function with args on stack."} , { 'CALL', 16#02, 1, true, 4, [is], call, "Call given function with args on stack."}
, { 'CALL_T', 16#04, 1, true, 4, [is], call_t, "Tail call to given function."}
, { 'CALL_R', 16#03, 2, true, 8, [a, is], call_r, "Remote call to given contract and function."} , { 'CALL_R', 16#03, 2, true, 8, [a, is], call_r, "Remote call to given contract and function."}
, { 'CALL_T', 16#04, 1, true, 4, [is], call_t, "Tail call to given function."}
, { 'CALL_TR', 16#05, 2, true, 8, [a, is], call_tr, "Remote tail call to given contract and function."} , { 'CALL_TR', 16#05, 2, true, 8, [a, is], call_tr, "Remote tail call to given contract and function."}
, { 'JUMP', 16#06, 1, true, 3, [ii], jump, "Jump to a basic block."} , { 'JUMP', 16#06, 1, true, 3, [ii], jump, "Jump to a basic block."}
, { 'JUMPIF', 16#07, 2, true, 4, [a, ii], jumpif, "Conditional jump to a basic block."} , { 'JUMPIF', 16#07, 2, true, 4, [a, ii], jumpif, "Conditional jump to a basic block."}
@ -56,13 +55,14 @@ ops_defs() ->
, { 'OR', 16#1e, 3, false, 3, [a,a,a], or_op, "Arg0 := Arg1 or Arg2."} , { 'OR', 16#1e, 3, false, 3, [a,a,a], or_op, "Arg0 := Arg1 or Arg2."}
, { 'NOT', 16#1f, 2, false, 3, [a,a], not_op, "Arg0 := not Arg1."} , { 'NOT', 16#1f, 2, false, 3, [a,a], not_op, "Arg0 := not Arg1."}
, { 'TUPLE', 16#20, 1, false, 3, [ii], tuple, "Create a tuple of size = Arg0. Elements on stack."} , { 'TUPLE', 16#20, 1, false, 3, [ii], tuple, "Create a tuple of size = Arg0. Elements on stack."}
, { 'ELEMET', 16#21, 4, false, 3, [t,a,a,a], element_op, "Arg1 := element(Arg2, Arg3). The element should be of type Arg1"} , { 'ELEMENT', 16#21, 4, false, 3, [t,a,a,a], element_op, "Arg1 := element(Arg2, Arg3). The element should be of type Arg1"}
, { 'MAP_EMPTY',16#22, 1, false, 3, [a], map_empty, "Arg0 := #{}."} , { 'MAP_EMPTY',16#22, 1, false, 3, [a], map_empty, "Arg0 := #{}."}
, { 'MAP_LOOKUP',16#23, 3, false, 3, [a, a, a], map_lookup, "Arg0 := lookup key Arg2 in map Arg1."} , { 'MAP_LOOKUP',16#23, 3, false, 3, [a, a, a], map_lookup, "Arg0 := lookup key Arg2 in map Arg1."}
, { 'MAP_LOOKUPD',16#69, 4, false, 3, [a, a, a, a], map_lookup, "Arg0 := lookup key Arg2 in map Arg1 if key exists in map otherwise Arg0 := Arg3."} , { 'MAP_LOOKUPD',16#69, 4, false, 3, [a, a, a, a], map_lookup, "Arg0 := lookup key Arg2 in map Arg1 if key exists in map otherwise Arg0 := Arg3."}
, { 'MAP_UPDATE',16#24, 4, false, 3, [a, a, a, a], map_update, "Arg0 := update key Arg2 in map Arg1 with value Arg3."} , { 'MAP_UPDATE',16#24, 4, false, 3, [a, a, a, a], map_update, "Arg0 := update key Arg2 in map Arg1 with value Arg3."}
, { 'MAP_DELETE',16#25, 3, false, 3, [a, a, a], map_delete, "Arg0 := delete key Arg2 from map Arg1."} , { 'MAP_DELETE',16#25, 3, false, 3, [a, a, a], map_delete, "Arg0 := delete key Arg2 from map Arg1."}
, { 'MAP_MEMBER',16#26, 3, false, 3, [a, a, a], map_member, "Arg0 := true if key Arg2 is in map Arg1."} , { 'MAP_MEMBER',16#26, 3, false, 3, [a, a, a], map_member, "Arg0 := true if key Arg2 is in map Arg1."}
, { 'MAP_FROM_LIST',16#27, 2, false, 3, [a, a], map_from_list, "Arg0 := make a map from (key, value) list in Arg1."}
, { 'NIL', 16#28, 1, false, 3, [a], nil, "Arg0 := []."} , { 'NIL', 16#28, 1, false, 3, [a], nil, "Arg0 := []."}
, { 'IS_NIL', 16#29, 2, false, 3, [a, a], is_nil, "Arg0 := true if Arg1 == []."} , { 'IS_NIL', 16#29, 2, false, 3, [a, a], is_nil, "Arg0 := true if Arg1 == []."}
, {'CONS', 16#2a, 3, false, 3, [a, a, a], cons, "Arg0 := [Arg1|Arg2]."} , {'CONS', 16#2a, 3, false, 3, [a, a, a], cons, "Arg0 := [Arg1|Arg2]."}
@ -78,7 +78,7 @@ ops_defs() ->
, {'INT_TO_ADDR', 16#32, 2, false, 3, [a, a], int_to_addr, "Arg0 := turn integer Arg1 into an address."} , {'INT_TO_ADDR', 16#32, 2, false, 3, [a, a], int_to_addr, "Arg0 := turn integer Arg1 into an address."}
, {'VARIANT', 16#33, 4, false, 3, [a, a, a, a], variant, "Arg0 := create a variant of size Arg1 with the tag Arg2 (Arg2 < Arg1) and take Arg3 elements from the stack."} , {'VARIANT', 16#33, 4, false, 3, [a, a, a, a], variant, "Arg0 := create a variant of size Arg1 with the tag Arg2 (Arg2 < Arg1) and take Arg3 elements from the stack."}
, {'VARIANT_TEST', 16#34,3, false, 3, [a, a, a], variant_test,"Arg0 := true if variant Arg1 has the tag Arg2."} , {'VARIANT_TEST', 16#34,3, false, 3, [a, a, a], variant_test,"Arg0 := true if variant Arg1 has the tag Arg2."}
, {'VARIANT_ELEMENT',16#35,3,false, 3, [a, a, a], variant_element,"Arg0 := element number Arg2 from variant Arg1."} , {'VARIANT_ELEMNT',16#35,3,false, 3, [a, a, a], variant_element,"Arg0 := element number Arg2 from variant Arg1."}
, {'BITS_NONEA', 16#6e, 0, false, 3, atomic, bits_none, "accumulator := empty bitmap."} , {'BITS_NONEA', 16#6e, 0, false, 3, atomic, bits_none, "accumulator := empty bitmap."}
, {'BITS_NONE', 16#36, 1, false, 3, [a], bits_none, "Arg0 := empty bitmap."} , {'BITS_NONE', 16#36, 1, false, 3, [a], bits_none, "Arg0 := empty bitmap."}
, {'BITS_ALLA', 16#6f, 0, false, 3, atomic, bits_all, "accumulator := full bitmap."} , {'BITS_ALLA', 16#6f, 0, false, 3, atomic, bits_all, "accumulator := full bitmap."}
@ -94,6 +94,21 @@ ops_defs() ->
, {'DUP', 16#0a, 1, false, 3, [a], dup, "push Arg0 stack pos on top of stack."} , {'DUP', 16#0a, 1, false, 3, [a], dup, "push Arg0 stack pos on top of stack."}
, {'POP', 16#0b, 1, false, 3, [a], pop, "Arg0 := top of stack."} , {'POP', 16#0b, 1, false, 3, [a], pop, "Arg0 := top of stack."}
, {'STORE', 16#10, 2, false, 3, [a, a], store, "Arg0 := Arg1."} , {'STORE', 16#10, 2, false, 3, [a, a], store, "Arg0 := Arg1."}
%% TODO: Check the documentation and update it.
, {'ADDRESS', 16#3f, 1, false, 3, [a], address, "Arg0 := The current contract address."}
, {'BALANCE', 16#3f, 1, false, 3, [a], balance, "Arg0 := The current contract address."}
, {'ORIGIN', 16#40, 1, false, 3, [a], origin, "Arg0 := Address of contract called by the call transaction."}
, {'CALLER', 16#41, 1, false, 3, [a], caller, "Arg0 := The address that signed the call transaction."}
, {'GASPRICE', 16#42, 1, false, 3, [a], gasprice, "Arg0 := The current gas price."}
, {'BLOCKHASH', 16#43, 1, false, 3, [a], blockhash, "Arg0 := The current blockhash."} %% TODO: Do we support has at height?
, {'BENEFICIARY',16#44, 1, false, 3, [a], beneficiary, "Arg0 := The address of the current beneficiary."}
, {'TIMESTAMP', 16#45, 1, false, 3, [a], timestamp, "Arg0 := The current timestamp. Unrelaiable, don't use for anything."}
, {'NUMBER', 16#46, 1, false, 3, [a], number, "Arg0 := The block height."}
, {'DIFFICULTY',16#47, 1, false, 3, [a], difficulty, "Arg0 := The current difficulty."}
, {'GASLIMIT', 16#48, 1, false, 3, [a], gaslimit, "Arg0 := The current gaslimit."}
, {'GAS', 16#49, 1, false, 3, [a], gas, "Arg0 := The amount of gas left."}
, {'ABORT', 16#4f, 1, false, 3, [a], abort, "Abort execution (dont use all gas) with error message in Arg0."}
, {'EXIT', 16#4e, 1, false, 3, [a], exit, "Abort execution (use upp all gas) with error message in Arg0."}
]. ].
@ -102,10 +117,13 @@ generate_header_file(Filename, Ops) ->
Defines = lists:flatten([gen_defines(Op) || Op <- Ops]), Defines = lists:flatten([gen_defines(Op) || Op <- Ops]),
io:format(File, "~s", [prelude("Provides opcode defines.\n")]), io:format(File, "~s", [prelude("Provides opcode defines.\n")]),
io:format(File, "%% FATE opcodes\n~s", [Defines]), io:format(File, "%% FATE opcodes\n~s", [Defines]),
io:format(File, "~s",
["-define('FUNCTION' , 16#fe).\n"
"-define('EXTEND' , 16#ff).\n\n"]),
file:close(File). file:close(File).
generate_opcodes_ops(Modulename, HrlFile, Ops) -> generate_opcodes_ops(Modulename, HrlFile, SrcDir, Ops) ->
Filename = atom_to_list(Modulename) ++ ".erl", Filename = SrcDir ++ atom_to_list(Modulename) ++ ".erl",
{ok, File} = file:open(Filename, [write]), {ok, File} = file:open(Filename, [write]),
Mnemonic = lists:flatten([gen_mnemonic(Op) || Op <- Ops]), Mnemonic = lists:flatten([gen_mnemonic(Op) || Op <- Ops]),
@ -135,8 +153,8 @@ generate_opcodes_ops(Modulename, HrlFile, Ops) ->
file:close(File). file:close(File).
generate_code_ops(Modulename, Ops) -> generate_code_ops(Modulename, SrcDir, Ops) ->
Filename = atom_to_list(Modulename) ++ ".erl", Filename = SrcDir ++ atom_to_list(Modulename) ++ ".erl",
{ok, File} = file:open(Filename, [write]), {ok, File} = file:open(Filename, [write]),
Types = lists:flatten([gen_type(Op) || Op <- Ops]), Types = lists:flatten([gen_type(Op) || Op <- Ops]),
@ -163,7 +181,6 @@ generate_code_ops(Modulename, Ops) ->
" | fate_arg_stack().\n\n" " | fate_arg_stack().\n\n"
"-type fate_arg_immediate() :: {immediate, aeb_fate_data:fate_type()}.\n" "-type fate_arg_immediate() :: {immediate, aeb_fate_data:fate_type()}.\n"
, []), , []),
io:format(File, "~s", [Types]), io:format(File, "~s", [Types]),
io:format(File, "-type fate_code() :: ~s\n~s .\n\n", io:format(File, "-type fate_code() :: ~s\n~s .\n\n",
[FirstType, FateTypes]), [FirstType, FateTypes]),
@ -173,7 +190,6 @@ generate_code_ops(Modulename, Ops) ->
io:format(File, "foo() -> \"A temp hack.\".\n", []), io:format(File, "foo() -> \"A temp hack.\".\n", []),
file:close(File). file:close(File).
gen_type(#{type_name := TypeName, type := Type}) -> gen_type(#{type_name := TypeName, type := Type}) ->
@ -248,7 +264,7 @@ ops_exports(Module, HrlFile, Exports) ->
lists:flatten(io_lib:format( lists:flatten(io_lib:format(
"-module(~w).\n\n" "-module(~w).\n\n"
"-export([ ~s ]).\n\n" "-export([ ~s ]).\n\n"
"-include_lib(\"aebytecode/include/" ++ HrlFile ++"\").\n\n" "-include_lib(\"aebytecode/" ++ HrlFile ++"\").\n\n"
"%%====================================================================\n" "%%====================================================================\n"
"%% API\n" "%% API\n"
"%%====================================================================\n", "%%====================================================================\n",

View File

@ -1,363 +0,0 @@
%%%-------------------------------------------------------------------
%%% @copyright (C) 2019, Aeternity Anstalt
%%% @doc
%%% Opcodes
%%% @end
%%%-------------------------------------------------------------------
-module(aeb_fate_opcodes).
-export([ args/1
, end_bb/1
, mnemonic/1
, m_to_op/1
, opcode/1
]).
-include_lib("aebytecode/include/aeb_fate_opcodes.hrl").
%%====================================================================
%% API
%%====================================================================
opcode(X) when X >= 0, X =< 255 -> X;
opcode({comment,X}) -> ?COMMENT(X).
mnemonic(?NOP) -> 'NOP' ;
mnemonic(?RETURN) -> 'RETURN' ;
mnemonic(?CALL) -> 'CALL' ;
mnemonic(?CALL_R) -> 'CALL_R' ;
mnemonic(?CALL_T) -> 'CALL_T' ;
mnemonic(?CALL_TR) -> 'CALL_TR' ;
mnemonic(?JUMP) -> 'JUMP' ;
mnemonic(?JUMPIF) -> 'JUMPIF' ;
mnemonic(?PUSH) -> 'PUSH' ;
mnemonic(?DUP) -> 'DUP' ;
mnemonic(?DUPA) -> 'DUPA' ;
mnemonic(?POP) -> 'POP' ;
mnemonic(?STORE) -> 'STORE' ;
mnemonic(?ADD) -> 'ADD' ;
mnemonic(?MUL) -> 'MUL' ;
mnemonic(?SUB) -> 'SUB' ;
mnemonic(?DIV) -> 'DIV' ;
mnemonic(?MOD) -> 'MOD' ;
mnemonic(?POW) -> 'POW' ;
mnemonic(?LT) -> 'LT' ;
mnemonic(?GT) -> 'GT' ;
mnemonic(?EQ) -> 'EQ' ;
mnemonic(?ELT) -> 'ELT' ;
mnemonic(?EGT) -> 'EGT' ;
mnemonic(?NEQ) -> 'NEQ' ;
mnemonic(?AND) -> 'AND' ;
mnemonic(?OR) -> 'OR' ;
mnemonic(?NOT) -> 'NOT' ;
mnemonic(?TUPLE) -> 'TUPLE' ;
mnemonic(?ELEMENT) -> 'ELEMENT' ;
mnemonic(?MAP_EMPTY) -> 'MAP_EMPTY' ;
mnemonic(?MAP_LOOKUP) -> 'MAP_LOOKUP' ;
mnemonic(?MAP_UPDATE) -> 'MAP_UPDATE' ;
mnemonic(?MAP_DELETE) -> 'MAP_DELETE' ;
mnemonic(?MAP_MEMBER) -> 'MAP_MEMBER' ;
mnemonic(?MAP_FROM_LIST) -> 'MAP_FROM_LIST' ;
mnemonic(?NIL) -> 'NIL' ;
mnemonic(?IS_NIL) -> 'IS_NIL' ;
mnemonic(?CONS) -> 'CONS' ;
mnemonic(?HD) -> 'HD' ;
mnemonic(?TL) -> 'TL' ;
mnemonic(?LENGTH) -> 'LENGTH' ;
mnemonic(?STR_EQ) -> 'STR_EQ' ;
mnemonic(?STR_JOIN) -> 'STR_JOIN' ;
mnemonic(?ADDR_TO_STR) -> 'ADDR_TO_STR' ;
mnemonic(?STR_REVERSE) -> 'STR_REVERSE' ;
mnemonic(?INT_TO_ADDR) -> 'INT_TO_ADDR' ;
mnemonic(?VARIANT) -> 'VARIANT' ;
mnemonic(?VARIANT_TEST) -> 'VARIANT_TEST' ;
mnemonic(?VARIANT_ELEMENT) -> 'VARIANT_ELEMENT' ;
mnemonic(?BITS_NONE) -> 'BITS_NONE' ;
mnemonic(?BITS_NONEA) -> 'BITS_NONEA' ;
mnemonic(?BITS_ALL) -> 'BITS_ALL' ;
mnemonic(?BITS_ALLA) -> 'BITS_ALLA' ;
mnemonic(?BITS_SET) -> 'BITS_SET' ;
mnemonic(?BITS_CLEAR) -> 'BITS_CLEAR' ;
mnemonic(?BITS_TEST) -> 'BITS_TEST' ;
mnemonic(?BITS_SUM) -> 'BITS_SUM' ;
mnemonic(?BITS_OR) -> 'BITS_OR' ;
mnemonic(?BITS_AND) -> 'BITS_AND' ;
mnemonic(?BITS_DIFF) -> 'BITS_DIFF' ;
mnemonic(?ADDRESS) -> 'ADDRESS' ;
mnemonic(?BALANCE) -> 'BALANCE' ;
mnemonic(?ORIGIN) -> 'ORIGIN' ;
mnemonic(?CALLER) -> 'CALLER' ;
mnemonic(?GASPRICE) -> 'GASPRICE' ;
mnemonic(?BLOCKHASH) -> 'BLOCKHASH' ;
mnemonic(?BENEFICIARY) -> 'BENEFICIARY' ;
mnemonic(?TIMESTAMP) -> 'TIMESTAMP' ;
mnemonic(?NUMBER) -> 'NUMBER' ;
mnemonic(?DIFFICULTY) -> 'DIFFICULTY' ;
mnemonic(?GASLIMIT) -> 'GASLIMIT' ;
mnemonic(?GAS) -> 'GAS' ;
mnemonic(?LOG0) -> 'LOG0' ;
mnemonic(?LOG1) -> 'LOG1' ;
mnemonic(?LOG2) -> 'LOG2' ;
mnemonic(?LOG3) -> 'LOG3' ;
mnemonic(?LOG4) -> 'LOG4' ;
mnemonic(?ABORT) -> 'ABORT' ;
mnemonic(?EXIT) -> 'EXIT' ;
mnemonic(?DEACTIVATE) -> 'DEACTIVATE' ;
mnemonic(?INC) -> 'INC' ;
mnemonic(?DEC) -> 'DEC' ;
mnemonic(?INCA) -> 'INCA' ;
mnemonic(?DECA) -> 'DECA' ;
mnemonic(?INT_TO_STR) -> 'INT_TO_STR' ;
mnemonic(?SPEND) -> 'SPEND' ;
mnemonic(?ORACLE_REGISTER) -> 'ORACLE_REGISTER' ;
mnemonic(?ORACLE_QUERY) -> 'ORACLE_QUERY' ;
mnemonic(?ORACLE_RESPOND) -> 'ORACLE_RESPOND' ;
mnemonic(?ORACLE_EXTEND) -> 'ORACLE_EXTEND' ;
mnemonic(?ORACLE_GET_ANSWER) -> 'ORACLE_GET_ANSWER' ;
mnemonic(?ORACLE_GET_QUESTION) -> 'ORACLE_GET_QUESTION' ;
mnemonic(?ORACLE_QUERY_FEE) -> 'ORACLE_QUERY_FEE' ;
mnemonic(?AENS_RESOLVE) -> 'AENS_RESOLVE' ;
mnemonic(?AENS_PRECLAIM) -> 'AENS_PRECLAIM' ;
mnemonic(?AENS_CLAIM) -> 'AENS_CLAIM' ;
mnemonic(?AENS_UPDATE) -> 'AENS_UPDATE' ;
mnemonic(?AENS_TRANSFER) -> 'AENS_TRANSFER' ;
mnemonic(?AENS_REVOKE) -> 'AENS_REVOKE' ;
mnemonic(?ECVERIFY) -> 'ECVERIFY' ;
mnemonic(?SHA3) -> 'SHA3' ;
mnemonic(?SHA256) -> 'SHA256' ;
mnemonic(?BLAKE2B) -> 'BLAKE2B' ;
mnemonic(?RETURNR) -> 'RETURNR' ;
mnemonic(?MAP_LOOKUPD) -> 'MAP_LOOKUPD' ;
mnemonic(?SWITCH_V2) -> 'SWITCH_V2' ;
mnemonic(?SWITCH_V3) -> 'SWITCH_V3' ;
mnemonic(?SWITCH_VN) -> 'SWITCH_VN' ;
mnemonic(?BITS_ALL_N) -> 'BITS_ALL_N' ;
mnemonic(?FUNCTION) -> 'FUNCTION' ;
mnemonic(?EXTEND) -> 'EXTEND'.
m_to_op('NOP') -> ?NOP ;
m_to_op('RETURN') -> ?RETURN ;
m_to_op('CALL') -> ?CALL ;
m_to_op('CALL_R') -> ?CALL_R ;
m_to_op('CALL_T') -> ?CALL_T ;
m_to_op('CALL_TR') -> ?CALL_TR ;
m_to_op('JUMP') -> ?JUMP ;
m_to_op('JUMPIF') -> ?JUMPIF ;
m_to_op('PUSH') -> ?PUSH ;
m_to_op('DUP') -> ?DUP ;
m_to_op('DUPA') -> ?DUPA ;
m_to_op('POP') -> ?POP ;
m_to_op('STORE') -> ?STORE ;
m_to_op('ADD') -> ?ADD ;
m_to_op('MUL') -> ?MUL ;
m_to_op('SUB') -> ?SUB ;
m_to_op('DIV') -> ?DIV ;
m_to_op('MOD') -> ?MOD ;
m_to_op('POW') -> ?POW ;
m_to_op('LT') -> ?LT ;
m_to_op('GT') -> ?GT ;
m_to_op('EQ') -> ?EQ ;
m_to_op('ELT') -> ?ELT ;
m_to_op('EGT') -> ?EGT ;
m_to_op('NEQ') -> ?NEQ ;
m_to_op('AND') -> ?AND ;
m_to_op('OR') -> ?OR ;
m_to_op('NOT') -> ?NOT ;
m_to_op('TUPLE') -> ?TUPLE ;
m_to_op('ELEMENT') -> ?ELEMENT ;
m_to_op('MAP_EMPTY') -> ?MAP_EMPTY ;
m_to_op('MAP_LOOKUP') -> ?MAP_LOOKUP ;
m_to_op('MAP_UPDATE') -> ?MAP_UPDATE ;
m_to_op('MAP_DELETE') -> ?MAP_DELETE ;
m_to_op('MAP_MEMBER') -> ?MAP_MEMBER ;
m_to_op('MAP_FROM_LIST') -> ?MAP_FROM_LIST ;
m_to_op('NIL') -> ?NIL ;
m_to_op('IS_NIL') -> ?IS_NIL ;
m_to_op('CONS') -> ?CONS ;
m_to_op('HD') -> ?HD ;
m_to_op('TL') -> ?TL ;
m_to_op('LENGTH') -> ?LENGTH ;
m_to_op('STR_EQ') -> ?STR_EQ ;
m_to_op('STR_JOIN') -> ?STR_JOIN ;
m_to_op('ADDR_TO_STR') -> ?ADDR_TO_STR ;
m_to_op('STR_REVERSE') -> ?STR_REVERSE ;
m_to_op('INT_TO_ADDR') -> ?INT_TO_ADDR ;
m_to_op('VARIANT') -> ?VARIANT ;
m_to_op('VARIANT_TEST') -> ?VARIANT_TEST ;
m_to_op('VARIANT_ELEMENT') -> ?VARIANT_ELEMENT ;
m_to_op('BITS_NONEA') -> ?BITS_NONEA ;
m_to_op('BITS_ALL') -> ?BITS_ALL ;
m_to_op('BITS_ALLA') -> ?BITS_ALLA ;
m_to_op('BITS_SET') -> ?BITS_SET ;
m_to_op('BITS_CLEAR') -> ?BITS_CLEAR ;
m_to_op('BITS_TEST') -> ?BITS_TEST ;
m_to_op('BITS_SUM') -> ?BITS_SUM ;
m_to_op('BITS_OR') -> ?BITS_OR ;
m_to_op('BITS_AND') -> ?BITS_AND ;
m_to_op('BITS_DIFF') -> ?BITS_DIFF ;
m_to_op('ADDRESS') -> ?ADDRESS ;
m_to_op('BALANCE') -> ?BALANCE ;
m_to_op('ORIGIN') -> ?ORIGIN ;
m_to_op('CALLER') -> ?CALLER ;
m_to_op('GASPRICE') -> ?GASPRICE ;
m_to_op('BLOCKHASH') -> ?BLOCKHASH ;
m_to_op('BENEFICIARY') -> ?BENEFICIARY ;
m_to_op('TIMESTAMP') -> ?TIMESTAMP ;
m_to_op('NUMBER') -> ?NUMBER ;
m_to_op('DIFFICULTY') -> ?DIFFICULTY ;
m_to_op('GASLIMIT') -> ?GASLIMIT ;
m_to_op('GAS') -> ?GAS ;
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('ABORT') -> ?ABORT ;
m_to_op('EXIT') -> ?EXIT ;
m_to_op('DEACTIVATE') -> ?DEACTIVATE ;
m_to_op('INC') -> ?INC ;
m_to_op('DEC') -> ?DEC ;
m_to_op('INCA') -> ?INCA ;
m_to_op('DECA') -> ?DECA ;
m_to_op('INT_TO_STR') -> ?INT_TO_STR ;
m_to_op('SPEND') -> ?SPEND ;
m_to_op('ORACLE_REGISTER') -> ?ORACLE_REGISTER ;
m_to_op('ORACLE_QUERY') -> ?ORACLE_QUERY ;
m_to_op('ORACLE_RESPOND') -> ?ORACLE_RESPOND ;
m_to_op('ORACLE_EXTEND') -> ?ORACLE_EXTEND ;
m_to_op('ORACLE_GET_ANSWER') -> ?ORACLE_GET_ANSWER ;
m_to_op('ORACLE_GET_QUESTION') -> ?ORACLE_GET_QUESTION ;
m_to_op('ORACLE_QUERY_FEE') -> ?ORACLE_QUERY_FEE ;
m_to_op('AENS_RESOLVE') -> ?AENS_RESOLVE ;
m_to_op('AENS_PRECLAIM') -> ?AENS_PRECLAIM ;
m_to_op('AENS_CLAIM') -> ?AENS_CLAIM ;
m_to_op('AENS_UPDATE') -> ?AENS_UPDATE ;
m_to_op('AENS_TRANSFER') -> ?AENS_TRANSFER ;
m_to_op('AENS_REVOKE') -> ?AENS_REVOKE ;
m_to_op('ECVERIFY') -> ?ECVERIFY ;
m_to_op('SHA3') -> ?SHA3 ;
m_to_op('SHA256') -> ?SHA256 ;
m_to_op('BLAKE2B') -> ?BLAKE2B ;
m_to_op('RETURNR') -> ?RETURNR ;
m_to_op('MAP_LOOKUPD') -> ?MAP_LOOKUPD ;
m_to_op('SWITCH_V2') -> ?SWITCH_V2 ;
m_to_op('SWITCH_V3') -> ?SWITCH_V3 ;
m_to_op('SWITCH_VN') -> ?SWITCH_VN ;
m_to_op('FUNCTION') -> ?FUNCTION ;
m_to_op('EXTEND') -> ?EXTEND.
args(?NOP) -> 0;
args(?RETURN) -> 0;
args(?INCA) -> 0;
args(?DECA) -> 0;
args(?DUPA) -> 0;
args(?BITS_NONEA) -> 0;
args(?BITS_ALLA) -> 0;
args(?INC) -> 1;
args(?DEC) -> 1;
args(?RETURNR) -> 1;
args(?PUSH) -> 1;
args(?JUMP) -> 1;
args(?CALL) -> 1;
args(?CALL_T) -> 1;
args(?TUPLE) -> 1;
args(?MAP_EMPTY) -> 1;
args(?DUP) -> 1;
args(?POP) -> 1;
args(?NIL) -> 1;
args(?BITS_NONE) -> 1;
args(?BITS_ALL) -> 1;
args(?ADDRESS) -> 1;
args(?BALANCE) -> 1;
args(?ORIGIN) -> 1;
args(?CALLER) -> 1;
args(?GASPRICE) -> 1;
args(?BLOCKHASH) -> 1;
args(?BENEFICIARY) -> 1;
args(?TIMESTAMP) -> 1;
args(?NUMBER) -> 1;
args(?DIFFICULTY)-> 1;
args(?GASLIMIT) -> 1;
args(?GAS) -> 1;
args(?ABORT) -> 1;
args(?EXIT) -> 1;
args(?JUMPIF) -> 2;
args(?CALL_R) -> 2;
args(?CALL_TR) -> 2;
args(?HD) -> 2;
args(?TL) -> 2;
args(?NOT) -> 2;
args(?STORE) -> 2;
args(?LENGTH) -> 2;
args(?IS_NIL) -> 2;
args(?BITS_SUM) -> 2;
args(?BITS_ALL_N) -> 2;
args(?ADDR_TO_STR) -> 2;
args(?STR_REVERSE) -> 2;
args(?INT_TO_ADDR) -> 2;
args(?MAP_FROM_LIST) -> 2;
args(?ADD) -> 3;
args(?SUB) -> 3;
args(?MUL) -> 3;
args(?DIV) -> 3;
args(?MOD) -> 3;
args(?POW) -> 3;
args(?AND) -> 3;
args(?OR) -> 3;
args(?LT) -> 3;
args(?GT) -> 3;
args(?EGT) -> 3;
args(?ELT) -> 3;
args(?EQ) -> 3;
args(?NEQ) -> 3;
args(?CONS) -> 3;
args(?STR_EQ) -> 3;
args(?STR_JOIN) -> 3;
args(?MAP_MEMBER) -> 3;
args(?MAP_LOOKUP) -> 3;
args(?MAP_DELETE) -> 3;
args(?BITS_OR) -> 3;
args(?BITS_AND) -> 3;
args(?BITS_SET) -> 3;
args(?BITS_DIFF) -> 3;
args(?BITS_TEST) -> 3;
args(?BITS_CLEAR) -> 3;
args(?VARIANT_TEST) -> 3;
args(?VARIANT_ELEMENT) -> 3;
args(?INT_TO_STR) -> 3;
args(?SWITCH_V2) -> 3;
args(?SWITCH_V3) -> 4;
args(?ELEMENT) -> 4;
args(?VARIANT) -> 4;
args(?MAP_UPDATE) -> 4;
args(?MAP_LOOKUPD) -> 4;
args(?SWITCH_VN) -> 2;
args(_) -> 0. %% TODO do not allow this
end_bb(?RETURN) -> true;
end_bb(?RETURNR) -> true;
end_bb(?JUMP) -> true;
end_bb(?JUMPIF) -> true;
end_bb(?CALL) -> true;
end_bb(?CALL_T) -> true;
end_bb(?CALL_R) -> true;
end_bb(?CALL_TR) -> true;
end_bb(?SWITCH_V2) -> true;
end_bb(?SWITCH_V3) -> true;
end_bb(?SWITCH_VN) -> true;
end_bb(?ABORT) -> true;
end_bb(?EXIT) -> true;
end_bb(_) -> false.