diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1CallStack.java b/src/main/java/dk/camelot64/kickc/passes/Pass1CallStack.java index c891d55a3..a07b5d08d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1CallStack.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1CallStack.java @@ -171,7 +171,7 @@ public class Pass1CallStack extends Pass2SsaOptimization { * @param stackReturnOffset The offset onto the stack to place the value at * @param source The source line * @param comments The comments - * @param stmtIt The statment iterator used to add statements to. + * @param stmtIt The statement iterator used to add statements to. */ private void generateStackReturnValues(RValue value, SymbolType returnType, ConstantValue stackReturnOffset, StatementSource source, List comments, ListIterator stmtIt) { if(!(value instanceof ValueList) || !(returnType instanceof SymbolTypeStruct)) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1CallVar.java b/src/main/java/dk/camelot64/kickc/passes/Pass1CallVar.java index 0e21201fb..6ab81758e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1CallVar.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1CallVar.java @@ -8,8 +8,13 @@ import dk.camelot64.kickc.model.symbols.Procedure; import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeStruct; +import dk.camelot64.kickc.model.values.CastValue; import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.ValueList; +import dk.camelot64.kickc.passes.unwinding.ValueSource; +import dk.camelot64.kickc.passes.unwinding.ValueSourceFactory; import java.util.List; import java.util.ListIterator; @@ -74,7 +79,7 @@ public class Pass1CallVar extends Pass2SsaOptimization { if(lValue!=null) { Variable returnVar = procedure.getLocalVariable("return"); stmtIt.previous(); - stmtIt.add(new StatementAssignment(lValue, returnVar.getRef(), call.isInitialAssignment(), source, comments)); + generateCallFinalize(lValue, returnVar, source, comments, stmtIt, statement); stmtIt.next(); } stmtIt.remove(); @@ -111,4 +116,35 @@ public class Pass1CallVar extends Pass2SsaOptimization { return false; } + private void generateCallFinalize(LValue lValue, Variable returnVar, StatementSource source, List comments, ListIterator stmtIt, Statement currentStmt) { + final SymbolType returnType = returnVar.getType(); + if(!(lValue instanceof ValueList) || !(returnType instanceof SymbolTypeStruct)) { + // A simple value - add simple assignment + final StatementAssignment stackPull = new StatementAssignment(lValue, returnVar.getRef(), false, source, comments); + stmtIt.add(stackPull); + getLog().append("Calling convention " + Procedure.CallingConvention.VAR_CALL + " adding return value assignment " + stackPull); + } else { + final CastValue structLValue = new CastValue(returnType, lValue); + // A struct to unwind + final ValueSource lValueSource = ValueSourceFactory.getValueSource(structLValue, getProgram(), getScope(), currentStmt, stmtIt, null); + final ValueSource rValueSource = ValueSourceFactory.getValueSource(returnVar.getRef(), getProgram(), getScope(), currentStmt, stmtIt, null); + Pass1UnwindStructValues.copyValues(lValueSource, rValueSource, null, false, currentStmt, null, stmtIt, getProgram()); + + + /* + final List memberLValues = ((ValueList) lValue).getList(); + final StructVariableMemberUnwinding structVariableMemberUnwinding = getProgram().getStructVariableMemberUnwinding(); + final StructVariableMemberUnwinding.VariableUnwinding returnVarUnwinding = structVariableMemberUnwinding.getVariableUnwinding(returnVar.getRef()); + for(RValue memberLValue : memberLValues) { + + } + for(int i = 0; i < structMemberVars.size(); i++) { + final Variable memberVar = structMemberVars.get(i); + final RValue memberValue = memberLValues.get(i); + generateCallFinalize(memberValue, memberVar.getType(), source, comments, stmtIt); + } + */ + } + } + } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java b/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java index 8c041a363..3b170fd2a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java @@ -233,7 +233,7 @@ public class Pass1UnwindStructValues extends Pass1Base { ValueSource lValueSource = ValueSourceFactory.getValueSource(lValue, getProgram(), getScope(), assignment, stmtIt, currentBlock); ValueSource rValueSource = ValueSourceFactory.getValueSource(rValue, getProgram(), getScope(), assignment, stmtIt, currentBlock); List lValueUnwoundList = new ArrayList<>(); - if(copyValues(lValueSource, rValueSource, lValueUnwoundList, initialAssignment, assignment, currentBlock, stmtIt)) { + if(copyValues(lValueSource, rValueSource, lValueUnwoundList, initialAssignment, assignment, currentBlock, stmtIt, getProgram())) { if(lValue instanceof VariableRef) { StructUnwoundPlaceholder unwoundPlaceholder = new StructUnwoundPlaceholder(lValueStructType, lValueUnwoundList); assignment.setrValue2(unwoundPlaceholder); @@ -246,20 +246,20 @@ public class Pass1UnwindStructValues extends Pass1Base { return false; } - private boolean copyValues(ValueSource lValueSource, ValueSource rValueSource, List lValueUnwoundList, boolean initialAssignment, Statement currentStmt, ControlFlowBlock currentBlock, ListIterator stmtIt) { + public static boolean copyValues(ValueSource lValueSource, ValueSource rValueSource, List lValueUnwoundList, boolean initialAssignment, Statement currentStmt, ControlFlowBlock currentBlock, ListIterator stmtIt, Program program) { if(lValueSource == null || rValueSource == null) return false; if(lValueSource.isSimple() && rValueSource.isSimple()) { stmtIt.previous(); - LValue lValueRef = (LValue) lValueSource.getSimpleValue(getScope()); - RValue rValueRef = rValueSource.getSimpleValue(getScope()); + LValue lValueRef = (LValue) lValueSource.getSimpleValue(program.getScope()); + RValue rValueRef = rValueSource.getSimpleValue(program.getScope()); if(lValueUnwoundList != null) lValueUnwoundList.add(lValueRef); Statement copyStmt = new StatementAssignment(lValueRef, rValueRef, initialAssignment, currentStmt.getSource(), Comment.NO_COMMENTS); stmtIt.add(copyStmt); stmtIt.next(); - if(getLog().isVerboseStructUnwind()) - getLog().append("Adding value simple copy " + copyStmt.toString(getProgram(), false)); + if(program.getLog().isVerboseStructUnwind()) + program.getLog().append("Adding value simple copy " + copyStmt.toString(program, false)); return true; } else if(lValueSource.isBulkCopyable() && rValueSource.isBulkCopyable()) { // Use bulk unwinding for a struct member that is an array @@ -267,23 +267,23 @@ public class Pass1UnwindStructValues extends Pass1Base { if(lValueSource.getArraySpec() != null) if(rValueSource.getArraySpec() == null || !lValueSource.getArraySpec().equals(rValueSource.getArraySpec())) throw new RuntimeException("ArraySpec mismatch!"); - LValue lValueMemberVarRef = lValueSource.getBulkLValue(getScope()); - RValue rValueBulkUnwinding = rValueSource.getBulkRValue(getScope()); + LValue lValueMemberVarRef = lValueSource.getBulkLValue(program.getScope()); + RValue rValueBulkUnwinding = rValueSource.getBulkRValue(program.getScope()); if(lValueUnwoundList != null) lValueUnwoundList.add(lValueMemberVarRef); Statement copyStmt = new StatementAssignment(lValueMemberVarRef, rValueBulkUnwinding, initialAssignment, currentStmt.getSource(), Comment.NO_COMMENTS); stmtIt.add(copyStmt); stmtIt.next(); - if(getLog().isVerboseStructUnwind()) - getLog().append("Adding value bulk copy " + copyStmt.toString(getProgram(), false)); + if(program.getLog().isVerboseStructUnwind()) + program.getLog().append("Adding value bulk copy " + copyStmt.toString(program, false)); return true; } else if(lValueSource.isUnwindable() && rValueSource.isUnwindable()) { - if(getLog().isVerboseStructUnwind()) - getLog().append("Unwinding value copy " + currentStmt.toString(getProgram(), false)); - for(String memberName : lValueSource.getMemberNames(getScope())) { - ValueSource lValueSubSource = lValueSource.getMemberUnwinding(memberName, getProgram(), getScope(), currentStmt, stmtIt, currentBlock); - ValueSource rValueSubSource = rValueSource.getMemberUnwinding(memberName, getProgram(), getScope(), currentStmt, stmtIt, currentBlock); - boolean success = copyValues(lValueSubSource, rValueSubSource, lValueUnwoundList, initialAssignment, currentStmt, currentBlock, stmtIt); + if(program.getLog().isVerboseStructUnwind()) + program.getLog().append("Unwinding value copy " + currentStmt.toString(program, false)); + for(String memberName : lValueSource.getMemberNames(program.getScope())) { + ValueSource lValueSubSource = lValueSource.getMemberUnwinding(memberName, program, program.getScope(), currentStmt, stmtIt, currentBlock); + ValueSource rValueSubSource = rValueSource.getMemberUnwinding(memberName, program, program.getScope(), currentStmt, stmtIt, currentBlock); + boolean success = copyValues(lValueSubSource, rValueSubSource, lValueUnwoundList, initialAssignment, currentStmt, currentBlock, stmtIt, program); if(!success) throw new InternalError("Error during value unwinding copy! ", currentStmt); } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 57d191729..cd3967b5b 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -48,6 +48,11 @@ public class TestPrograms { // compileAndCompare("unknown-var-problem.c", log().verboseParse()); //} + @Test + public void testVarCall4() throws IOException, URISyntaxException { + compileAndCompare("varcall-4.c", log().verboseStructUnwind().verboseCreateSsa()); + } + @Test public void testVarCall3() throws IOException, URISyntaxException { compileAndCompare("varcall-3.c"); diff --git a/src/test/kc/varcall-4.c b/src/test/kc/varcall-4.c new file mode 100644 index 000000000..2b21060c5 --- /dev/null +++ b/src/test/kc/varcall-4.c @@ -0,0 +1,22 @@ +// Test __varcall calling convention +// Struct parameter & return value + +struct Cols { + char border; + char bg; +}; + +struct Cols * const COLS = 0xd020; + +void main() { + struct Cols a = { 1, 2 }; + //*COLS = a; + a = plus(a, { 2, 3 } ); + *COLS = a; + //a = plus(a, a); + //*COLS = a; +} + +__varcall struct Cols plus(struct Cols a, struct Cols b) { + return { a.border+b.border, a.bg+b.bg }; +} \ No newline at end of file