1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-26 03:32:23 +00:00

Fixed problem with passing struck values to __stackcall. Closes #366

This commit is contained in:
jespergravgaard 2020-03-06 09:38:09 +01:00
parent 797c3bbd21
commit 689aeb0ca6
8 changed files with 404 additions and 463 deletions

View File

@ -60,6 +60,10 @@ public class ValueSourceFactory {
final ValueSource structValueSource = getValueSource(structValue, program, programScope, currentStmt, stmtIt, currentBlock);
return structValueSource.getMemberUnwinding(((StructMemberRef) value).getMemberName(), program, programScope, currentStmt, stmtIt, currentBlock);
}
if(valueType instanceof SymbolTypeStruct && value instanceof ParamValue) {
final StructDefinition structDefinition = ((SymbolTypeStruct) valueType).getStructDefinition(programScope);
return new ValueSourceParamList((ParamValue) value, structDefinition);
}
return null;
}

View File

@ -0,0 +1,65 @@
package dk.camelot64.kickc.passes.unwinding;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.symbols.ArraySpec;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.StructDefinition;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.ParamValue;
import dk.camelot64.kickc.model.values.RValue;
import java.util.ListIterator;
/** A parameter value list. */
public class ValueSourceParamList extends ValueSourceBase {
private final StructDefinition structDefinition;
private final ParamValue paramValue;
public ValueSourceParamList(ParamValue paramValue, StructDefinition structDefinition) {
this.paramValue = paramValue;
this.structDefinition = structDefinition;
}
@Override
public SymbolType getSymbolType() {
return structDefinition.getType();
}
@Override
public ArraySpec getArraySpec() {
return null;
}
@Override
protected boolean isStructClassic() {
return false;
}
@Override
public RValue getSimpleValue(ProgramScope programScope) {
throw new InternalError("Not a simple value");
}
@Override
public LValue getBulkLValue(ProgramScope scope) {
throw new InternalError("Not a bulk value");
}
@Override
public RValue getBulkRValue(ProgramScope scope) {
throw new InternalError("Not a bulk value");
}
@Override
public ValueSource getMemberUnwinding(String memberName, Program program, ProgramScope programScope, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
final ValueSource paramValueSource = ValueSourceFactory.getValueSource(paramValue.getParameter(), program, programScope, currentStmt, stmtIt, currentBlock);
final ValueSource memberUnwinding = paramValueSource.getMemberUnwinding(memberName, program, programScope, currentStmt, stmtIt, currentBlock);
return new ValueSourceParamValue(memberUnwinding);
}
}

View File

@ -0,0 +1,61 @@
package dk.camelot64.kickc.passes.unwinding;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.symbols.ArraySpec;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.ParamValue;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.ListIterator;
/** An unwound parameter value. */
public class ValueSourceParamValue extends ValueSourceBase {
private final ValueSource valueSource;
public ValueSourceParamValue(ValueSource valueSource) {
this.valueSource = valueSource;
}
@Override
public SymbolType getSymbolType() {
return valueSource.getSymbolType();
}
@Override
public ArraySpec getArraySpec() {
return valueSource.getArraySpec();
}
@Override
protected boolean isStructClassic() {
return false;
}
@Override
public RValue getSimpleValue(ProgramScope programScope) {
return new ParamValue((VariableRef) valueSource.getSimpleValue(programScope));
}
@Override
public LValue getBulkLValue(ProgramScope scope) {
throw new InternalError("Not a bulk value");
}
@Override
public RValue getBulkRValue(ProgramScope scope) {
throw new InternalError("Not a bulk value");
}
@Override
public ValueSource getMemberUnwinding(String memberName, Program program, ProgramScope programScope, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
throw new InternalError("Not unwindable");
}
}

View File

@ -281,7 +281,7 @@ public class TestPrograms {
@Test
public void testProcedureCallingConventionStack10() throws IOException, URISyntaxException {
compileAndCompare("procedure-callingconvention-stack-10", log().verboseCreateSsa());
compileAndCompare("procedure-callingconvention-stack-10");
}
@Test

View File

@ -14,9 +14,19 @@ __bbegin:
sta.z idx
jsr main
rts
// print(byte register(A) p_x, byte register(X) p_y)
// print(byte register(Y) p_x, byte register(X) p_y)
print: {
.const OFFSET_STACK_P_X = 1
.const OFFSET_STACK_P_Y = 0
// }
tsx
lda STACK_BASE+OFFSET_STACK_P_X,x
tay
tsx
lda STACK_BASE+OFFSET_STACK_P_Y,x
tax
// SCREEN[idx++] = p.x
tya
ldy.z idx
sta SCREEN,y
// SCREEN[idx++] = p.x;

View File

@ -11,48 +11,48 @@
__stackcall (void()) print((byte) print::p_x , (byte) print::p_y)
print: scope:[print] from
[5] (byte) print::p_y#0 ← phi( )
[5] (byte) print::p_x#0 ← phi( )
[6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0
[7] (byte) idx ← ++ (byte) idx
[8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0
[9] (byte) idx ← ++ (byte) idx
[5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X)
[6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y)
[7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0
[8] (byte) idx ← ++ (byte) idx
[9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0
[10] (byte) idx ← ++ (byte) idx
to:print::@return
print::@return: scope:[print] from print
[10] return
[11] return
to:@return
__stackcall (struct Point()) get((byte) get::i)
get: scope:[get] from
[11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I)
[12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1
[13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0
[14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0
[15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p)
[16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)
[12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I)
[13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1
[14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0
[15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0
[16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p)
[17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)
to:get::@return
get::@return: scope:[get] from get
[17] return { (byte) get::return_x#0, (byte) get::return_y#0 }
[18] return { (byte) get::return_x#0, (byte) get::return_y#0 }
to:@return
__stackcall (void()) main()
main: scope:[main] from
[18] (byte) main::i ← (byte) 0
[19] (byte) main::i ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@2
[19] if((byte) main::i<(byte) 5) goto main::@2
[20] if((byte) main::i<(byte) 5) goto main::@2
to:main::@return
main::@return: scope:[main] from main::@1
[20] return
[21] return
to:@return
main::@2: scope:[main] from main::@1
[21] callprepare get (byte) main::i
[22] callexecute get
[23] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get
[24] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x
[25] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
[26] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)
[27] callexecute print
[28] callfinalize print
[29] (byte) main::i ← ++ (byte) main::i
[22] callprepare get (byte) main::i
[23] callexecute get
[24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get
[25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x
[26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y
[27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)
[28] callexecute print
[29] callfinalize print
[30] (byte) main::i ← ++ (byte) main::i
to:main::@1

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ __stackcall (struct Point()) get((byte) get::i)
(byte) get::return_x#0 reg byte a 1.0
(byte) get::return_y
(byte) get::return_y#0 reg byte y 2.0
(byte) idx loadstore zp[1]:2 0.7368421052631579
(byte) idx loadstore zp[1]:2 0.7
__stackcall (void()) main()
(byte~) main::$1_x zp[1]:4 0.8461538461538461
(byte~) main::$1_y zp[1]:5 0.8461538461538461
@ -31,14 +31,16 @@ __stackcall (void()) main()
(struct Point) main::p loadstore zp[2]:6
__stackcall (void()) print((byte) print::p_x , (byte) print::p_y)
(label) print::@return
(const byte) print::OFFSET_STACK_P_X = (byte) 1
(const byte) print::OFFSET_STACK_P_Y = (byte) 0
(byte) print::p_x
(byte) print::p_x#0 reg byte a 2.0
(byte) print::p_x#0 reg byte y 2.0
(byte) print::p_y
(byte) print::p_y#0 reg byte x 0.6666666666666666
(byte) print::p_y#0 reg byte x 1.3333333333333333
reg byte a [ print::p_x#0 ]
reg byte x [ print::p_y#0 ]
zp[1]:2 [ idx ]
reg byte y [ print::p_x#0 ]
reg byte x [ print::p_y#0 ]
reg byte x [ get::i#0 ]
reg byte a [ get::$0 ]
reg byte a [ get::return_x#0 ]