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:
parent
30218564d2
commit
a411a57688
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user