1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-02 06:05:57 +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 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<Comment> comments, ListIterator<Statement> stmtIt) {
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.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<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 rValueSource = ValueSourceFactory.getValueSource(rValue, getProgram(), getScope(), assignment, stmtIt, currentBlock);
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) {
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<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)
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);
}

View File

@ -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");

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