From ab54ce17c82e55cb26bf5c0dd7512decbd941b12 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 6 Jun 2014 17:40:45 +0200 Subject: [PATCH] improved ast simplify of const functions --- frontends/ast/simplify.cc | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index a20aacff5..5f40b60a8 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -140,7 +140,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_FUNCTION || type == AST_TASK) return false; - // deactivate all calls non-synthesis system taks + // deactivate all calls to non-synthesis system taks if ((type == AST_FCALL || type == AST_TCALL) && (str == "$display" || str == "$stop" || str == "$finish")) { delete_children(); str = std::string(); @@ -245,9 +245,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case AST_ASSIGN_EQ: case AST_ASSIGN_LE: case AST_ASSIGN: - while (!children[0]->basic_prep && children[0]->simplify(false, false, true, stage, -1, false, false) == true) + while (!children[0]->basic_prep && children[0]->simplify(false, false, true, stage, -1, false, in_param) == true) did_something = true; - while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, false) == true) + while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, in_param) == true) did_something = true; children[0]->detectSignWidth(backup_width_hint, backup_sign_hint); children[1]->detectSignWidth(width_hint, sign_hint); @@ -1825,12 +1825,16 @@ void AstNode::replace_variables(std::map &varia if (type == AST_IDENTIFIER && variables.count(str)) { int offset = variables.at(str).offset, width = variables.at(str).val.bits.size(); if (!children.empty()) { + if (children.size() != 1 || children.at(0)->type != AST_RANGE) + log_error("Memory access in constant function is not supported in %s:%d (called from %s:%d).\n", + filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum); + children.at(0)->replace_variables(variables, fcall); while (simplify(true, false, false, 1, -1, false, true)) { } - if (!range_valid) + if (!children.at(0)->range_valid) log_error("Non-constant range in %s:%d (called from %s:%d).\n", filename.c_str(), linenum, fcall->filename.c_str(), fcall->linenum); - offset = std::min(range_left, range_right); - width = std::min(std::abs(range_left - range_right) + 1, width); + offset = std::min(children.at(0)->range_left, children.at(0)->range_right); + width = std::min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width); } offset -= variables.at(str).offset; std::vector &var_bits = variables.at(str).val.bits; @@ -1850,6 +1854,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) { std::map backup_scope; std::map variables; + bool delete_temp_block = false; AstNode *block = NULL; size_t argidx = 0; @@ -1878,6 +1883,16 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) continue; } + if (child->type == AST_ASSIGN_EQ) + { + log_assert(block == NULL); + delete_temp_block = true; + block = new AstNode(AST_BLOCK); + block->children.push_back(child->clone()); + continue; + } + + child->dumpAst(NULL, "unexpected> "); log_abort(); } @@ -1900,8 +1915,11 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) stmt->children.at(1)->replace_variables(variables, fcall); while (stmt->simplify(true, false, false, 1, -1, false, true)) { } + if (stmt->type != AST_ASSIGN_EQ) + continue; + if (stmt->children.at(1)->type != AST_CONSTANT) - log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n", + log_error("Non-constant expression in constant function at %s:%d (called from %s:%d). X\n", stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum); if (stmt->children.at(0)->type != AST_IDENTIFIER || !stmt->children.at(0)->children.empty()) @@ -2011,6 +2029,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) log_abort(); } + if (delete_temp_block) + delete block; + for (auto &it : backup_scope) if (it.second == NULL) current_scope.erase(it.first); -- 2.30.2