1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-01 00:51:12 +00:00

Made statement loops simpler.

This commit is contained in:
jespergravgaard 2023-04-10 11:19:32 +02:00
parent c78b8c59b1
commit 55bec51f09
34 changed files with 591 additions and 702 deletions

View File

@ -74,10 +74,8 @@ public class ControlFlowGraph implements Graph {
* Clear all statement indices,
*/
public void clearStatementIndices() {
for(var block : getAllBlocks()) {
for(Statement statement : block.getStatements()) {
statement.setIndex(null);
}
for (Statement statement : getAllStatements()) {
statement.setIndex(null);
}
}

View File

@ -62,11 +62,9 @@ public interface Graph {
* @return The statement
*/
default Statement getStatementByIndex(int statementIdx) {
for(Graph.Block block : getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement.getIndex() != null && statementIdx == statement.getIndex()) {
return statement;
}
for (Statement statement : getAllStatements()) {
if (statement.getIndex() != null && statementIdx == statement.getIndex()) {
return statement;
}
}
return null;

View File

@ -45,10 +45,8 @@ public class LiveRangeVariablesEffectiveCallPaths implements LiveRangeVariablesE
this.referenceInfo = referenceInfo;
this.blockSuccessorClosure = blockSuccessorClosure;
this.statementLiveVariables = new LinkedHashMap<>();
for(Graph.Block block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
statementLiveVariables.put(statement.getIndex(), liveRangeVariables.getAlive(statement.getIndex()));
}
for (Statement statement : program.getGraph().getAllStatements()) {
statementLiveVariables.put(statement.getIndex(), liveRangeVariables.getAlive(statement.getIndex()));
}
}

View File

@ -24,16 +24,14 @@ public class Pass1AssertNoLValueIntermediate extends Pass1Base {
@Override
public boolean step() {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
LValue lValue = ((StatementLValue) statement).getlValue();
if(lValue instanceof LvalueIntermediate) {
VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable();
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(intermediateVar, getGraph(), getProgramScope());
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
throw new CompileError("LValue is illegal. " + statement + " - definition of lValue " + varAssignment, varAssignment.getSource());
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementLValue) {
LValue lValue = ((StatementLValue) statement).getlValue();
if(lValue instanceof LvalueIntermediate) {
VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable();
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(intermediateVar, getGraph(), getProgramScope());
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
throw new CompileError("LValue is illegal. " + statement + " - definition of lValue " + varAssignment, varAssignment.getSource());
}
}
}

View File

@ -20,14 +20,16 @@ public class Pass1AssertNoModifyVars extends Pass1Base {
@Override
public boolean step() {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue statementLValue = (StatementLValue) statement;
if(!statementLValue.isInitialAssignment() && statementLValue.getlValue() instanceof VariableRef) {
Variable assignedVar = getProgramScope().getVariable((VariableRef) statementLValue.getlValue());
if(assignedVar.isNoModify())
throw new CompileError("const variable may not be modified! " + assignedVar.toString(), statement);
for(var statement : getGraph().getAllStatements()) {
if (statement instanceof StatementLValue) {
StatementLValue statementLValue = (StatementLValue) statement;
if (!statementLValue.isInitialAssignment()
&& statementLValue.getlValue() instanceof VariableRef) {
Variable assignedVar = getProgramScope().getVariable(
(VariableRef) statementLValue.getlValue());
if (assignedVar.isNoModify()) {
throw new CompileError(
"const variable may not be modified! " + assignedVar.toString(), statement);
}
}
}

View File

@ -26,29 +26,31 @@ public class Pass1CallVoidReturns extends Pass2SsaOptimization {
getProgram().clearControlFlowBlockSuccessorClosure();
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCall) {
final ProcedureRef procedureRef = ((StatementCall) statement).getProcedure();
final Procedure procedure = getProgramScope().getProcedure(procedureRef);
if(SymbolType.VOID.equals(procedure.getReturnType())) {
// Found a call to a VOID returning procedure
final LValue lValue = ((StatementCall) statement).getlValue();
if(lValue instanceof VariableRef) {
VariableRef tmpVar = (VariableRef) lValue;
final Collection<Integer> usages = referenceInfos.getVarUseStatements(tmpVar);
if(usages.size() > 0) {
final Integer usageIdx = usages.iterator().next();
final Statement usage = getProgram().getStatementInfos().getStatement(usageIdx);
throw new CompileError("Function " + procedure.getLocalName() + " does not return a value! ", usage);
} else {
// Delete the temporary variable
final Variable var = getProgramScope().getVar(tmpVar);
var.getScope().remove(var);
// And remove the lValue
((StatementCall) statement).setlValue(null);
if(getLog().isVerbosePass1CreateSsa())
getLog().append("Removing LValue from call to function returning void");
for(var statement : getGraph().getAllStatements()) {
if (statement instanceof StatementCall) {
final ProcedureRef procedureRef = ((StatementCall) statement).getProcedure();
final Procedure procedure = getProgramScope().getProcedure(procedureRef);
if (SymbolType.VOID.equals(procedure.getReturnType())) {
// Found a call to a VOID returning procedure
final LValue lValue = ((StatementCall) statement).getlValue();
if (lValue instanceof VariableRef) {
VariableRef tmpVar = (VariableRef) lValue;
final Collection<Integer> usages = referenceInfos.getVarUseStatements(tmpVar);
if (usages.size() > 0) {
final Integer usageIdx = usages.iterator().next();
final Statement usage = getProgram().getStatementInfos()
.getStatement(usageIdx);
throw new CompileError(
"Function " + procedure.getLocalName() + " does not return a value! ",
usage);
} else {
// Delete the temporary variable
final Variable var = getProgramScope().getVar(tmpVar);
var.getScope().remove(var);
// And remove the lValue
((StatementCall) statement).setlValue(null);
if (getLog().isVerbosePass1CreateSsa()) {
getLog().append("Removing LValue from call to function returning void");
}
}
}

View File

@ -75,8 +75,8 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
}
}
// Remove the statements
for(var allBlock : getGraph().getAllBlocks()) {
allBlock.getStatements().removeIf(removeStmt::contains);
for(var block : getGraph().getAllBlocks()) {
block.getStatements().removeIf(removeStmt::contains);
}
// Replace all variable refs with constant refs
ProgramValueIterator.execute(getProgram(), new AliasReplacer(aliases));

View File

@ -46,14 +46,11 @@ public class Pass1EliminateUncalledProcedures extends Pass1Base {
*/
public static Set<ProcedureRef> getAllCalledProcedures(Graph graph) {
Set<ProcedureRef> calledProcedures = new LinkedHashSet<>();
for(Graph.Block block : graph.getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCalling) {
StatementCalling call = (StatementCalling) statement;
for(var statement : graph.getAllStatements()) {
if(statement instanceof StatementCalling call) {
ProcedureRef procedureRef = call.getProcedure();
calledProcedures.add(procedureRef);
}
}
}
return calledProcedures;
}

View File

@ -49,20 +49,21 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
* Version all non-versioned non-intermediary being assigned a value.
*/
private void versionAllAssignments() {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue statementLValue = (StatementLValue) statement;
LValue lValue = statementLValue.getlValue();
if(lValue instanceof VariableRef) {
versionAssignment((VariableRef) lValue, new ProgramValue.ProgramValueLValue(statementLValue), statementLValue.getSource());
} else if(lValue instanceof ValueList) {
List<RValue> lValueList = ((ValueList) lValue).getList();
for(int i = 0; i < lValueList.size(); i++) {
LValue lVal = (LValue) lValueList.get(i);
if(lVal instanceof VariableRef) {
versionAssignment((VariableRef) lVal, new ProgramValue.ProgramValueListElement((ValueList) lValue, i), statementLValue.getSource());
}
for(var statement : getGraph().getAllStatements()) {
if (statement instanceof StatementLValue statementLValue) {
LValue lValue = statementLValue.getlValue();
if (lValue instanceof VariableRef) {
versionAssignment((VariableRef) lValue,
new ProgramValue.ProgramValueLValue(statementLValue),
statementLValue.getSource());
} else if (lValue instanceof ValueList) {
List<RValue> lValueList = ((ValueList) lValue).getList();
for (int i = 0; i < lValueList.size(); i++) {
LValue lVal = (LValue) lValueList.get(i);
if (lVal instanceof VariableRef) {
versionAssignment((VariableRef) lVal,
new ProgramValue.ProgramValueListElement((ValueList) lValue, i),
statementLValue.getSource());
}
}
}
@ -107,8 +108,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
programValue.set(version.getRef());
}
// Update map of versions encountered in the block
if(currentStmt instanceof StatementLValue && programValue instanceof ProgramValue.ProgramValueLValue) {
StatementLValue statementLValue = (StatementLValue) currentStmt;
if(currentStmt instanceof StatementLValue statementLValue && programValue instanceof ProgramValue.ProgramValueLValue) {
LValue lValue = statementLValue.getlValue();
if(lValue instanceof VariableRef) {
updateBlockVersions((VariableRef) lValue, blockVersions);

View File

@ -27,21 +27,20 @@ public class Pass1UnrollConditionVariableSsa extends Pass2SsaOptimization {
@Override
public boolean step() {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
final StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
if(conditionalJump.isDeclaredUnroll()) {
Collection<VariableRef> referencedVars = new LinkedHashSet<>();
findAllReferencedVars(referencedVars, conditionalJump.getrValue1());
findAllReferencedVars(referencedVars, conditionalJump.getrValue2());
for(VariableRef referencedVar : referencedVars) {
final Variable variable = getProgramScope().getVariable(referencedVar);
if(variable.isKindLoadStore()) {
// Convert the variable to versioned if it is load/store
getLog().append("Converting unrolled condition variable to single-static-assignment "+variable);
variable.setKind(Variable.Kind.PHI_MASTER);
}
for(var statement : getGraph().getAllStatements()) {
if (statement instanceof final StatementConditionalJump conditionalJump) {
if (conditionalJump.isDeclaredUnroll()) {
Collection<VariableRef> referencedVars = new LinkedHashSet<>();
findAllReferencedVars(referencedVars, conditionalJump.getrValue1());
findAllReferencedVars(referencedVars, conditionalJump.getrValue2());
for (VariableRef referencedVar : referencedVars) {
final Variable variable = getProgramScope().getVariable(referencedVar);
if (variable.isKindLoadStore()) {
// Convert the variable to versioned if it is load/store
getLog().append(
"Converting unrolled condition variable to single-static-assignment "
+ variable);
variable.setKind(Variable.Kind.PHI_MASTER);
}
}
}

View File

@ -1,10 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Initializers;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.symbols.Procedure;
@ -12,8 +9,10 @@ import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.values.CastValue;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.ValueList;
import java.util.List;
/**
@ -29,38 +28,34 @@ public class Pass1UnwindStructPrepare extends Pass2SsaOptimization {
@Override
public boolean step() {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getOperator()==null) {
SymbolType lValueType = SymbolTypeInference.inferType(getProgram().getScope(), assignment.getlValue());
RValue rValue = assignment.getrValue2();
if(!(rValue instanceof ConstantValue) && lValueType instanceof SymbolTypeStruct) {
// TODO: Constantify all R-Values?
Initializers.ValueTypeSpec lValueTypeSpec = new Initializers.ValueTypeSpec(lValueType);
RValue rValueConstantified = Initializers.constantify(rValue, lValueTypeSpec, getProgram(), assignment.getSource());
if(!rValue.equals(rValueConstantified)) {
assignment.setrValue2(rValueConstantified);
getLog().append("Constantified RValue "+assignment.toString(getProgram(), false));
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment assignment) {
if(assignment.getOperator()==null) {
SymbolType lValueType = SymbolTypeInference.inferType(getProgram().getScope(), assignment.getlValue());
RValue rValue = assignment.getrValue2();
if(!(rValue instanceof ConstantValue) && lValueType instanceof SymbolTypeStruct) {
// TODO: Constantify all R-Values?
Initializers.ValueTypeSpec lValueTypeSpec = new Initializers.ValueTypeSpec(lValueType);
RValue rValueConstantified = Initializers.constantify(rValue, lValueTypeSpec, getProgram(), assignment.getSource());
if(!rValue.equals(rValueConstantified)) {
assignment.setrValue2(rValueConstantified);
getLog().append("Constantified RValue "+assignment.toString(getProgram(), false));
}
}
}
if(statement instanceof StatementCall) {
final StatementCall call = (StatementCall) statement;
final Procedure procedure = getProgramScope().getProcedure(call.getProcedure());
final List<Variable> paramDefs = procedure.getParameters();
final List<RValue> paramVals = call.getParameters();
for(int i=0;i<paramDefs.size();i++) {
final Variable paramDef = paramDefs.get(i);
final RValue paramVal = paramVals.get(i);
if(paramDef.getType() instanceof SymbolTypeStruct && paramVal instanceof ValueList) {
// Add a cast to the parameter value list
paramVals.set(i, new CastValue(paramDef.getType(), paramVal));
getLog().append("Added struct type cast to parameter value list "+call.toString(getProgram(), false));
}
}
if(statement instanceof final StatementCall call) {
final Procedure procedure = getProgramScope().getProcedure(call.getProcedure());
final List<Variable> paramDefs = procedure.getParameters();
final List<RValue> paramVals = call.getParameters();
for(int i=0;i<paramDefs.size();i++) {
final Variable paramDef = paramDefs.get(i);
final RValue paramVal = paramVals.get(i);
if(paramDef.getType() instanceof SymbolTypeStruct && paramVal instanceof ValueList) {
// Add a cast to the parameter value list
paramVals.set(i, new CastValue(paramDef.getType(), paramVal));
getLog().append("Added struct type cast to parameter value list "+call.toString(getProgram(), false));
}
}
}

View File

@ -24,17 +24,15 @@ public class Pass2AssertSingleAssignment extends Pass2SsaAssertion {
Map<VariableRef, Statement> assignments = new LinkedHashMap<>();
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
LValue lValue = ((StatementLValue) statement).getlValue();
if(lValue instanceof VariableRef) {
checkAssignment(assignments, (VariableRef) lValue, statement);
}
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
checkAssignment(assignments, phiVariable.getVariable(), statement);
}
for(var statement : getGraph().getAllStatements()) {
if (statement instanceof StatementLValue) {
LValue lValue = ((StatementLValue) statement).getlValue();
if (lValue instanceof VariableRef) {
checkAssignment(assignments, (VariableRef) lValue, statement);
}
} else if (statement instanceof StatementPhiBlock) {
for (StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
checkAssignment(assignments, phiVariable.getVariable(), statement);
}
}
}

View File

@ -35,39 +35,37 @@ public class Pass2ComparisonOptimization extends Pass2SsaOptimization {
*/
@Override
public boolean step() {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
Operator operator = conditionalJump.getOperator();
if(operator!=null && conditionalJump.getrValue2() instanceof ConstantValue) {
SymbolType valueType = SymbolTypeInference.inferType(getProgramScope(), conditionalJump.getrValue1());
ConstantValue constantValue = (ConstantValue) conditionalJump.getrValue2();
ConstantLiteral constantLiteral = null;
try {
constantLiteral = constantValue.calculateLiteral(getProgramScope());
} catch(ConstantNotLiteral e) {
// Ignore
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementConditionalJump) {
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
Operator operator = conditionalJump.getOperator();
if(operator!=null && conditionalJump.getrValue2() instanceof ConstantValue) {
SymbolType valueType = SymbolTypeInference.inferType(getProgramScope(), conditionalJump.getrValue1());
ConstantValue constantValue = (ConstantValue) conditionalJump.getrValue2();
ConstantLiteral constantLiteral = null;
try {
constantLiteral = constantValue.calculateLiteral(getProgramScope());
} catch(ConstantNotLiteral e) {
// Ignore
}
if(Operators.GT.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
// Found > C - rewrite to >= C+1 if possible
Long longValue = (Long) constantLiteral.getValue();
if(longValue > 0x00L && longValue < 0xffL) {
// Rewrite is possible - do it
getLog().append("Rewriting conditional comparison " + statement.toString(getProgram(), false));
conditionalJump.setOperator(Operators.GE);
conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L)));
}
if(Operators.GT.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
// Found > C - rewrite to >= C+1 if possible
Long longValue = (Long) constantLiteral.getValue();
if(longValue > 0x00L && longValue < 0xffL) {
// Rewrite is possible - do it
getLog().append("Rewriting conditional comparison " + statement.toString(getProgram(), false));
conditionalJump.setOperator(Operators.GE);
conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L)));
}
}
if(Operators.LE.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
// Found <= C - rewrite to < C+1 if possible
Long longValue = (Long) constantLiteral.getValue();
if(longValue > 0x00L && longValue < 0xffL) {
// Rewrite is possible - do it
getLog().append("Rewriting conditional comparison " + statement.toString(getProgram(), false));
conditionalJump.setOperator(Operators.LT);
conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L)));
}
}
if(Operators.LE.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
// Found <= C - rewrite to < C+1 if possible
Long longValue = (Long) constantLiteral.getValue();
if(longValue > 0x00L && longValue < 0xffL) {
// Rewrite is possible - do it
getLog().append("Rewriting conditional comparison " + statement.toString(getProgram(), false));
conditionalJump.setOperator(Operators.LT);
conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L)));
}
}
}

View File

@ -66,33 +66,29 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
private List<SimpleCondition> getSimpleConditionTodos() {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
List<SimpleCondition> todos = new ArrayList<>();
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
if(conditionalJump.getrValue1() == null && conditionalJump.getOperator() == null) {
RValue conditionRValue = conditionalJump.getrValue2();
if(conditionRValue instanceof VariableRef) {
VariableRef conditionVar = (VariableRef) conditionRValue;
final Collection<Integer> conditionRvalueUsages = variableReferenceInfos.getVarUseStatements(conditionVar);
final Integer conditionDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
if(conditionRvalueUsages.size() == 1 && conditionDefineStmtIdx != null) {
final Statement conditionDefineStmt = getGraph().getStatementByIndex(conditionDefineStmtIdx);
if(conditionDefineStmt instanceof StatementAssignment && ((StatementAssignment) conditionDefineStmt).getOperator() != null) {
StatementAssignment conditionAssignment = (StatementAssignment) conditionDefineStmt;
switch(conditionAssignment.getOperator().getOperator()) {
case "==":
case "<>":
case "!=":
case "<":
case ">":
case "<=":
case "=<":
case ">=":
case "=>":
todos.add(new SimpleCondition(conditionalJump, conditionAssignment, conditionVar));
default:
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementConditionalJump conditionalJump) {
if(conditionalJump.getrValue1() == null && conditionalJump.getOperator() == null) {
RValue conditionRValue = conditionalJump.getrValue2();
if(conditionRValue instanceof VariableRef conditionVar) {
final Collection<Integer> conditionRvalueUsages = variableReferenceInfos.getVarUseStatements(conditionVar);
final Integer conditionDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
if(conditionRvalueUsages.size() == 1 && conditionDefineStmtIdx != null) {
final Statement conditionDefineStmt = getGraph().getStatementByIndex(conditionDefineStmtIdx);
if(conditionDefineStmt instanceof StatementAssignment conditionAssignment
&& ((StatementAssignment) conditionDefineStmt).getOperator() != null) {
switch(conditionAssignment.getOperator().getOperator()) {
case "==":
case "<>":
case "!=":
case "<":
case ">":
case "<=":
case "=<":
case ">=":
case "=>":
todos.add(new SimpleCondition(conditionalJump, conditionAssignment, conditionVar));
default:
}
}
}

View File

@ -55,20 +55,18 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
});
// Examine all assignments - performing constant consolidation for +/-
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
Operator operator = assignment.getOperator();
if(operator != null) {
switch(operator.getOperator()) {
case "+":
optimized[0] |= optimizePlus(assignment);
break;
case "*idx":
optimized[0] |= optimizeArrayDeref(assignment);
break;
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
Operator operator = assignment.getOperator();
if(operator != null) {
switch(operator.getOperator()) {
case "+":
optimized[0] |= optimizePlus(assignment);
break;
case "*idx":
optimized[0] |= optimizeArrayDeref(assignment);
break;
}
}
}

View File

@ -59,7 +59,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
// NULL pointer assigment is OK
;
else if(!SymbolTypeConversion.assignmentTypeMatch(variableType, valueType)) {
ConstantLiteral constantLiteral = null;
ConstantLiteral<?> constantLiteral = null;
try {
constantLiteral = constVal.calculateLiteral(getProgramScope());
} catch(ConstantNotLiteral e) {
@ -92,16 +92,16 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
private static class ConstantVariableValue {
/** The variable that has been determined to be constant. */
private VariableRef variableRef;
private final VariableRef variableRef;
/** The constant value of the variable. */
private ConstantValue constantValue;
private final ConstantValue constantValue;
/**
* The statement that assigns the variable its value (the assignment will be removed at the end).
* Either a {@link StatementAssignment} or a {@link StatementPhiBlock}.
*/
private Statement assignment;
private final Statement assignment;
public ConstantVariableValue(VariableRef variableRef, ConstantValue constantValue, Statement assignment) {
this.variableRef = variableRef;
@ -131,39 +131,34 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
final Map<VariableRef, ConstantVariableValue> constants = new LinkedHashMap<>();
// Look for constants among versions, intermediates & declared constants
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
LValue lValue = assignment.getlValue();
if(lValue instanceof VariableRef) {
VariableRef varRef = (VariableRef) lValue;
Variable var = getProgramScope().getVariable(varRef);
if(var.isVolatile() || var.isKindLoadStore())
// Do not examine volatiles and non-versioned variables
continue;
if(var.getRegister() != null && var.getRegister().isMem())
// Skip variables allocated into memory
continue;
ConstantValue constant = getConstant(assignment.getrValue2());
if(assignment.getrValue1() == null && assignment.getOperator() == null && constant != null) {
constants.put(varRef, new ConstantVariableValue(varRef, constant, assignment));
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment assignment) {
LValue lValue = assignment.getlValue();
if(lValue instanceof VariableRef varRef) {
Variable var = getProgramScope().getVariable(varRef);
if(var.isVolatile() || var.isKindLoadStore())
// Do not examine volatiles and non-versioned variables
continue;
if(var.getRegister() != null && var.getRegister().isMem())
// Skip variables allocated into memory
continue;
ConstantValue constant = getConstant(assignment.getrValue2());
if(assignment.getrValue1() == null && assignment.getOperator() == null && constant != null) {
constants.put(varRef, new ConstantVariableValue(varRef, constant, assignment));
}
} else if(statement instanceof StatementPhiBlock) {
StatementPhiBlock phi = (StatementPhiBlock) statement;
for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
if(phiVariable.getValues().size() == 1) {
StatementPhiBlock.PhiRValue phiRValue = phiVariable.getValues().get(0);
if(getConstant(phiRValue.getrValue()) != null) {
VariableRef varRef = phiVariable.getVariable();
Variable var = getProgramScope().getVariable(varRef);
if(var.isVolatile() || var.isKindLoadStore())
// Do not examine volatiles and non-versioned variables
continue;
ConstantValue constant = getConstant(phiRValue.getrValue());
constants.put(varRef, new ConstantVariableValue(varRef, constant, phi));
}
}
} else if(statement instanceof StatementPhiBlock phi) {
for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
if(phiVariable.getValues().size() == 1) {
StatementPhiBlock.PhiRValue phiRValue = phiVariable.getValues().get(0);
if(getConstant(phiRValue.getrValue()) != null) {
VariableRef varRef = phiVariable.getVariable();
Variable var = getProgramScope().getVariable(varRef);
if(var.isVolatile() || var.isKindLoadStore())
// Do not examine volatiles and non-versioned variables
continue;
ConstantValue constant = getConstant(phiRValue.getrValue());
constants.put(varRef, new ConstantVariableValue(varRef, constant, phi));
}
}
}
@ -186,8 +181,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
continue;
StatementAssignment assignment = (StatementAssignment) varAssignment.statementLValue;
LValue lValue = assignment.getlValue();
if(lValue instanceof VariableRef) {
VariableRef varRef = (VariableRef) lValue;
if(lValue instanceof VariableRef varRef) {
ConstantValue constant = getConstant(assignment.getrValue2());
if(assignment.getrValue1() == null && assignment.getOperator() == null && constant != null) {
constants.put(varRef, new ConstantVariableValue(varRef, constant, assignment));
@ -209,11 +203,9 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
public static ConstantValue getConstant(RValue rValue) {
if(rValue instanceof ConstantValue) {
return (ConstantValue) rValue;
} else if(rValue instanceof Variable && ((Variable) rValue).isKindConstant()) {
Variable constantVar = (Variable) rValue;
} else if(rValue instanceof Variable constantVar && ((Variable) rValue).isKindConstant()) {
return constantVar.getConstantRef();
} else if(rValue instanceof CastValue) {
CastValue castValue = (CastValue) rValue;
} else if(rValue instanceof CastValue castValue) {
ConstantValue castConstant = getConstant(castValue.getValue());
if(castConstant != null) {
return new ConstantCastValue(castValue.getToType(), castConstant);
@ -236,47 +228,43 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
return new ConstantBinary(c1, operator, c2);
}
switch(operator.getOperator()) {
case "-":
case "*":
case "/":
case "%":
case "&":
case "|":
case "&&":
case "||":
case "^":
case "<<":
case ">>":
case "==":
case "!=":
case ">":
case "<":
case ">=":
case "<=":
return new ConstantBinary(c1, operator, c2);
case "w=":
return new ConstantBinary(new ConstantBinary(c1, Operators.MULTIPLY, new ConstantInteger(256L)), Operators.PLUS, c2);
case "dw=":
return new ConstantBinary(new ConstantBinary(c1, Operators.MULTIPLY, new ConstantInteger(65536L)), Operators.PLUS, c2);
case "byte0=":
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffffff00L)), Operators.BOOL_OR, c2);
case "byte1=":
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffff00ffL)), Operators.BOOL_OR, new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x100L)));
case "byte2=":
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xff00ffffL)), Operators.BOOL_OR, new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x10000L)));
case "byte3=":
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0x00ffffffL)), Operators.BOOL_OR, new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x1000000L)));
case "word0=":
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffff0000L)), Operators.BOOL_OR, c2);
case "word1=":
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0x0000ffffL)), Operators.BOOL_OR, new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x10000L)));
case "*idx":
return switch (operator.getOperator()) {
case "-", "*", "/", "%", "&", "|", "&&", "||", "^", "<<", ">>", "==", "!=", ">", "<", ">=", "<=" ->
new ConstantBinary(c1, operator, c2);
case "w=" -> new ConstantBinary(
new ConstantBinary(c1, Operators.MULTIPLY, new ConstantInteger(256L)), Operators.PLUS,
c2);
case "dw=" -> new ConstantBinary(
new ConstantBinary(c1, Operators.MULTIPLY, new ConstantInteger(65536L)),
Operators.PLUS, c2);
case "byte0=" -> new ConstantBinary(
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffffff00L)),
Operators.BOOL_OR, c2);
case "byte1=" -> new ConstantBinary(
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffff00ffL)),
Operators.BOOL_OR,
new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x100L)));
case "byte2=" -> new ConstantBinary(
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xff00ffffL)),
Operators.BOOL_OR,
new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x10000L)));
case "byte3=" -> new ConstantBinary(
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0x00ffffffL)),
Operators.BOOL_OR,
new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x1000000L)));
case "word0=" -> new ConstantBinary(
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffff0000L)),
Operators.BOOL_OR, c2);
case "word1=" -> new ConstantBinary(
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0x0000ffffL)),
Operators.BOOL_OR,
new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x10000L)));
case "*idx" ->
// Pointer dereference - not constant
return null;
default:
throw new RuntimeException("Unhandled Binary Operator " + operator.getOperator());
}
null;
default ->
throw new RuntimeException("Unhandled Binary Operator " + operator.getOperator());
};
}
@ -301,13 +289,10 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
}
// Examine all statements
for(var block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && procedureRef.equals(assignment.getrValue2())) {
return true;
}
for(var statement : program.getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment assignment) {
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && procedureRef.equals(assignment.getrValue2())) {
return true;
}
}
}

View File

@ -1,12 +1,9 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
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.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
@ -33,20 +30,17 @@ public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
@Override
public boolean step() {
boolean modified = false;
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getrValue1() != null || assignment.getOperator() != null || !(assignment.getrValue2() instanceof ConstantValue)) {
SymbolType lValueType = SymbolTypeInference.inferType(getProgramScope(), assignment.getlValue());
ConstantValue constant = getConstantAssignmentValue(assignment, lValueType);
if(constant != null) {
getLog().append("Constant right-side identified " + assignment.toString(getProgram(), false));
assignment.setrValue2(constant);
assignment.setOperator(null);
assignment.setrValue1(null);
modified = true;
}
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;
}
}
}
@ -58,10 +52,9 @@ public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
* Examine the right side of an assignment and if it is constant then return the constant value.
*
* @param assignment The assignment to examine
* @param lValueType The type of the lvalue
* @return The constant value if the right side is constant
*/
private ConstantValue getConstantAssignmentValue(StatementAssignment assignment, SymbolType lValueType) {
private ConstantValue getConstantAssignmentValue(StatementAssignment assignment) {
if(assignment.getrValue1() == null && Pass2ConstantIdentification.getConstant(assignment.getrValue2()) != null) {
if(assignment.getOperator() == null) {

View File

@ -1,15 +1,11 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.SymbolVariableRef;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.LinkedHashMap;
import java.util.ListIterator;
import java.util.Map;
@ -27,42 +23,39 @@ public class Pass2IdenticalPhiElimination extends Pass2SsaOptimization {
@Override
public boolean step() {
Map<VariableRef, RValue> phiIdentical = new LinkedHashMap<>();
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementPhiBlock) {
StatementPhiBlock statementPhi = (StatementPhiBlock) statement;
ListIterator<StatementPhiBlock.PhiVariable> phiVariableIt = statementPhi.getPhiVariables().listIterator();
while(phiVariableIt.hasNext()) {
StatementPhiBlock.PhiVariable phiVariable = phiVariableIt.next();
RValue rValue = null;
boolean identical = true;
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if(phiRValue.getrValue() instanceof SymbolVariableRef) {
Variable symbolVar = (Variable) getProgramScope().getSymbol((SymbolVariableRef) phiRValue.getrValue());
if(symbolVar.getRegister() != null) { //TODO: Handle register/memory/storage strategy differently!
// Do not collapse PHI's for variables with declared registers (this prevents procedure parameters from being turned into constants)
identical = false;
break;
}
}
if(phiRValue.getrValue().equals(phiVariable.getVariable())) {
// Self PHI - skip that
continue;
}
if(rValue == null) {
rValue = phiRValue.getrValue();
} else {
if(!rValue.equals(phiRValue.getrValue())) {
identical = false;
break;
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementPhiBlock statementPhi) {
ListIterator<StatementPhiBlock.PhiVariable> phiVariableIt = statementPhi.getPhiVariables().listIterator();
while(phiVariableIt.hasNext()) {
StatementPhiBlock.PhiVariable phiVariable = phiVariableIt.next();
RValue rValue = null;
boolean identical = true;
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if(phiRValue.getrValue() instanceof SymbolVariableRef) {
Variable symbolVar = (Variable) getProgramScope().getSymbol((SymbolVariableRef) phiRValue.getrValue());
if(symbolVar.getRegister() != null) { //TODO: Handle register/memory/storage strategy differently!
// Do not collapse PHI's for variables with declared registers (this prevents procedure parameters from being turned into constants)
identical = false;
break;
}
}
if(identical && rValue!=null) {
// Found a phi-value with all rValues being identical
phiIdentical.put(phiVariable.getVariable(), rValue);
phiVariableIt.remove();
if(phiRValue.getrValue().equals(phiVariable.getVariable())) {
// Self PHI - skip that
continue;
}
if(rValue == null) {
rValue = phiRValue.getrValue();
} else {
if(!rValue.equals(phiRValue.getrValue())) {
identical = false;
break;
}
}
}
if(identical && rValue!=null) {
// Found a phi-value with all rValues being identical
phiIdentical.put(phiVariable.getVariable(), rValue);
phiVariableIt.remove();
}
}
}

View File

@ -1,10 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.OperatorCast;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.CastValue;
@ -19,17 +16,14 @@ public class Pass2InlineCast extends Pass2SsaOptimization {
@Override
public boolean step() {
boolean optimized = false;
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getrValue1()==null && assignment.getOperator() instanceof OperatorCast) {
SymbolType toType = ((OperatorCast) assignment.getOperator()).getToType();
assignment.setrValue2(new CastValue(toType, assignment.getrValue2()));
assignment.setOperator(null);
getLog().append("Inlining cast "+assignment.toString(getProgram(), false));
optimized = true;
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment assignment) {
if(assignment.getrValue1()==null && assignment.getOperator() instanceof OperatorCast) {
SymbolType toType = ((OperatorCast) assignment.getOperator()).getToType();
assignment.setrValue2(new CastValue(toType, assignment.getrValue2()));
assignment.setOperator(null);
getLog().append("Inlining cast "+assignment.toString(getProgram(), false));
optimized = true;
}
}
}

View File

@ -1,14 +1,11 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
/**
* Check that the unrolling of a loop was sucessfully completed.
* Check that the unrolling of a loop was successfully completed.
* This is done by checking that no conditional jumps exist marked as wasUnrolled.
* Since unrolling requires the loop iteration count to be constant the conditionals must always be resolved to true or false and thus deleted or changed to jumps.
*/
@ -20,12 +17,10 @@ public class Pass2LoopUnrollAssertComplete extends Pass2SsaOptimization {
@Override
public boolean step() {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
if(((StatementConditionalJump) statement).isWasUnrolled()) {
throw new CompileError("Loop cannot be unrolled. Condition not resolvable to a constant true/false. ", statement);
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementConditionalJump) {
if(((StatementConditionalJump) statement).isWasUnrolled()) {
throw new CompileError("Loop cannot be unrolled. Condition not resolvable to a constant true/false. ", statement);
}
}
}

View File

@ -1,14 +1,11 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.ArrayList;
import java.util.List;
@ -35,63 +32,53 @@ public class Pass2UnaryNotSimplification extends Pass2SsaOptimization {
/**
* Examine all unary nots. If they are the only usage of a reversible unary not replace the unary not with the reversed comparison - and eliminate the original variable.
*
* @param assignments Assignments to examine
* @param usages All variable usages
* @return Unused comparisons (because they have been replaced with reversed comparisons)
*/
private List<VariableRef> optimizeUnaryNots() {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
final List<VariableRef> unused = new ArrayList<>();
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getrValue1() == null
&& assignment.getOperator() != null
&& ("!".equals(assignment.getOperator().getOperator()) || "not".equals(assignment.getOperator().getOperator()))
&& assignment.getrValue2() instanceof VariableRef
) {
VariableRef tempVar = (VariableRef) assignment.getrValue2();
final Integer tempVarDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(tempVar);
if(tempVarDefineStmtIdx != null) {
final Statement tempVarDefineStmt = getGraph().getStatementByIndex(tempVarDefineStmtIdx);
if(tempVarDefineStmt instanceof StatementAssignment) {
StatementAssignment tempAssignment = (StatementAssignment) tempVarDefineStmt;
int tempVarUsages = variableReferenceInfos.getVarUseStatements(tempVar).size();
if(tempVarUsages == 1 && tempAssignment.getOperator() != null) {
switch(tempAssignment.getOperator().getOperator()) {
case "<":
createInverse(">=", assignment, tempAssignment);
unused.add(tempVar);
break;
case ">":
createInverse("<=", assignment, tempAssignment);
unused.add(tempVar);
break;
case "<=":
case "=<":
createInverse(">", assignment, tempAssignment);
unused.add(tempVar);
break;
case ">=":
case "=>":
createInverse("<", assignment, tempAssignment);
unused.add(tempVar);
break;
case "==":
createInverse("!=", assignment, tempAssignment);
unused.add(tempVar);
break;
case "!=":
case "<>":
createInverse("==", assignment, tempAssignment);
unused.add(tempVar);
break;
case "!":
case "not":
createInverse(null, assignment, tempAssignment);
unused.add(tempVar);
break;
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment assignment) {
if(assignment.getrValue1() == null
&& assignment.getOperator() != null
&& ("!".equals(assignment.getOperator().getOperator()) || "not".equals(assignment.getOperator().getOperator()))
&& assignment.getrValue2() instanceof VariableRef
) {
VariableRef tempVar = (VariableRef) assignment.getrValue2();
final Integer tempVarDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(tempVar);
if(tempVarDefineStmtIdx != null) {
final Statement tempVarDefineStmt = getGraph().getStatementByIndex(tempVarDefineStmtIdx);
if(tempVarDefineStmt instanceof StatementAssignment tempAssignment) {
int tempVarUsages = variableReferenceInfos.getVarUseStatements(tempVar).size();
if(tempVarUsages == 1 && tempAssignment.getOperator() != null) {
switch (tempAssignment.getOperator().getOperator()) {
case "<" -> {
createInverse(">=", assignment, tempAssignment);
unused.add(tempVar);
}
case ">" -> {
createInverse("<=", assignment, tempAssignment);
unused.add(tempVar);
}
case "<=", "=<" -> {
createInverse(">", assignment, tempAssignment);
unused.add(tempVar);
}
case ">=", "=>" -> {
createInverse("<", assignment, tempAssignment);
unused.add(tempVar);
}
case "==" -> {
createInverse("!=", assignment, tempAssignment);
unused.add(tempVar);
}
case "!=", "<>" -> {
createInverse("==", assignment, tempAssignment);
unused.add(tempVar);
}
case "!", "not" -> {
createInverse(null, assignment, tempAssignment);
unused.add(tempVar);
}
}
}

View File

@ -1,10 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAsm;
import dk.camelot64.kickc.model.statements.StatementKickAsm;
import dk.camelot64.kickc.model.symbols.Procedure;
@ -14,7 +11,6 @@ import dk.camelot64.kickc.model.values.ConstantRef;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.SymbolRef;
import java.util.List;
import java.util.Map;
@ -34,44 +30,39 @@ public class Pass3AssertConstants extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementKickAsm) {
RValue bytes = ((StatementKickAsm) statement).getBytes();
if(bytes != null && !(bytes instanceof ConstantValue)) {
throw new CompileError("KickAssembler bytes is not constant " + bytes.toString(), statement);
}
RValue cycles = ((StatementKickAsm) statement).getCycles();
if(cycles != null && !(cycles instanceof ConstantValue)) {
throw new CompileError("KickAssembler cycles is not constant " + cycles.toString(), statement);
}
} else if(statement instanceof StatementAsm) {
StatementAsm statementAsm = (StatementAsm) statement;
Map<String, SymbolRef> referenced = statementAsm.getReferenced();
for(String label : referenced.keySet()) {
SymbolRef symbolRef = referenced.get(label);
Symbol symbol = getScope().getSymbol(symbolRef);
if(symbol instanceof Procedure)
// Referencing procedures are fine!
continue;
else if(symbol instanceof Variable && ((Variable) symbol).isKindConstant())
// Referencing constants are fine!
continue;
else if(symbol instanceof Variable && ((Variable) symbol).isKindLoadStore())
// Referencing load/store is fine!
continue;
else
throw new CompileError("Inline ASM reference is not constant " + label, statement);
}
} else if(statement instanceof StatementKickAsm) {
StatementKickAsm statementAsm = (StatementKickAsm) statement;
List<SymbolRef> uses = statementAsm.getUses();
for(SymbolRef use : uses) {
if(!(use instanceof ConstantRef)) {
throw new CompileError("Inline KickAsm reference is not constant " + use, statement);
}
for(var statement : getProgram().getGraph().getAllStatements()) {
if(statement instanceof StatementKickAsm statementKickAsm) {
RValue bytes = statementKickAsm.getBytes();
if(bytes != null && !(bytes instanceof ConstantValue)) {
throw new CompileError("KickAssembler bytes is not constant " + bytes.toString(), statement);
}
RValue cycles = statementKickAsm.getCycles();
if(cycles != null && !(cycles instanceof ConstantValue)) {
throw new CompileError("KickAssembler cycles is not constant " + cycles.toString(), statement);
}
List<SymbolRef> uses = statementKickAsm.getUses();
for(SymbolRef use : uses) {
if(!(use instanceof ConstantRef)) {
throw new CompileError("Inline KickAsm reference is not constant " + use, statement);
}
}
} else if(statement instanceof StatementAsm statementAsm) {
Map<String, SymbolRef> referenced = statementAsm.getReferenced();
for(String label : referenced.keySet()) {
SymbolRef symbolRef = referenced.get(label);
Symbol symbol = getScope().getSymbol(symbolRef);
if(symbol instanceof Procedure)
// Referencing procedures are fine!
continue;
else if(symbol instanceof Variable && ((Variable) symbol).isKindConstant())
// Referencing constants are fine!
continue;
else if(symbol instanceof Variable && ((Variable) symbol).isKindLoadStore())
// Referencing load/store is fine!
continue;
else
throw new CompileError("Inline ASM reference is not constant " + label, statement);
}
}
}
}

View File

@ -1,11 +1,8 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
/**
@ -19,21 +16,17 @@ public class Pass3AssertNoMulDivMod extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(Graph.Block block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(Operators.MULTIPLY.equals(assignment.getOperator())) {
throw new CompileError("Runtime multiplication not supported. "+statement.toString(getProgram(), false), statement.getSource());
}
if(Operators.DIVIDE.equals(assignment.getOperator())) {
throw new CompileError("Runtime division not supported. "+statement.toString(getProgram(), false), statement.getSource());
}
if(Operators.MODULO.equals(assignment.getOperator())) {
throw new CompileError("Runtime modulo not supported. "+statement.toString(getProgram(), false), statement.getSource());
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment assignment) {
if(Operators.MULTIPLY.equals(assignment.getOperator())) {
throw new CompileError("Runtime multiplication not supported. "+statement.toString(getProgram(), false), statement.getSource());
}
if(Operators.DIVIDE.equals(assignment.getOperator())) {
throw new CompileError("Runtime division not supported. "+statement.toString(getProgram(), false), statement.getSource());
}
if(Operators.MODULO.equals(assignment.getOperator())) {
throw new CompileError("Runtime modulo not supported. "+statement.toString(getProgram(), false), statement.getSource());
}
}
}

View File

@ -1,7 +1,5 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
@ -23,22 +21,20 @@ public class Pass3AssertNoNumbers extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
checkValue(((StatementAssignment) statement).getlValue(), statement);
checkValue(((StatementAssignment) statement).getrValue1(), statement);
checkValue(((StatementAssignment) statement).getrValue2(), statement);
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
for(StatementPhiBlock.PhiRValue value : phiVariable.getValues()) {
checkValue(value.getrValue(), statement);
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof final StatementAssignment assignment) {
checkValue(assignment.getlValue(), statement);
checkValue(assignment.getrValue1(), statement);
checkValue(assignment.getrValue2(), statement);
} else if(statement instanceof final StatementPhiBlock phiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
for(StatementPhiBlock.PhiRValue value : phiVariable.getValues()) {
checkValue(value.getrValue(), statement);
}
} else if(statement instanceof StatementConditionalJump) {
checkValue(((StatementConditionalJump) statement).getrValue1(), statement);
checkValue(((StatementConditionalJump) statement).getrValue2(), statement);
}
} else if(statement instanceof final StatementConditionalJump conditionalJump) {
checkValue(conditionalJump.getrValue1(), statement);
checkValue(conditionalJump.getrValue2(), statement);
}
}
}

View File

@ -55,15 +55,13 @@ public class Pass4MemoryCoalesceAssignment extends Pass2Base {
public CoalesceVarScores(Program program) {
this.scores = new LinkedHashMap<>();
VariableReferenceInfos variableReferenceInfos = program.getVariableReferenceInfos();
for(var block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
Collection<VariableRef> definedVars = variableReferenceInfos.getDefinedVars(statement);
Collection<VariableRef> usedVars = variableReferenceInfos.getUsedVars(statement);
if(definedVars != null && definedVars.size() > 0) {
for(VariableRef definedVar : definedVars) {
for(VariableRef usedVar : usedVars) {
incScore(definedVar, usedVar);
}
for(var statement : program.getGraph().getAllStatements()) {
Collection<VariableRef> definedVars = variableReferenceInfos.getDefinedVars(statement);
Collection<VariableRef> usedVars = variableReferenceInfos.getUsedVars(statement);
if (definedVars != null && definedVars.size() > 0) {
for (VariableRef definedVar : definedVars) {
for (VariableRef usedVar : usedVars) {
incScore(definedVar, usedVar);
}
}
}

View File

@ -170,11 +170,9 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
* @return true if the register allocation contains an overlapping allocation. false otherwise.
*/
public static boolean isAllocationOverlapping(Program program) {
for(var block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(isStatementAllocationOverlapping(program, statement)) {
return true;
}
for(var statement : program.getGraph().getAllStatements()) {
if(isStatementAllocationOverlapping(program, statement)) {
return true;
}
}
return false;

View File

@ -1,20 +1,20 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCallPointer;
import dk.camelot64.kickc.model.types.*;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeConversion;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeProcedure;
import dk.camelot64.kickc.model.values.ConstantSymbolPointer;
import dk.camelot64.kickc.model.values.PointerDereferenceSimple;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.SymbolRef;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@ -22,7 +22,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
private boolean pass1;
private final boolean pass1;
public PassNAddTypeConversionAssignment(Program program, boolean pass1) {
super(program);
@ -33,8 +33,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
public boolean step() {
AtomicBoolean modified = new AtomicBoolean(false);
ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
if(programExpression instanceof ProgramExpressionBinary) {
ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression;
if(programExpression instanceof ProgramExpressionBinary binary) {
RValue left = binary.getLeft();
RValue right = binary.getRight();
SymbolType leftType;
@ -71,22 +70,20 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
});
// Add dereference to call to pointer to function
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCallPointer) {
RValue procedure = ((StatementCallPointer) statement).getProcedure();
SymbolType procType = SymbolTypeInference.inferType(getProgramScope(), procedure);
if(procType instanceof SymbolTypePointer && ((SymbolTypePointer) procType).getElementType() instanceof SymbolTypeProcedure) {
// Allow calling pointer to procedure directly
// Add an automatic dereference to a pointer to procedure
if(!pass1 || getLog().isVerbosePass1CreateSsa())
getLog().append("Adding dereference to call function pointer " + procedure.toString() + " in " + statement.toString(getProgram(), false));
((StatementCallPointer) statement).setProcedure(new PointerDereferenceSimple(procedure));
}
for(var statement : getProgram().getGraph().getAllStatements()) {
if(statement instanceof StatementCallPointer) {
final StatementCallPointer callPointer = (StatementCallPointer) statement;
RValue procedure = callPointer.getProcedure();
SymbolType procType = SymbolTypeInference.inferType(getProgramScope(), procedure);
if(procType instanceof SymbolTypePointer && ((SymbolTypePointer) procType).getElementType() instanceof SymbolTypeProcedure) {
// Allow calling pointer to procedure directly
// Add an automatic dereference to a pointer to procedure
if(!pass1 || getLog().isVerbosePass1CreateSsa())
getLog().append("Adding dereference to call function pointer " + procedure.toString() + " in " + statement.toString(getProgram(), false));
callPointer.setProcedure(new PointerDereferenceSimple(procedure));
}
}
}
return modified.get();
}

View File

@ -1,14 +1,10 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.values.PointerDereferenceIndexed;
import dk.camelot64.kickc.model.values.RValue;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@ -24,20 +20,16 @@ public class PassNArrayElementAddressOfRewriting extends Pass2SsaOptimization {
public boolean step() {
AtomicBoolean modified = new AtomicBoolean(false);
// Examine all statements
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) ) {
RValue rValue = assignment.getrValue2();
if(rValue instanceof PointerDereferenceIndexed) {
PointerDereferenceIndexed dereferenceIndexed = (PointerDereferenceIndexed) rValue;
assignment.setrValue1(dereferenceIndexed.getPointer());
assignment.setOperator(Operators.PLUS);
assignment.setrValue2(dereferenceIndexed.getIndex());
getLog().append("Rewriting array member address-of to pointer addition "+assignment.toString(getProgram(), false));
modified.set(true);
}
for(var statement : getProgram().getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment assignment) {
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) ) {
RValue rValue = assignment.getrValue2();
if(rValue instanceof PointerDereferenceIndexed dereferenceIndexed) {
assignment.setrValue1(dereferenceIndexed.getPointer());
assignment.setOperator(Operators.PLUS);
assignment.setrValue2(dereferenceIndexed.getIndex());
getLog().append("Rewriting array member address-of to pointer addition "+assignment.toString(getProgram(), false));
modified.set(true);
}
}
}

View File

@ -1,15 +1,11 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementLValue;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.HashSet;
import java.util.Set;
@ -25,19 +21,16 @@ public class PassNAssertConstantModification extends Pass2SsaOptimization {
@Override
public boolean step() {
Set<VariableRef> assigned = new HashSet<>();
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
LValue lValue = ((StatementLValue) statement).getlValue();
if(lValue instanceof VariableRef) {
VariableRef variableRef = (VariableRef) lValue;
Variable variable = getProgramScope().getVariable(variableRef);
if(variable.isKindConstant() || variable.isNoModify()) {
if(assigned.contains(variableRef)) {
throw new CompileError("const variable may not be modified "+variable.toString(getProgram()), statement.getSource());
} else {
assigned.add(variableRef);
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof final StatementLValue statementLValue) {
LValue lValue = statementLValue.getlValue();
if(lValue instanceof VariableRef variableRef) {
Variable variable = getProgramScope().getVariable(variableRef);
if(variable.isKindConstant() || variable.isNoModify()) {
if(assigned.contains(variableRef)) {
throw new CompileError("const variable may not be modified "+variable.toString(getProgram()), statement.getSource());
} else {
assigned.add(variableRef);
}
}
}

View File

@ -24,13 +24,11 @@ public class PassNAssertTypeMatch extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
checkAssignment((StatementAssignment) statement);
}
// TODO: Implement checking for calls / ...
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof final StatementAssignment assignment) {
checkAssignment(assignment);
}
// TODO: Implement checking for calls / ...
}
for(Variable var : getScope().getAllVars(true)) {
if(var.getInitValue()!=null) {

View File

@ -1,17 +1,25 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ConstantNotLiteral;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.values.ConstantArrayList;
import dk.camelot64.kickc.model.values.ConstantBinary;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantLiteral;
import dk.camelot64.kickc.model.values.ConstantRef;
import dk.camelot64.kickc.model.values.ConstantString;
import dk.camelot64.kickc.model.values.ConstantUnary;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.SymbolVariableRef;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@ -27,22 +35,18 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
public boolean step() {
AtomicBoolean modified = new AtomicBoolean(false);
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(Operators.SIZEOF.equals(assignment.getOperator())) {
if(assignment.getrValue2() instanceof SymbolVariableRef) {
SymbolVariableRef symbolRef = (SymbolVariableRef) assignment.getrValue2();
Variable symbolVar = (Variable) getProgramScope().getSymbol(symbolRef);
SymbolType symbolType = symbolVar.getType();
if(!(symbolVar.isArray())) {
getLog().append("Resolving sizeof() " + assignment.toString(getProgram(), false));
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), symbolType);
assignment.setrValue2(sizeOfConstantVar);
assignment.setOperator(null);
modified.set(true);
}
for(var statement : getGraph().getAllStatements()) {
if(statement instanceof StatementAssignment assignment) {
if(Operators.SIZEOF.equals(assignment.getOperator())) {
if(assignment.getrValue2() instanceof SymbolVariableRef symbolRef) {
Variable symbolVar = (Variable) getProgramScope().getSymbol(symbolRef);
SymbolType symbolType = symbolVar.getType();
if(!(symbolVar.isArray())) {
getLog().append("Resolving sizeof() " + assignment.toString(getProgram(), false));
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), symbolType);
assignment.setrValue2(sizeOfConstantVar);
assignment.setOperator(null);
modified.set(true);
}
}
}
@ -50,8 +54,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
}
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
if(programValue.get() instanceof ConstantUnary) {
ConstantUnary unary = (ConstantUnary) programValue.get();
if(programValue.get() instanceof ConstantUnary unary) {
if(unary.getOperator().equals(Operators.SIZEOF)) {
ConstantValue operand = unary.getOperand();
resolveConstantSizeOf(modified, programValue, unary, operand);
@ -67,8 +70,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
if(operand instanceof ConstantRef) {
Variable constant = getProgramScope().getConstant((ConstantRef) operand);
SymbolType symbolType = constant.getType();
if(constant.isArray() && symbolType instanceof SymbolTypePointer) {
SymbolTypePointer arrayType = (SymbolTypePointer) symbolType;
if(constant.isArray() && symbolType instanceof SymbolTypePointer arrayType) {
ConstantValue arraySize = constant.getArraySize();
if(arraySize!=null) {
getLog().append("Resolving array sizeof() " + unary.toString(getProgram()));
@ -83,14 +85,13 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
modified.set(true);
} else {
// Try to calculate the literal to check if it is a string
ConstantLiteral stringLiteral = null;
ConstantLiteral<?> stringLiteral = null;
try {
stringLiteral = constant.getInitValue().calculateLiteral(getProgram().getScope());
} catch(ConstantNotLiteral e) {
// Ignore
}
if(stringLiteral instanceof ConstantString) {
ConstantString constString = (ConstantString) stringLiteral;
if(stringLiteral instanceof ConstantString constString) {
int length = constString.getStringLength();
getLog().append("Resolving string sizeof() " + unary.toString(getProgram()));
ConstantRef sizeOfChar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), SymbolType.BYTE);
@ -107,7 +108,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
modified.set(true);
} else {
getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
ConstantLiteral literal = operand.calculateLiteral(getProgram().getScope());
ConstantLiteral<?> literal = operand.calculateLiteral(getProgram().getScope());
SymbolType constType = literal.getType(getProgram().getScope());
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), constType);
programValue.set(sizeOfConstantVar);
@ -115,7 +116,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
}
} else {
getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
ConstantLiteral literal = operand.calculateLiteral(getProgram().getScope());
ConstantLiteral<?> literal = operand.calculateLiteral(getProgram().getScope());
SymbolType constType = literal.getType(getProgram().getScope());
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), constType);
programValue.set(sizeOfConstantVar);

View File

@ -22,10 +22,8 @@ public class PassNStatementIndices extends Pass2SsaOptimization {
@Override
public boolean step() {
int currentIdx = 0;
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
statement.setIndex(currentIdx++);
}
for(var statement : getProgram().getGraph().getAllStatements()) {
statement.setIndex(currentIdx++);
}
return false;
}

View File

@ -22,19 +22,17 @@ public class PassNTypeInference extends Pass2SsaOptimization {
@Override
public boolean step() {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
try {
if(statement instanceof StatementLValue) {
updateInferedTypeLValue(getProgram(), (StatementLValue) statement);
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
updateInferedTypePhiVariable(getProgram(), phiVariable);
}
for(var statement : getProgram().getGraph().getAllStatements()) {
try {
if(statement instanceof final StatementLValue statementLValue) {
updateInferedTypeLValue(getProgram(), statementLValue);
} else if(statement instanceof final StatementPhiBlock statementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : statementPhiBlock.getPhiVariables()) {
updateInferedTypePhiVariable(getProgram(), phiVariable);
}
} catch(CompileError e) {
throw new CompileError(e.getMessage(), statement.getSource());
}
} catch(CompileError e) {
throw new CompileError(e.getMessage(), statement.getSource());
}
}
return false;

View File

@ -82,84 +82,96 @@ public class PassNCalcLiveRangeVariables extends PassNCalcBase<LiveRangeVariable
VariableReferenceInfos referenceInfo = getProgram().getVariableReferenceInfos();
boolean modified = false;
LiveRangeVariables.LiveRangeVariablesByStatement liveRangeVariablesByStatement = liveRanges.getLiveRangeVariablesByStatement();
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement nextStmt : block.getStatements()) {
List<VariableRef> aliveNextStmt = liveRangeVariablesByStatement.getAlive(nextStmt.getIndex());
Collection<VariableRef> definedNextStmt = referenceInfo.getDefinedVars(nextStmt);
initLiveRange(liveRanges, definedNextStmt);
Collection<PreviousStatement> previousStmts = getPreviousStatements(nextStmt);
for(PreviousStatement previousStmt : previousStmts) {
if(PreviousStatement.Type.NORMAL.equals(previousStmt.getType())) {
// Add all vars alive in the next statement
for(VariableRef aliveVar : aliveNextStmt) {
if(!definedNextStmt.contains(aliveVar)) {
boolean addAlive = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
modified |= addAlive;
if(addAlive && getLog().isVerboseLiveRanges()) {
getLog().append("Propagated alive var " + aliveVar + " to " + previousStmt.getStatement());
}
for (Statement nextStmt : getProgram().getGraph().getAllStatements()) {
List<VariableRef> aliveNextStmt = liveRangeVariablesByStatement.getAlive(
nextStmt.getIndex());
Collection<VariableRef> definedNextStmt = referenceInfo.getDefinedVars(nextStmt);
initLiveRange(liveRanges, definedNextStmt);
Collection<PreviousStatement> previousStmts = getPreviousStatements(nextStmt);
for (PreviousStatement previousStmt : previousStmts) {
if (PreviousStatement.Type.NORMAL.equals(previousStmt.getType())) {
// Add all vars alive in the next statement
for (VariableRef aliveVar : aliveNextStmt) {
if (!definedNextStmt.contains(aliveVar)) {
boolean addAlive = liveRanges.addAlive(aliveVar,
previousStmt.getStatementIdx());
modified |= addAlive;
if (addAlive && getLog().isVerboseLiveRanges()) {
getLog().append("Propagated alive var " + aliveVar + " to "
+ previousStmt.getStatement());
}
}
// Add all used variables to the previous statement (taking into account phi from blocks)
modified |= initUsedVars(liveRanges, nextStmt, previousStmt);
} else if(PreviousStatement.Type.LAST_IN_METHOD.equals(previousStmt.getType())) {
// Add all vars that are referenced in the method
StatementCalling call = (StatementCalling) nextStmt;
ProcedureRef procedure = call.getProcedure();
Collection<VariableRef> procUsed = procedureReferencedVars.get(procedure);
// The call statement has no used or defined by itself so only work with the alive vars
for(VariableRef aliveVar : aliveNextStmt) {
// Add all variables to previous that are not used inside the method
if(procUsed.contains(aliveVar)) {
boolean added = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
modified |= added;
if(added && getLog().isVerboseLiveRanges()) {
getLog().append("Propagated alive var used in method into method " + aliveVar + " to " + previousStmt.getStatement());
}
}
}
} else if(PreviousStatement.Type.SKIP_METHOD.equals(previousStmt.getType())) {
// Add all vars from next statement that the method does not use
StatementCalling call = (StatementCalling) nextStmt;
ProcedureRef procedure = call.getProcedure();
if(procedure!=null) {
Collection<VariableRef> procReferenced = procedureReferencedVars.get(procedure);
// The call statement has no used or defined by itself so only work with the alive vars
for(VariableRef aliveVar : aliveNextStmt) {
// Add all variables to previous that are not used inside the method
if(!procReferenced.contains(aliveVar) && !definedNextStmt.contains(aliveVar)) {
boolean added = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
modified |= added;
if(added && getLog().isVerboseLiveRanges()) {
getLog().append("Propagated alive var unused in method by skipping call " + aliveVar + " to " + previousStmt.getStatement());
}
}
}
}
} else if(PreviousStatement.Type.BEFORE_METHOD.equals(previousStmt.getType())) {
// Add all alive variables to previous that are used inside the method
Graph.Block procBlock = getProgram().getStatementInfos().getBlock(nextStmt);
Procedure procedure = (Procedure) getProgram().getScope().getSymbol(procBlock.getLabel());
Collection<VariableRef> procReferenced = procedureReferencedVars.get(procedure.getRef());
// The call statement has no used or defined by itself so only work with the alive vars
for(VariableRef aliveVar : aliveNextStmt) {
// Add all variables to previous that are used inside the method
if(procReferenced.contains(aliveVar)) {
if(!definedNextStmt.contains(aliveVar)) {
boolean added = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
modified |= added;
if(added && getLog().isVerboseLiveRanges()) {
getLog().append("Propagated alive used in method out of method " + aliveVar + " to " + previousStmt.getStatement());
}
}
} else {
// Do nothing
// getLog().append("Not propagating "+aliveVar.toString(getProgram()) +" in BEFORE_METHOD case from "+nextStmt.toString(getProgram(), false)+ " to "+previousStmt.getStatement().toString(getProgram(), false));
}
}
// Add all used variables to the previous statement (taking into account phi from blocks)
modified |= initUsedVars(liveRanges, nextStmt, previousStmt);
}
// Add all used variables to the previous statement (taking into account phi from blocks)
modified |= initUsedVars(liveRanges, nextStmt, previousStmt);
} else if (PreviousStatement.Type.LAST_IN_METHOD.equals(previousStmt.getType())) {
// Add all vars that are referenced in the method
StatementCalling call = (StatementCalling) nextStmt;
ProcedureRef procedure = call.getProcedure();
Collection<VariableRef> procUsed = procedureReferencedVars.get(procedure);
// The call statement has no used or defined by itself so only work with the alive vars
for (VariableRef aliveVar : aliveNextStmt) {
// Add all variables to previous that are not used inside the method
if (procUsed.contains(aliveVar)) {
boolean added = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
modified |= added;
if (added && getLog().isVerboseLiveRanges()) {
getLog().append(
"Propagated alive var used in method into method " + aliveVar + " to "
+ previousStmt.getStatement());
}
}
}
} else if (PreviousStatement.Type.SKIP_METHOD.equals(previousStmt.getType())) {
// Add all vars from next statement that the method does not use
StatementCalling call = (StatementCalling) nextStmt;
ProcedureRef procedure = call.getProcedure();
if (procedure != null) {
Collection<VariableRef> procReferenced = procedureReferencedVars.get(procedure);
// The call statement has no used or defined by itself so only work with the alive vars
for (VariableRef aliveVar : aliveNextStmt) {
// Add all variables to previous that are not used inside the method
if (!procReferenced.contains(aliveVar) && !definedNextStmt.contains(
aliveVar)) {
boolean added = liveRanges.addAlive(aliveVar,
previousStmt.getStatementIdx());
modified |= added;
if (added && getLog().isVerboseLiveRanges()) {
getLog().append(
"Propagated alive var unused in method by skipping call " + aliveVar
+ " to " + previousStmt.getStatement());
}
}
}
}
} else if (PreviousStatement.Type.BEFORE_METHOD.equals(previousStmt.getType())) {
// Add all alive variables to previous that are used inside the method
Graph.Block procBlock = getProgram().getStatementInfos().getBlock(nextStmt);
Procedure procedure = (Procedure) getProgram().getScope()
.getSymbol(procBlock.getLabel());
Collection<VariableRef> procReferenced = procedureReferencedVars.get(
procedure.getRef());
// The call statement has no used or defined by itself so only work with the alive vars
for (VariableRef aliveVar : aliveNextStmt) {
// Add all variables to previous that are used inside the method
if (procReferenced.contains(aliveVar)) {
if (!definedNextStmt.contains(aliveVar)) {
boolean added = liveRanges.addAlive(aliveVar,
previousStmt.getStatementIdx());
modified |= added;
if (added && getLog().isVerboseLiveRanges()) {
getLog().append(
"Propagated alive used in method out of method " + aliveVar + " to "
+ previousStmt.getStatement());
}
}
} else {
// Do nothing
// getLog().append("Not propagating "+aliveVar.toString(getProgram()) +" in BEFORE_METHOD case from "+nextStmt.toString(getProgram(), false)+ " to "+previousStmt.getStatement().toString(getProgram(), false));
}
}
// Add all used variables to the previous statement (taking into account phi from blocks)
modified |= initUsedVars(liveRanges, nextStmt, previousStmt);
}
}
}