1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-09 18:29:36 +00:00
kickc/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
2023-04-10 11:19:32 +02:00

109 lines
5.5 KiB
Java

package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.OperatorBinary;
import dk.camelot64.kickc.model.operators.OperatorUnary;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantSymbolPointer;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.SymbolRef;
/**
* Compiler Pass consolidating R-values that are constant into a single {@link ConstantValue}
*/
public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
public Pass2ConstantRValueConsolidation(Program program) {
super(program);
}
/**
* Propagate constants, replacing variables with constants where possible.
*
* @return true optimization was performed. false if no optimization was possible.
*/
@Override
public boolean step() {
boolean modified = false;
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment assignment) {
if(assignment.getrValue1() != null || assignment.getOperator() != null || !(assignment.getrValue2() instanceof ConstantValue)) {
SymbolType lValueType = SymbolTypeInference.inferType(getProgramScope(), assignment.getlValue());
ConstantValue constant = getConstantAssignmentValue(assignment);
if(constant != null) {
getLog().append("Constant right-side identified " + assignment.toString(getProgram(), false));
assignment.setrValue2(constant);
assignment.setOperator(null);
assignment.setrValue1(null);
modified = true;
}
}
}
}
return modified;
}
/**
* Examine the right side of an assignment and if it is constant then return the constant value.
*
* @param assignment The assignment to examine
* @return The constant value if the right side is constant
*/
private ConstantValue getConstantAssignmentValue(StatementAssignment assignment) {
if(assignment.getrValue1() == null && Pass2ConstantIdentification.getConstant(assignment.getrValue2()) != null) {
if(assignment.getOperator() == null) {
// Constant assignment
return Pass2ConstantIdentification.getConstant(assignment.getrValue2());
} else {
// Constant unary expression
return Pass2ConstantIdentification.createUnary(
(OperatorUnary) assignment.getOperator(),
Pass2ConstantIdentification.getConstant(assignment.getrValue2())
);
}
} else if(Pass2ConstantIdentification.getConstant(assignment.getrValue1()) != null && Pass2ConstantIdentification.getConstant(assignment.getrValue2()) != null) {
// Constant binary expression
return Pass2ConstantIdentification.createBinary(
Pass2ConstantIdentification.getConstant(assignment.getrValue1()),
(OperatorBinary) assignment.getOperator(),
Pass2ConstantIdentification.getConstant(assignment.getrValue2()),
getProgramScope());
} else if(Operators.BYTE1.equals(assignment.getOperator()) && assignment.getrValue1() == null) {
final SymbolType rVal2Type = SymbolTypeInference.inferType(getProgramScope(), assignment.getrValue2());
if(SymbolType.isInteger(rVal2Type) && rVal2Type.getSizeBytes() < 2)
return new ConstantInteger(0l, SymbolType.BYTE);
} else if(Operators.BYTE2.equals(assignment.getOperator()) && assignment.getrValue1() == null) {
final SymbolType rVal2Type = SymbolTypeInference.inferType(getProgramScope(), assignment.getrValue2());
if(SymbolType.isInteger(rVal2Type) && rVal2Type.getSizeBytes() < 3)
return new ConstantInteger(0l, SymbolType.BYTE);
else if(rVal2Type instanceof SymbolTypePointer)
return new ConstantInteger(0l, SymbolType.BYTE);
} else if(Operators.BYTE3.equals(assignment.getOperator()) && assignment.getrValue1() == null) {
final SymbolType rVal2Type = SymbolTypeInference.inferType(getProgramScope(), assignment.getrValue2());
if(SymbolType.isInteger(rVal2Type) && rVal2Type.getSizeBytes() < 4)
return new ConstantInteger(0l, SymbolType.BYTE);
else if(rVal2Type instanceof SymbolTypePointer)
return new ConstantInteger(0l, SymbolType.BYTE);
} else if(Operators.WORD1.equals(assignment.getOperator()) && assignment.getrValue1() == null) {
final SymbolType rVal2Type = SymbolTypeInference.inferType(getProgramScope(), assignment.getrValue2());
if(SymbolType.isInteger(rVal2Type) && rVal2Type.getSizeBytes() < 3)
return new ConstantInteger(0l, SymbolType.WORD);
else if(rVal2Type instanceof SymbolTypePointer)
return new ConstantInteger(0l, SymbolType.WORD);
} else if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && assignment.getrValue1() == null) {
// Constant address-of variable
if(assignment.getrValue2() instanceof SymbolRef) {
return new ConstantSymbolPointer((SymbolRef) assignment.getrValue2());
}
}
return null;
}
}