+2008-11-29 Jürg Billeter <j@bitron.ch>
+
+ * vala/valaaddressofexpression.vala:
+ * vala/valaarraycreationexpression.vala:
+ * vala/valaassignment.vala:
+ * vala/valabaseaccess.vala:
+ * vala/valabinaryexpression.vala:
+ * vala/valacastexpression.vala:
+ * vala/valaconditionalexpression.vala:
+ * vala/valadostatement.vala:
+ * vala/valaelementaccess.vala:
+ * vala/valaexpression.vala:
+ * vala/valaforstatement.vala:
+ * vala/valainitializerlist.vala:
+ * vala/valalambdaexpression.vala:
+ * vala/valaliteral.vala:
+ * vala/valamemberaccess.vala:
+ * vala/valamethodcall.vala:
+ * vala/valaobjectcreationexpression.vala:
+ * vala/valaparenthesizedexpression.vala:
+ * vala/valapointerindirection.vala:
+ * vala/valapostfixexpression.vala:
+ * vala/valareferencetransferexpression.vala:
+ * vala/valasizeofexpression.vala:
+ * vala/valatuple.vala:
+ * vala/valatypecheck.vala:
+ * vala/valatypeofexpression.vala:
+ * vala/valaunaryexpression.vala:
+ * vala/valawhilestatement.vala:
+
+ Convert binary conditional expressions into if statements
+
2008-11-29 Jürg Billeter <j@bitron.ch>
* vala/valaflowanalyzer.vala:
return !error;
}
+
+ public override bool in_single_basic_block () {
+ return inner.in_single_basic_block ();
+ }
}
return !error;
}
+
+ public override bool in_single_basic_block () {
+ foreach (Expression size in sizes) {
+ if (!size.in_single_basic_block ()) {
+ return false;
+ }
+ }
+ return true;
+ }
}
}
right.get_used_variables (collection);
}
+
+ public override bool in_single_basic_block () {
+ return left.in_single_basic_block () && right.in_single_basic_block ();
+ }
}
public enum Vala.AssignmentOperator {
return !error;
}
+
+ public override bool in_single_basic_block () {
+ return true;
+ }
}
checked = true;
+ if (operator == BinaryOperator.AND || operator == BinaryOperator.OR) {
+ // convert conditional expression into if statement
+ // required for flow analysis and exception handling
+
+ var local = new LocalVariable (new ValueType (analyzer.bool_type.data_type), get_temp_name (), null, source_reference);
+ var decl = new DeclarationStatement (local, source_reference);
+ decl.check (analyzer);
+
+ var right_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, right.source_reference), right, AssignmentOperator.SIMPLE, right.source_reference), right.source_reference);
+
+ var stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, left.source_reference), new BooleanLiteral ((operator == BinaryOperator.OR), left.source_reference), AssignmentOperator.SIMPLE, left.source_reference), left.source_reference);
+
+ var true_block = new Block (source_reference);
+ var false_block = new Block (source_reference);
+
+ if (operator == BinaryOperator.AND) {
+ true_block.add_statement (right_stmt);
+ false_block.add_statement (stmt);
+ } else {
+ true_block.add_statement (stmt);
+ false_block.add_statement (right_stmt);
+ }
+
+ var if_stmt = new IfStatement (left, true_block, false_block, source_reference);
+
+ insert_statement ((Block) analyzer.current_symbol, decl);
+ insert_statement ((Block) analyzer.current_symbol, if_stmt);
+
+ if (!if_stmt.check (analyzer)) {
+ return false;
+ }
+
+ var ma = new MemberAccess.simple (local.name, source_reference);
+ ma.target_type = target_type;
+ ma.check (analyzer);
+
+ parent_node.replace_expression (this, ma);
+
+ return true;
+ }
+
if (!left.check (analyzer) || !right.check (analyzer)) {
/* if there were any errors in inner expressions, skip type check */
error = true;
// integer type or flags type
value_type = left.value_type;
- } else if (operator == BinaryOperator.AND
- || operator == BinaryOperator.OR) {
- if (!left.value_type.compatible (analyzer.bool_type) || !right.value_type.compatible (analyzer.bool_type)) {
- error = true;
- Report.error (source_reference, "Operands must be boolean");
- }
-
- value_type = analyzer.bool_type;
} else if (operator == BinaryOperator.IN) {
if (left.value_type.compatible (analyzer.int_type)
&& right.value_type.compatible (analyzer.int_type)) {
left.get_used_variables (collection);
right.get_used_variables (collection);
}
+
+ public override bool in_single_basic_block () {
+ if (operator == BinaryOperator.AND
+ || operator == BinaryOperator.OR) {
+ return false;
+ }
+ return left.in_single_basic_block () && right.in_single_basic_block ();
+ }
}
public enum Vala.BinaryOperator {
public override void get_used_variables (Collection<LocalVariable> collection) {
inner.get_used_variables (collection);
}
+
+ public override bool in_single_basic_block () {
+ return inner.in_single_basic_block ();
+ }
}
true_expression.target_type = target_type;
false_expression.target_type = target_type;
+ var local = new LocalVariable (null, temp_name, null, source_reference);
+ var decl = new DeclarationStatement (local, source_reference);
+
var true_local = new LocalVariable (null, temp_name, true_expression, true_expression.source_reference);
var true_block = new Block (true_expression.source_reference);
var true_decl = new DeclarationStatement (true_local, true_expression.source_reference);
false_block.add_statement (false_decl);
var if_stmt = new IfStatement (condition, true_block, false_block, source_reference);
+
+ insert_statement ((Block) analyzer.current_symbol, decl);
+ insert_statement ((Block) analyzer.current_symbol, if_stmt);
+
if (!if_stmt.check (analyzer)) {
return false;
}
value_type.value_owned = (true_expression.value_type.value_owned || false_expression.value_type.value_owned);
- var local = new LocalVariable (value_type, temp_name, null, source_reference);
- var decl = new DeclarationStatement (local, source_reference);
+ local.variable_type = value_type;
decl.check (analyzer);
true_expression.target_type = value_type;
true_block.replace_statement (true_decl, true_stmt);
false_block.replace_statement (false_decl, false_stmt);
- insert_statement ((Block) analyzer.current_symbol, decl);
- insert_statement ((Block) analyzer.current_symbol, if_stmt);
-
var ma = new MemberAccess.simple (local.name, source_reference);
ma.target_type = target_type;
ma.check (analyzer);
return true;
}
+
+ public override bool in_single_basic_block () {
+ return false;
+ }
}
checked = true;
+ if (!condition.in_single_basic_block ()) {
+ /* move condition into the loop body to allow split
+ * in multiple statements
+ *
+ * first = false;
+ * do {
+ * if (first) {
+ * if (!condition) {
+ * break;
+ * }
+ * }
+ * first = true;
+ * ...
+ * } while (true);
+ */
+
+ var first_local = new LocalVariable (new ValueType (analyzer.bool_type.data_type), get_temp_name (), new BooleanLiteral (false, source_reference), source_reference);
+ var first_decl = new DeclarationStatement (first_local, source_reference);
+ first_decl.check (analyzer);
+ var block = (Block) analyzer.current_symbol;
+ block.insert_before (this, first_decl);
+
+ var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference);
+ var true_block = new Block (condition.source_reference);
+ true_block.add_statement (new BreakStatement (condition.source_reference));
+ var if_stmt = new IfStatement (if_condition, true_block, null, condition.source_reference);
+
+ var condition_block = new Block (condition.source_reference);
+ condition_block.add_statement (if_stmt);
+
+ var first_if = new IfStatement (new MemberAccess.simple (first_local.name, source_reference), condition_block, null, source_reference);
+ body.insert_statement (0, first_if);
+ body.insert_statement (1, new ExpressionStatement (new Assignment (new MemberAccess.simple (first_local.name, source_reference), new BooleanLiteral (true, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference));
+
+ condition = new BooleanLiteral (true, source_reference);
+ }
+
body.check (analyzer);
if (!condition.check (analyzer)) {
index.get_used_variables (collection);
}
}
+
+ public override bool in_single_basic_block () {
+ foreach (Expression index in indices) {
+ if (!index.in_single_basic_block ()) {
+ return false;
+ }
+ }
+ return container.in_single_basic_block ();
+ }
}
public void insert_statement (Block block, Statement stmt) {
block.insert_before (parent_statement, stmt);
}
+
+ /**
+ * Returns whether this expression is guaranteed to be part of a
+ * single basic block in the control flow graph.
+ */
+ public abstract bool in_single_basic_block ();
}
checked = true;
+
+ if (condition != null && !condition.in_single_basic_block ()) {
+ // move condition into the loop body to allow split
+ // in multiple statements
+
+ var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference);
+ var true_block = new Block (condition.source_reference);
+ true_block.add_statement (new BreakStatement (condition.source_reference));
+ var if_stmt = new IfStatement (if_condition, true_block, null, condition.source_reference);
+ body.insert_statement (0, if_stmt);
+
+ condition = new BooleanLiteral (true, source_reference);
+ }
+
foreach (Expression init_expr in initializer) {
init_expr.check (analyzer);
}
return !error;
}
+
+ public override bool in_single_basic_block () {
+ foreach (Expression initializer in initializers) {
+ if (!initializer.in_single_basic_block ()) {
+ return false;
+ }
+ }
+ return true;
+ }
}
return !error;
}
+
+ public override bool in_single_basic_block () {
+ return true;
+ }
}
public override bool is_pure () {
return true;
}
+
+ public override bool in_single_basic_block () {
+ return true;
+ }
}
collection.add (local);
}
}
+
+ public override bool in_single_basic_block () {
+ return inner == null || inner.in_single_basic_block ();
+ }
}
arg.get_used_variables (collection);
}
}
+
+ public override bool in_single_basic_block () {
+ foreach (Expression arg in argument_list) {
+ if (!arg.in_single_basic_block ()) {
+ return false;
+ }
+ }
+ return call.in_single_basic_block ();
+ }
}
arg.get_used_variables (collection);
}
}
+
+ public override bool in_single_basic_block () {
+ foreach (Expression arg in argument_list) {
+ if (!arg.in_single_basic_block ()) {
+ return false;
+ }
+ }
+ return true;
+ }
}
public override void get_used_variables (Collection<LocalVariable> collection) {
inner.get_used_variables (collection);
}
+
+ public override bool in_single_basic_block () {
+ return inner.in_single_basic_block ();
+ }
}
public override void get_used_variables (Collection<LocalVariable> collection) {
inner.get_used_variables (collection);
}
+
+ public override bool in_single_basic_block () {
+ return inner.in_single_basic_block ();
+ }
}
return !error;
}
+
+ public override bool in_single_basic_block () {
+ return true;
+ }
}
public override void get_used_variables (Collection<LocalVariable> collection) {
inner.get_used_variables (collection);
}
+
+ public override bool in_single_basic_block () {
+ return inner.in_single_basic_block ();
+ }
}
return !error;
}
+
+ public override bool in_single_basic_block () {
+ return true;
+ }
}
public override bool is_pure () {
return false;
}
+
+ public override bool in_single_basic_block () {
+ foreach (Expression expr in expression_list) {
+ if (!expr.in_single_basic_block ()) {
+ return false;
+ }
+ }
+ return true;
+ }
}
return !error;
}
+
+ public override bool in_single_basic_block () {
+ return expression.in_single_basic_block ();
+ }
}
return !error;
}
+
+ public override bool in_single_basic_block () {
+ return true;
+ }
}
inner.get_used_variables (collection);
}
}
+
+ public override bool in_single_basic_block () {
+ return inner.in_single_basic_block ();
+ }
}
public enum Vala.UnaryOperator {
checked = true;
+ if (!condition.in_single_basic_block ()) {
+ // move condition into the loop body to allow split
+ // in multiple statements
+
+ var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference);
+ var true_block = new Block (condition.source_reference);
+ true_block.add_statement (new BreakStatement (condition.source_reference));
+ var if_stmt = new IfStatement (if_condition, true_block, null, condition.source_reference);
+ body.insert_statement (0, if_stmt);
+
+ condition = new BooleanLiteral (true, source_reference);
+ }
+
condition.check (analyzer);
body.check (analyzer);