1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-02-16 18:30:37 +00:00

Working on struct return values

This commit is contained in:
Jesper Gravgaard 2019-06-09 23:39:24 +02:00
parent 30218564d2
commit a411a57688
4 changed files with 102 additions and 31 deletions

View File

@ -203,21 +203,23 @@ public class Compiler {
getLog().append(program.getProcedureModifiedVars().toString(program));
}
getLog().append("CONTROL FLOW GRAPH (CLEANED)");
getLog().append(program.getGraph().toString(program));
//getLog().append("CONTROL FLOW GRAPH (CLEANED)");
//getLog().append(program.getGraph().toString(program));
new Pass1ProcedureCallParameters(program).generate();
getLog().append("CONTROL FLOW GRAPH (CALL PARAMETERS)");
getLog().append(program.getGraph().toString(program));
new PassNUnwindLValueLists(program).execute();
//getLog().append("CONTROL FLOW GRAPH (CALL PARAMETERS)");
//getLog().append(program.getGraph().toString(program));
new Pass1GenerateSingleStaticAssignmentForm(program).execute();
getLog().append("CONTROL FLOW GRAPH (SSA)");
getLog().append(program.getGraph().toString(program));
//getLog().append("CONTROL FLOW GRAPH (SSA)");
//getLog().append(program.getGraph().toString(program));
program.setGraph(new Pass1ProcedureCallsReturnValue(program).generate());
getLog().append("\nCONTROL FLOW GRAPH SSA (RETURN VALUES)");
getLog().append("\nCONTROL FLOW GRAPH SSA");
getLog().append(program.getGraph().toString(program));
getLog().append("SYMBOL TABLE SSA");

View File

@ -667,7 +667,7 @@ public interface ProgramValue {
private ValueList list;
private int idx;
ProgramValueListElement(ValueList list, int idx) {
public ProgramValueListElement(ValueList list, int idx) {
this.list = list;
this.idx = idx;
}

View File

@ -5,10 +5,7 @@ import dk.camelot64.kickc.model.ControlFlowBlock;
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.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementLValue;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeArray;
@ -49,30 +46,20 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
* Version all non-versioned non-intermediary being assigned a value.
*/
private void versionAllAssignments() {
Collection<VariableRef> earlyIdentifiedConstants = getProgram().getEarlyIdentifiedConstants();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue statementLValue = (StatementLValue) statement;
dk.camelot64.kickc.model.values.LValue lValue = statementLValue.getlValue();
LValue lValue = statementLValue.getlValue();
if(lValue instanceof VariableRef) {
VariableRef lValueRef = (VariableRef) lValue;
Variable assignedVar = getScope().getVariable(lValueRef);
if(assignedVar instanceof VariableUnversioned) {
// Assignment to a non-versioned non-intermediary variable
VariableUnversioned assignedSymbol = (VariableUnversioned) assignedVar;
VariableVersion version;
if(assignedSymbol.isDeclaredConstant() || earlyIdentifiedConstants.contains(assignedSymbol.getRef())) {
Collection<VariableVersion> versions = assignedVar.getScope().getVersions(assignedSymbol);
if(versions.size() != 0) {
throw new CompileError("Error! Constants can not be modified " + statement, statement.getSource());
}
version = assignedSymbol.createVersion();
version.setDeclaredConstant(true);
} else {
version = assignedSymbol.createVersion();
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());
}
statementLValue.setlValue(version.getRef());
}
}
}
@ -80,6 +67,33 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
}
}
/**
* Version a single unversioned variable being assigned
* @param lValueRef The variable being assigned
* @param programLValue Program Value usable for updating the variable
* @param source The statement source - usable for error messages
*/
private void versionAssignment(VariableRef lValueRef, ProgramValue programLValue, StatementSource source) {
Collection<VariableRef> earlyIdentifiedConstants = getProgram().getEarlyIdentifiedConstants();
Variable assignedVar = getScope().getVariable(lValueRef);
if(assignedVar instanceof VariableUnversioned) {
// Assignment to a non-versioned non-intermediary variable
VariableUnversioned assignedSymbol = (VariableUnversioned) assignedVar;
VariableVersion version;
if(assignedSymbol.isDeclaredConstant() || earlyIdentifiedConstants.contains(assignedSymbol.getRef())) {
Collection<VariableVersion> versions = assignedVar.getScope().getVersions(assignedSymbol);
if(versions.size() != 0) {
throw new CompileError("Error! Constants can not be modified", source);
}
version = assignedSymbol.createVersion();
version.setDeclaredConstant(true);
} else {
version = assignedSymbol.createVersion();
}
programLValue.set(version.getRef());
}
}
/**
* Version all uses of non-versioned non-intermediary variables
*/
@ -242,6 +256,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
/**
* Get all predecessors for a control flow block.
* If the block is the start of an interrupt the @begin is included as a predecessor.
*
* @param block The block to examine
* @return All predecessor blocks
*/
@ -250,7 +265,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
Symbol symbol = program.getScope().getSymbol(block.getLabel());
if(symbol instanceof Procedure) {
Procedure procedure = (Procedure) symbol;
if(procedure.getInterruptType()!=null || Pass2ConstantIdentification.isAddressOfUsed(procedure.getRef(), program)) {
if(procedure.getInterruptType() != null || Pass2ConstantIdentification.isAddressOfUsed(procedure.getRef(), program)) {
// Find all root-level predecessors to the main block
ControlFlowBlock mainBlock = program.getGraph().getBlock(new LabelRef(SymbolRef.MAIN_PROC_NAME));
List<ControlFlowBlock> mainPredecessors = program.getGraph().getPredecessors(mainBlock);

View File

@ -0,0 +1,54 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
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.values.LValue;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.ValueList;
import java.util.ListIterator;
/** If both LValue and RValue is a list then unwind them */
public class PassNUnwindLValueLists extends Pass2SsaOptimization {
public PassNUnwindLValueLists(Program program) {
super(program);
}
@Override
public boolean step() {
boolean modified = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getlValue() instanceof ValueList && assignment.getOperator()==null && assignment.getrValue2() instanceof ValueList) {
// Value-list to value list copy - unwind it
ValueList lValueList = (ValueList) assignment.getlValue();
ValueList rValueList = (ValueList) assignment.getrValue2();
if(lValueList.getList().size()!=rValueList.getList().size()) {
throw new CompileError("Assignment value lists have different sizes ", statement);
}
stmtIt.remove();
for(int i = 0; i < lValueList.getList().size(); i++) {
LValue lValue = (LValue) lValueList.getList().get(i);
RValue rValue = (RValue) rValueList.getList().get(i);
stmtIt.add(new StatementAssignment(lValue, rValue, assignment.getSource(), Comment.NO_COMMENTS));
}
getLog().append("Unwinding list assignment "+assignment.toString(getProgram(), false));
modified = true;
}
}
}
}
return modified;
}
}