mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-27 06:34:19 +00:00
Working on static initialization rewrite _init(). #257
This commit is contained in:
parent
d129efb95f
commit
a989e63f5b
@ -69,7 +69,7 @@ public class VariableReferenceInfos {
|
|||||||
this.referencedSymbol = referencedSymbol;
|
this.referencedSymbol = referencedSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer getStatementIdx() {
|
public Integer getStatementIdx() {
|
||||||
return statementIdx;
|
return statementIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ public class VariableReferenceInfos {
|
|||||||
this.referencedSymbol = referencedSymbol;
|
this.referencedSymbol = referencedSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolVariableRef getReferencingSymbol() {
|
public SymbolVariableRef getReferencingSymbol() {
|
||||||
return referencingSymbol;
|
return referencingSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,6 +296,41 @@ public class VariableReferenceInfos {
|
|||||||
return stmts;
|
return stmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all constants (or symbol definitions) referencing another constant
|
||||||
|
*
|
||||||
|
* @param constRef The constant to look for
|
||||||
|
* @return All constants (or symbol definitions) that reference the constant in their value
|
||||||
|
*/
|
||||||
|
public Collection<SymbolVariableRef> getConstRefSymbols(ConstantRef constRef) {
|
||||||
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
||||||
|
LinkedHashSet<SymbolVariableRef> constRefs = new LinkedHashSet<>();
|
||||||
|
if(refs != null) {
|
||||||
|
refs.stream()
|
||||||
|
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()))
|
||||||
|
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol)
|
||||||
|
.forEach(referenceToSymbolVar -> constRefs.add(((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol()));
|
||||||
|
}
|
||||||
|
return constRefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all usages of a constant. (only returns places where the constant is used, not where it is defined)
|
||||||
|
* @param constRef The constant to look for
|
||||||
|
* @return All statements or other constants that use the constant
|
||||||
|
*/
|
||||||
|
public Collection<ReferenceToSymbolVar> getConstRefAllUses(ConstantRef constRef) {
|
||||||
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
||||||
|
if(refs != null) {
|
||||||
|
final List<ReferenceToSymbolVar> allUses = refs.stream()
|
||||||
|
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return allUses;
|
||||||
|
} else
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the index of the statement defining a variable. Only returns if there is exactly one defining statement.
|
* Get the index of the statement defining a variable. Only returns if there is exactly one defining statement.
|
||||||
*
|
*
|
||||||
@ -366,22 +401,5 @@ public class VariableReferenceInfos {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all constants (or symbol definitions) referencing another constant
|
|
||||||
*
|
|
||||||
* @param constRef The constant to look for
|
|
||||||
* @return All constants (or symbol definitions) that reference the constant in their value
|
|
||||||
*/
|
|
||||||
public Collection<SymbolVariableRef> getSymbolRefConsts(ConstantRef constRef) {
|
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
|
||||||
LinkedHashSet<SymbolVariableRef> constRefs = new LinkedHashSet<>();
|
|
||||||
if(refs != null) {
|
|
||||||
refs.stream()
|
|
||||||
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()))
|
|
||||||
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol)
|
|
||||||
.forEach(referenceToSymbolVar -> constRefs.add(((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol()));
|
|
||||||
}
|
|
||||||
return constRefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,22 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
return program.getProcedureCompilation(currentProcedure.getRef());
|
return program.getProcedureCompilation(currentProcedure.getRef());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an intermediate variable to the current scope.
|
||||||
|
*
|
||||||
|
* If the current scope is global the variable is added to the _init() scope.
|
||||||
|
*
|
||||||
|
* @return The new intermediate variable
|
||||||
|
*/
|
||||||
|
private Variable addIntermediateVar() {
|
||||||
|
Scope currentScope = getCurrentScope();
|
||||||
|
if(ScopeRef.ROOT.equals(currentScope.getRef())) {
|
||||||
|
Procedure initProc = program.getScope().getLocalProcedure(SymbolRef.INIT_PROC_NAME);
|
||||||
|
currentScope = initProc;
|
||||||
|
}
|
||||||
|
return currentScope.addVariableIntermediate();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a statement to the current procedure.
|
* Add a statement to the current procedure.
|
||||||
*/
|
*/
|
||||||
@ -1249,7 +1265,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
RValue exprVal = (RValue) this.visit(ctx.commaExpr());
|
RValue exprVal = (RValue) this.visit(ctx.commaExpr());
|
||||||
if(notConsumed(exprVal)) {
|
if(notConsumed(exprVal)) {
|
||||||
// Make a tmpVar to create the statement
|
// Make a tmpVar to create the statement
|
||||||
Variable tmpVar = getCurrentScope().addVariableIntermediate();
|
Variable tmpVar = addIntermediateVar();
|
||||||
List<Comment> comments = ensureUnusedComments(getCommentsSymbol(ctx));
|
List<Comment> comments = ensureUnusedComments(getCommentsSymbol(ctx));
|
||||||
RValue rVal = exprVal;
|
RValue rVal = exprVal;
|
||||||
if(exprVal instanceof LValue) {
|
if(exprVal instanceof LValue) {
|
||||||
@ -1270,7 +1286,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
List<Comment> comments = ensureUnusedComments(getCommentsSymbol(ctx));
|
List<Comment> comments = ensureUnusedComments(getCommentsSymbol(ctx));
|
||||||
if(elseStmt == null) {
|
if(elseStmt == null) {
|
||||||
// If without else - skip the entire section if condition not met
|
// If without else - skip the entire section if condition not met
|
||||||
SymbolVariableRef notExprVar = getCurrentScope().addVariableIntermediate().getRef();
|
SymbolVariableRef notExprVar = addIntermediateVar().getRef();
|
||||||
addStatement(new StatementAssignment((LValue) notExprVar, null, Operators.LOGIC_NOT, rValue, true, StatementSource.ifThen(ctx), comments));
|
addStatement(new StatementAssignment((LValue) notExprVar, null, Operators.LOGIC_NOT, rValue, true, StatementSource.ifThen(ctx), comments));
|
||||||
Label endJumpLabel = getCurrentScope().addLabelIntermediate();
|
Label endJumpLabel = getCurrentScope().addLabelIntermediate();
|
||||||
addStatement(new StatementConditionalJump(notExprVar, endJumpLabel.getRef(), StatementSource.ifThen(ctx), Comment.NO_COMMENTS));
|
addStatement(new StatementConditionalJump(notExprVar, endJumpLabel.getRef(), StatementSource.ifThen(ctx), Comment.NO_COMMENTS));
|
||||||
@ -1394,7 +1410,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
// If modifiers are present the RValue must be assigned before the post-modifier is executed
|
// If modifiers are present the RValue must be assigned before the post-modifier is executed
|
||||||
if(!(rValue instanceof VariableRef)) {
|
if(!(rValue instanceof VariableRef)) {
|
||||||
// Make a new temporary variable and assign that
|
// Make a new temporary variable and assign that
|
||||||
Variable tmpVar = getCurrentScope().addVariableIntermediate();
|
Variable tmpVar = addIntermediateVar();
|
||||||
Statement stmtExpr = new StatementAssignment(tmpVar.getVariableRef(), rValue, true, statementSource, Comment.NO_COMMENTS);
|
Statement stmtExpr = new StatementAssignment(tmpVar.getVariableRef(), rValue, true, statementSource, Comment.NO_COMMENTS);
|
||||||
addStatement(stmtExpr);
|
addStatement(stmtExpr);
|
||||||
rValue = tmpVar.getRef();
|
rValue = tmpVar.getRef();
|
||||||
@ -1603,7 +1619,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
addStatement(stmtNxt);
|
addStatement(stmtNxt);
|
||||||
// Add condition i!=last+1 or i!=last-1
|
// Add condition i!=last+1 or i!=last-1
|
||||||
RValue beyondLastVal = new RangeComparison(rangeFirstValue, rangeLastValue, lValue.getType());
|
RValue beyondLastVal = new RangeComparison(rangeFirstValue, rangeLastValue, lValue.getType());
|
||||||
Variable tmpVar = getCurrentScope().addVariableIntermediate();
|
Variable tmpVar = addIntermediateVar();
|
||||||
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
||||||
Statement stmtTmpVar = new StatementAssignment((LValue) tmpVarRef, lValue.getRef(), Operators.NEQ, beyondLastVal, true, statementSource, Comment.NO_COMMENTS);
|
Statement stmtTmpVar = new StatementAssignment((LValue) tmpVarRef, lValue.getRef(), Operators.NEQ, beyondLastVal, true, statementSource, Comment.NO_COMMENTS);
|
||||||
addStatement(stmtTmpVar);
|
addStatement(stmtTmpVar);
|
||||||
@ -2221,7 +2237,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
} else {
|
} else {
|
||||||
// sizeof(expression) - add a unary expression to be resolved later
|
// sizeof(expression) - add a unary expression to be resolved later
|
||||||
RValue child = (RValue) this.visit(ctx.expr());
|
RValue child = (RValue) this.visit(ctx.expr());
|
||||||
Variable tmpVar = getCurrentScope().addVariableIntermediate();
|
Variable tmpVar = addIntermediateVar();
|
||||||
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
||||||
Statement stmt = new StatementAssignment((LValue) tmpVarRef, Operators.SIZEOF, child, true, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
|
Statement stmt = new StatementAssignment((LValue) tmpVarRef, Operators.SIZEOF, child, true, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
|
||||||
addStatement(stmt);
|
addStatement(stmt);
|
||||||
@ -2239,7 +2255,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
} else {
|
} else {
|
||||||
// typeid(expression) - add a unary expression to be resolved later
|
// typeid(expression) - add a unary expression to be resolved later
|
||||||
RValue child = (RValue) this.visit(ctx.expr());
|
RValue child = (RValue) this.visit(ctx.expr());
|
||||||
Variable tmpVar = getCurrentScope().addVariableIntermediate();
|
Variable tmpVar = addIntermediateVar();
|
||||||
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
||||||
Statement stmt = new StatementAssignment((LValue) tmpVarRef, Operators.TYPEID, child, true, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
|
Statement stmt = new StatementAssignment((LValue) tmpVarRef, Operators.TYPEID, child, true, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
|
||||||
addStatement(stmt);
|
addStatement(stmt);
|
||||||
@ -2257,7 +2273,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
} else {
|
} else {
|
||||||
parameters = new ArrayList<>();
|
parameters = new ArrayList<>();
|
||||||
}
|
}
|
||||||
Variable tmpVar = getCurrentScope().addVariableIntermediate();
|
Variable tmpVar = addIntermediateVar();
|
||||||
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
||||||
|
|
||||||
String procedureName;
|
String procedureName;
|
||||||
@ -2362,7 +2378,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
if(left instanceof ConstantValue && right instanceof ConstantValue) {
|
if(left instanceof ConstantValue && right instanceof ConstantValue) {
|
||||||
return new ConstantBinary((ConstantValue) left, (OperatorBinary) operator, (ConstantValue) right);
|
return new ConstantBinary((ConstantValue) left, (OperatorBinary) operator, (ConstantValue) right);
|
||||||
} else {
|
} else {
|
||||||
Variable tmpVar = getCurrentScope().addVariableIntermediate();
|
Variable tmpVar = addIntermediateVar();
|
||||||
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
||||||
Statement stmt = new StatementAssignment((LValue) tmpVarRef, left, operator, right, true, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
|
Statement stmt = new StatementAssignment((LValue) tmpVarRef, left, operator, right, true, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
|
||||||
addStatement(stmt);
|
addStatement(stmt);
|
||||||
@ -2396,7 +2412,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
} else if(child instanceof ConstantValue) {
|
} else if(child instanceof ConstantValue) {
|
||||||
return new ConstantUnary((OperatorUnary) operator, (ConstantValue) child);
|
return new ConstantUnary((OperatorUnary) operator, (ConstantValue) child);
|
||||||
} else {
|
} else {
|
||||||
Variable tmpVar = getCurrentScope().addVariableIntermediate();
|
Variable tmpVar = addIntermediateVar();
|
||||||
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
SymbolVariableRef tmpVarRef = tmpVar.getRef();
|
||||||
Statement stmt = new StatementAssignment((LValue) tmpVarRef, operator, child, true, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
|
Statement stmt = new StatementAssignment((LValue) tmpVarRef, operator, child, true, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
|
||||||
addStatement(stmt);
|
addStatement(stmt);
|
||||||
@ -2453,19 +2469,19 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
addStatement(new StatementConditionalJump(condValue, trueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
addStatement(new StatementConditionalJump(condValue, trueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||||
addStatement(new StatementLabel(falseLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
addStatement(new StatementLabel(falseLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||||
RValue falseValue = (RValue) this.visit(ctx.expr(2));
|
RValue falseValue = (RValue) this.visit(ctx.expr(2));
|
||||||
SymbolVariableRef falseVar = getCurrentScope().addVariableIntermediate().getRef();
|
SymbolVariableRef falseVar = addIntermediateVar().getRef();
|
||||||
addStatement(new StatementAssignment((LValue) falseVar, falseValue, true, new StatementSource(ctx), Comment.NO_COMMENTS));
|
addStatement(new StatementAssignment((LValue) falseVar, falseValue, true, new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||||
LabelRef falseExitLabel = getCurrentProcedureCompilation().getStatementSequence().getCurrentBlockLabel();
|
LabelRef falseExitLabel = getCurrentProcedureCompilation().getStatementSequence().getCurrentBlockLabel();
|
||||||
addStatement(new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
addStatement(new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||||
addStatement(new StatementLabel(trueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
addStatement(new StatementLabel(trueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||||
RValue trueValue = (RValue) this.visit(ctx.expr(1));
|
RValue trueValue = (RValue) this.visit(ctx.expr(1));
|
||||||
SymbolVariableRef trueVar = getCurrentScope().addVariableIntermediate().getRef();
|
SymbolVariableRef trueVar = addIntermediateVar().getRef();
|
||||||
addStatement(new StatementAssignment((LValue) trueVar, trueValue, true, new StatementSource(ctx), Comment.NO_COMMENTS));
|
addStatement(new StatementAssignment((LValue) trueVar, trueValue, true, new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||||
LabelRef trueExitLabel = getCurrentProcedureCompilation().getStatementSequence().getCurrentBlockLabel();
|
LabelRef trueExitLabel = getCurrentProcedureCompilation().getStatementSequence().getCurrentBlockLabel();
|
||||||
addStatement(new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
addStatement(new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||||
StatementPhiBlock phiBlock = new StatementPhiBlock(Comment.NO_COMMENTS);
|
StatementPhiBlock phiBlock = new StatementPhiBlock(Comment.NO_COMMENTS);
|
||||||
phiBlock.setSource(new StatementSource(ctx));
|
phiBlock.setSource(new StatementSource(ctx));
|
||||||
SymbolVariableRef finalVar = getCurrentScope().addVariableIntermediate().getRef();
|
SymbolVariableRef finalVar = addIntermediateVar().getRef();
|
||||||
StatementPhiBlock.PhiVariable phiVariable = phiBlock.addPhiVariable((VariableRef) finalVar);
|
StatementPhiBlock.PhiVariable phiVariable = phiBlock.addPhiVariable((VariableRef) finalVar);
|
||||||
phiVariable.setrValue(trueExitLabel, trueVar);
|
phiVariable.setrValue(trueExitLabel, trueVar);
|
||||||
phiVariable.setrValue(falseExitLabel, falseVar);
|
phiVariable.setrValue(falseExitLabel, falseVar);
|
||||||
|
@ -199,6 +199,10 @@ public class Pass1ProcedureInline extends Pass1Base {
|
|||||||
StatementAsm procAsm = (StatementAsm) procStatement;
|
StatementAsm procAsm = (StatementAsm) procStatement;
|
||||||
StatementAsm inlinedAsm = new StatementAsm(procAsm.getAsmLines(), new LinkedHashMap<>(procAsm.getReferenced()), procAsm.getDeclaredClobber(), procAsm.getSource(), Comment.NO_COMMENTS);
|
StatementAsm inlinedAsm = new StatementAsm(procAsm.getAsmLines(), new LinkedHashMap<>(procAsm.getReferenced()), procAsm.getDeclaredClobber(), procAsm.getSource(), Comment.NO_COMMENTS);
|
||||||
inlinedStatement = inlinedAsm;
|
inlinedStatement = inlinedAsm;
|
||||||
|
} else if(procStatement instanceof StatementKickAsm) {
|
||||||
|
StatementKickAsm procKasm = (StatementKickAsm) procStatement;
|
||||||
|
StatementKickAsm inlinedAsm = new StatementKickAsm(procKasm.getKickAsmCode(), procKasm.getLocation(), procKasm.getBytes(), procKasm.getCycles(), procKasm.getUses(), procKasm.getDeclaredClobber(), procKasm.getSource(), Comment.NO_COMMENTS);
|
||||||
|
inlinedStatement = inlinedAsm;
|
||||||
} else if(procStatement instanceof StatementConditionalJump) {
|
} else if(procStatement instanceof StatementConditionalJump) {
|
||||||
StatementConditionalJump procConditional = (StatementConditionalJump) procStatement;
|
StatementConditionalJump procConditional = (StatementConditionalJump) procStatement;
|
||||||
LabelRef procDestinationRef = procConditional.getDestination();
|
LabelRef procDestinationRef = procConditional.getDestination();
|
||||||
|
@ -370,7 +370,7 @@ public class Pass4CodeGeneration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Collection<SymbolVariableRef> symbolRefConsts = program.getVariableReferenceInfos().getSymbolRefConsts(constantVar.getConstantRef());
|
Collection<SymbolVariableRef> symbolRefConsts = program.getVariableReferenceInfos().getConstRefSymbols(constantVar.getConstantRef());
|
||||||
if(symbolRefConsts != null) {
|
if(symbolRefConsts != null) {
|
||||||
for(SymbolVariableRef symbolRefConst : symbolRefConsts) {
|
for(SymbolVariableRef symbolRefConst : symbolRefConsts) {
|
||||||
Variable symbolRefVar = (Variable) program.getScope().getSymbol(symbolRefConst);
|
Variable symbolRefVar = (Variable) program.getScope().getSymbol(symbolRefConst);
|
||||||
|
@ -2,9 +2,15 @@ package dk.camelot64.kickc.passes;
|
|||||||
|
|
||||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||||
import dk.camelot64.kickc.model.Program;
|
import dk.camelot64.kickc.model.Program;
|
||||||
|
import dk.camelot64.kickc.model.StatementInfos;
|
||||||
|
import dk.camelot64.kickc.model.VariableReferenceInfos;
|
||||||
import dk.camelot64.kickc.model.statements.*;
|
import dk.camelot64.kickc.model.statements.*;
|
||||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||||
|
import dk.camelot64.kickc.model.symbols.Scope;
|
||||||
|
import dk.camelot64.kickc.model.symbols.Symbol;
|
||||||
|
import dk.camelot64.kickc.model.symbols.Variable;
|
||||||
import dk.camelot64.kickc.model.values.ProcedureRef;
|
import dk.camelot64.kickc.model.values.ProcedureRef;
|
||||||
|
import dk.camelot64.kickc.model.values.SymbolVariableRef;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -24,16 +30,58 @@ public class PassNEliminateEmptyProcedure extends Pass2SsaOptimization {
|
|||||||
boolean optimized = false;
|
boolean optimized = false;
|
||||||
for(Procedure procedure : allProcedures) {
|
for(Procedure procedure : allProcedures) {
|
||||||
if(hasEmptyBody(procedure.getRef())) {
|
if(hasEmptyBody(procedure.getRef())) {
|
||||||
// Remove all calls
|
if(!hasExternalUsages(procedure.getRef(), getProgram())) {
|
||||||
removeAllCalls(procedure.getRef());
|
// Remove all calls
|
||||||
// Remove the procedure
|
removeAllCalls(procedure.getRef());
|
||||||
Pass2EliminateUnusedBlocks.removeProcedure(procedure.getRef(), new HashSet<>(), getProgram());
|
// Remove the procedure
|
||||||
optimized = true;
|
Pass2EliminateUnusedBlocks.removeProcedure(procedure.getRef(), new HashSet<>(), getProgram());
|
||||||
|
optimized = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return optimized;
|
return optimized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Examines whether there are any constants inside a procedure with external usages
|
||||||
|
*
|
||||||
|
* @param procedureRef
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected static boolean hasExternalUsages(ProcedureRef procedureRef, Program program) {
|
||||||
|
program.clearVariableReferenceInfos();
|
||||||
|
program.clearStatementInfos();
|
||||||
|
new PassNStatementIndices(program).execute();
|
||||||
|
final VariableReferenceInfos variableReferenceInfos = program.getVariableReferenceInfos();
|
||||||
|
final StatementInfos statementInfos = program.getStatementInfos();
|
||||||
|
|
||||||
|
final Procedure startProc = program.getScope().getProcedure(procedureRef);
|
||||||
|
final Collection<Variable> startConsts = startProc.getAllConstants(true);
|
||||||
|
for(Variable startConst : startConsts) {
|
||||||
|
final Collection<VariableReferenceInfos.ReferenceToSymbolVar> uses = variableReferenceInfos.getConstRefAllUses(startConst.getConstantRef());
|
||||||
|
for(VariableReferenceInfos.ReferenceToSymbolVar use : uses) {
|
||||||
|
if(use instanceof VariableReferenceInfos.ReferenceInStatement) {
|
||||||
|
final Integer statementIdx = ((VariableReferenceInfos.ReferenceInStatement) use).getStatementIdx();
|
||||||
|
final ControlFlowBlock block = statementInfos.getBlock(statementIdx);
|
||||||
|
final Procedure useProcedure = block.getProcedure(program);
|
||||||
|
if(!procedureRef.equals(useProcedure.getRef())) {
|
||||||
|
// Usage in a another procedure
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if(use instanceof VariableReferenceInfos.ReferenceInSymbol) {
|
||||||
|
final SymbolVariableRef referencingSymbolRef = ((VariableReferenceInfos.ReferenceInSymbol) use).getReferencingSymbol();
|
||||||
|
final Symbol referencingSymbol = program.getScope().getSymbol(referencingSymbolRef);
|
||||||
|
final Scope referencingScope = referencingSymbol.getScope();
|
||||||
|
if(!procedureRef.equals(referencingScope.getRef())) {
|
||||||
|
// Usage in a another constant
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void removeAllCalls(ProcedureRef ref) {
|
private void removeAllCalls(ProcedureRef ref) {
|
||||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||||
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
|
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
|
||||||
|
@ -23,10 +23,13 @@ public class PassNEliminateEmptyStart extends Pass2SsaOptimization {
|
|||||||
final ProcedureRef startProcRef = new ProcedureRef(SymbolRef.START_PROC_NAME);
|
final ProcedureRef startProcRef = new ProcedureRef(SymbolRef.START_PROC_NAME);
|
||||||
StatementCall singleCall = getSingleCall(startProcRef);
|
StatementCall singleCall = getSingleCall(startProcRef);
|
||||||
if(singleCall != null) {
|
if(singleCall != null) {
|
||||||
// Start only has a single call
|
// Are there any constants in the scope that are used elsewhere?
|
||||||
getProgram().setStartProcedure(singleCall.getProcedure());
|
if(!PassNEliminateEmptyProcedure.hasExternalUsages(startProcRef, getProgram())) {
|
||||||
Pass2EliminateUnusedBlocks.removeProcedure(startProcRef, new HashSet<>(), getProgram());
|
// Start only has a single call - and no external usages
|
||||||
return true;
|
getProgram().setStartProcedure(singleCall.getProcedure());
|
||||||
|
Pass2EliminateUnusedBlocks.removeProcedure(startProcRef, new HashSet<>(), getProgram());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -49,7 +52,7 @@ public class PassNEliminateEmptyStart extends Pass2SsaOptimization {
|
|||||||
// Another call already encountered
|
// Another call already encountered
|
||||||
return null;
|
return null;
|
||||||
final StatementCall call = (StatementCall) statement;
|
final StatementCall call = (StatementCall) statement;
|
||||||
if(call.getParameters()==null && call.getlValue() == null)
|
if(call.getParameters() == null && call.getlValue() == null)
|
||||||
// Call is no-args no-return
|
// Call is no-args no-return
|
||||||
singleCall = call;
|
singleCall = call;
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user