mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-05 21:30:52 +00:00
Renamed ValueReplacer classes to ValueIterator to better illustrate the generic nature.
This commit is contained in:
parent
a14fa4dec3
commit
f17422a564
@ -6,16 +6,20 @@ import dk.camelot64.kickc.model.types.SymbolTypeArray;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
/**
|
||||
* Interface representing an RValue that can be replaced.
|
||||
* The value may have sub-values that can also be replaced.
|
||||
* An RValue in the program being iterated by {@link ProgramValueIterator}.
|
||||
*
|
||||
* The RValue can be inspected using get() and replaced inside the model using set(val).
|
||||
*
|
||||
* The context of the RValue can be determined from the sub-class containing it plus the parameters to the ProgramValueHandler.
|
||||
*
|
||||
*/
|
||||
public abstract class ReplaceableValue {
|
||||
public abstract class ProgramValue {
|
||||
|
||||
public abstract RValue get();
|
||||
|
||||
public abstract void set(RValue value);
|
||||
|
||||
public static class ConstantVariableValue extends ReplaceableValue {
|
||||
public static class ConstantVariableValue extends ProgramValue {
|
||||
private final ConstantVar constantVar;
|
||||
|
||||
public ConstantVariableValue(ConstantVar constantVar) {
|
||||
@ -34,8 +38,8 @@ public abstract class ReplaceableValue {
|
||||
|
||||
}
|
||||
|
||||
/** Replaceable size inside a fixed size array. */
|
||||
public static class TypeArraySize extends ReplaceableValue {
|
||||
/** Size inside a fixed size array. */
|
||||
public static class TypeArraySize extends ProgramValue {
|
||||
private final SymbolTypeArray array;
|
||||
|
||||
public TypeArraySize(SymbolTypeArray array) {
|
||||
@ -54,8 +58,8 @@ public abstract class ReplaceableValue {
|
||||
|
||||
}
|
||||
|
||||
/** Replaceable value inside a array filled expression. */
|
||||
public static class ArrayFilledSize extends ReplaceableValue {
|
||||
/** Value inside a array filled expression. */
|
||||
public static class ArrayFilledSize extends ProgramValue {
|
||||
private final ArrayFilled array;
|
||||
|
||||
ArrayFilledSize(ArrayFilled array) {
|
||||
@ -74,8 +78,8 @@ public abstract class ReplaceableValue {
|
||||
|
||||
}
|
||||
|
||||
/** Replaceable value inside a constant array filled expression. */
|
||||
public static class ConstantArrayFilledSize extends ReplaceableValue {
|
||||
/** Value inside a constant array filled expression. */
|
||||
public static class ConstantArrayFilledSize extends ProgramValue {
|
||||
private final ConstantArrayFilled array;
|
||||
|
||||
ConstantArrayFilledSize(ConstantArrayFilled array) {
|
||||
@ -94,8 +98,8 @@ public abstract class ReplaceableValue {
|
||||
|
||||
}
|
||||
|
||||
/** Replaceable value inside a constant unary expression. */
|
||||
public static class ConstantUnaryValue extends ReplaceableValue {
|
||||
/** Value inside a constant unary expression. */
|
||||
public static class ConstantUnaryValue extends ProgramValue {
|
||||
private final ConstantUnary unary;
|
||||
|
||||
ConstantUnaryValue(ConstantUnary unary) {
|
||||
@ -114,8 +118,8 @@ public abstract class ReplaceableValue {
|
||||
|
||||
}
|
||||
|
||||
/** Replaceable left value inside a constant binary expression. */
|
||||
public static class ConstantBinaryLeft extends ReplaceableValue {
|
||||
/** Left value inside a constant binary expression. */
|
||||
public static class ConstantBinaryLeft extends ProgramValue {
|
||||
private final ConstantBinary binary;
|
||||
|
||||
ConstantBinaryLeft(ConstantBinary binary) {
|
||||
@ -134,8 +138,8 @@ public abstract class ReplaceableValue {
|
||||
|
||||
}
|
||||
|
||||
/** Replaceable right value inside a constant binary expression. */
|
||||
public static class ConstantBinaryRight extends ReplaceableValue {
|
||||
/** Right value inside a constant binary expression. */
|
||||
public static class ConstantBinaryRight extends ProgramValue {
|
||||
private final ConstantBinary binary;
|
||||
|
||||
ConstantBinaryRight(ConstantBinary range) {
|
||||
@ -155,9 +159,9 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable first value inside a ranged comparison value.
|
||||
* First value inside a ranged comparison value.
|
||||
*/
|
||||
public static class RangeFirst extends ReplaceableValue {
|
||||
public static class RangeFirst extends ProgramValue {
|
||||
private final RangeValue range;
|
||||
|
||||
RangeFirst(RangeValue range) {
|
||||
@ -177,9 +181,9 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable last value inside inside a ranged comparison value.
|
||||
* Last value inside inside a ranged comparison value.
|
||||
*/
|
||||
public static class RangeLast extends ReplaceableValue {
|
||||
public static class RangeLast extends ProgramValue {
|
||||
private final RangeValue range;
|
||||
|
||||
RangeLast(RangeValue range) {
|
||||
@ -199,9 +203,9 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable LValue as part of an assignment statement (or a call).
|
||||
* LValue as part of an assignment statement (or a call).
|
||||
*/
|
||||
public static class LValue extends ReplaceableValue {
|
||||
public static class LValue extends ProgramValue {
|
||||
private final StatementLValue statement;
|
||||
|
||||
public LValue(StatementLValue statement) {
|
||||
@ -221,9 +225,9 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable pointer inside a pointer dererence value.
|
||||
* Pointer inside a pointer dererence value.
|
||||
*/
|
||||
public static class Pointer extends ReplaceableValue {
|
||||
public static class Pointer extends ProgramValue {
|
||||
private final PointerDereference pointer;
|
||||
|
||||
Pointer(PointerDereference pointer) {
|
||||
@ -243,9 +247,9 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable value inside a noop cast.
|
||||
* Value inside a noop cast.
|
||||
*/
|
||||
public static class CastValue extends ReplaceableValue {
|
||||
public static class CastValue extends ProgramValue {
|
||||
private final dk.camelot64.kickc.model.values.CastValue castValue;
|
||||
|
||||
|
||||
@ -266,9 +270,9 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable value inside a constant noop cast.
|
||||
* Value inside a constant noop cast.
|
||||
*/
|
||||
public static class ConstantCastValue extends ReplaceableValue {
|
||||
public static class ConstantCastValue extends ProgramValue {
|
||||
private final dk.camelot64.kickc.model.values.ConstantCastValue castValue;
|
||||
|
||||
|
||||
@ -289,9 +293,9 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable pointer inside a variable pointer.
|
||||
* Pointer inside a variable pointer.
|
||||
*/
|
||||
public static class VarPointer extends ReplaceableValue {
|
||||
public static class VarPointer extends ProgramValue {
|
||||
private final ConstantVarPointer varPointer;
|
||||
|
||||
|
||||
@ -311,7 +315,7 @@ public abstract class ReplaceableValue {
|
||||
|
||||
}
|
||||
|
||||
public static class ConstantArrayElement extends ReplaceableValue {
|
||||
public static class ConstantArrayElement extends ProgramValue {
|
||||
private final ConstantArrayList arrayList;
|
||||
private final int idx;
|
||||
|
||||
@ -331,7 +335,7 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ListElement extends ReplaceableValue {
|
||||
public static class ListElement extends ProgramValue {
|
||||
private ValueList list;
|
||||
private int idx;
|
||||
|
||||
@ -353,9 +357,9 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable pointer index inside a indexed pointer dererence value.
|
||||
* Pointer index inside a indexed pointer dererence value.
|
||||
*/
|
||||
public static class PointerIndex extends ReplaceableValue {
|
||||
public static class PointerIndex extends ProgramValue {
|
||||
private final PointerDereferenceIndexed pointer;
|
||||
|
||||
PointerIndex(PointerDereferenceIndexed pointer) {
|
||||
@ -374,7 +378,7 @@ public abstract class ReplaceableValue {
|
||||
|
||||
}
|
||||
|
||||
public static class RValue1 extends ReplaceableValue {
|
||||
public static class RValue1 extends ProgramValue {
|
||||
private final StatementAssignment statement;
|
||||
|
||||
public RValue1(StatementAssignment statement) {
|
||||
@ -392,7 +396,7 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class RValue2 extends ReplaceableValue {
|
||||
public static class RValue2 extends ProgramValue {
|
||||
private final StatementAssignment statement;
|
||||
|
||||
public RValue2(StatementAssignment statement) {
|
||||
@ -410,7 +414,7 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class CallParameter extends ReplaceableValue {
|
||||
public static class CallParameter extends ProgramValue {
|
||||
private final StatementCall call;
|
||||
private final int i;
|
||||
|
||||
@ -430,7 +434,7 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class CondRValue1 extends ReplaceableValue {
|
||||
public static class CondRValue1 extends ProgramValue {
|
||||
private final StatementConditionalJump statement;
|
||||
|
||||
public CondRValue1(StatementConditionalJump statement) {
|
||||
@ -448,7 +452,7 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class CondRValue2 extends ReplaceableValue {
|
||||
public static class CondRValue2 extends ProgramValue {
|
||||
private final StatementConditionalJump statement;
|
||||
|
||||
public CondRValue2(StatementConditionalJump statement) {
|
||||
@ -466,7 +470,7 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class Return extends ReplaceableValue {
|
||||
public static class Return extends ProgramValue {
|
||||
private final StatementReturn statement;
|
||||
|
||||
public Return(StatementReturn statement) {
|
||||
@ -484,7 +488,7 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class PhiValue extends ReplaceableValue {
|
||||
public static class PhiValue extends ProgramValue {
|
||||
private final StatementPhiBlock.PhiVariable phiVariable;
|
||||
private final int i;
|
||||
|
||||
@ -505,9 +509,9 @@ public abstract class ReplaceableValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaceable LValue as part of an assignment statement (or a call).
|
||||
* LValue as part of an assignment statement (or a call).
|
||||
*/
|
||||
public static class PhiVariable extends ReplaceableValue {
|
||||
public static class PhiVariable extends ProgramValue {
|
||||
private final StatementPhiBlock.PhiVariable phiVariable;
|
||||
|
||||
public PhiVariable(StatementPhiBlock.PhiVariable phiVariable) {
|
||||
@ -526,8 +530,8 @@ public abstract class ReplaceableValue {
|
||||
|
||||
}
|
||||
|
||||
/** A generic replaceable value. */
|
||||
public static class GenericValue extends ReplaceableValue {
|
||||
/** A generic Value. */
|
||||
public static class GenericValue extends ProgramValue {
|
||||
private ConstantValue constantValue;
|
||||
|
||||
public GenericValue(ConstantValue constantValue) {
|
@ -0,0 +1,24 @@
|
||||
package dk.camelot64.kickc.model.iterator;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
/** A handler that performs some action for RValues in the program.
|
||||
* A {@link }ProgramValueIterator} can be used to iterate all RValues in a part of the program.
|
||||
* The Handler then receives all program values one at a time. The Handler has the option of replacing the value with another. After the handler is executed all sub-values are recursed.
|
||||
* The execute() method furthermore receives some extra parameters with information about the context of the passed value.
|
||||
*/
|
||||
public interface ProgramValueHandler {
|
||||
/**
|
||||
* Handle a single RValue
|
||||
*
|
||||
* @param programValue The programValue 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(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
|
||||
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
package dk.camelot64.kickc.model.iterator;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.ControlFlowGraph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.symbols.SymbolVariable;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeArray;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* Capable of iterating the different structures of a Program (graph, block, statement, symboltable, symbol).
|
||||
* Creates appropriate ProgramValues and passes them to a ProgramValueHandler.
|
||||
* Iteration might be guided (eg. filtering some types of the structure to iterate at call-time or guided by a return value from the ProgramValueHandler)
|
||||
*/
|
||||
public class ProgramValueIterator {
|
||||
|
||||
/**
|
||||
* Execute a handler on all values in the entire program (both in the control flow graph and the symbol table.)
|
||||
*
|
||||
* @param program The program
|
||||
* @param handler The handler to execute
|
||||
*/
|
||||
public static void execute(Program program, ProgramValueHandler handler) {
|
||||
execute(program.getScope(), handler);
|
||||
execute(program.getGraph(), handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a handler on all values in the program scope
|
||||
*
|
||||
* @param programScope The program scope
|
||||
* @param handler The handler to execute
|
||||
*/
|
||||
public static void execute(ProgramScope programScope, ProgramValueHandler handler) {
|
||||
for(SymbolVariable symbolVariable : programScope.getAllSymbolVariables(true)) {
|
||||
execute(symbolVariable, handler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a programValueHandler on all values in a variable symbol (variable or constant).
|
||||
*
|
||||
* @param symbolVariable The symbol variable
|
||||
* @param programValueHandler The programValueHandler to execute
|
||||
*/
|
||||
private static void execute(SymbolVariable symbolVariable, ProgramValueHandler programValueHandler) {
|
||||
if(symbolVariable.getType() instanceof SymbolTypeArray) {
|
||||
execute(new ProgramValue.TypeArraySize((SymbolTypeArray) symbolVariable.getType()), programValueHandler, null, null, null);
|
||||
}
|
||||
if(symbolVariable instanceof ConstantVar) {
|
||||
execute(new ProgramValue.ConstantVariableValue((ConstantVar) symbolVariable), programValueHandler, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a handler on all values in the program control flow graph
|
||||
*
|
||||
* @param graph The program control flow graph
|
||||
* @param handler The handler to execute
|
||||
*/
|
||||
public static void execute(ControlFlowGraph graph, ProgramValueHandler handler) {
|
||||
for(ControlFlowBlock block : graph.getAllBlocks()) {
|
||||
execute(block, handler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a handler on all values in a block of the control flow graph
|
||||
*
|
||||
* @param block The control flow graph block
|
||||
* @param handler The handler to execute
|
||||
*/
|
||||
public static void execute(ControlFlowBlock block, ProgramValueHandler handler) {
|
||||
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
|
||||
while(statementsIt.hasNext()) {
|
||||
Statement statement = statementsIt.next();
|
||||
execute(statement, handler, statementsIt, block);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a handler on all values in a statement
|
||||
*
|
||||
* @param statement The statement
|
||||
* @param handler The handler to execute
|
||||
*/
|
||||
public static void execute(Statement statement, ProgramValueHandler handler, ListIterator<Statement> statementsIt, ControlFlowBlock block) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
// The sequence RValue1, RValue2, LValue is important - as it is essential for {@link dk.camelot64.kickc.passes.Pass1GenerateSingleStaticAssignmentForm} to create the correct SSA
|
||||
execute(new ProgramValue.RValue1((StatementAssignment) statement), handler, statement, statementsIt, block);
|
||||
execute(new ProgramValue.RValue2((StatementAssignment) statement), handler, statement, statementsIt, block);
|
||||
execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
||||
} else if(statement instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) statement;
|
||||
if(call.getParameters() != null) {
|
||||
int size = call.getParameters().size();
|
||||
for(int i = 0; i < size; i++) {
|
||||
execute(new ProgramValue.CallParameter(call, i), handler, statement, statementsIt, block);
|
||||
}
|
||||
}
|
||||
execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
||||
} else if(statement instanceof StatementConditionalJump) {
|
||||
execute(new ProgramValue.CondRValue1((StatementConditionalJump) statement), handler, statement, statementsIt, block);
|
||||
execute(new ProgramValue.CondRValue2((StatementConditionalJump) statement), handler, statement, statementsIt, block);
|
||||
} else if(statement instanceof StatementReturn) {
|
||||
execute(new ProgramValue.Return((StatementReturn) statement), handler, statement, statementsIt, block);
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||
int size = phiVariable.getValues().size();
|
||||
for(int i = 0; i < size; i++) {
|
||||
execute(new ProgramValue.PhiValue(phiVariable, i), handler, statement, statementsIt, block);
|
||||
}
|
||||
execute(new ProgramValue.PhiVariable(phiVariable), handler, statement, statementsIt, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the a handler on a value and all sub-values of the value.
|
||||
*
|
||||
* @param programValue The programValue value
|
||||
* @param handler The value handler
|
||||
*/
|
||||
public static void execute(ProgramValue programValue, ProgramValueHandler handler, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
handler.execute(programValue, currentStmt, stmtIt, currentBlock);
|
||||
for(ProgramValue subValue : getSubValues(programValue.get())) {
|
||||
execute(subValue, handler, currentStmt, stmtIt, currentBlock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sub values for an RValue.
|
||||
*
|
||||
* @param value The RValue
|
||||
* @return The sub-values of the RValue (only one level down, recursion is needed to get all contained sub-values)
|
||||
*/
|
||||
private static Collection<ProgramValue> getSubValues(RValue value) {
|
||||
ArrayList<ProgramValue> subValues = new ArrayList<>();
|
||||
if(value instanceof PointerDereferenceIndexed) {
|
||||
subValues.add(new ProgramValue.Pointer((PointerDereference) value));
|
||||
subValues.add(new ProgramValue.PointerIndex((PointerDereferenceIndexed) value));
|
||||
} else if(value instanceof PointerDereferenceSimple) {
|
||||
subValues.add(new ProgramValue.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 ProgramValue.ListElement(valueList, i));
|
||||
}
|
||||
} else if(value instanceof ConstantArrayList) {
|
||||
ConstantArrayList constantArrayList = (ConstantArrayList) value;
|
||||
int size = constantArrayList.getElements().size();
|
||||
for(int i = 0; i < size; i++) {
|
||||
subValues.add(new ProgramValue.ConstantArrayElement(constantArrayList, i));
|
||||
}
|
||||
} else if(value instanceof CastValue) {
|
||||
subValues.add(new ProgramValue.CastValue((CastValue) value));
|
||||
} else if(value instanceof ConstantCastValue) {
|
||||
subValues.add(new ProgramValue.ConstantCastValue((ConstantCastValue) value));
|
||||
} else if(value instanceof ConstantVarPointer) {
|
||||
subValues.add(new ProgramValue.VarPointer((ConstantVarPointer) value));
|
||||
} else if(value instanceof RangeValue) {
|
||||
subValues.add(new ProgramValue.RangeFirst((RangeValue) value));
|
||||
subValues.add(new ProgramValue.RangeLast((RangeValue) value));
|
||||
} else if(value instanceof ConstantBinary) {
|
||||
subValues.add(new ProgramValue.ConstantBinaryLeft((ConstantBinary) value));
|
||||
subValues.add(new ProgramValue.ConstantBinaryRight((ConstantBinary) value));
|
||||
} else if(value instanceof ConstantUnary) {
|
||||
subValues.add(new ProgramValue.ConstantUnaryValue((ConstantUnary) value));
|
||||
} else if(value instanceof ArrayFilled) {
|
||||
subValues.add(new ProgramValue.ArrayFilledSize((ArrayFilled) value));
|
||||
} else if(value instanceof ConstantArrayFilled) {
|
||||
subValues.add(new ProgramValue.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,19 +0,0 @@
|
||||
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);
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
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()) {
|
||||
executeAll(block, replacer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a replacer on all replaceable values in a block of the control flow graph
|
||||
*
|
||||
* @param block The control flow graph block
|
||||
* @param replacer The replacer to execute
|
||||
*/
|
||||
public static void executeAll(ControlFlowBlock block, Replacer replacer) {
|
||||
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) {
|
||||
// The sequence RValue1, RValue2, LValue is important - as it is essential for {@link dk.camelot64.kickc.passes.Pass1GenerateSingleStaticAssignmentForm} to create the correct SSA
|
||||
executeAll(new ReplaceableValue.RValue1((StatementAssignment) statement), replacer, statement, statementsIt, block);
|
||||
executeAll(new ReplaceableValue.RValue2((StatementAssignment) statement), replacer, statement, statementsIt, block);
|
||||
executeAll(new ReplaceableValue.LValue((StatementLValue) statement), replacer, statement, statementsIt, block);
|
||||
} else if(statement instanceof StatementCall) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
executeAll(new ReplaceableValue.LValue((StatementLValue) statement), 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()) {
|
||||
int size = phiVariable.getValues().size();
|
||||
for(int i = 0; i < size; i++) {
|
||||
executeAll(new ReplaceableValue.PhiValue(phiVariable, i), replacer, statement, statementsIt, block);
|
||||
}
|
||||
executeAll(new ReplaceableValue.PhiVariable(phiVariable), 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sub values for an RValue.
|
||||
* @param value The RValue
|
||||
* @return The sub-values of the RValue (only one level down, recursion is needed to get all contained sub-values)
|
||||
*/
|
||||
private 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 ConstantArrayList) {
|
||||
ConstantArrayList constantArrayList = (ConstantArrayList) value;
|
||||
int size = constantArrayList.getElements().size();
|
||||
for(int i=0;i<size;i++) {
|
||||
subValues.add(new ReplaceableValue.ConstantArrayElement(constantArrayList, 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,8 +1,10 @@
|
||||
package dk.camelot64.kickc.model.symbols;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.Registers;
|
||||
import dk.camelot64.kickc.model.VariableRegisterWeights;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -185,33 +187,35 @@ public abstract class Scope implements Symbol {
|
||||
return getConstant(constantRef.getFullName());
|
||||
}
|
||||
|
||||
public Collection<Variable> getAllVariables(boolean includeSubScopes) {
|
||||
Collection<Variable> vars = new ArrayList<>();
|
||||
public Collection<SymbolVariable> getAllSymbolVariables(boolean includeSubScopes) {
|
||||
Collection<SymbolVariable> vars = new ArrayList<>();
|
||||
for(Symbol symbol : symbols.values()) {
|
||||
if(symbol instanceof Variable) {
|
||||
vars.add((Variable) symbol);
|
||||
if(symbol instanceof SymbolVariable) {
|
||||
vars.add((SymbolVariable) symbol);
|
||||
}
|
||||
if(includeSubScopes && symbol instanceof Scope) {
|
||||
Scope subScope = (Scope) symbol;
|
||||
vars.addAll(subScope.getAllVariables(true));
|
||||
vars.addAll(subScope.getAllSymbolVariables(true));
|
||||
}
|
||||
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
public Collection<ConstantVar> getAllConstants(boolean includeSubScopes) {
|
||||
Collection<ConstantVar> vars = new ArrayList<>();
|
||||
for(Symbol symbol : symbols.values()) {
|
||||
if(symbol instanceof ConstantVar) {
|
||||
vars.add((ConstantVar) symbol);
|
||||
}
|
||||
if(includeSubScopes && symbol instanceof Scope) {
|
||||
Scope subScope = (Scope) symbol;
|
||||
vars.addAll(subScope.getAllConstants(true));
|
||||
}
|
||||
public Collection<Variable> getAllVariables(boolean includeSubScopes) {
|
||||
Collection<SymbolVariable> symbolVariables = getAllSymbolVariables(includeSubScopes);
|
||||
Collection<Variable> vars = new ArrayList<>();
|
||||
symbolVariables.stream().
|
||||
filter(symbolVariable -> (symbolVariable instanceof Variable)).
|
||||
forEach(symbolVariable -> vars.add((Variable) symbolVariable));
|
||||
return vars;
|
||||
}
|
||||
|
||||
}
|
||||
public Collection<ConstantVar> getAllConstants(boolean includeSubScopes) {
|
||||
Collection<SymbolVariable> symbolVariables = getAllSymbolVariables(includeSubScopes);
|
||||
Collection<ConstantVar> vars = new ArrayList<>();
|
||||
symbolVariables.stream().
|
||||
filter(symbolVariable -> (symbolVariable instanceof ConstantVar)).
|
||||
forEach(symbolVariable -> vars.add((ConstantVar) symbolVariable));
|
||||
return vars;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
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.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueHandler;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
@ -11,8 +11,8 @@ import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
|
||||
/** A {@link ValueReplacer} that replaces symbols with their alias. */
|
||||
public class AliasReplacer implements Replacer {
|
||||
/** A {@link ProgramValueIterator} that replaces symbols with their alias. */
|
||||
public class AliasReplacer implements ProgramValueHandler {
|
||||
|
||||
|
||||
/** true if anything has ben replaced. */
|
||||
@ -31,16 +31,16 @@ public class AliasReplacer implements Replacer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute alias replacement on a replaceable value
|
||||
* Execute alias replacement on a value
|
||||
*
|
||||
* @param replaceable The replaceable value
|
||||
* @param programValue The value
|
||||
*/
|
||||
@Override
|
||||
public void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
if(replaceable.get() != null) {
|
||||
RValue replacement = getReplacement(replaceable.get(), aliases);
|
||||
public void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
if(programValue.get() != null) {
|
||||
RValue replacement = getReplacement(programValue.get(), aliases);
|
||||
if(replacement != null) {
|
||||
replaceable.set(replacement);
|
||||
programValue.set(replacement);
|
||||
this.replaced = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.iterator.ValueReplacer;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.values.ConstantString;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
@ -23,15 +23,15 @@ public class Pass1ExtractInlineStrings extends Pass1Base {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> {
|
||||
ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
String nameHint = null;
|
||||
if(currentStmt instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) currentStmt;
|
||||
List<RValue> parameters = call.getParameters();
|
||||
for(int i = 0; i < parameters.size(); i++) {
|
||||
RValue parameter = parameters.get(i);
|
||||
if(parameter.equals(replaceable.get())) {
|
||||
// The replaceable value is the parameter - use the parameter name as name hint
|
||||
if(parameter.equals(programValue.get())) {
|
||||
// The programValue value is the parameter - use the parameter name as name hint
|
||||
Procedure procedure = Pass1ExtractInlineStrings.this.getProgram().getScope().getProcedure(call.getProcedure());
|
||||
nameHint = procedure.getParameterNames().get(i);
|
||||
break;
|
||||
@ -39,10 +39,10 @@ public class Pass1ExtractInlineStrings extends Pass1Base {
|
||||
}
|
||||
}
|
||||
Scope blockScope = Pass1ExtractInlineStrings.this.getProgram().getScope().getScope(currentBlock.getScope());
|
||||
RValue value = replaceable.get();
|
||||
RValue value = programValue.get();
|
||||
if(value instanceof ConstantString) {
|
||||
ConstantVar strConst = Pass1ExtractInlineStrings.this.createStringConstantVar(blockScope, (ConstantString) replaceable.get(), nameHint);
|
||||
replaceable.set(strConst.getRef());
|
||||
ConstantVar strConst = Pass1ExtractInlineStrings.this.createStringConstantVar(blockScope, (ConstantString) programValue.get(), nameHint);
|
||||
programValue.set(strConst.getRef());
|
||||
}
|
||||
});
|
||||
return false;
|
||||
|
@ -3,8 +3,8 @@ 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.ValueReplacer;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementLValue;
|
||||
@ -89,14 +89,14 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
||||
Map<VariableUnversioned, VariableVersion> blockVersions = new LinkedHashMap<>();
|
||||
// New phi functions introduced in the block to create versions of variables.
|
||||
Map<VariableUnversioned, VariableVersion> blockNewPhis = new LinkedHashMap<>();
|
||||
ValueReplacer.executeAll(block, (replaceable, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue value = replaceable.get();
|
||||
ProgramValueIterator.execute(block, (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue value = programValue.get();
|
||||
VariableVersion version = findOrCreateVersion(value, blockVersions, blockNewPhis);
|
||||
if(version != null) {
|
||||
replaceable.set(version.getRef());
|
||||
programValue.set(version.getRef());
|
||||
}
|
||||
// Update map of versions encountered in the block
|
||||
if(currentStmt instanceof StatementAssignment && replaceable instanceof ReplaceableValue.LValue) {
|
||||
if(currentStmt instanceof StatementAssignment && programValue instanceof ProgramValue.LValue) {
|
||||
StatementAssignment assignment = (StatementAssignment) currentStmt;
|
||||
LValue lValue = assignment.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
|
@ -3,9 +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.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueHandler;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
@ -191,7 +191,7 @@ public class Pass1ProcedureInline extends Pass1Base {
|
||||
throw new CompileError("Statement type of Inline function not handled " + procStatement, procStatement.getSource());
|
||||
}
|
||||
if(inlinedStatement!=null) {
|
||||
ValueReplacer.executeAll(inlinedStatement, new RValueInliner(procedure, serial, callScope), null, null);
|
||||
ProgramValueIterator.execute(inlinedStatement, new RValueInliner(procedure, serial, callScope), null, null);
|
||||
}
|
||||
return inlinedStatement;
|
||||
}
|
||||
@ -200,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 Replacer {
|
||||
private class RValueInliner implements ProgramValueHandler {
|
||||
|
||||
/** The scope where the precedure is being inlined into. */
|
||||
private final Scope callScope;
|
||||
@ -216,24 +216,24 @@ public class Pass1ProcedureInline extends Pass1Base {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
RValue rValue = replaceable.get();
|
||||
public void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
RValue rValue = programValue.get();
|
||||
if(rValue instanceof VariableRef) {
|
||||
VariableRef procVarRef = (VariableRef) rValue;
|
||||
Variable procVar = Pass1ProcedureInline.this.getScope().getVariable(procVarRef);
|
||||
if(procVar.getScope().equals(procedure)) {
|
||||
String inlineSymbolName = Pass1ProcedureInline.this.getInlineSymbolName(procedure, procVar, serial);
|
||||
Variable inlineVar = callScope.getVariable(inlineSymbolName);
|
||||
replaceable.set(inlineVar.getRef());
|
||||
programValue.set(inlineVar.getRef());
|
||||
}
|
||||
} else if(rValue instanceof PointerDereferenceSimple) {
|
||||
replaceable.set(new PointerDereferenceSimple(((PointerDereferenceSimple) rValue).getPointer()));
|
||||
programValue.set(new PointerDereferenceSimple(((PointerDereferenceSimple) rValue).getPointer()));
|
||||
} else if(rValue instanceof PointerDereferenceIndexed) {
|
||||
replaceable.set(new PointerDereferenceIndexed(((PointerDereferenceIndexed) rValue).getPointer(), ((PointerDereferenceIndexed) rValue).getIndex()));
|
||||
programValue.set(new PointerDereferenceIndexed(((PointerDereferenceIndexed) rValue).getPointer(), ((PointerDereferenceIndexed) rValue).getIndex()));
|
||||
} else if(rValue instanceof CastValue) {
|
||||
replaceable.set(new CastValue(((CastValue) rValue).getToType(), ((CastValue) rValue).getValue()));
|
||||
programValue.set(new CastValue(((CastValue) rValue).getToType(), ((CastValue) rValue).getValue()));
|
||||
} else if(rValue instanceof ValueList) {
|
||||
replaceable.set(new ValueList(new ArrayList<>(((ValueList) rValue).getList())));
|
||||
programValue.set(new ValueList(new ArrayList<>(((ValueList) rValue).getList())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +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.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.symbols.Scope;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.values.ForwardVariableRef;
|
||||
@ -17,15 +17,15 @@ public class Pass1ResolveForwardReferences extends Pass1Base {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue rValue = replaceable.get();
|
||||
ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue rValue = programValue.get();
|
||||
if(rValue instanceof ForwardVariableRef) {
|
||||
String varName = ((ForwardVariableRef) rValue).getName();
|
||||
Scope currentScope = getScope().getScope(currentBlock.getScope());
|
||||
Variable variable = currentScope.getVariable(varName);
|
||||
if(variable!=null) {
|
||||
getLog().append("Resolved forward reference " + varName+" to "+variable.toString(getProgram()));
|
||||
replaceable.set(variable.getRef());
|
||||
programValue.set(variable.getRef());
|
||||
} else {
|
||||
getLog().append("ERROR! Unknown variable " + varName);
|
||||
throw new CompileError("ERROR! Unknown variable " + varName, currentStmt.getSource());
|
||||
|
@ -2,7 +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.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.values.ForwardVariableRef;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
@ -16,8 +16,8 @@ public class Pass2AssertRValues extends Pass2SsaAssertion {
|
||||
|
||||
@Override
|
||||
public void check() throws AssertionFailed {
|
||||
ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue rValue = replaceable.get();
|
||||
ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue rValue = programValue.get();
|
||||
if(rValue instanceof ForwardVariableRef) {
|
||||
throw new CompileError("No forward references allowed "+currentStmt.toString(getProgram(), false), currentStmt.getSource());
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.iterator.ReplaceableValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.operators.Operator;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
@ -46,13 +46,13 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(assignment.getlValue() instanceof PointerDereferenceIndexed) {
|
||||
optimized |= optimizePointerDereferenceIndexed(new ReplaceableValue.LValue(assignment));
|
||||
optimized |= optimizePointerDereferenceIndexed(new ProgramValue.LValue(assignment));
|
||||
}
|
||||
if(assignment.getrValue1() instanceof PointerDereferenceIndexed) {
|
||||
optimized |= optimizePointerDereferenceIndexed(new ReplaceableValue.RValue1(assignment));
|
||||
optimized |= optimizePointerDereferenceIndexed(new ProgramValue.RValue1(assignment));
|
||||
}
|
||||
if(assignment.getrValue2() instanceof PointerDereferenceIndexed) {
|
||||
optimized |= optimizePointerDereferenceIndexed(new ReplaceableValue.RValue2(assignment));
|
||||
optimized |= optimizePointerDereferenceIndexed(new ProgramValue.RValue2(assignment));
|
||||
}
|
||||
|
||||
Operator operator = assignment.getOperator();
|
||||
@ -69,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 ReplaceableValue.CondRValue1(jump));
|
||||
optimized |= optimizePointerDereferenceIndexed(new ProgramValue.CondRValue1(jump));
|
||||
}
|
||||
if(jump.getrValue2() instanceof PointerDereferenceIndexed) {
|
||||
optimized |= optimizePointerDereferenceIndexed(new ReplaceableValue.CondRValue2(jump));
|
||||
optimized |= optimizePointerDereferenceIndexed(new ProgramValue.CondRValue2(jump));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -80,7 +80,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
return optimized;
|
||||
}
|
||||
|
||||
private boolean optimizePointerDereferenceIndexed(ReplaceableValue value) {
|
||||
private boolean optimizePointerDereferenceIndexed(ProgramValue value) {
|
||||
PointerDereferenceIndexed pointerDereferenceIndexed = (PointerDereferenceIndexed) value.get();
|
||||
if(pointerDereferenceIndexed.getPointer() instanceof ConstantValue && pointerDereferenceIndexed.getIndex() instanceof ConstantValue) {
|
||||
ConstantValue ptrConstant = (ConstantValue) pointerDereferenceIndexed.getPointer();
|
||||
|
@ -1,9 +1,8 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.iterator.ReplaceableValue;
|
||||
import dk.camelot64.kickc.model.iterator.ValueReplacer;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeArray;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
@ -64,28 +63,6 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any alias within the constant defintions inside the symbol table
|
||||
*
|
||||
* @param inline The replacements to make
|
||||
*/
|
||||
private void replaceInSymbolTable(Map<ConstantRef, ConstantValue> inline) {
|
||||
Collection<ConstantVar> allConstants = getProgram().getScope().getAllConstants(true);
|
||||
for(ConstantVar constantVar : allConstants) {
|
||||
|
||||
// First check if the type is an array - and replace inside the type if it is
|
||||
SymbolType constantType = constantVar.getType();
|
||||
if(constantType instanceof SymbolTypeArray) {
|
||||
SymbolTypeArray arrayType = (SymbolTypeArray) constantType;
|
||||
ReplaceableValue.TypeArraySize replaceableArrayType = new ReplaceableValue.TypeArraySize(arrayType);
|
||||
ValueReplacer.executeAll(replaceableArrayType, new AliasReplacer(inline), null, null, null);
|
||||
}
|
||||
|
||||
ReplaceableValue.ConstantVariableValue replaceableConstantVal = new ReplaceableValue.ConstantVariableValue(constantVar);
|
||||
ValueReplacer.executeAll(replaceableConstantVal, new AliasReplacer(inline), null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any aliases within the constant values themselves
|
||||
*
|
||||
@ -97,16 +74,25 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
||||
replaced = false;
|
||||
for(ConstantRef constantRef : inline.keySet()) {
|
||||
ConstantValue constantValue = inline.get(constantRef);
|
||||
ReplaceableValue.GenericValue replaceable = new ReplaceableValue.GenericValue(constantValue);
|
||||
ProgramValue.GenericValue genericValue = new ProgramValue.GenericValue(constantValue);
|
||||
AliasReplacer replacer = new AliasReplacer(inline);
|
||||
ValueReplacer.executeAll(replaceable, replacer, null, null, null);
|
||||
ProgramValueIterator.execute(genericValue, replacer, null, null, null);
|
||||
if(replacer.isReplaced()) {
|
||||
inline.put(constantRef, (ConstantValue) replaceable.get());
|
||||
inline.put(constantRef, (ConstantValue) genericValue.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any alias within the constant defintions inside the symbol table
|
||||
*
|
||||
* @param inline The replacements to make
|
||||
*/
|
||||
private void replaceInSymbolTable(Map<ConstantRef, ConstantValue> inline) {
|
||||
ProgramValueIterator.execute(getScope(), new AliasReplacer(inline));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all unnamed constants $1 = VIC+$20
|
||||
*
|
||||
|
@ -1,9 +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.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueHandler;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.operators.Operator;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
@ -32,9 +32,9 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
|
||||
@Override
|
||||
public boolean step() {
|
||||
WordConstructor wordConstructor = new WordConstructor();
|
||||
ValueReplacer.executeAll(getGraph(), wordConstructor);
|
||||
ProgramValueIterator.execute(getGraph(), wordConstructor);
|
||||
DWordConstructor dwordConstructor = new DWordConstructor();
|
||||
ValueReplacer.executeAll(getGraph(), dwordConstructor);
|
||||
ProgramValueIterator.execute(getGraph(), dwordConstructor);
|
||||
return wordConstructor.isOptimized() || dwordConstructor.isOptimized();
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
|
||||
private abstract class InlineConstructor implements Replacer {
|
||||
private abstract class InlineConstructor implements ProgramValueHandler {
|
||||
private SymbolTypeInteger constructType;
|
||||
private Operator constructOperator;
|
||||
private boolean optimized;
|
||||
@ -82,8 +82,8 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
RValue rValue = replaceable.get();
|
||||
public void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
|
||||
RValue rValue = programValue.get();
|
||||
if(rValue instanceof ValueList) {
|
||||
ValueList list = (ValueList) rValue;
|
||||
if(list.getList().size() == 2) {
|
||||
@ -117,7 +117,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
|
||||
// Move back before the current statement
|
||||
stmtIt.next();
|
||||
// Replace current value with the reference
|
||||
replaceable.set(tmpVar.getRef());
|
||||
programValue.set(tmpVar.getRef());
|
||||
Pass2FixInlineConstructors.this.getLog().append("Fixing inline constructor with " + assignment.toString());
|
||||
optimized = true;
|
||||
}
|
||||
|
@ -2,7 +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.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
@ -29,8 +29,8 @@ public class Pass2RangeResolving extends Pass2SsaOptimization {
|
||||
public boolean step() {
|
||||
boolean modified = false;
|
||||
|
||||
ValueReplacer.executeAll(getProgram().getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue value = replaceable.get();
|
||||
ProgramValueIterator.execute(getProgram().getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue value = programValue.get();
|
||||
if(value instanceof RangeValue) {
|
||||
RangeValue rangeValue = (RangeValue) value;
|
||||
if(rangeValue.getRangeFirst() instanceof ConstantValue && rangeValue.getRangeLast() instanceof ConstantValue) {
|
||||
@ -81,7 +81,7 @@ public class Pass2RangeResolving extends Pass2SsaOptimization {
|
||||
beyondLastVal = new ConstantCastValue(type, beyondLastVal );
|
||||
}
|
||||
getLog().append("Resolved ranged comparison value "+currentStmt+" to "+beyondLastVal.toString(getProgram()));
|
||||
replaceable.set(beyondLastVal);
|
||||
programValue.set(beyondLastVal);
|
||||
} else if(rangeValue instanceof RangeNext) {
|
||||
StatementAssignment assignment = (StatementAssignment) currentStmt;
|
||||
if(firstInt <= lastInt) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.iterator.ValueReplacer;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.Symbol;
|
||||
@ -46,8 +46,7 @@ public abstract class Pass2SsaOptimization extends Pass1Base {
|
||||
* @param aliases Variables that have alias values.
|
||||
*/
|
||||
public void replaceVariables(final Map<? extends SymbolRef, ? extends RValue> aliases) {
|
||||
AliasReplacer replacer = new AliasReplacer(aliases);
|
||||
ValueReplacer.executeAll(getGraph(), replacer);
|
||||
ProgramValueIterator.execute(getGraph(), new AliasReplacer(aliases));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,7 +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.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.RangeValue;
|
||||
import dk.camelot64.kickc.model.values.ValueList;
|
||||
@ -21,8 +21,8 @@ public class Pass3AssertRValues extends Pass2SsaAssertion {
|
||||
|
||||
@Override
|
||||
public void check() throws AssertionFailed {
|
||||
ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue value = replaceable.get();
|
||||
ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
RValue value = programValue.get();
|
||||
if(value instanceof ValueList) {
|
||||
throw new CompileError(
|
||||
"Error! Value list not resolved to word constructor or array initializer" +
|
||||
|
Loading…
x
Reference in New Issue
Block a user