mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-26 18:29:54 +00:00
Fixed problem with passing struck values to __stackcall. Closes #366
This commit is contained in:
parent
797c3bbd21
commit
689aeb0ca6
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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 ]
|
||||
|
Loading…
Reference in New Issue
Block a user