1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-12 11:12:16 +00:00

[Tolk] Refactor: get rid of split_vars, construct valid LET ops

In FunC (and in Tolk before), tensor vars (actually occupying
several stack slots) were represented as a single var in terms
or IR vars (Ops):
> var a = (1, 2);
> LET (_i) = (_1, _2)

Now, every tensor of N stack slots is represented as N IR vars.
> LET (_i, _j) = (_1, _2)

This will give an ability to control access to parts of a tensor
when implementing `tensorVar.0` syntax.
This commit is contained in:
tolk-vm 2024-12-18 19:26:26 +03:00
parent 989629a832
commit 565bc59735
No known key found for this signature in database
GPG key ID: 7905DD7FE0324B12
17 changed files with 100 additions and 217 deletions

View file

@ -104,9 +104,9 @@ fun testStartBalanceCodegen2() {
testDumpDontPolluteStack PROC:<{
...
DUMPSTK
x{6d79} PUSHSLICE // f s _9
x{6d79} PUSHSLICE // f s _5
STRDUMP DROP
SBITS // f _11
SBITS // f _6
}>
"""

View file

@ -220,11 +220,11 @@ Note, that since 'compute-asm-ltr' became on be default, chaining methods codege
1 PUSHINT // _0 _1=1
SWAP // _1=1 _0
32 STU // _0
2 PUSHINT // _0 _5=2
SWAP // _5=2 _0
2 PUSHINT // _0 _4=2
SWAP // _4=2 _0
32 STU // _0
3 PUSHINT // _0 _9=3
SWAP // _9=3 _0
3 PUSHINT // _0 _7=3
SWAP // _7=3 _0
32 STU // _0
}>
"""

View file

@ -332,15 +332,15 @@ These are moments of future optimizations. For now, it's more than enough.
DUP // x x
IFNOTJMP:<{ // x
DROP //
1 PUSHINT // _7=1
1 PUSHINT // _5=1
}> // x
DUP // x x
IFNOTJMP:<{ // x
DROP //
1 PUSHINT // _8=1
1 PUSHINT // _6=1
}> // x
100 THROWIFNOT
-4 PUSHINT // _12=-4
-4 PUSHINT // _9=-4
}>
"""

View file

@ -307,7 +307,7 @@ fun main(){}
...
incrementTwoInPlace CALLDICT // x y sum1
-ROT
10 PUSHINT // sum1 x y _8=10
10 PUSHINT // sum1 x y _10=10
incrementTwoInPlace CALLDICT // sum1 x y sum2
s1 s3 s0 XCHG3 // x y sum1 sum2
}>
@ -317,8 +317,8 @@ fun main(){}
"""
load_next PROC:<{
// cs
32 LDI // _3 cs
SWAP // cs _3
32 LDI // _4 cs
SWAP // cs _4
}>
"""

View file

@ -113,7 +113,7 @@ fun main() {
CONS // numbers
UNCONS // h numbers
DUP // h numbers numbers
CAR // h numbers _12
CAR // h numbers _13
"""
@fif_codegen
@ -133,7 +133,7 @@ fun main() {
"""
test7 PROC:<{
...
LDOPTREF // b _18 _17
LDOPTREF // b _8 _7
DROP // b c
ISNULL // b _11
10 MULCONST // b _13

View file

@ -31,16 +31,6 @@ void TmpVar::dump(std::ostream& os) const {
os << " : " << v_type << " (width ";
os << v_type->calc_width_on_stack();
os << ")";
if (coord > 0) {
os << " = _" << (coord >> 8) << '.' << (coord & 255);
} else if (coord < 0) {
int n = (~coord >> 8), k = (~coord & 0xff);
if (k) {
os << " = (_" << n << ".._" << (n + k - 1) << ")";
} else {
os << " = ()";
}
}
os << std::endl;
}
@ -51,7 +41,7 @@ void TmpVar::show(std::ostream& os, int omit_idx) const {
return;
}
}
os << '_' << idx;
os << '_' << ir_idx;
}
std::ostream& operator<<(std::ostream& os, const TmpVar& var) {
@ -182,47 +172,6 @@ void VarDescrList::show(std::ostream& os) const {
os << " ]\n";
}
void Op::split_vars(const std::vector<TmpVar>& vars) {
split_var_list(left, vars);
split_var_list(right, vars);
for (auto& op : block0) {
op.split_vars(vars);
}
for (auto& op : block1) {
op.split_vars(vars);
}
}
void Op::split_var_list(std::vector<var_idx_t>& var_list, const std::vector<TmpVar>& vars) {
int new_size = 0, changes = 0;
for (var_idx_t v : var_list) {
int c = vars.at(v).coord;
if (c < 0) {
++changes;
new_size += (~c & 0xff);
} else {
++new_size;
}
}
if (!changes) {
return;
}
std::vector<var_idx_t> new_var_list;
new_var_list.reserve(new_size);
for (var_idx_t v : var_list) {
int c = vars.at(v).coord;
if (c < 0) {
int n = (~c >> 8), k = (~c & 0xff);
while (k-- > 0) {
new_var_list.push_back(n++);
}
} else {
new_var_list.push_back(v);
}
}
var_list = std::move(new_var_list);
}
void Op::show(std::ostream& os, const std::vector<TmpVar>& vars, std::string pfx, int mode) const {
if (mode & 2) {
os << pfx << " [";
@ -444,26 +393,22 @@ void CodeBlob::print(std::ostream& os, int flags) const {
os << "-------- END ---------\n\n";
}
var_idx_t CodeBlob::create_var(TypePtr var_type, const LocalVarData* v_sym, SrcLocation location) {
vars.emplace_back(var_cnt, var_type, v_sym, location);
return var_cnt++;
std::vector<var_idx_t> CodeBlob::create_var(TypePtr var_type, const LocalVarData* v_sym, SrcLocation loc) {
std::vector<var_idx_t> ir_idx;
ir_idx.reserve(var_type->calc_width_on_stack());
if (const TypeDataTensor* t_tensor = var_type->try_as<TypeDataTensor>()) {
for (TypePtr item : t_tensor->items) {
std::vector<var_idx_t> nested = create_var(item, v_sym, loc);
ir_idx.insert(ir_idx.end(), nested.begin(), nested.end());
}
bool CodeBlob::import_params(FormalArgList&& arg_list) {
if (var_cnt || in_var_cnt) {
return false;
} else if (var_type != TypeDataVoid::create()) {
tolk_assert(var_type->calc_width_on_stack() == 1);
vars.emplace_back(var_cnt, var_type, v_sym, loc);
ir_idx.emplace_back(var_cnt);
var_cnt++;
}
std::vector<var_idx_t> list;
for (const auto& par : arg_list) {
TypePtr arg_type;
const LocalVarData* arg_sym;
SrcLocation arg_loc;
std::tie(arg_type, arg_sym, arg_loc) = par;
list.push_back(create_var(arg_type, arg_sym, arg_loc));
}
emplace_back(loc, Op::_Import, list);
in_var_cnt = var_cnt;
return true;
tolk_assert(static_cast<int>(ir_idx.size()) == var_type->calc_width_on_stack());
return ir_idx;
}
} // namespace tolk

View file

@ -26,40 +26,6 @@ namespace tolk {
*
*/
int CodeBlob::split_vars(bool strict) {
int n = var_cnt, changes = 0;
for (int j = 0; j < var_cnt; j++) {
TmpVar& var = vars[j];
int width_j = var.v_type->calc_width_on_stack();
if (strict && width_j < 0) {
throw ParseError{var.where, "variable does not have fixed width, cannot manipulate it"};
}
if (width_j == 1) {
continue;
}
std::vector<TypePtr> comp_types;
var.v_type->extract_components(comp_types);
tolk_assert(width_j <= 254 && n <= 0x7fff00);
tolk_assert((unsigned)width_j == comp_types.size());
var.coord = ~((n << 8) + width_j);
for (int i = 0; i < width_j; i++) {
auto v = create_var(comp_types[i], vars[j].v_sym, vars[j].where);
tolk_assert(v == n + i);
tolk_assert(vars[v].idx == v);
vars[v].coord = ((int)j << 8) + i + 1;
}
n += width_j;
++changes;
}
if (!changes) {
return 0;
}
for (auto& op : ops) {
op.split_vars(vars);
}
return changes;
}
bool CodeBlob::compute_used_code_vars() {
VarDescrList empty_var_info;
return compute_used_code_vars(ops, empty_var_info, true);

View file

@ -202,8 +202,8 @@ td::Result<std::vector<TypePtr>> deduce_substitutionTs_on_generic_func_call(cons
try {
GenericSubstitutionsDeduceForFunctionCall deducing(called_fun);
for (const LocalVarData& param : called_fun->parameters) {
if (param.declared_type->has_genericT_inside() && param.idx < static_cast<int>(arg_types.size())) {
deducing.consider_next_condition(param.declared_type, arg_types[param.idx]);
if (param.declared_type->has_genericT_inside() && param.param_idx < static_cast<int>(arg_types.size())) {
deducing.consider_next_condition(param.declared_type, arg_types[param.param_idx]);
}
}
int idx = deducing.get_first_not_deduced_idx();
@ -233,7 +233,7 @@ const FunctionData* instantiate_generic_function(SrcLocation loc, const Function
std::vector<LocalVarData> parameters;
parameters.reserve(fun_ref->get_num_params());
for (const LocalVarData& orig_p : fun_ref->parameters) {
parameters.emplace_back(orig_p.name, orig_p.loc, replace_genericT_with_deduced(orig_p.declared_type, fun_ref->genericTs, substitutionTs), orig_p.flags, orig_p.idx);
parameters.emplace_back(orig_p.name, orig_p.loc, replace_genericT_with_deduced(orig_p.declared_type, fun_ref->genericTs, substitutionTs), orig_p.flags, orig_p.param_idx);
}
TypePtr declared_return_type = replace_genericT_with_deduced(fun_ref->declared_return_type, fun_ref->genericTs, substitutionTs);
const GenericsInstantiation* instantiationTs = new GenericsInstantiation(loc, std::move(substitutionTs));

View file

@ -34,15 +34,15 @@
namespace tolk {
struct LValGlobs {
std::vector<std::pair<const GlobalVarData*, var_idx_t>> globs;
std::vector<std::pair<const GlobalVarData*, std::vector<var_idx_t>>> globs;
void add_modified_glob(const GlobalVarData* g_sym, var_idx_t local_ir_idx) {
globs.emplace_back(g_sym, local_ir_idx);
void add_modified_glob(const GlobalVarData* g_sym, std::vector<var_idx_t> local_ir_idx) {
globs.emplace_back(g_sym, std::move(local_ir_idx));
}
void gen_ops_set_globs(CodeBlob& code, SrcLocation loc) const {
for (const auto& [g_sym, ir_idx] : globs) {
Op& op = code.emplace_back(loc, Op::_SetGlob, std::vector<var_idx_t>{}, std::vector<var_idx_t>{ ir_idx }, g_sym);
Op& op = code.emplace_back(loc, Op::_SetGlob, std::vector<var_idx_t>{}, ir_idx, g_sym);
op.set_impure_flag();
}
}
@ -93,7 +93,9 @@ static std::vector<std::vector<var_idx_t>> pre_compile_tensor_inner(CodeBlob& co
void on_var_modified(var_idx_t ir_idx, SrcLocation loc, CodeBlob& code) {
tolk_assert(is_watched(ir_idx));
var_idx_t tmp_idx = code.create_tmp_var(code.vars[ir_idx].v_type, loc);
std::vector<var_idx_t> tmp_idx_arr = code.create_tmp_var(code.vars[ir_idx].v_type, loc);
tolk_assert(tmp_idx_arr.size() == 1);
var_idx_t tmp_idx = tmp_idx_arr[0];
code.emplace_back(loc, Op::_Let, std::vector{tmp_idx}, std::vector{ir_idx});
for (std::vector<var_idx_t>& prev_vars : res_lists) {
std::replace(prev_vars.begin(), prev_vars.end(), ir_idx, tmp_idx);
@ -143,7 +145,7 @@ static std::vector<var_idx_t> pre_compile_let(CodeBlob& code, AnyExprV lhs, AnyE
std::vector<var_idx_t> right = pre_compile_expr(rhs, code);
const TypeDataTypedTuple* inferred_tuple = rhs->inferred_type->try_as<TypeDataTypedTuple>();
std::vector<TypePtr> types_list = inferred_tuple->items;
std::vector<var_idx_t> rvect = {code.create_tmp_var(TypeDataTensor::create(std::move(types_list)), rhs->loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(TypeDataTensor::create(std::move(types_list)), rhs->loc);
code.emplace_back(lhs->loc, Op::_UnTuple, rvect, std::move(right));
LValGlobs globs;
std::vector<var_idx_t> left = pre_compile_tensor(code, lhs->as<ast_typed_tuple>()->get_items(), &globs);
@ -164,7 +166,7 @@ static std::vector<var_idx_t> pre_compile_let(CodeBlob& code, AnyExprV lhs, AnyE
static std::vector<var_idx_t> gen_op_call(CodeBlob& code, TypePtr ret_type, SrcLocation here,
std::vector<var_idx_t>&& args_vars, const FunctionData* fun_ref) {
std::vector<var_idx_t> rvect = {code.create_tmp_var(ret_type, here)};
std::vector<var_idx_t> rvect = code.create_tmp_var(ret_type, here);
Op& op = code.emplace_back(here, Op::_Call, rvect, std::move(args_vars), fun_ref);
if (!fun_ref->is_marked_as_pure()) {
op.set_impure_flag();
@ -175,9 +177,9 @@ static std::vector<var_idx_t> gen_op_call(CodeBlob& code, TypePtr ret_type, SrcL
static std::vector<var_idx_t> process_symbol(SrcLocation loc, const Symbol* sym, CodeBlob& code, LValGlobs* lval_globs) {
if (const auto* glob_ref = sym->try_as<GlobalVarData>()) {
std::vector<var_idx_t> rvect = {code.create_tmp_var(glob_ref->declared_type, loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(glob_ref->declared_type, loc);
if (lval_globs) {
lval_globs->add_modified_glob(glob_ref, rvect[0]);
lval_globs->add_modified_glob(glob_ref, rvect);
return rvect;
} else {
code.emplace_back(loc, Op::_GlobVar, rvect, std::vector<var_idx_t>{}, glob_ref);
@ -186,22 +188,25 @@ static std::vector<var_idx_t> process_symbol(SrcLocation loc, const Symbol* sym,
}
if (const auto* const_ref = sym->try_as<GlobalConstData>()) {
if (const_ref->is_int_const()) {
std::vector<var_idx_t> rvect = {code.create_tmp_var(TypeDataInt::create(), loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(TypeDataInt::create(), loc);
code.emplace_back(loc, Op::_IntConst, rvect, const_ref->as_int_const());
return rvect;
} else {
std::vector<var_idx_t> rvect = {code.create_tmp_var(TypeDataSlice::create(), loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(TypeDataSlice::create(), loc);
code.emplace_back(loc, Op::_SliceConst, rvect, const_ref->as_slice_const());
return rvect;
}
}
if (const auto* fun_ref = sym->try_as<FunctionData>()) {
std::vector<var_idx_t> rvect = {code.create_tmp_var(fun_ref->inferred_full_type, loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(fun_ref->inferred_full_type, loc);
code.emplace_back(loc, Op::_GlobVar, rvect, std::vector<var_idx_t>{}, fun_ref);
return rvect;
}
if (const auto* var_ref = sym->try_as<LocalVarData>()) {
return {var_ref->idx};
#ifdef TOLK_DEBUG
tolk_assert(static_cast<int>(var_ref->ir_idx.size()) == var_ref->declared_type->calc_width_on_stack());
#endif
return var_ref->ir_idx;
}
throw Fatal("process_symbol");
}
@ -244,7 +249,7 @@ static std::vector<var_idx_t> process_binary_operator(V<ast_binary_operator> v,
v_b_ne_0->mutate()->assign_fun_ref(lookup_global_symbol("_!=_")->as<FunctionData>());
std::vector<var_idx_t> cond = pre_compile_expr(v->get_lhs(), code);
tolk_assert(cond.size() == 1);
std::vector<var_idx_t> rvect = {code.create_tmp_var(v->inferred_type, v->loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(v->inferred_type, v->loc);
Op& if_op = code.emplace_back(v->loc, Op::_If, cond);
code.push_set_cur(if_op.block0);
code.emplace_back(v->loc, Op::_Let, rvect, pre_compile_expr(t == tok_logical_and ? v_b_ne_0 : v_1, code));
@ -266,7 +271,7 @@ static std::vector<var_idx_t> process_unary_operator(V<ast_unary_operator> v, Co
static std::vector<var_idx_t> process_ternary_operator(V<ast_ternary_operator> v, CodeBlob& code) {
std::vector<var_idx_t> cond = pre_compile_expr(v->get_cond(), code);
tolk_assert(cond.size() == 1);
std::vector<var_idx_t> rvect = {code.create_tmp_var(v->inferred_type, v->loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(v->inferred_type, v->loc);
Op& if_op = code.emplace_back(v->loc, Op::_If, cond);
code.push_set_cur(if_op.block0);
code.emplace_back(v->get_when_true()->loc, Op::_Let, rvect, pre_compile_expr(v->get_when_true(), code));
@ -299,7 +304,7 @@ static std::vector<var_idx_t> process_function_call(V<ast_function_call> v, Code
std::vector<var_idx_t> tfunc = pre_compile_expr(v->get_callee(), code);
tolk_assert(tfunc.size() == 1);
args_vars.push_back(tfunc[0]);
std::vector<var_idx_t> rvect = {code.create_tmp_var(v->inferred_type, v->loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(v->inferred_type, v->loc);
Op& op = code.emplace_back(v->loc, Op::_CallInd, rvect, std::move(args_vars));
op.set_impure_flag();
return rvect;
@ -361,8 +366,8 @@ static std::vector<var_idx_t> process_function_call(V<ast_function_call> v, Code
}
}
}
std::vector<var_idx_t> rvect = {code.create_tmp_var(real_ret_type, v->loc)};
left.push_back(rvect[0]);
std::vector<var_idx_t> rvect = code.create_tmp_var(real_ret_type, v->loc);
left.insert(left.end(), rvect.begin(), rvect.end());
code.on_var_modification(left, v->loc);
code.emplace_back(v->loc, Op::_Let, std::move(left), rvect_apply);
local_globs.gen_ops_set_globs(code, v->loc);
@ -388,21 +393,21 @@ static std::vector<var_idx_t> process_typed_tuple(V<ast_typed_tuple> v, CodeBlob
if (lval_globs) { // todo some time, make "var (a, [b,c]) = (1, [2,3])" work
v->error("[...] can not be used as lvalue here");
}
std::vector<var_idx_t> left = std::vector{code.create_tmp_var(v->inferred_type, v->loc)};
std::vector<var_idx_t> left = code.create_tmp_var(v->inferred_type, v->loc);
std::vector<var_idx_t> right = pre_compile_tensor(code, v->get_items());
code.emplace_back(v->loc, Op::_Tuple, left, std::move(right));
return left;
}
static std::vector<var_idx_t> process_int_const(V<ast_int_const> v, CodeBlob& code) {
std::vector<var_idx_t> rvect = {code.create_tmp_var(v->inferred_type, v->loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(v->inferred_type, v->loc);
code.emplace_back(v->loc, Op::_IntConst, rvect, v->intval);
return rvect;
}
static std::vector<var_idx_t> process_string_const(V<ast_string_const> v, CodeBlob& code) {
ConstantValue value = eval_const_init_value(v);
std::vector<var_idx_t> rvect = {code.create_tmp_var(v->inferred_type, v->loc)};
std::vector<var_idx_t> rvect = code.create_tmp_var(v->inferred_type, v->loc);
if (value.is_int()) {
code.emplace_back(v->loc, Op::_IntConst, rvect, value.as_int());
} else {
@ -426,9 +431,9 @@ static std::vector<var_idx_t> process_local_var(V<ast_local_var_lhs> v, CodeBlob
return process_symbol(v->loc, v->var_ref, code, nullptr);
}
tolk_assert(v->var_ref->idx == -1);
v->var_ref->mutate()->assign_idx(code.create_var(v->inferred_type, v->var_ref, v->loc));
return {v->var_ref->idx};
tolk_assert(v->var_ref->ir_idx.empty());
v->var_ref->mutate()->assign_ir_idx(code.create_var(v->inferred_type, v->var_ref, v->loc));
return v->var_ref->ir_idx;
}
static std::vector<var_idx_t> process_local_vars_declaration(V<ast_local_vars_declaration>, CodeBlob&) {
@ -439,7 +444,7 @@ static std::vector<var_idx_t> process_local_vars_declaration(V<ast_local_vars_de
static std::vector<var_idx_t> process_underscore(V<ast_underscore> v, CodeBlob& code) {
// when _ is used as left side of assignment, like `(cs, _) = cs.loadAndReturn()`
return {code.create_tmp_var(v->inferred_type, v->loc)};
return code.create_tmp_var(v->inferred_type, v->loc);
}
std::vector<var_idx_t> pre_compile_expr(AnyExprV v, CodeBlob& code, LValGlobs* lval_globs) {
@ -516,8 +521,8 @@ static void process_assert_statement(V<ast_assert_statement> v, CodeBlob& code)
static void process_catch_variable(AnyExprV v_catch_var, CodeBlob& code) {
if (auto v_ref = v_catch_var->try_as<ast_reference>(); v_ref && v_ref->sym) { // not underscore
const LocalVarData* var_ref = v_ref->sym->as<LocalVarData>();
tolk_assert(var_ref->idx == -1);
var_ref->mutate()->assign_idx(code.create_var(v_catch_var->inferred_type, var_ref, v_catch_var->loc));
tolk_assert(var_ref->ir_idx.empty());
var_ref->mutate()->assign_ir_idx(code.create_var(v_catch_var->inferred_type, var_ref, v_catch_var->loc));
}
}
@ -627,14 +632,13 @@ static void process_throw_statement(V<ast_throw_statement> v, CodeBlob& code) {
static void process_return_statement(V<ast_return_statement> v, CodeBlob& code) {
std::vector<var_idx_t> return_vars = v->has_return_value() ? pre_compile_expr(v->get_return_value(), code) : std::vector<var_idx_t>{};
if (code.fun_ref->does_return_self()) {
tolk_assert(return_vars.size() == 1);
return_vars = {};
}
if (code.fun_ref->has_mutate_params()) {
std::vector<var_idx_t> mutated_vars;
for (const LocalVarData& p_sym: code.fun_ref->parameters) {
if (p_sym.is_mutate_parameter()) {
mutated_vars.push_back(p_sym.idx);
mutated_vars.insert(mutated_vars.end(), p_sym.ir_idx.begin(), p_sym.ir_idx.end());
}
}
return_vars.insert(return_vars.begin(), mutated_vars.begin(), mutated_vars.end());
@ -647,7 +651,7 @@ static void append_implicit_return_statement(SrcLocation loc_end, CodeBlob& code
if (code.fun_ref->has_mutate_params()) {
for (const LocalVarData& p_sym: code.fun_ref->parameters) {
if (p_sym.is_mutate_parameter()) {
mutated_vars.push_back(p_sym.idx);
mutated_vars.insert(mutated_vars.end(), p_sym.ir_idx.begin(), p_sym.ir_idx.end());
}
}
}
@ -685,11 +689,23 @@ void process_any_statement(AnyV v, CodeBlob& code) {
static void convert_function_body_to_CodeBlob(const FunctionData* fun_ref, FunctionBodyCode* code_body) {
auto v_body = fun_ref->ast_root->as<ast_function_declaration>()->get_body()->as<ast_sequence>();
CodeBlob* blob = new CodeBlob{fun_ref->name, fun_ref->loc, fun_ref};
FormalArgList legacy_arg_list;
for (const LocalVarData& param : fun_ref->parameters) {
legacy_arg_list.emplace_back(param.declared_type, &param, param.loc);
std::vector<var_idx_t> rvect_import;
int total_arg_width = 0;
for (int i = 0; i < fun_ref->get_num_params(); ++i) {
total_arg_width += fun_ref->parameters[i].declared_type->calc_width_on_stack();
}
blob->import_params(std::move(legacy_arg_list));
rvect_import.reserve(total_arg_width);
for (int i = 0; i < fun_ref->get_num_params(); ++i) {
const LocalVarData& param_i = fun_ref->parameters[i];
std::vector<var_idx_t> ir_idx = blob->create_var(param_i.declared_type, &param_i, param_i.loc);
rvect_import.insert(rvect_import.end(), ir_idx.begin(), ir_idx.end());
param_i.mutate()->assign_ir_idx(std::move(ir_idx));
}
blob->emplace_back(fun_ref->loc, Op::_Import, rvect_import);
blob->in_var_cnt = blob->var_cnt;
tolk_assert(blob->var_cnt == total_arg_width);
for (AnyV item : v_body->get_items()) {
process_any_statement(item, *blob);

View file

@ -38,7 +38,7 @@ static void fire_error_cannot_be_used_as_lvalue(AnyV v, const std::string& detai
GNU_ATTRIBUTE_NORETURN GNU_ATTRIBUTE_COLD
static void fire_error_modifying_immutable_variable(AnyExprV v, const LocalVarData* var_ref) {
if (var_ref->idx == 0 && var_ref->name == "self") {
if (var_ref->param_idx == 0 && var_ref->name == "self") {
v->error("modifying `self`, which is immutable by default; probably, you want to declare `mutate self`");
} else {
v->error("modifying immutable variable `" + var_ref->name + "`");

View file

@ -54,11 +54,6 @@ static void generate_output_func(const FunctionData* fun_ref) {
std::cerr << "after prune_unreachable: \n";
code->print(std::cerr, 0);
}
code->split_vars(true);
if (G.is_verbosity(5)) {
std::cerr << "after split_vars: \n";
code->print(std::cerr, 0);
}
for (int i = 0; i < 8; i++) {
code->compute_used_code_vars();
if (G.is_verbosity(4)) {

View file

@ -38,11 +38,11 @@ static void fire_error_invalid_mutate_arg_passed(AnyExprV v, const FunctionData*
std::string arg_str(arg_expr->type == ast_reference ? arg_expr->as<ast_reference>()->get_name() : "obj");
// case: `loadInt(cs, 32)`; suggest: `cs.loadInt(32)`
if (p_sym.is_mutate_parameter() && !arg_passed_as_mutate && !called_as_method && p_sym.idx == 0 && fun_ref->does_accept_self()) {
if (p_sym.is_mutate_parameter() && !arg_passed_as_mutate && !called_as_method && p_sym.param_idx == 0 && fun_ref->does_accept_self()) {
v->error("`" + fun_ref->name + "` is a mutating method; consider calling `" + arg_str + "." + fun_ref->name + "()`, not `" + fun_ref->name + "(" + arg_str + ")`");
}
// case: `cs.mutating_function()`; suggest: `mutating_function(mutate cs)` or make it a method
if (p_sym.is_mutate_parameter() && called_as_method && p_sym.idx == 0 && !fun_ref->does_accept_self()) {
if (p_sym.is_mutate_parameter() && called_as_method && p_sym.param_idx == 0 && !fun_ref->does_accept_self()) {
v->error("function `" + fun_ref->name + "` mutates parameter `" + p_sym.name + "`; consider calling `" + fun_ref->name + "(mutate " + arg_str + ")`, not `" + arg_str + "." + fun_ref->name + "`(); alternatively, rename parameter to `self` to make it a method");
}
// case: `mutating_function(arg)`; suggest: `mutate arg`

View file

@ -93,8 +93,8 @@ void GlobalConstData::assign_resolved_type(TypePtr declared_type) {
this->declared_type = declared_type;
}
void LocalVarData::assign_idx(int idx) {
this->idx = idx;
void LocalVarData::assign_ir_idx(std::vector<int>&& ir_idx) {
this->ir_idx = std::move(ir_idx);
}
void LocalVarData::assign_resolved_type(TypePtr declared_type) {

View file

@ -59,20 +59,23 @@ struct LocalVarData final : Symbol {
TypePtr declared_type; // either at declaration `var x:int`, or if omitted, from assigned value `var x=2`
int flags;
int idx;
int param_idx; // 0...N for function parameters, -1 for local vars
std::vector<int> ir_idx;
LocalVarData(std::string name, SrcLocation loc, TypePtr declared_type, int flags, int idx)
LocalVarData(std::string name, SrcLocation loc, TypePtr declared_type, int flags, int param_idx)
: Symbol(std::move(name), loc)
, declared_type(declared_type)
, flags(flags)
, idx(idx) {
, param_idx(param_idx) {
}
bool is_parameter() const { return param_idx >= 0; }
bool is_immutable() const { return flags & flagImmutable; }
bool is_mutate_parameter() const { return flags & flagMutateParameter; }
LocalVarData* mutate() const { return const_cast<LocalVarData*>(this); }
void assign_idx(int idx);
void assign_ir_idx(std::vector<int>&& ir_idx);
void assign_resolved_type(TypePtr declared_type);
void assign_inferred_type(TypePtr inferred_type);
};

View file

@ -45,17 +45,15 @@ typedef int const_idx_t;
struct TmpVar {
TypePtr v_type;
var_idx_t idx;
var_idx_t ir_idx;
const LocalVarData* v_sym; // points to var defined in code; nullptr for implicitly created tmp vars
int coord;
SrcLocation where;
std::vector<std::function<void(SrcLocation)>> on_modification;
TmpVar(var_idx_t _idx, TypePtr type, const LocalVarData* v_sym, SrcLocation loc)
TmpVar(var_idx_t ir_idx, TypePtr type, const LocalVarData* v_sym, SrcLocation loc)
: v_type(type)
, idx(_idx)
, ir_idx(ir_idx)
, v_sym(v_sym)
, coord(0)
, where(loc) {
}
@ -345,8 +343,6 @@ struct Op {
void show_var_list(std::ostream& os, const std::vector<VarDescr>& list, const std::vector<TmpVar>& vars) const;
static void show_block(std::ostream& os, const Op* block, const std::vector<TmpVar>& vars, std::string pfx = "",
int mode = 0);
void split_vars(const std::vector<TmpVar>& vars);
static void split_var_list(std::vector<var_idx_t>& var_list, const std::vector<TmpVar>& vars);
bool compute_used_vars(const CodeBlob& code, bool edit);
bool std_compute_used_vars(bool disabled = false);
bool set_var_info(const VarDescrList& new_var_info);
@ -385,9 +381,6 @@ inline ListIterator<const Op> end(const Op* op_list) {
return ListIterator<const Op>{};
}
typedef std::tuple<TypePtr, const LocalVarData*, SrcLocation> FormalArg;
typedef std::vector<FormalArg> FormalArgList;
struct AsmOpList;
struct FunctionBodyCode {
@ -1115,12 +1108,10 @@ struct CodeBlob {
#endif
return res;
}
bool import_params(FormalArgList&& arg_list);
var_idx_t create_var(TypePtr var_type, const LocalVarData* v_sym, SrcLocation loc);
var_idx_t create_tmp_var(TypePtr var_type, SrcLocation loc) {
std::vector<var_idx_t> create_var(TypePtr var_type, const LocalVarData* v_sym, SrcLocation loc);
std::vector<var_idx_t> create_tmp_var(TypePtr var_type, SrcLocation loc) {
return create_var(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;
void print(std::ostream& os, int flags = 0) const;

View file

@ -537,31 +537,6 @@ bool TypeDataVoid::can_be_casted_with_as_operator(TypePtr cast_to) const {
}
// --------------------------------------------
// extract_components()
//
// used in code generation (transforming Ops to other Ops)
// to be removed in the future
//
void TypeDataGenericT::extract_components(std::vector<TypePtr>& comp_types) const {
assert(false);
}
void TypeDataTensor::extract_components(std::vector<TypePtr>& comp_types) const {
for (TypePtr item : items) {
item->extract_components(comp_types);
}
}
void TypeDataUnresolved::extract_components(std::vector<TypePtr>& comp_types) const {
assert(false);
}
void TypeDataVoid::extract_components(std::vector<TypePtr>& comp_types) const {
}
// --------------------------------------------
// parsing type from tokens
//

View file

@ -97,10 +97,6 @@ public:
virtual int calc_width_on_stack() const {
return 1;
}
virtual void extract_components(std::vector<TypePtr>& comp_types) const {
comp_types.push_back(this);
}
};
/*
@ -291,7 +287,6 @@ public:
bool can_rhs_be_assigned(TypePtr rhs) const override;
bool can_be_casted_with_as_operator(TypePtr cast_to) const override;
int calc_width_on_stack() const override;
void extract_components(std::vector<TypePtr>& comp_types) const override;
};
/*
@ -318,7 +313,6 @@ public:
void traverse(const TraverserCallbackT& callback) const override;
TypePtr replace_children_custom(const ReplacerCallbackT& callback) const override;
int calc_width_on_stack() const override;
void extract_components(std::vector<TypePtr>& comp_types) const override;
};
/*
@ -387,7 +381,6 @@ public:
bool can_rhs_be_assigned(TypePtr rhs) const override;
bool can_be_casted_with_as_operator(TypePtr cast_to) const override;
int calc_width_on_stack() const override;
void extract_components(std::vector<TypePtr>& comp_types) const override;
};
/*
@ -408,7 +401,6 @@ public:
bool can_rhs_be_assigned(TypePtr rhs) const override;
bool can_be_casted_with_as_operator(TypePtr cast_to) const override;
int calc_width_on_stack() const override;
void extract_components(std::vector<TypePtr>& comp_types) const override;
};