mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-14 23:04:57 +00:00
Refacing ValueReplacer
This commit is contained in:
parent
62cfda6468
commit
f9449997cb
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user