/*
This file is part of TON Blockchain source code.
TON Blockchain is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
TON Blockchain is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TON Blockchain. If not, see .
*/
#include "tolk.h"
#include "ast.h"
#include "ast-replacer.h"
#include "type-system.h"
/*
* This pipe is supposed to do constant folding, like replacing `2 + 3` with `5`.
* It happens after type inferring and validity checks, one of the last ones.
*
* Currently, it just replaces `-1` (ast_unary_operator ast_int_const) with a number -1
* and `!true` with false.
* More rich constant folding should be done some day, but even without this, IR optimizations
* (operating low-level stack variables) pretty manage to do all related optimizations.
* Constant folding in the future, done at AST level, just would slightly reduce amount of work for optimizer.
*/
namespace tolk {
class ConstantFoldingReplacer final : public ASTReplacerInFunctionBody {
static V create_int_const(SrcLocation loc, td::RefInt256&& intval) {
auto v_int = createV(loc, std::move(intval), {});
v_int->assign_inferred_type(TypeDataInt::create());
v_int->assign_rvalue_true();
return v_int;
}
static V create_bool_const(SrcLocation loc, bool bool_val) {
auto v_bool = createV(loc, bool_val);
v_bool->assign_inferred_type(TypeDataBool::create());
v_bool->assign_rvalue_true();
return v_bool;
}
AnyExprV replace(V v) override {
parent::replace(v);
TokenType t = v->tok;
// convert "-1" (tok_minus tok_int_const) to a const -1
if (t == tok_minus && v->get_rhs()->type == ast_int_const) {
td::RefInt256 intval = v->get_rhs()->as()->intval;
tolk_assert(!intval.is_null());
intval = -intval;
if (intval.is_null() || !intval->signed_fits_bits(257)) {
v->error("integer overflow");
}
return create_int_const(v->loc, std::move(intval));
}
// same for "+1"
if (t == tok_plus && v->get_rhs()->type == ast_int_const) {
return v->get_rhs();
}
// `!true` / `!false`
if (t == tok_logical_not && v->get_rhs()->type == ast_bool_const) {
return create_bool_const(v->loc, !v->get_rhs()->as()->bool_val);
}
// `!0`
if (t == tok_logical_not && v->get_rhs()->type == ast_int_const) {
return create_bool_const(v->loc, v->get_rhs()->as()->intval == 0);
}
return v;
}
public:
bool should_visit_function(const FunctionData* fun_ref) override {
return fun_ref->is_code_function() && !fun_ref->is_generic_function();
}
};
void pipeline_constant_folding() {
replace_ast_of_all_functions();
}
} // namespace tolk