#include <msp/core/raii.h>
#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
#include "optimize.h"
#include "reflect.h"
}
-BasicTypeDeclaration::Kind ConstantFolder::get_value_kind(const Variant &value)
-{
- if(value.check_type<bool>())
- return BasicTypeDeclaration::BOOL;
- else if(value.check_type<int>())
- return BasicTypeDeclaration::INT;
- else if(value.check_type<float>())
- return BasicTypeDeclaration::FLOAT;
- else
- return BasicTypeDeclaration::VOID;
-}
-
template<typename T>
T ConstantFolder::evaluate_logical(char oper, T left, T right)
{
}
}
+template<typename T>
+T ConstantFolder::evaluate_int_special_op(char oper, T left, T right)
+{
+ switch(oper)
+ {
+ case '%': return left%right;
+ case '<': return left<<right;
+ case '>': return left>>right;
+ default: return T();
+ }
+}
+
+template<typename T>
+void ConstantFolder::convert_to_result(const Variant &value)
+{
+ if(value.check_type<bool>())
+ set_result(static_cast<T>(value.value<bool>()));
+ else if(value.check_type<int>())
+ set_result(static_cast<T>(value.value<int>()));
+ else if(value.check_type<float>())
+ set_result(static_cast<T>(value.value<float>()));
+}
+
void ConstantFolder::set_result(const Variant &value, bool literal)
{
r_constant_value = value;
if(!r_constant || r_literal || r_uses_iter_var)
return;
- BasicTypeDeclaration::Kind kind = get_value_kind(r_constant_value);
- if(kind==BasicTypeDeclaration::VOID)
- {
- r_constant = false;
- return;
- }
-
RefPtr<Literal> literal = new Literal;
- if(kind==BasicTypeDeclaration::BOOL)
+ if(r_constant_value.check_type<bool>())
literal->token = (r_constant_value.value<bool>() ? "true" : "false");
- else if(kind==BasicTypeDeclaration::INT)
+ else if(r_constant_value.check_type<int>())
literal->token = lexical_cast<string>(r_constant_value.value<int>());
- else if(kind==BasicTypeDeclaration::FLOAT)
+ else if(r_constant_value.check_type<float>())
+ {
literal->token = lexical_cast<string>(r_constant_value.value<float>());
+ if(isnumrc(literal->token))
+ literal->token += ".0";
+ }
+ else
+ {
+ r_constant = false;
+ return;
+ }
literal->value = r_constant_value;
expr = literal;
}
if(!can_fold)
return;
- BasicTypeDeclaration::Kind kind = get_value_kind(r_constant_value);
-
char oper = unary.oper->token[0];
char oper2 = unary.oper->token[1];
if(oper=='!')
{
- if(kind==BasicTypeDeclaration::BOOL)
+ if(r_constant_value.check_type<bool>())
set_result(!r_constant_value.value<bool>());
}
else if(oper=='~')
{
- if(kind==BasicTypeDeclaration::INT)
+ if(r_constant_value.check_type<int>())
set_result(~r_constant_value.value<int>());
+ else if(r_constant_value.check_type<unsigned>())
+ set_result(~r_constant_value.value<unsigned>());
}
else if(oper=='-' && !oper2)
{
- if(kind==BasicTypeDeclaration::INT)
+ if(r_constant_value.check_type<int>())
set_result(-r_constant_value.value<int>());
- else if(kind==BasicTypeDeclaration::FLOAT)
+ else if(r_constant_value.check_type<unsigned>())
+ set_result(-r_constant_value.value<unsigned>());
+ else if(r_constant_value.check_type<float>())
set_result(-r_constant_value.value<float>());
}
}
if(!can_fold)
return;
- BasicTypeDeclaration::Kind left_kind = get_value_kind(left_value);
- BasicTypeDeclaration::Kind right_kind = get_value_kind(r_constant_value);
// Currently only expressions with both sides of equal types are handled.
- if(left_kind!=right_kind)
+ if(!left_value.check_same_type(r_constant_value))
return;
char oper = binary.oper->token[0];
char oper2 = binary.oper->token[1];
if(oper=='&' || oper=='|' || oper=='^')
{
- if(oper2==oper && left_kind==BasicTypeDeclaration::BOOL)
+ if(oper2==oper && left_value.check_type<bool>())
set_result(evaluate_logical(oper, left_value.value<bool>(), r_constant_value.value<bool>()));
- else if(!oper2 && left_kind==BasicTypeDeclaration::INT)
+ else if(!oper2 && left_value.check_type<int>())
set_result(evaluate_logical(oper, left_value.value<int>(), r_constant_value.value<int>()));
}
else if((oper=='<' || oper=='>') && oper2!=oper)
{
- if(left_kind==BasicTypeDeclaration::INT)
+ if(left_value.check_type<int>())
set_result(evaluate_relation(binary.oper->token, left_value.value<int>(), r_constant_value.value<int>()));
- else if(left_kind==BasicTypeDeclaration::FLOAT)
+ else if(left_value.check_type<float>())
set_result(evaluate_relation(binary.oper->token, left_value.value<float>(), r_constant_value.value<float>()));
}
else if((oper=='=' || oper=='!') && oper2=='=')
{
- if(left_kind==BasicTypeDeclaration::INT)
+ if(left_value.check_type<int>())
set_result((left_value.value<int>()==r_constant_value.value<int>()) == (oper=='='));
- if(left_kind==BasicTypeDeclaration::FLOAT)
+ if(left_value.check_type<float>())
set_result((left_value.value<float>()==r_constant_value.value<float>()) == (oper=='='));
}
else if(oper=='+' || oper=='-' || oper=='*' || oper=='/')
{
- if(left_kind==BasicTypeDeclaration::INT)
+ if(left_value.check_type<int>())
set_result(evaluate_arithmetic(oper, left_value.value<int>(), r_constant_value.value<int>()));
- else if(left_kind==BasicTypeDeclaration::FLOAT)
+ else if(left_value.check_type<float>())
set_result(evaluate_arithmetic(oper, left_value.value<float>(), r_constant_value.value<float>()));
}
else if(oper=='%' || ((oper=='<' || oper=='>') && oper2==oper))
{
- if(left_kind!=BasicTypeDeclaration::INT)
- return;
-
- if(oper=='%')
- set_result(left_value.value<int>()%r_constant_value.value<int>());
- else if(oper=='<')
- set_result(left_value.value<int>()<<r_constant_value.value<int>());
- else if(oper=='>')
- set_result(left_value.value<int>()>>r_constant_value.value<int>());
+ if(left_value.check_type<int>())
+ set_result(evaluate_int_special_op(oper, left_value.value<int>(), r_constant_value.value<int>()));
}
}
void ConstantFolder::visit(FunctionCall &call)
{
+ if(call.constructor && call.type && call.arguments.size()==1)
+ {
+ const BasicTypeDeclaration *basic = dynamic_cast<const BasicTypeDeclaration *>(call.type);
+ if(basic)
+ {
+ call.arguments[0]->visit(*this);
+ bool can_fold = r_constant;
+ r_constant = false;
+ if(!can_fold)
+ return;
+
+ if(basic->kind==BasicTypeDeclaration::BOOL)
+ convert_to_result<bool>(r_constant_value);
+ else if(basic->kind==BasicTypeDeclaration::INT && basic->size==32)
+ convert_to_result<int>(r_constant_value);
+ else if(basic->kind==BasicTypeDeclaration::FLOAT && basic->size==32)
+ convert_to_result<float>(r_constant_value);
+
+ return;
+ }
+ }
+
TraversingVisitor::visit(call);
r_constant = false;
}
r_assignment(0),
assignment_target(false),
r_side_effects(false),
+ in_struct(false),
composite_reference(false)
{ }
unused_nodes.insert(&expr);
}
+void UnusedVariableRemover::visit(StructDeclaration &strct)
+{
+ SetFlag set_struct(in_struct);
+ TraversingVisitor::visit(strct);
+}
+
void UnusedVariableRemover::visit(VariableDeclaration &var)
{
+ TraversingVisitor::visit(var);
+
+ if(in_struct)
+ return;
+
VariableInfo &var_info = variables[&var];
var_info.interface_block = interface_block;
var_info.initialized = true;
record_assignment(&var, *var.init_expression);
}
- TraversingVisitor::visit(var);
}
void UnusedVariableRemover::visit(InterfaceBlock &iface)