Skip to content

Commit

Permalink
Refactor Bytecode.If #502
Browse files Browse the repository at this point in the history
This refactors Bytecode.If to accept only one argument rather than two
and a comparator.  Instead the comparator is implemented as a
Bytecode.Operator.
  • Loading branch information
DavePearce committed Mar 30, 2016
1 parent 18f2c8c commit bebfd56
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 237 deletions.
59 changes: 20 additions & 39 deletions modules/wyc/src/wyc/builder/CodeGenerator.java
Expand Up @@ -1341,10 +1341,8 @@ public void generateCondition(String target, Expr condition, Environment environ
// true. In some cases, we could actually do better. For
// example, !(x < 5) could be rewritten into x >= 5.

int r1 = generate(condition, environment, block, forest, context);
int r2 = environment.allocate(Type.T_BOOL);
block.add(Bytecode.Const(r2, Constant.V_BOOL(true)), attributes(condition));
block.add(Bytecode.If(Type.T_BOOL, r1, r2, Bytecode.Comparator.EQ, target), attributes(condition));
int result = generate(condition, environment, block, forest, context);
block.add(Bytecode.If(Type.T_BOOL, result, target), attributes(condition));

} else {
syntaxError(errorMessage(INVALID_BOOLEAN_EXPRESSION), context, condition);
Expand Down Expand Up @@ -1435,10 +1433,7 @@ private void generateCondition(String target, Expr.BinOp v, Environment environm
generateTypeCondition(target, v, environment, block, forest, context);

} else {

Bytecode.Comparator cop = OP2COP(bop, v, context);

if (cop == Bytecode.Comparator.EQ && v.lhs instanceof Expr.LocalVariable && v.rhs instanceof Expr.Constant
if (bop == Expr.BOp.EQ && v.lhs instanceof Expr.LocalVariable && v.rhs instanceof Expr.Constant
&& ((Expr.Constant) v.rhs).value == Constant.V_NULL) {
// this is a simple rewrite to enable type inference.
Expr.LocalVariable lhs = (Expr.LocalVariable) v.lhs;
Expand All @@ -1447,7 +1442,7 @@ private void generateCondition(String target, Expr.BinOp v, Environment environm
}
int slot = environment.get(lhs.var);
block.add(Bytecode.IfIs(v.srcType.raw(), slot, Type.T_NULL, target), attributes(v));
} else if (cop == Bytecode.Comparator.NEQ && v.lhs instanceof Expr.LocalVariable
} else if (bop == Expr.BOp.NEQ && v.lhs instanceof Expr.LocalVariable
&& v.rhs instanceof Expr.Constant && ((Expr.Constant) v.rhs).value == Constant.V_NULL) {
// this is a simple rewrite to enable type inference.
String exitLabel = CodeUtils.freshLabel();
Expand All @@ -1460,9 +1455,8 @@ private void generateCondition(String target, Expr.BinOp v, Environment environm
block.add(Bytecode.Goto(target));
block.add(Bytecode.Label(exitLabel));
} else {
int lhs = generate(v.lhs, environment, block, forest, context);
int rhs = generate(v.rhs, environment, block, forest, context);
block.add(Bytecode.If(v.srcType.raw(), lhs, rhs, cop, target), attributes(v));
int result = generate(v, environment, block, forest, context);
block.add(Bytecode.If(v.srcType.raw(), result, target), attributes(v));
}
}
}
Expand Down Expand Up @@ -1949,10 +1943,8 @@ private int generate(Expr.Cast expr, Environment environment, CodeForest.Block b

private int generate(Expr.BinOp v, Environment environment, CodeForest.Block block, CodeForest forest,
Context context) throws Exception {

// could probably use a range test for this somehow
if (v.op == Expr.BOp.EQ || v.op == Expr.BOp.NEQ || v.op == Expr.BOp.LT || v.op == Expr.BOp.LTEQ
|| v.op == Expr.BOp.GT || v.op == Expr.BOp.GTEQ || v.op == Expr.BOp.AND || v.op == Expr.BOp.OR) {
if(v.op == Expr.BOp.AND || v.op == Expr.BOp.OR) {
String trueLabel = CodeUtils.freshLabel();
String exitLabel = CodeUtils.freshLabel();
generateCondition(trueLabel, v, environment, block, forest, context);
Expand All @@ -1963,7 +1955,6 @@ private int generate(Expr.BinOp v, Environment environment, CodeForest.Block blo
block.add(Bytecode.Const(target, Constant.V_BOOL(true)), attributes(v));
block.add(Bytecode.Label(exitLabel));
return target;

} else {
Type result = v.result().raw();
int[] targets = new int[] { environment.allocate(result) };
Expand All @@ -1972,8 +1963,7 @@ private int generate(Expr.BinOp v, Environment environment, CodeForest.Block blo
generate(v.rhs, environment, block, forest, context)
};

block.add(Bytecode.Operator(result, targets, operands, OP2BOP(v.op, v, context)),
attributes(v));
block.add(Bytecode.Operator(result, targets, operands, OP2BOP(v.op, v, context)), attributes(v));

return targets[0];
}
Expand Down Expand Up @@ -2070,6 +2060,18 @@ private Bytecode.OperatorKind OP2BOP(Expr.BOp bop, SyntacticElement elem, Contex
return Bytecode.OperatorKind.DIV;
case REM:
return Bytecode.OperatorKind.REM;
case EQ:
return Bytecode.OperatorKind.EQ;
case NEQ:
return Bytecode.OperatorKind.NEQ;
case LT:
return Bytecode.OperatorKind.LT;
case LTEQ:
return Bytecode.OperatorKind.LTEQ;
case GT:
return Bytecode.OperatorKind.GT;
case GTEQ:
return Bytecode.OperatorKind.GTEQ;
case BITWISEAND:
return Bytecode.OperatorKind.BITWISEAND;
case BITWISEOR:
Expand All @@ -2087,27 +2089,6 @@ private Bytecode.OperatorKind OP2BOP(Expr.BOp bop, SyntacticElement elem, Contex
return null;
}

private Bytecode.Comparator OP2COP(Expr.BOp bop, SyntacticElement elem, Context context) {
switch (bop) {
case EQ:
return Bytecode.Comparator.EQ;
case NEQ:
return Bytecode.Comparator.NEQ;
case LT:
return Bytecode.Comparator.LT;
case LTEQ:
return Bytecode.Comparator.LTEQ;
case GT:
return Bytecode.Comparator.GT;
case GTEQ:
return Bytecode.Comparator.GTEQ;
default:
syntaxError(errorMessage(INVALID_BOOLEAN_EXPRESSION), context, elem);
}
// dead-code
return null;
}

@SuppressWarnings("incomplete-switch")
private static Expr invert(Expr e) {
if (e instanceof Expr.BinOp) {
Expand Down
2 changes: 1 addition & 1 deletion modules/wyil/src/wyil/checks/DefiniteAssignmentCheck.java
Expand Up @@ -121,7 +121,7 @@ public HashSet<Integer> propagate(CodeForest.Index index, Bytecode code, HashSet
public Pair<HashSet<Integer>, HashSet<Integer>> propagate(CodeForest.Index index,
Bytecode.If igoto, HashSet<Integer> in) {

if (!in.contains(igoto.operand(0)) || !in.contains(igoto.operand(1))) {
if (!in.contains(igoto.operand(0))) {
syntaxError(errorMessage(VARIABLE_POSSIBLY_UNITIALISED), filename,
forest.get(index).attribute(SourceLocation.class));
}
Expand Down
57 changes: 31 additions & 26 deletions modules/wyil/src/wyil/io/WyilFileReader.java
Expand Up @@ -962,63 +962,68 @@ public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types
// =========================================================================
// Binary Operators
// =========================================================================
schemas[Bytecode.OPCODE_ifeq] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){
schemas[Bytecode.OPCODE_if] = new Schema(Targets.ZERO, Operands.ONE, Types.ONE, Extras.TARGET){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.EQ, (String) extras[0]);
return Bytecode.If(types[0], operands[0], (String) extras[0]);
}
};
schemas[Bytecode.OPCODE_ifne] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){

// =========================================================================
// Binary Assignables
// =========================================================================
schemas[Bytecode.OPCODE_add] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.NEQ, (String) extras[0]);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.ADD);
}
};
schemas[Bytecode.OPCODE_iflt] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){
schemas[Bytecode.OPCODE_sub] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.LT, (String) extras[0]);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.SUB);
}
};
schemas[Bytecode.OPCODE_ifle] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){
schemas[Bytecode.OPCODE_mul] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.LTEQ, (String) extras[0]);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.MUL);
}
};
schemas[Bytecode.OPCODE_ifgt] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){
schemas[Bytecode.OPCODE_div] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.GT, (String) extras[0]);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.DIV);
}
};
schemas[Bytecode.OPCODE_ifge] = new Schema(Targets.ZERO, Operands.TWO, Types.ONE, Extras.TARGET){
schemas[Bytecode.OPCODE_rem] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.If(types[0], operands[0], operands[1], Bytecode.Comparator.GTEQ, (String) extras[0]);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.REM);
}
};

// =========================================================================
// Binary Assignables
// =========================================================================
schemas[Bytecode.OPCODE_add] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
schemas[Bytecode.OPCODE_eq] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.ADD);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.EQ);
}
};
schemas[Bytecode.OPCODE_sub] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
schemas[Bytecode.OPCODE_ne] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.SUB);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.NEQ);
}
};
schemas[Bytecode.OPCODE_mul] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
schemas[Bytecode.OPCODE_lt] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.MUL);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.LT);
}
};
schemas[Bytecode.OPCODE_div] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
schemas[Bytecode.OPCODE_le] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.DIV);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.LTEQ);
}
};
schemas[Bytecode.OPCODE_rem] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
schemas[Bytecode.OPCODE_gt] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.REM);
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.GT);
}
};
schemas[Bytecode.OPCODE_ge] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
public Bytecode construct(int opcode,int[] targets, int[] operands, Type[] types, Object[] extras) {
return Bytecode.Operator(types[0], targets, operands, Bytecode.OperatorKind.GTEQ);
}
};
schemas[Bytecode.OPCODE_bitwiseor] = new Schema(Targets.ONE, Operands.TWO, Types.ONE){
Expand Down

0 comments on commit bebfd56

Please sign in to comment.