1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Refacing ValueReplacer

This commit is contained in:
Jesper Gravgaard 2018-07-21 23:29:11 +09:00
parent 62cfda6468
commit f9449997cb
15 changed files with 653 additions and 626 deletions

View File

@ -0,0 +1,469 @@
package dk.camelot64.kickc.model.iterator;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.values.*;
import java.util.Collection;
/**
* Interface representing an RValue that can be replaced.
* The value may have sub-values that can also be replaced.
*/
public abstract class ReplaceableValue {
public abstract RValue get();
public abstract void set(RValue value);
/** Replaceable value inside a array filled expression. */
public static class ArrayFilledSize extends ReplaceableValue {
private final ArrayFilled array;
ArrayFilledSize(ArrayFilled array) {
this.array = array;
}
@Override
public RValue get() {
return array.getSize();
}
@Override
public void set(RValue val) {
array.setSize(val);
}
}
/** Replaceable value inside a constant array filled expression. */
public static class ConstantArrayFilledSize extends ReplaceableValue {
private final ConstantArrayFilled array;
ConstantArrayFilledSize(ConstantArrayFilled array) {
this.array = array;
}
@Override
public RValue get() {
return array.getSize();
}
@Override
public void set(RValue val) {
array.setSize((ConstantValue) val);
}
}
/** Replaceable value inside a constant unary expression. */
public static class ConstantUnaryValue extends ReplaceableValue {
private final ConstantUnary unary;
ConstantUnaryValue(ConstantUnary unary) {
this.unary = unary;
}
@Override
public RValue get() {
return unary.getOperand();
}
@Override
public void set(RValue val) {
unary.setOperand((ConstantValue) val);
}
}
/** Replaceable left value inside a constant binary expression. */
public static class ConstantBinaryLeft extends ReplaceableValue {
private final ConstantBinary binary;
ConstantBinaryLeft(ConstantBinary binary) {
this.binary = binary;
}
@Override
public RValue get() {
return binary.getLeft();
}
@Override
public void set(RValue val) {
binary.setLeft((ConstantValue) val);
}
}
/** Replaceable right value inside a constant binary expression. */
public static class ConstantBinaryRight extends ReplaceableValue {
private final ConstantBinary binary;
ConstantBinaryRight(ConstantBinary range) {
this.binary = range;
}
@Override
public RValue get() {
return binary.getRight();
}
@Override
public void set(RValue val) {
binary.setRight((ConstantValue) val);
}
}
/**
* Replaceable first value inside a ranged comparison value.
*/
public static class RangeFirst extends ReplaceableValue {
private final RangeValue range;
RangeFirst(RangeValue range) {
this.range = range;
}
@Override
public RValue get() {
return range.getRangeFirst();
}
@Override
public void set(RValue val) {
range.setRangeFirst(val);
}
}
/**
* Replaceable last value inside inside a ranged comparison value.
*/
public static class RangeLast extends ReplaceableValue {
private final RangeValue range;
RangeLast(RangeValue range) {
this.range = range;
}
@Override
public RValue get() {
return range.getRangeLast();
}
@Override
public void set(RValue val) {
range.setRangeLast(val);
}
}
/**
* Replaceable LValue as part of an assignment statement (or a call).
*/
public static class LValue extends ReplaceableValue {
private final StatementLValue statement;
public LValue(StatementLValue statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getlValue();
}
@Override
public void set(RValue value) {
statement.setlValue((dk.camelot64.kickc.model.values.LValue) value);
}
}
/**
* Replaceable pointer inside a pointer dererence value.
*/
public static class Pointer extends ReplaceableValue {
private final PointerDereference pointer;
Pointer(PointerDereference pointer) {
this.pointer = pointer;
}
@Override
public RValue get() {
return pointer.getPointer();
}
@Override
public void set(RValue val) {
pointer.setPointer(val);
}
}
/**
* Replaceable value inside a noop cast.
*/
public static class CastValue extends ReplaceableValue {
private final dk.camelot64.kickc.model.values.CastValue castValue;
public CastValue(dk.camelot64.kickc.model.values.CastValue castValue) {
this.castValue = castValue;
}
@Override
public RValue get() {
return castValue.getValue();
}
@Override
public void set(RValue val) {
castValue.setValue(val);
}
}
/**
* Replaceable value inside a constant noop cast.
*/
public static class ConstantCastValue extends ReplaceableValue {
private final dk.camelot64.kickc.model.values.ConstantCastValue castValue;
public ConstantCastValue(dk.camelot64.kickc.model.values.ConstantCastValue castValue) {
this.castValue = castValue;
}
@Override
public RValue get() {
return castValue.getValue();
}
@Override
public void set(RValue val) {
castValue.setValue((ConstantValue) val);
}
}
/**
* Replaceable pointer inside a variable pointer.
*/
public static class VarPointer extends ReplaceableValue {
private final ConstantVarPointer varPointer;
public VarPointer(ConstantVarPointer varPointer) {
this.varPointer = varPointer;
}
@Override
public RValue get() {
return varPointer.getToVar();
}
@Override
public void set(RValue val) {
varPointer.setToVar((VariableRef) val);
}
}
public static class ListElement extends ReplaceableValue {
private ValueList list;
private int idx;
public ListElement(ValueList list, int idx) {
this.list = list;
this.idx = idx;
}
@Override
public RValue get() {
return list.getList().get(idx);
}
@Override
public void set(RValue value) {
list.getList().set(idx, value);
}
}
/**
* Replaceable pointer index inside a indexed pointer dererence value.
*/
public static class PointerIndex extends ReplaceableValue {
private final PointerDereferenceIndexed pointer;
PointerIndex(PointerDereferenceIndexed pointer) {
this.pointer = pointer;
}
@Override
public RValue get() {
return pointer.getIndex();
}
@Override
public void set(RValue val) {
pointer.setIndex(val);
}
}
public static class RValue1 extends ReplaceableValue {
private final StatementAssignment statement;
public RValue1(StatementAssignment statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getrValue1();
}
@Override
public void set(RValue value) {
statement.setrValue1(value);
}
}
public static class RValue2 extends ReplaceableValue {
private final StatementAssignment statement;
public RValue2(StatementAssignment statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getrValue2();
}
@Override
public void set(RValue value) {
statement.setrValue2(value);
}
}
public static class CallParameter extends ReplaceableValue {
private final StatementCall call;
private final int i;
public CallParameter(StatementCall call, int i) {
this.call = call;
this.i = i;
}
@Override
public RValue get() {
return call.getParameters().get(i);
}
@Override
public void set(RValue value) {
call.getParameters().set(i, value);
}
}
public static class CondRValue1 extends ReplaceableValue {
private final StatementConditionalJump statement;
public CondRValue1(StatementConditionalJump statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getrValue1();
}
@Override
public void set(RValue value) {
statement.setrValue1(value);
}
}
public static class CondRValue2 extends ReplaceableValue {
private final StatementConditionalJump statement;
public CondRValue2(StatementConditionalJump statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getrValue2();
}
@Override
public void set(RValue value) {
statement.setrValue2(value);
}
}
public static class Return extends ReplaceableValue {
private final StatementReturn statement;
public Return(StatementReturn statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getValue();
}
@Override
public void set(RValue value) {
statement.setValue(value);
}
}
public static class PhiValue extends ReplaceableValue {
private final StatementPhiBlock.PhiVariable phiVariable;
private final int i;
public PhiValue(StatementPhiBlock.PhiVariable phiVariable, int i) {
this.phiVariable = phiVariable;
this.i = i;
}
@Override
public RValue get() {
return phiVariable.getValues().get(i).getrValue();
}
@Override
public void set(RValue value) {
phiVariable.getValues().get(i).setrValue(value);
}
}
/**
* Replaceable LValue as part of an assignment statement (or a call).
*/
public static class PhiVariable extends ReplaceableValue {
private final StatementPhiBlock.PhiVariable phiVariable;
public PhiVariable(StatementPhiBlock.PhiVariable phiVariable) {
this.phiVariable = phiVariable;
}
@Override
public RValue get() {
return phiVariable.getVariable();
}
@Override
public void set(RValue value) {
phiVariable.setVariable((VariableRef) value);
}
}
}

View File

@ -0,0 +1,19 @@
package dk.camelot64.kickc.model.iterator;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.statements.Statement;
import java.util.ListIterator;
/** A replacer that receives a replaceable value and has the potential to replace the value or recurse into sub-values. */
public interface Replacer {
/**
* Execute replacement of a replaceable value.
*
* @param replaceable The replaceable value
* @param currentStmt The statement iterator - just past the current statement that the value is a part of. Current statment can be retrieved by calling
* @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block.
* @param currentBlock The current block that the value is a part of
*/
void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
}

View File

@ -0,0 +1,125 @@
package dk.camelot64.kickc.model.iterator;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.statements.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ListIterator;
/**
* A replacer capable to alias all usages of a variable (or constant var) with a suitable replacement
*/
public class ValueReplacer {
/**
* Execute a replacer on all replaceable values in the program control flow graph
*
* @param graph The program control flow graph
* @param replacer The replacer to execute
*/
public static void executeAll(ControlFlowGraph graph, Replacer replacer) {
for(ControlFlowBlock block : graph.getAllBlocks()) {
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
while(statementsIt.hasNext()) {
Statement statement = statementsIt.next();
executeAll(statement, replacer, statementsIt, block);
}
}
}
/**
* Execute a replacer on all replaceable values in a statement
*
* @param statement The statement
* @param replacer The replacer to execute
*/
public static void executeAll(Statement statement, Replacer replacer, ListIterator<Statement> statementsIt, ControlFlowBlock block) {
if(statement instanceof StatementAssignment) {
executeAll(new ReplaceableValue.LValue((StatementLValue) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableValue.RValue1((StatementAssignment) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableValue.RValue2((StatementAssignment) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementCall) {
executeAll(new ReplaceableValue.LValue((StatementLValue) statement), replacer, statement, statementsIt, block);
StatementCall call = (StatementCall) statement;
if(call.getParameters() != null) {
int size = call.getParameters().size();
for(int i = 0; i < size; i++) {
executeAll(new ReplaceableValue.CallParameter(call, i), replacer, statement, statementsIt, block);
}
}
} else if(statement instanceof StatementConditionalJump) {
executeAll(new ReplaceableValue.CondRValue1((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableValue.CondRValue2((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementReturn) {
executeAll(new ReplaceableValue.Return((StatementReturn) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
executeAll(new ReplaceableValue.PhiVariable(phiVariable), replacer, statement, statementsIt, block);
int size = phiVariable.getValues().size();
for(int i = 0; i < size; i++) {
executeAll(new ReplaceableValue.PhiValue(phiVariable, i), replacer, statement, statementsIt, block);
}
}
}
}
/**
* Execute the a replacer on a replaceable value and all sub-values of the value.
*
* @param replaceable The replaceable value
* @param replacer The value replacer
*/
public static void executeAll(ReplaceableValue replaceable, Replacer replacer, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
replacer.execute(replaceable, currentStmt, stmtIt, currentBlock);
for(ReplaceableValue subValue : getSubValues(replaceable.get())) {
executeAll(subValue, replacer, currentStmt, stmtIt, currentBlock);
}
}
public static Collection<ReplaceableValue> getSubValues(RValue value) {
ArrayList<ReplaceableValue> subValues = new ArrayList<>();
if(value instanceof PointerDereferenceIndexed) {
subValues.add(new ReplaceableValue.Pointer((PointerDereference) value));
subValues.add(new ReplaceableValue.PointerIndex((PointerDereferenceIndexed) value));
} else if(value instanceof PointerDereferenceSimple) {
subValues.add(new ReplaceableValue.Pointer((PointerDereference) value));
} else if(value instanceof ValueList) {
ValueList valueList = (ValueList) value;
int size = valueList.getList().size();
for(int i = 0; i < size; i++) {
subValues.add(new ReplaceableValue.ListElement(valueList, i));
}
} else if(value instanceof CastValue) {
subValues.add(new ReplaceableValue.CastValue((CastValue) value));
} else if(value instanceof ConstantCastValue) {
subValues.add(new ReplaceableValue.ConstantCastValue((ConstantCastValue) value));
} else if(value instanceof ConstantVarPointer) {
subValues.add(new ReplaceableValue.VarPointer((ConstantVarPointer) value));
} else if(value instanceof RangeValue) {
subValues.add(new ReplaceableValue.RangeFirst((RangeValue) value));
subValues.add(new ReplaceableValue.RangeLast((RangeValue) value));
} else if(value instanceof ConstantBinary) {
subValues.add(new ReplaceableValue.ConstantBinaryLeft((ConstantBinary) value));
subValues.add(new ReplaceableValue.ConstantBinaryRight((ConstantBinary) value));
} else if(value instanceof ConstantUnary) {
subValues.add(new ReplaceableValue.ConstantUnaryValue((ConstantUnary) value));
} else if(value instanceof ArrayFilled) {
subValues.add(new ReplaceableValue.ArrayFilledSize((ArrayFilled) value));
} else if(value instanceof ConstantArrayFilled) {
subValues.add(new ReplaceableValue.ConstantArrayFilledSize((ConstantArrayFilled) value));
} else if( value == null ||
value instanceof VariableRef ||
value instanceof ConstantLiteral ||
value instanceof ConstantRef ||
value instanceof LvalueIntermediate
) {
// No sub values
} else {
throw new RuntimeException("Unhandled value type " + value.getClass());
}
return subValues;
}
}

View File

@ -1,6 +1,9 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ReplaceableValue;
import dk.camelot64.kickc.model.iterator.Replacer;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.statements.Statement;
@ -9,7 +12,7 @@ import java.util.ListIterator;
import java.util.Map;
/** A {@link ValueReplacer} that replaces symbols with their alias. */
public class AliasReplacer implements ValueReplacer.Replacer {
public class AliasReplacer implements Replacer {
private Map<? extends SymbolRef, ? extends RValue> aliases;
@ -99,7 +102,7 @@ public class AliasReplacer implements ValueReplacer.Replacer {
* @param replaceable The replaceable value
*/
@Override
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
public void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
if(replaceable.get() != null) {
RValue replacement = getReplacement(replaceable.get(), aliases);
if(replacement != null) {

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.values.ConstantString;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.statements.StatementCall;

View File

@ -1,7 +1,8 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.iterator.ReplaceableValue;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.VariableRef;
@ -47,7 +48,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue statementLValue = (StatementLValue) statement;
LValue lValue = statementLValue.getlValue();
dk.camelot64.kickc.model.values.LValue lValue = statementLValue.getlValue();
if(lValue instanceof VariableRef) {
VariableRef lValueRef = (VariableRef) lValue;
Variable assignedVar = getScope().getVariable(lValueRef);
@ -81,7 +82,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
* @param blockNewPhis New phi functions introduced in the block to create versions of variables.
*/
private void execute(
ValueReplacer.ReplaceableValue replaceableValue,
ReplaceableValue replaceableValue,
Map<VariableUnversioned, VariableVersion> blockVersions,
Map<VariableUnversioned, VariableVersion> blockNewPhis) {
RValue value = replaceableValue.get();
@ -89,7 +90,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
if(version != null) {
replaceableValue.set(version.getRef());
}
for(ValueReplacer.ReplaceableValue subValue : replaceableValue.getSubValues()) {
for(ReplaceableValue subValue : ValueReplacer.getSubValues(replaceableValue.get())) {
execute(subValue, blockVersions, blockNewPhis);
}
}
@ -105,17 +106,17 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
Map<VariableUnversioned, VariableVersion> blockNewPhis = new LinkedHashMap<>();
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementReturn) {
execute(new ValueReplacer.ReplaceableReturn((StatementReturn) statement), blockVersions, blockNewPhis);
execute(new ReplaceableValue.Return((StatementReturn) statement), blockVersions, blockNewPhis);
} else if(statement instanceof StatementConditionalJump) {
execute(new ValueReplacer.ReplaceableCondRValue2((StatementConditionalJump) statement), blockVersions, blockNewPhis);
execute(new ReplaceableValue.CondRValue2((StatementConditionalJump) statement), blockVersions, blockNewPhis);
} else if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
execute(new ValueReplacer.ReplaceableRValue1(assignment), blockVersions, blockNewPhis);
execute(new ValueReplacer.ReplaceableRValue2(assignment), blockVersions, blockNewPhis);
execute(new ValueReplacer.ReplaceableLValue(assignment), blockVersions, blockNewPhis);
execute(new ReplaceableValue.RValue1(assignment), blockVersions, blockNewPhis);
execute(new ReplaceableValue.RValue2(assignment), blockVersions, blockNewPhis);
execute(new ReplaceableValue.LValue(assignment), blockVersions, blockNewPhis);
// Update map of versions encountered in the block
LValue lValue = assignment.getlValue();
dk.camelot64.kickc.model.values.LValue lValue = assignment.getlValue();
if(lValue instanceof VariableRef) {
VariableRef lValueRef = (VariableRef) lValue;
Variable variable = getScope().getVariable(lValueRef);
@ -260,7 +261,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
return symbolMap;
}
private void addSymbolToMap(Map<LabelRef, Map<VariableUnversioned, VariableVersion>> symbolMap, ControlFlowBlock block, LValue lValue) {
private void addSymbolToMap(Map<LabelRef, Map<VariableUnversioned, VariableVersion>> symbolMap, ControlFlowBlock block, dk.camelot64.kickc.model.values.LValue lValue) {
if(lValue instanceof VariableRef) {
Variable lValueVar = getScope().getVariable((VariableRef) lValue);
if(lValueVar instanceof VariableVersion) {

View File

@ -3,6 +3,9 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ReplaceableValue;
import dk.camelot64.kickc.model.iterator.Replacer;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.SymbolType;
@ -197,7 +200,7 @@ public class Pass1ProcedureInline extends Pass1Base {
* Ensures that all VariableRefs pointing to variables in the procedure being inlined are converted to refs to the new inlined variables
* Also copies all intermediate RValue objects to ensure they are not references to objects from the original statements in the procedure being inlined
*/
private class RValueInliner implements ValueReplacer.Replacer {
private class RValueInliner implements Replacer {
/** The scope where the precedure is being inlined into. */
private final Scope callScope;
@ -213,7 +216,7 @@ public class Pass1ProcedureInline extends Pass1Base {
}
@Override
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
public void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
RValue rValue = replaceable.get();
if(rValue instanceof VariableRef) {
VariableRef procVarRef = (VariableRef) rValue;

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.ForwardVariableRef;

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.values.ForwardVariableRef;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.VariableRef;

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ReplaceableValue;
import dk.camelot64.kickc.model.operators.Operator;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.values.*;
@ -45,13 +46,13 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getlValue() instanceof PointerDereferenceIndexed) {
optimized |= optimizePointerDereferenceIndexed(new ValueReplacer.ReplaceableLValue(assignment));
optimized |= optimizePointerDereferenceIndexed(new ReplaceableValue.LValue(assignment));
}
if(assignment.getrValue1() instanceof PointerDereferenceIndexed) {
optimized |= optimizePointerDereferenceIndexed(new ValueReplacer.ReplaceableRValue1(assignment));
optimized |= optimizePointerDereferenceIndexed(new ReplaceableValue.RValue1(assignment));
}
if(assignment.getrValue2() instanceof PointerDereferenceIndexed) {
optimized |= optimizePointerDereferenceIndexed(new ValueReplacer.ReplaceableRValue2(assignment));
optimized |= optimizePointerDereferenceIndexed(new ReplaceableValue.RValue2(assignment));
}
Operator operator = assignment.getOperator();
@ -68,10 +69,10 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
} else if(statement instanceof StatementConditionalJump) {
StatementConditionalJump jump = (StatementConditionalJump) statement;
if(jump.getrValue1() instanceof PointerDereferenceIndexed) {
optimized |= optimizePointerDereferenceIndexed(new ValueReplacer.ReplaceableCondRValue1(jump));
optimized |= optimizePointerDereferenceIndexed(new ReplaceableValue.CondRValue1(jump));
}
if(jump.getrValue2() instanceof PointerDereferenceIndexed) {
optimized |= optimizePointerDereferenceIndexed(new ValueReplacer.ReplaceableCondRValue2(jump));
optimized |= optimizePointerDereferenceIndexed(new ReplaceableValue.CondRValue2(jump));
}
}
}
@ -79,7 +80,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
return optimized;
}
private boolean optimizePointerDereferenceIndexed(ValueReplacer.ReplaceableValue value) {
private boolean optimizePointerDereferenceIndexed(ReplaceableValue value) {
PointerDereferenceIndexed pointerDereferenceIndexed = (PointerDereferenceIndexed) value.get();
if(pointerDereferenceIndexed.getPointer() instanceof ConstantValue && pointerDereferenceIndexed.getIndex() instanceof ConstantValue) {
ConstantValue ptrConstant = (ConstantValue) pointerDereferenceIndexed.getPointer();

View File

@ -1,6 +1,9 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ReplaceableValue;
import dk.camelot64.kickc.model.iterator.Replacer;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.operators.Operator;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.values.RValue;
@ -62,7 +65,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
}
private abstract class InlineConstructor implements ValueReplacer.Replacer {
private abstract class InlineConstructor implements Replacer {
private SymbolTypeInteger constructType;
private Operator constructOperator;
private boolean optimized;
@ -79,7 +82,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
}
@Override
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
public void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
RValue rValue = replaceable.get();
if(rValue instanceof ValueList) {
ValueList list = (ValueList) rValue;

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.types.SymbolType;

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Symbol;

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ValueReplacer;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.RangeValue;
import dk.camelot64.kickc.model.values.ValueList;

View File

@ -1,603 +0,0 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.statements.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ListIterator;
/**
* A replacer capable to alias all usages of a variable (or constant var) with a suitable replacement
*/
public class ValueReplacer {
/**
* Execute a replacer on all replaceable values in the program control flow graph
*
* @param graph The program control flow graph
* @param replacer The replacer to execute
*/
public static void executeAll(ControlFlowGraph graph, Replacer replacer) {
for(ControlFlowBlock block : graph.getAllBlocks()) {
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
while(statementsIt.hasNext()) {
Statement statement = statementsIt.next();
executeAll(statement, replacer, statementsIt, block);
}
}
}
/**
* Execute a replacer on all replaceable values in a statement
*
* @param statement The statement
* @param replacer The replacer to execute
*/
public static void executeAll(Statement statement, Replacer replacer, ListIterator<Statement> statementsIt, ControlFlowBlock block) {
if(statement instanceof StatementAssignment) {
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableRValue1((StatementAssignment) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableRValue2((StatementAssignment) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementCall) {
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
StatementCall call = (StatementCall) statement;
if(call.getParameters() != null) {
int size = call.getParameters().size();
for(int i = 0; i < size; i++) {
executeAll(new ReplaceableCallParameter(call, i), replacer, statement, statementsIt, block);
}
}
} else if(statement instanceof StatementConditionalJump) {
executeAll(new ReplaceableCondRValue1((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableCondRValue2((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementReturn) {
executeAll(new ReplaceableReturn((StatementReturn) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
executeAll(new ReplaceablePhiVariable(phiVariable), replacer, statement, statementsIt, block);
int size = phiVariable.getValues().size();
for(int i = 0; i < size; i++) {
executeAll(new ReplaceablePhiValue(phiVariable, i), replacer, statement, statementsIt, block);
}
}
}
}
/**
* Execute the a replacer on a replaceable value and all sub-values of the value.
*
* @param replaceable The replaceable value
* @param replacer The value replacer
*/
public static void executeAll(ReplaceableValue replaceable, Replacer replacer, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
replacer.execute(replaceable, currentStmt, stmtIt, currentBlock);
for(ReplaceableValue subValue : replaceable.getSubValues()) {
executeAll(subValue, replacer, currentStmt, stmtIt, currentBlock);
}
}
/** A replacer that receives a replaceable value and has the potential to replace the value or recurse into sub-values. */
public interface Replacer {
/**
* Execute replacement of a replaceable value.
*
* @param replaceable The replaceable value
* @param currentStmt The statement iterator - just past the current statement that the value is a part of. Current statment can be retrieved by calling
* @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block.
* @param currentBlock The current block that the value is a part of
*/
void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
}
/**
* Interface representing an RValue that can be replaced.
* The value may have sub-values that can also be replaced.
*/
public static abstract class ReplaceableValue {
public abstract RValue get();
public abstract void set(RValue value);
public Collection<ReplaceableValue> getSubValues() {
RValue value = get();
ArrayList<ReplaceableValue> subValues = new ArrayList<>();
if(value instanceof PointerDereferenceIndexed) {
subValues.add(new ReplaceablePointer((PointerDereference) value));
subValues.add(new ReplaceablePointerIndex((PointerDereferenceIndexed) value));
} else if(value instanceof PointerDereferenceSimple) {
subValues.add(new ReplaceablePointer((PointerDereference) value));
} else if(value instanceof ValueList) {
ValueList valueList = (ValueList) value;
int size = valueList.getList().size();
for(int i = 0; i < size; i++) {
subValues.add(new ReplaceableListElement(valueList, i));
}
} else if(value instanceof CastValue) {
subValues.add(new ReplaceableCastValue((CastValue) value));
} else if(value instanceof ConstantCastValue) {
subValues.add(new ReplaceableConstantCastValue((ConstantCastValue) value));
} else if(value instanceof ConstantVarPointer) {
subValues.add(new ReplaceableVarPointer((ConstantVarPointer) value));
} else if(value instanceof RangeValue) {
subValues.add(new ReplaceableRangeFirst((RangeValue) value));
subValues.add(new ReplaceableRangeLast((RangeValue) value));
} else if(value instanceof ConstantBinary) {
subValues.add(new ReplaceableConstantBinaryLeft((ConstantBinary) value));
subValues.add(new ReplaceableConstantBinaryRight((ConstantBinary) value));
} else if(value instanceof ConstantUnary) {
subValues.add(new ReplaceableConstantUnaryValue((ConstantUnary) value));
} else if(value instanceof ArrayFilled) {
subValues.add(new ReplaceableArrayFilledSize((ArrayFilled) value));
} else if(value instanceof ConstantArrayFilled) {
subValues.add(new ReplaceableConstantArrayFilledSize((ConstantArrayFilled) value));
} else if(
value == null ||
value instanceof VariableRef ||
value instanceof ConstantLiteral ||
value instanceof ConstantRef ||
value instanceof LvalueIntermediate
) {
// No sub values
} else {
throw new RuntimeException("Unhandled value type " + value.getClass());
}
return subValues;
}
}
/** Replaceable value inside a array filled expression. */
public static class ReplaceableArrayFilledSize extends ReplaceableValue {
private final ArrayFilled array;
ReplaceableArrayFilledSize(ArrayFilled array) {
this.array = array;
}
@Override
public RValue get() {
return array.getSize();
}
@Override
public void set(RValue val) {
array.setSize(val);
}
}
/** Replaceable value inside a constant array filled expression. */
public static class ReplaceableConstantArrayFilledSize extends ReplaceableValue {
private final ConstantArrayFilled array;
ReplaceableConstantArrayFilledSize(ConstantArrayFilled array) {
this.array = array;
}
@Override
public RValue get() {
return array.getSize();
}
@Override
public void set(RValue val) {
array.setSize((ConstantValue) val);
}
}
/** Replaceable value inside a constant unary expression. */
public static class ReplaceableConstantUnaryValue extends ReplaceableValue {
private final ConstantUnary unary;
ReplaceableConstantUnaryValue(ConstantUnary unary) {
this.unary = unary;
}
@Override
public RValue get() {
return unary.getOperand();
}
@Override
public void set(RValue val) {
unary.setOperand((ConstantValue) val);
}
}
/** Replaceable left value inside a constant binary expression. */
public static class ReplaceableConstantBinaryLeft extends ReplaceableValue {
private final ConstantBinary binary;
ReplaceableConstantBinaryLeft(ConstantBinary binary) {
this.binary = binary;
}
@Override
public RValue get() {
return binary.getLeft();
}
@Override
public void set(RValue val) {
binary.setLeft((ConstantValue) val);
}
}
/** Replaceable right value inside a constant binary expression. */
public static class ReplaceableConstantBinaryRight extends ReplaceableValue {
private final ConstantBinary binary;
ReplaceableConstantBinaryRight(ConstantBinary range) {
this.binary = range;
}
@Override
public RValue get() {
return binary.getRight();
}
@Override
public void set(RValue val) {
binary.setRight((ConstantValue) val);
}
}
/**
* Replaceable first value inside a ranged comparison value.
*/
public static class ReplaceableRangeFirst extends ReplaceableValue {
private final RangeValue range;
ReplaceableRangeFirst(RangeValue range) {
this.range = range;
}
@Override
public RValue get() {
return range.getRangeFirst();
}
@Override
public void set(RValue val) {
range.setRangeFirst(val);
}
}
/**
* Replaceable last value inside inside a ranged comparison value.
*/
public static class ReplaceableRangeLast extends ReplaceableValue {
private final RangeValue range;
ReplaceableRangeLast(RangeValue range) {
this.range = range;
}
@Override
public RValue get() {
return range.getRangeLast();
}
@Override
public void set(RValue val) {
range.setRangeLast(val);
}
}
/**
* Replaceable LValue as part of an assignment statement (or a call).
*/
public static class ReplaceableLValue extends ReplaceableValue {
private final StatementLValue statement;
public ReplaceableLValue(StatementLValue statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getlValue();
}
@Override
public void set(RValue value) {
statement.setlValue((LValue) value);
}
}
/**
* Replaceable pointer inside a pointer dererence value.
*/
public static class ReplaceablePointer extends ReplaceableValue {
private final PointerDereference pointer;
ReplaceablePointer(PointerDereference pointer) {
this.pointer = pointer;
}
@Override
public RValue get() {
return pointer.getPointer();
}
@Override
public void set(RValue val) {
pointer.setPointer(val);
}
}
/**
* Replaceable value inside a noop cast.
*/
public static class ReplaceableCastValue extends ReplaceableValue {
private final CastValue castValue;
public ReplaceableCastValue(CastValue castValue) {
this.castValue = castValue;
}
@Override
public RValue get() {
return castValue.getValue();
}
@Override
public void set(RValue val) {
castValue.setValue(val);
}
}
/**
* Replaceable value inside a constant noop cast.
*/
public static class ReplaceableConstantCastValue extends ReplaceableValue {
private final ConstantCastValue castValue;
public ReplaceableConstantCastValue(ConstantCastValue castValue) {
this.castValue = castValue;
}
@Override
public RValue get() {
return castValue.getValue();
}
@Override
public void set(RValue val) {
castValue.setValue((ConstantValue) val);
}
}
/**
* Replaceable pointer inside a variable pointer.
*/
public static class ReplaceableVarPointer extends ReplaceableValue {
private final ConstantVarPointer varPointer;
public ReplaceableVarPointer(ConstantVarPointer varPointer) {
this.varPointer = varPointer;
}
@Override
public RValue get() {
return varPointer.getToVar();
}
@Override
public void set(RValue val) {
varPointer.setToVar((VariableRef) val);
}
}
public static class ReplaceableListElement extends ReplaceableValue {
private ValueList list;
private int idx;
public ReplaceableListElement(ValueList list, int idx) {
this.list = list;
this.idx = idx;
}
@Override
public RValue get() {
return list.getList().get(idx);
}
@Override
public void set(RValue value) {
list.getList().set(idx, value);
}
}
/**
* Replaceable pointer index inside a indexed pointer dererence value.
*/
public static class ReplaceablePointerIndex extends ReplaceableValue {
private final PointerDereferenceIndexed pointer;
ReplaceablePointerIndex(PointerDereferenceIndexed pointer) {
this.pointer = pointer;
}
@Override
public RValue get() {
return pointer.getIndex();
}
@Override
public void set(RValue val) {
pointer.setIndex(val);
}
}
public static class ReplaceableRValue1 extends ReplaceableValue {
private final StatementAssignment statement;
public ReplaceableRValue1(StatementAssignment statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getrValue1();
}
@Override
public void set(RValue value) {
statement.setrValue1(value);
}
}
public static class ReplaceableRValue2 extends ReplaceableValue {
private final StatementAssignment statement;
public ReplaceableRValue2(StatementAssignment statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getrValue2();
}
@Override
public void set(RValue value) {
statement.setrValue2(value);
}
}
public static class ReplaceableCallParameter extends ReplaceableValue {
private final StatementCall call;
private final int i;
public ReplaceableCallParameter(StatementCall call, int i) {
this.call = call;
this.i = i;
}
@Override
public RValue get() {
return call.getParameters().get(i);
}
@Override
public void set(RValue value) {
call.getParameters().set(i, value);
}
}
public static class ReplaceableCondRValue1 extends ReplaceableValue {
private final StatementConditionalJump statement;
public ReplaceableCondRValue1(StatementConditionalJump statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getrValue1();
}
@Override
public void set(RValue value) {
statement.setrValue1(value);
}
}
public static class ReplaceableCondRValue2 extends ReplaceableValue {
private final StatementConditionalJump statement;
public ReplaceableCondRValue2(StatementConditionalJump statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getrValue2();
}
@Override
public void set(RValue value) {
statement.setrValue2(value);
}
}
public static class ReplaceableReturn extends ReplaceableValue {
private final StatementReturn statement;
public ReplaceableReturn(StatementReturn statement) {
this.statement = statement;
}
@Override
public RValue get() {
return statement.getValue();
}
@Override
public void set(RValue value) {
statement.setValue(value);
}
}
public static class ReplaceablePhiValue extends ReplaceableValue {
private final StatementPhiBlock.PhiVariable phiVariable;
private final int i;
public ReplaceablePhiValue(StatementPhiBlock.PhiVariable phiVariable, int i) {
this.phiVariable = phiVariable;
this.i = i;
}
@Override
public RValue get() {
return phiVariable.getValues().get(i).getrValue();
}
@Override
public void set(RValue value) {
phiVariable.getValues().get(i).setrValue(value);
}
}
/**
* Replaceable LValue as part of an assignment statement (or a call).
*/
public static class ReplaceablePhiVariable extends ReplaceableValue {
private final StatementPhiBlock.PhiVariable phiVariable;
public ReplaceablePhiVariable(StatementPhiBlock.PhiVariable phiVariable) {
this.phiVariable = phiVariable;
}
@Override
public RValue get() {
return phiVariable.getVariable();
}
@Override
public void set(RValue value) {
phiVariable.setVariable((VariableRef) value);
}
}
}