1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

func/fift: bugfixes

This commit is contained in:
ton 2019-10-09 20:00:54 +04:00
parent f67f5d879b
commit 38c3e39066
41 changed files with 248 additions and 99 deletions

View file

@ -193,21 +193,21 @@ void AsmOp::out(std::ostream& os) const {
os << (b ? "SWAP" : "NOP");
break;
}
os << "s" << a << " s" << b << " XCHG";
os << SReg(a) << ' ' << SReg(b) << " XCHG";
break;
case a_push:
if (!(a & -2)) {
os << (a ? "OVER" : "DUP");
break;
}
os << "s" << a << " PUSH";
os << SReg(a) << " PUSH";
break;
case a_pop:
if (!(a & -2)) {
os << (a ? "NIP" : "DROP");
break;
}
os << "s" << a << " POP";
os << SReg(a) << " POP";
break;
default:
throw src::Fatal{"unknown assembler operation"};

View file

@ -406,8 +406,11 @@ bool Op::generate_code_step(Stack& stack) {
}
func->compile(stack.o, res, args); // compile res := f (args)
} else {
auto fv = dynamic_cast<const SymValCodeFunc*>(fun_ref->value);
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size(), (int)left.size());
bool is_inline = (fv && (fv->flags & 3));
stack.o << AsmOp::Custom(name + (is_inline ? " INLINECALLDICT" : " CALLDICT"), (int)right.size(),
(int)left.size());
}
}
stack.s.resize(k);
@ -553,7 +556,7 @@ bool Op::generate_code_step(Stack& stack) {
stack.opt_show();
stack.s.pop_back();
stack.modified();
if (!next->is_empty()) {
if (true || !next->is_empty()) {
stack.o << "REPEAT:<{";
stack.o.indent();
stack.forget_const();
@ -601,7 +604,7 @@ bool Op::generate_code_step(Stack& stack) {
case _Until: {
// stack.drop_vars_except(block0->var_info);
// stack.opt_show();
if (!next->is_empty()) {
if (true || !next->is_empty()) {
stack.o << "UNTIL:<{";
stack.o.indent();
stack.forget_const();
@ -632,7 +635,7 @@ bool Op::generate_code_step(Stack& stack) {
stack.drop_vars_except(block0->var_info);
stack.opt_show();
StackLayout layout1 = stack.vars();
bool next_empty = next->is_empty();
bool next_empty = false && next->is_empty();
stack.o << "WHILE:<{";
stack.o.indent();
stack.forget_const();

View file

@ -83,7 +83,8 @@ void generate_output_func(SymDef* func_sym) {
if (verbosity >= 2) {
std::cerr << "\n---------- resulting code for " << name << " -------------\n";
}
*outs << std::string(indent * 2, ' ') << name << " PROC:<{\n";
bool inline_ref = (func_val->flags & 2);
*outs << std::string(indent * 2, ' ') << name << " PROC" << (inline_ref ? "REF" : "") << ":<{\n";
code.generate_code(
*outs,
(stack_layout_comments ? Stack::_StkCmt | Stack::_CptStkCmt : 0) | (opt_level < 2 ? Stack::_DisableOpt : 0),

View file

@ -79,6 +79,9 @@ enum Keyword {
_RshiftLet,
_RshiftRLet,
_RshiftCLet,
_AndLet,
_OrLet,
_XorLet,
_Int,
_Cell,
_Slice,
@ -90,6 +93,8 @@ enum Keyword {
_Asm,
_Impure,
_Extern,
_Inline,
_InlineRef,
_MethodId,
_Operator,
_Infix,
@ -632,6 +637,9 @@ struct CodeBlob {
}
bool import_params(FormalArgList arg_list);
var_idx_t create_var(int cls, TypeExpr* var_type = 0, SymDef* sym = 0, const SrcLocation* loc = 0);
var_idx_t create_tmp_var(TypeExpr* var_type = 0, const SrcLocation* loc = 0) {
return create_var(TmpVar::_Tmp, var_type, nullptr, loc);
}
int split_vars(bool strict = false);
bool compute_used_code_vars();
bool compute_used_code_vars(std::unique_ptr<Op>& ops, const VarDescrList& var_info, bool edit) const;
@ -670,8 +678,9 @@ struct SymVal : sym::SymValBase {
TypeExpr* sym_type;
td::RefInt256 method_id;
bool impure;
short flags; // +1 = inline, +2 = inline_ref
SymVal(int _type, int _idx, TypeExpr* _stype = nullptr, bool _impure = false)
: sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure) {
: sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure), flags(0) {
}
~SymVal() override = default;
TypeExpr* get_type() const {
@ -802,6 +811,10 @@ struct Expr {
int define_new_vars(CodeBlob& code);
int predefine_vars();
std::vector<var_idx_t> pre_compile(CodeBlob& code) const;
var_idx_t new_tmp(CodeBlob& code) const;
std::vector<var_idx_t> new_tmp_vect(CodeBlob& code) const {
return {new_tmp(code)};
}
};
/*

View file

@ -212,6 +212,10 @@ int Expr::predefine_vars() {
return 0;
}
var_idx_t Expr::new_tmp(CodeBlob& code) const {
return code.create_tmp_var(e_type, &here);
}
std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
switch (cls) {
case _Tuple: {
@ -241,8 +245,7 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
res.insert(res.end(), add.cbegin(), add.cend());
}
}
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
std::vector<var_idx_t> rvect{rv};
auto rvect = new_tmp_vect(code);
auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), sym);
if (flags & _IsImpure) {
op.flags |= Op::_Impure;
@ -256,57 +259,52 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
return {val};
case _VarApply:
if (args[0]->cls == _Glob) {
std::vector<var_idx_t> res = args[1]->pre_compile(code);
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
std::vector<var_idx_t> rvect{rv};
auto res = args[1]->pre_compile(code);
auto rvect = new_tmp_vect(code);
auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), args[0]->sym);
if (args[0]->flags & _IsImpure) {
op.flags |= Op::_Impure;
}
return rvect;
} else {
std::vector<var_idx_t> res = args[1]->pre_compile(code);
std::vector<var_idx_t> tfunc = args[0]->pre_compile(code);
auto res = args[1]->pre_compile(code);
auto tfunc = args[0]->pre_compile(code);
if (tfunc.size() != 1) {
throw src::Fatal{"stack tuple used as a function"};
}
res.push_back(tfunc[0]);
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
std::vector<var_idx_t> rvect{rv};
auto rvect = new_tmp_vect(code);
code.emplace_back(here, Op::_CallInd, rvect, std::move(res));
return rvect;
}
case _Const: {
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
std::vector<var_idx_t> rvect{rv};
auto rvect = new_tmp_vect(code);
code.emplace_back(here, Op::_IntConst, rvect, intval);
return rvect;
}
case _Glob: {
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
std::vector<var_idx_t> rvect{rv};
auto rvect = new_tmp_vect(code);
code.emplace_back(here, Op::_GlobVar, rvect, std::vector<var_idx_t>{}, sym);
return rvect;
}
case _Letop: {
std::vector<var_idx_t> right = args[1]->pre_compile(code);
std::vector<var_idx_t> left = args[0]->pre_compile(code);
code.emplace_back(here, Op::_Let, left, std::move(right));
return left;
auto right = args[1]->pre_compile(code);
auto left = args[0]->pre_compile(code);
code.emplace_back(here, Op::_Let, std::move(left), right);
return right;
}
case _LetFirst: {
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
std::vector<var_idx_t> right = args[1]->pre_compile(code);
std::vector<var_idx_t> left = args[0]->pre_compile(code);
left.push_back(rv);
auto rvect = new_tmp_vect(code);
auto right = args[1]->pre_compile(code);
auto left = args[0]->pre_compile(code);
left.push_back(rvect[0]);
code.emplace_back(here, Op::_Let, std::move(left), std::move(right));
return std::vector<var_idx_t>{rv};
return rvect;
}
case _CondExpr: {
auto cond = args[0]->pre_compile(code);
assert(cond.size() == 1);
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
std::vector<var_idx_t> rvect{rv};
auto rvect = new_tmp_vect(code);
Op& if_op = code.emplace_back(here, Op::_If, cond);
code.push_set_cur(if_op.block0);
code.emplace_back(here, Op::_Let, rvect, args[1]->pre_compile(code));

View file

@ -79,7 +79,10 @@ void define_keywords() {
.add_keyword("<<=", Kw::_LshiftLet)
.add_keyword(">>=", Kw::_RshiftLet)
.add_keyword(">>~=", Kw::_RshiftRLet)
.add_keyword(">>^=", Kw::_RshiftCLet);
.add_keyword(">>^=", Kw::_RshiftCLet)
.add_keyword("&=", Kw::_AndLet)
.add_keyword("|=", Kw::_OrLet)
.add_keyword("^=", Kw::_XorLet);
sym::symbols.add_keyword("return", Kw::_Return)
.add_keyword("var", Kw::_Var)
@ -105,6 +108,8 @@ void define_keywords() {
sym::symbols.add_keyword("extern", Kw::_Extern)
.add_keyword("asm", Kw::_Asm)
.add_keyword("impure", Kw::_Impure)
.add_keyword("inline", Kw::_Inline)
.add_keyword("inline_ref", Kw::_InlineRef)
.add_keyword("method_id", Kw::_MethodId)
.add_keyword("operator", Kw::_Operator)
.add_keyword("infix", Kw::_Infix)

View file

@ -428,7 +428,6 @@ Expr* parse_expr80(Lexer& lex, CodeBlob& code, bool nv) {
res->flags = Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0);
res->deduce_type(lex.cur());
if (modify) {
// FIXME (use _LetFirst instead of _Letop)
auto tmp = res;
res = new Expr{Expr::_LetFirst, {obj->copy(), tmp}};
res->here = loc;
@ -587,7 +586,8 @@ Expr* parse_expr10(Lexer& lex, CodeBlob& code, bool nv) {
auto x = parse_expr13(lex, code, nv);
int t = lex.tp();
if (t == _PlusLet || t == _MinusLet || t == _TimesLet || t == _DivLet || t == _DivRLet || t == _DivCLet ||
t == _ModLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet || t == _RshiftRLet) {
t == _ModLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet || t == _RshiftRLet || t == _AndLet ||
t == _OrLet || t == _XorLet) {
x->chk_lvalue(lex.cur());
x->chk_rvalue(lex.cur());
sym_idx_t name = symbols.lookup_add(std::string{"^_"} + lex.cur().str + "_");
@ -974,6 +974,11 @@ void parse_func_def(Lexer& lex) {
if (impure) {
lex.next();
}
int f = 0;
if (lex.tp() == _Inline || lex.tp() == _InlineRef) {
f = (lex.tp() == _Inline) ? 1 : 2;
lex.next();
}
td::RefInt256 method_id;
std::string method_name;
if (lex.tp() == _MethodId) {
@ -1071,6 +1076,17 @@ void parse_func_def(Lexer& lex) {
lex.cur().error("integer method identifier for `"s + func_name.str + "` changed to a different value");
}
}
if (f) {
auto val = dynamic_cast<SymVal*>(func_sym->value);
if (!val) {
lex.cur().error("cannot set unknown function `"s + func_name.str + "` as an inline");
}
if (!(val->flags & 3)) {
val->flags = (short)(val->flags | f);
} else if ((val->flags & 3) != f) {
lex.cur().error("inline mode for `"s + func_name.str + "` changed with respect to a previous declaration");
}
}
if (verbosity >= 1) {
std::cerr << "new type of function " << func_name.str << " : " << func_type << std::endl;
}

20
crypto/func/test/b3.fc Normal file
View file

@ -0,0 +1,20 @@
;; inline test
_ unpack() inline {
var ds = get_data().begin_parse();
var res = (ds~load_uint(8), ds~load_int(32), ds~load_int(32));
return res;
}
() pack(a, x, y) impure inline_ref {
set_data(begin_cell()
.store_uint(a, 8)
.store_int(x, 32)
.store_int(y, 32)
.end_cell());
}
() main() impure {
var (a, x, y) = unpack();
x += y;
pack(a, x, y);
}

9
crypto/func/test/w1.fc Normal file
View file

@ -0,0 +1,9 @@
(int, int) nested_if(int id) method_id {
dump_stack();
if (id > 0) {
if (id > 10) {
return (2 * id, 3 * id);
}
}
return (5, 6);
}

14
crypto/func/test/w2.fc Normal file
View file

@ -0,0 +1,14 @@
_ f(cs) {
return (cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8));
}
_ main(cs) {
var (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19) = f(cs);
return x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
+ x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19;
}