1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-08-15 13:27:36 +00:00

Struggling with struct return values.

This commit is contained in:
jespergravgaard
2020-11-23 11:46:54 +01:00
parent 19893e25f6
commit 34a5ca474a
5 changed files with 81 additions and 18 deletions

View File

@@ -171,7 +171,7 @@ public class Pass1CallStack extends Pass2SsaOptimization {
* @param stackReturnOffset The offset onto the stack to place the value at * @param stackReturnOffset The offset onto the stack to place the value at
* @param source The source line * @param source The source line
* @param comments The comments * @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<Comment> comments, ListIterator<Statement> stmtIt) { private void generateStackReturnValues(RValue value, SymbolType returnType, ConstantValue stackReturnOffset, StatementSource source, List<Comment> comments, ListIterator<Statement> stmtIt) {
if(!(value instanceof ValueList) || !(returnType instanceof SymbolTypeStruct)) { if(!(value instanceof ValueList) || !(returnType instanceof SymbolTypeStruct)) {

View File

@@ -8,8 +8,13 @@ import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolType; 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.LValue;
import dk.camelot64.kickc.model.values.RValue; 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.List;
import java.util.ListIterator; import java.util.ListIterator;
@@ -74,7 +79,7 @@ public class Pass1CallVar extends Pass2SsaOptimization {
if(lValue!=null) { if(lValue!=null) {
Variable returnVar = procedure.getLocalVariable("return"); Variable returnVar = procedure.getLocalVariable("return");
stmtIt.previous(); stmtIt.previous();
stmtIt.add(new StatementAssignment(lValue, returnVar.getRef(), call.isInitialAssignment(), source, comments)); generateCallFinalize(lValue, returnVar, source, comments, stmtIt, statement);
stmtIt.next(); stmtIt.next();
} }
stmtIt.remove(); stmtIt.remove();
@@ -111,4 +116,35 @@ public class Pass1CallVar extends Pass2SsaOptimization {
return false; return false;
} }
private void generateCallFinalize(LValue lValue, Variable returnVar, StatementSource source, List<Comment> comments, ListIterator<Statement> 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<RValue> 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);
}
*/
}
}
} }

View File

@@ -233,7 +233,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
ValueSource lValueSource = ValueSourceFactory.getValueSource(lValue, getProgram(), getScope(), assignment, stmtIt, currentBlock); ValueSource lValueSource = ValueSourceFactory.getValueSource(lValue, getProgram(), getScope(), assignment, stmtIt, currentBlock);
ValueSource rValueSource = ValueSourceFactory.getValueSource(rValue, getProgram(), getScope(), assignment, stmtIt, currentBlock); ValueSource rValueSource = ValueSourceFactory.getValueSource(rValue, getProgram(), getScope(), assignment, stmtIt, currentBlock);
List<RValue> lValueUnwoundList = new ArrayList<>(); List<RValue> 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) { if(lValue instanceof VariableRef) {
StructUnwoundPlaceholder unwoundPlaceholder = new StructUnwoundPlaceholder(lValueStructType, lValueUnwoundList); StructUnwoundPlaceholder unwoundPlaceholder = new StructUnwoundPlaceholder(lValueStructType, lValueUnwoundList);
assignment.setrValue2(unwoundPlaceholder); assignment.setrValue2(unwoundPlaceholder);
@@ -246,20 +246,20 @@ public class Pass1UnwindStructValues extends Pass1Base {
return false; return false;
} }
private boolean copyValues(ValueSource lValueSource, ValueSource rValueSource, List<RValue> lValueUnwoundList, boolean initialAssignment, Statement currentStmt, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt) { public static boolean copyValues(ValueSource lValueSource, ValueSource rValueSource, List<RValue> lValueUnwoundList, boolean initialAssignment, Statement currentStmt, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt, Program program) {
if(lValueSource == null || rValueSource == null) if(lValueSource == null || rValueSource == null)
return false; return false;
if(lValueSource.isSimple() && rValueSource.isSimple()) { if(lValueSource.isSimple() && rValueSource.isSimple()) {
stmtIt.previous(); stmtIt.previous();
LValue lValueRef = (LValue) lValueSource.getSimpleValue(getScope()); LValue lValueRef = (LValue) lValueSource.getSimpleValue(program.getScope());
RValue rValueRef = rValueSource.getSimpleValue(getScope()); RValue rValueRef = rValueSource.getSimpleValue(program.getScope());
if(lValueUnwoundList != null) if(lValueUnwoundList != null)
lValueUnwoundList.add(lValueRef); lValueUnwoundList.add(lValueRef);
Statement copyStmt = new StatementAssignment(lValueRef, rValueRef, initialAssignment, currentStmt.getSource(), Comment.NO_COMMENTS); Statement copyStmt = new StatementAssignment(lValueRef, rValueRef, initialAssignment, currentStmt.getSource(), Comment.NO_COMMENTS);
stmtIt.add(copyStmt); stmtIt.add(copyStmt);
stmtIt.next(); stmtIt.next();
if(getLog().isVerboseStructUnwind()) if(program.getLog().isVerboseStructUnwind())
getLog().append("Adding value simple copy " + copyStmt.toString(getProgram(), false)); program.getLog().append("Adding value simple copy " + copyStmt.toString(program, false));
return true; return true;
} else if(lValueSource.isBulkCopyable() && rValueSource.isBulkCopyable()) { } else if(lValueSource.isBulkCopyable() && rValueSource.isBulkCopyable()) {
// Use bulk unwinding for a struct member that is an array // 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(lValueSource.getArraySpec() != null)
if(rValueSource.getArraySpec() == null || !lValueSource.getArraySpec().equals(rValueSource.getArraySpec())) if(rValueSource.getArraySpec() == null || !lValueSource.getArraySpec().equals(rValueSource.getArraySpec()))
throw new RuntimeException("ArraySpec mismatch!"); throw new RuntimeException("ArraySpec mismatch!");
LValue lValueMemberVarRef = lValueSource.getBulkLValue(getScope()); LValue lValueMemberVarRef = lValueSource.getBulkLValue(program.getScope());
RValue rValueBulkUnwinding = rValueSource.getBulkRValue(getScope()); RValue rValueBulkUnwinding = rValueSource.getBulkRValue(program.getScope());
if(lValueUnwoundList != null) if(lValueUnwoundList != null)
lValueUnwoundList.add(lValueMemberVarRef); lValueUnwoundList.add(lValueMemberVarRef);
Statement copyStmt = new StatementAssignment(lValueMemberVarRef, rValueBulkUnwinding, initialAssignment, currentStmt.getSource(), Comment.NO_COMMENTS); Statement copyStmt = new StatementAssignment(lValueMemberVarRef, rValueBulkUnwinding, initialAssignment, currentStmt.getSource(), Comment.NO_COMMENTS);
stmtIt.add(copyStmt); stmtIt.add(copyStmt);
stmtIt.next(); stmtIt.next();
if(getLog().isVerboseStructUnwind()) if(program.getLog().isVerboseStructUnwind())
getLog().append("Adding value bulk copy " + copyStmt.toString(getProgram(), false)); program.getLog().append("Adding value bulk copy " + copyStmt.toString(program, false));
return true; return true;
} else if(lValueSource.isUnwindable() && rValueSource.isUnwindable()) { } else if(lValueSource.isUnwindable() && rValueSource.isUnwindable()) {
if(getLog().isVerboseStructUnwind()) if(program.getLog().isVerboseStructUnwind())
getLog().append("Unwinding value copy " + currentStmt.toString(getProgram(), false)); program.getLog().append("Unwinding value copy " + currentStmt.toString(program, false));
for(String memberName : lValueSource.getMemberNames(getScope())) { for(String memberName : lValueSource.getMemberNames(program.getScope())) {
ValueSource lValueSubSource = lValueSource.getMemberUnwinding(memberName, getProgram(), getScope(), currentStmt, stmtIt, currentBlock); ValueSource lValueSubSource = lValueSource.getMemberUnwinding(memberName, program, program.getScope(), currentStmt, stmtIt, currentBlock);
ValueSource rValueSubSource = rValueSource.getMemberUnwinding(memberName, getProgram(), 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); boolean success = copyValues(lValueSubSource, rValueSubSource, lValueUnwoundList, initialAssignment, currentStmt, currentBlock, stmtIt, program);
if(!success) if(!success)
throw new InternalError("Error during value unwinding copy! ", currentStmt); throw new InternalError("Error during value unwinding copy! ", currentStmt);
} }

View File

@@ -48,6 +48,11 @@ public class TestPrograms {
// compileAndCompare("unknown-var-problem.c", log().verboseParse()); // compileAndCompare("unknown-var-problem.c", log().verboseParse());
//} //}
@Test
public void testVarCall4() throws IOException, URISyntaxException {
compileAndCompare("varcall-4.c", log().verboseStructUnwind().verboseCreateSsa());
}
@Test @Test
public void testVarCall3() throws IOException, URISyntaxException { public void testVarCall3() throws IOException, URISyntaxException {
compileAndCompare("varcall-3.c"); compileAndCompare("varcall-3.c");

22
src/test/kc/varcall-4.c Normal file
View File

@@ -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 };
}