From 565bc597356481d5de047625fa94ae1b66658539 Mon Sep 17 00:00:00 2001 From: tolk-vm Date: Wed, 18 Dec 2024 19:26:26 +0300 Subject: [PATCH] [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. --- tolk-tester/tests/a10.tolk | 4 +- tolk-tester/tests/cells-slices.tolk | 8 +-- tolk-tester/tests/logical-operators.tolk | 6 +- tolk-tester/tests/mutate-methods.tolk | 6 +- tolk-tester/tests/null-keyword.tolk | 4 +- tolk/abscode.cpp | 87 +++++------------------- tolk/analyzer.cpp | 34 --------- tolk/generics-helpers.cpp | 6 +- tolk/pipe-ast-to-legacy.cpp | 84 ++++++++++++++--------- tolk/pipe-check-rvalue-lvalue.cpp | 2 +- tolk/pipe-generate-fif-output.cpp | 5 -- tolk/pipe-refine-lvalue-for-mutate.cpp | 4 +- tolk/symtable.cpp | 4 +- tolk/symtable.h | 11 +-- tolk/tolk.h | 19 ++---- tolk/type-system.cpp | 25 ------- tolk/type-system.h | 8 --- 17 files changed, 100 insertions(+), 217 deletions(-) diff --git a/tolk-tester/tests/a10.tolk b/tolk-tester/tests/a10.tolk index 7301f1d5..af104248 100644 --- a/tolk-tester/tests/a10.tolk +++ b/tolk-tester/tests/a10.tolk @@ -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 }> """ diff --git a/tolk-tester/tests/cells-slices.tolk b/tolk-tester/tests/cells-slices.tolk index 6f316f2e..0a2807e6 100644 --- a/tolk-tester/tests/cells-slices.tolk +++ b/tolk-tester/tests/cells-slices.tolk @@ -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 }> """ diff --git a/tolk-tester/tests/logical-operators.tolk b/tolk-tester/tests/logical-operators.tolk index fb437bb3..9ef4858d 100644 --- a/tolk-tester/tests/logical-operators.tolk +++ b/tolk-tester/tests/logical-operators.tolk @@ -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 }> """ diff --git a/tolk-tester/tests/mutate-methods.tolk b/tolk-tester/tests/mutate-methods.tolk index 816e4c8d..0a5ca191 100644 --- a/tolk-tester/tests/mutate-methods.tolk +++ b/tolk-tester/tests/mutate-methods.tolk @@ -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 }> """ diff --git a/tolk-tester/tests/null-keyword.tolk b/tolk-tester/tests/null-keyword.tolk index 9ace9995..40e391c8 100644 --- a/tolk-tester/tests/null-keyword.tolk +++ b/tolk-tester/tests/null-keyword.tolk @@ -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 diff --git a/tolk/abscode.cpp b/tolk/abscode.cpp index 7bcb0f84..25ddd10e 100644 --- a/tolk/abscode.cpp +++ b/tolk/abscode.cpp @@ -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& 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_list, const std::vector& 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 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& 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++; -} - -bool CodeBlob::import_params(FormalArgList&& arg_list) { - if (var_cnt || in_var_cnt) { - return false; +std::vector CodeBlob::create_var(TypePtr var_type, const LocalVarData* v_sym, SrcLocation loc) { + std::vector ir_idx; + ir_idx.reserve(var_type->calc_width_on_stack()); + if (const TypeDataTensor* t_tensor = var_type->try_as()) { + for (TypePtr item : t_tensor->items) { + std::vector nested = create_var(item, v_sym, loc); + ir_idx.insert(ir_idx.end(), nested.begin(), nested.end()); + } + } 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 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(ir_idx.size()) == var_type->calc_width_on_stack()); + return ir_idx; } } // namespace tolk diff --git a/tolk/analyzer.cpp b/tolk/analyzer.cpp index 8539afdd..9303bc83 100644 --- a/tolk/analyzer.cpp +++ b/tolk/analyzer.cpp @@ -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 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); diff --git a/tolk/generics-helpers.cpp b/tolk/generics-helpers.cpp index 3d353cc4..7a2dd83f 100644 --- a/tolk/generics-helpers.cpp +++ b/tolk/generics-helpers.cpp @@ -202,8 +202,8 @@ td::Result> 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(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(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 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)); diff --git a/tolk/pipe-ast-to-legacy.cpp b/tolk/pipe-ast-to-legacy.cpp index d60bb8b3..c64fe751 100644 --- a/tolk/pipe-ast-to-legacy.cpp +++ b/tolk/pipe-ast-to-legacy.cpp @@ -34,15 +34,15 @@ namespace tolk { struct LValGlobs { - std::vector> globs; + std::vector>> 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 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{}, std::vector{ ir_idx }, g_sym); + Op& op = code.emplace_back(loc, Op::_SetGlob, std::vector{}, ir_idx, g_sym); op.set_impure_flag(); } } @@ -93,7 +93,9 @@ static std::vector> 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 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& prev_vars : res_lists) { std::replace(prev_vars.begin(), prev_vars.end(), ir_idx, tmp_idx); @@ -143,7 +145,7 @@ static std::vector pre_compile_let(CodeBlob& code, AnyExprV lhs, AnyE std::vector right = pre_compile_expr(rhs, code); const TypeDataTypedTuple* inferred_tuple = rhs->inferred_type->try_as(); std::vector types_list = inferred_tuple->items; - std::vector rvect = {code.create_tmp_var(TypeDataTensor::create(std::move(types_list)), rhs->loc)}; + std::vector 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 left = pre_compile_tensor(code, lhs->as()->get_items(), &globs); @@ -164,7 +166,7 @@ static std::vector pre_compile_let(CodeBlob& code, AnyExprV lhs, AnyE static std::vector gen_op_call(CodeBlob& code, TypePtr ret_type, SrcLocation here, std::vector&& args_vars, const FunctionData* fun_ref) { - std::vector rvect = {code.create_tmp_var(ret_type, here)}; + std::vector 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 gen_op_call(CodeBlob& code, TypePtr ret_type, SrcL static std::vector process_symbol(SrcLocation loc, const Symbol* sym, CodeBlob& code, LValGlobs* lval_globs) { if (const auto* glob_ref = sym->try_as()) { - std::vector rvect = {code.create_tmp_var(glob_ref->declared_type, loc)}; + std::vector 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{}, glob_ref); @@ -186,22 +188,25 @@ static std::vector process_symbol(SrcLocation loc, const Symbol* sym, } if (const auto* const_ref = sym->try_as()) { if (const_ref->is_int_const()) { - std::vector rvect = {code.create_tmp_var(TypeDataInt::create(), loc)}; + std::vector 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 rvect = {code.create_tmp_var(TypeDataSlice::create(), loc)}; + std::vector 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()) { - std::vector rvect = {code.create_tmp_var(fun_ref->inferred_full_type, loc)}; + std::vector rvect = code.create_tmp_var(fun_ref->inferred_full_type, loc); code.emplace_back(loc, Op::_GlobVar, rvect, std::vector{}, fun_ref); return rvect; } if (const auto* var_ref = sym->try_as()) { - return {var_ref->idx}; +#ifdef TOLK_DEBUG + tolk_assert(static_cast(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 process_binary_operator(V v, v_b_ne_0->mutate()->assign_fun_ref(lookup_global_symbol("_!=_")->as()); std::vector cond = pre_compile_expr(v->get_lhs(), code); tolk_assert(cond.size() == 1); - std::vector rvect = {code.create_tmp_var(v->inferred_type, v->loc)}; + std::vector 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 process_unary_operator(V v, Co static std::vector process_ternary_operator(V v, CodeBlob& code) { std::vector cond = pre_compile_expr(v->get_cond(), code); tolk_assert(cond.size() == 1); - std::vector rvect = {code.create_tmp_var(v->inferred_type, v->loc)}; + std::vector 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 process_function_call(V v, Code std::vector tfunc = pre_compile_expr(v->get_callee(), code); tolk_assert(tfunc.size() == 1); args_vars.push_back(tfunc[0]); - std::vector rvect = {code.create_tmp_var(v->inferred_type, v->loc)}; + std::vector 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 process_function_call(V v, Code } } } - std::vector rvect = {code.create_tmp_var(real_ret_type, v->loc)}; - left.push_back(rvect[0]); + std::vector 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 process_typed_tuple(V 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 left = std::vector{code.create_tmp_var(v->inferred_type, v->loc)}; + std::vector left = code.create_tmp_var(v->inferred_type, v->loc); std::vector right = pre_compile_tensor(code, v->get_items()); code.emplace_back(v->loc, Op::_Tuple, left, std::move(right)); return left; } static std::vector process_int_const(V v, CodeBlob& code) { - std::vector rvect = {code.create_tmp_var(v->inferred_type, v->loc)}; + std::vector 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 process_string_const(V v, CodeBlob& code) { ConstantValue value = eval_const_init_value(v); - std::vector rvect = {code.create_tmp_var(v->inferred_type, v->loc)}; + std::vector 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 process_local_var(V 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 process_local_vars_declaration(V, CodeBlob&) { @@ -439,7 +444,7 @@ static std::vector process_local_vars_declaration(V process_underscore(V 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 pre_compile_expr(AnyExprV v, CodeBlob& code, LValGlobs* lval_globs) { @@ -516,8 +521,8 @@ static void process_assert_statement(V v, CodeBlob& code) static void process_catch_variable(AnyExprV v_catch_var, CodeBlob& code) { if (auto v_ref = v_catch_var->try_as(); v_ref && v_ref->sym) { // not underscore const LocalVarData* var_ref = v_ref->sym->as(); - 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 v, CodeBlob& code) { static void process_return_statement(V v, CodeBlob& code) { std::vector return_vars = v->has_return_value() ? pre_compile_expr(v->get_return_value(), code) : std::vector{}; if (code.fun_ref->does_return_self()) { - tolk_assert(return_vars.size() == 1); return_vars = {}; } if (code.fun_ref->has_mutate_params()) { std::vector 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()->get_body()->as(); 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, ¶m, param.loc); + + std::vector 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 ir_idx = blob->create_var(param_i.declared_type, ¶m_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); diff --git a/tolk/pipe-check-rvalue-lvalue.cpp b/tolk/pipe-check-rvalue-lvalue.cpp index 038b0999..943dfb96 100644 --- a/tolk/pipe-check-rvalue-lvalue.cpp +++ b/tolk/pipe-check-rvalue-lvalue.cpp @@ -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 + "`"); diff --git a/tolk/pipe-generate-fif-output.cpp b/tolk/pipe-generate-fif-output.cpp index 9092e564..7ef6ba7b 100644 --- a/tolk/pipe-generate-fif-output.cpp +++ b/tolk/pipe-generate-fif-output.cpp @@ -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)) { diff --git a/tolk/pipe-refine-lvalue-for-mutate.cpp b/tolk/pipe-refine-lvalue-for-mutate.cpp index 45dd3a94..540d7413 100644 --- a/tolk/pipe-refine-lvalue-for-mutate.cpp +++ b/tolk/pipe-refine-lvalue-for-mutate.cpp @@ -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()->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` diff --git a/tolk/symtable.cpp b/tolk/symtable.cpp index 918fdab3..c56dc6ed 100644 --- a/tolk/symtable.cpp +++ b/tolk/symtable.cpp @@ -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&& ir_idx) { + this->ir_idx = std::move(ir_idx); } void LocalVarData::assign_resolved_type(TypePtr declared_type) { diff --git a/tolk/symtable.h b/tolk/symtable.h index 3cda24ed..27753ceb 100644 --- a/tolk/symtable.h +++ b/tolk/symtable.h @@ -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 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(this); } - void assign_idx(int idx); + void assign_ir_idx(std::vector&& ir_idx); void assign_resolved_type(TypePtr declared_type); void assign_inferred_type(TypePtr inferred_type); }; diff --git a/tolk/tolk.h b/tolk/tolk.h index 5ec4d3e0..7b44931e 100644 --- a/tolk/tolk.h +++ b/tolk/tolk.h @@ -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> 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& list, const std::vector& vars) const; static void show_block(std::ostream& os, const Op* block, const std::vector& vars, std::string pfx = "", int mode = 0); - void split_vars(const std::vector& vars); - static void split_var_list(std::vector& var_list, const std::vector& 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 end(const Op* op_list) { return ListIterator{}; } -typedef std::tuple FormalArg; -typedef std::vector 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 create_var(TypePtr var_type, const LocalVarData* v_sym, SrcLocation loc); + std::vector 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& ops, const VarDescrList& var_info, bool edit) const; void print(std::ostream& os, int flags = 0) const; diff --git a/tolk/type-system.cpp b/tolk/type-system.cpp index 72419d8c..401c72af 100644 --- a/tolk/type-system.cpp +++ b/tolk/type-system.cpp @@ -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& comp_types) const { - assert(false); -} - -void TypeDataTensor::extract_components(std::vector& comp_types) const { - for (TypePtr item : items) { - item->extract_components(comp_types); - } -} - -void TypeDataUnresolved::extract_components(std::vector& comp_types) const { - assert(false); -} - -void TypeDataVoid::extract_components(std::vector& comp_types) const { -} - - // -------------------------------------------- // parsing type from tokens // diff --git a/tolk/type-system.h b/tolk/type-system.h index 0db42709..482039e6 100644 --- a/tolk/type-system.h +++ b/tolk/type-system.h @@ -97,10 +97,6 @@ public: virtual int calc_width_on_stack() const { return 1; } - - virtual void extract_components(std::vector& 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& 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& 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& 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& comp_types) const override; };