1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-03 07:29:37 +00:00
kickc/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIntrinsics.java

77 lines
3.6 KiB
Java

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.statements.StatementCall;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.ConstantBinary;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.RValue;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/**
* Compiler Pass propagating identifying (intrinsic) calls that return a constant value
*/
public class Pass2ConstantIntrinsics extends Pass2SsaOptimization {
public Pass2ConstantIntrinsics(Program program) {
super(program);
}
@Override
public boolean step() {
for(var block : getGraph().getAllBlocks()) {
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
if(statement instanceof StatementCall) {
final StatementCall call = (StatementCall) statement;
final Procedure procedure = getProgramScope().getProcedure(call.getProcedure());
if(procedure.isDeclaredIntrinsic()) {
if(procedure.getFullName().equals(Pass1ByteXIntrinsicRewrite.INTRINSIC_MAKELONG4)) {
List<ConstantValue> constParams = new ArrayList<>();
for(RValue parameter : call.getParameters()) {
final ConstantValue constParam = Pass2ConstantIdentification.getConstant(parameter);
if(constParam == null) break;
constParams.add(constParam);
}
if(constParams.size() == 4) {
// All parameters are constant - dword is constant
final ConstantBinary constValue = new ConstantBinary(
new ConstantBinary(constParams.get(0), Operators.MULTIPLY, new ConstantInteger(0x1000000l, SymbolType.DWORD)),
Operators.PLUS,
new ConstantBinary(
new ConstantBinary(constParams.get(1), Operators.MULTIPLY, new ConstantInteger(0x10000l, SymbolType.DWORD)),
Operators.PLUS,
new ConstantBinary(
new ConstantBinary(constParams.get(2), Operators.MULTIPLY, new ConstantInteger(0x100l, SymbolType.DWORD)),
Operators.PLUS,
constParams.get(3)
)
)
);
// Remove the intrinsic call
stmtIt.remove();
// Add the constant assignment
stmtIt.add(new StatementAssignment(call.getlValue(), constValue, call.isInitialAssignment(), call.getSource(), call.getComments()));
getLog().append("Identified constant dword "+call.toString(getProgram(), false));
}
}
}
}
}
}
return false;
}
}