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:
@@ -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)) {
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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
22
src/test/kc/varcall-4.c
Normal 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 };
|
||||||
|
}
|
Reference in New Issue
Block a user