mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-07 07:29:49 +00:00
Added stack clean-up. Added parameter stack fetch type. #316
This commit is contained in:
parent
c6a5c54909
commit
5e1c05dc2e
@ -357,8 +357,8 @@ public class AsmFragmentInstanceSpecFactory {
|
||||
bind(name, value);
|
||||
return name;
|
||||
} else if(value instanceof ParamStackValue) {
|
||||
// TODO: Handle different parameter types!
|
||||
return "_stackbyte_"+bind(((ParamStackValue) value).getStackOffset());
|
||||
ParamStackValue paramStackValue = (ParamStackValue) value;
|
||||
return "_stack"+paramStackValue.getValueType().getTypeName()+"_"+bind(paramStackValue.getStackOffset());
|
||||
} else if(value instanceof ParamStackPush) {
|
||||
return "_push"+((ParamStackPush) value).getType().getTypeName()+"_";
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.model.values;
|
||||
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
|
||||
/** The value passed into a function for a specific parameter using the stack. */
|
||||
public class ParamStackValue implements RValue {
|
||||
@ -8,8 +9,12 @@ public class ParamStackValue implements RValue {
|
||||
/** The constant holding the stack offset of the parameter. */
|
||||
private ConstantRef stackOffset;
|
||||
|
||||
public ParamStackValue(ConstantRef stackOffset) {
|
||||
/** The type of the value to fetch from the stack. */
|
||||
private SymbolType valueType;
|
||||
|
||||
public ParamStackValue(ConstantRef stackOffset, SymbolType valueType) {
|
||||
this.stackOffset = stackOffset;
|
||||
this.valueType = valueType;
|
||||
}
|
||||
|
||||
public ConstantRef getStackOffset() {
|
||||
@ -20,9 +25,17 @@ public class ParamStackValue implements RValue {
|
||||
this.stackOffset = stackOffset;
|
||||
}
|
||||
|
||||
public SymbolType getValueType() {
|
||||
return valueType;
|
||||
}
|
||||
|
||||
public void setValueType(SymbolType valueType) {
|
||||
this.valueType = valueType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Program program) {
|
||||
return "paramstack("+stackOffset+")";
|
||||
return "paramstack("+valueType.getTypeName()+","+stackOffset+")";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -757,8 +757,19 @@ public class Pass4CodeGeneration {
|
||||
generateAsm(asm, asmFragmentInstanceSpecFactory);
|
||||
}
|
||||
}
|
||||
|
||||
asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
||||
// Clean up the stack
|
||||
if(Procedure.CallingConvension.STACK_CALL.equals(procedure.getCallingConvension())) {
|
||||
int parameterBytes = 0;
|
||||
for(RValue parameter : call.getParameters()) {
|
||||
SymbolType parameterType = SymbolTypeInference.inferType(program.getScope(), parameter);
|
||||
parameterBytes += parameterType.getSizeBytes();
|
||||
}
|
||||
// TODO: Replace with fragment - to allow hand-coded handling of the stack pointer modifications - eg. using TSX, TXA, AXS #{}, TXS
|
||||
for(int i = 0; i < parameterBytes; i++) {
|
||||
asm.addInstruction("pla", AsmAddressingMode.NON, null, false);
|
||||
}
|
||||
}
|
||||
} else if(statement instanceof StatementReturn) {
|
||||
Procedure.InterruptType interruptType = null;
|
||||
ScopeRef scope = block.getScope();
|
||||
|
@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -42,8 +43,9 @@ public class PassNCallingConventionStack extends Pass2SsaOptimization {
|
||||
// Convert ParamValues to calling-convention specific param-value
|
||||
ParamValue paramValue = (ParamValue) programValue.get();
|
||||
VariableRef parameterRef = paramValue.getParameter();
|
||||
SymbolType parameterType = SymbolTypeInference.inferType(getScope(), paramValue.getParameter());
|
||||
if(offsetConstants.containsKey(parameterRef)) {
|
||||
ParamStackValue paramStackValue = new ParamStackValue(offsetConstants.get(parameterRef));
|
||||
ParamStackValue paramStackValue = new ParamStackValue(offsetConstants.get(parameterRef), parameterType);
|
||||
programValue.set(paramStackValue);
|
||||
getLog().append("Calling convention " + Procedure.CallingConvension.STACK_CALL + " replacing " + paramValue.toString(getProgram()) + " with " + paramStackValue.toString(getProgram()));
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ main: {
|
||||
lda #7
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
pla
|
||||
sty SCREEN
|
||||
rts
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ main::@return: scope:[main] from main
|
||||
|
||||
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
|
||||
plus: scope:[plus] from
|
||||
[8] (byte) plus::a#0 ← paramstack(plus::OFFSET_STACK_A)
|
||||
[9] (byte) plus::b#0 ← paramstack(plus::OFFSET_STACK_B)
|
||||
[8] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A)
|
||||
[9] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B)
|
||||
[10] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
|
||||
to:plus::@return
|
||||
plus::@return: scope:[plus] from plus
|
||||
|
@ -89,8 +89,8 @@ Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Calling convention STACK_CALL replacing param((byte) plus::a) with paramstack(plus::OFFSET_STACK_A)
|
||||
Calling convention STACK_CALL replacing param((byte) plus::b) with paramstack(plus::OFFSET_STACK_B)
|
||||
Calling convention STACK_CALL replacing param((byte) plus::a) with paramstack(byte,plus::OFFSET_STACK_A)
|
||||
Calling convention STACK_CALL replacing param((byte) plus::b) with paramstack(byte,plus::OFFSET_STACK_B)
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
@ -115,8 +115,8 @@ main::@return: scope:[main] from main
|
||||
|
||||
__stackcall (byte()) plus((byte) plus::a , (byte) plus::b)
|
||||
plus: scope:[plus] from
|
||||
[8] (byte) plus::a#0 ← paramstack(plus::OFFSET_STACK_A)
|
||||
[9] (byte) plus::b#0 ← paramstack(plus::OFFSET_STACK_B)
|
||||
[8] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A)
|
||||
[9] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B)
|
||||
[10] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0
|
||||
to:plus::@return
|
||||
plus::@return: scope:[plus] from plus
|
||||
@ -187,6 +187,8 @@ main: {
|
||||
lda #7
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
pla
|
||||
// [6] *((const byte*) SCREEN#0) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1
|
||||
lda.z _0
|
||||
sta SCREEN
|
||||
@ -204,11 +206,11 @@ plus: {
|
||||
.label a = 3
|
||||
.label b = 4
|
||||
.label return = 5
|
||||
// [8] (byte) plus::a#0 ← paramstack(plus::OFFSET_STACK_A) -- vbuz1=_stackbyte_vbuc1
|
||||
// [8] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_A,x
|
||||
sta.z a
|
||||
// [9] (byte) plus::b#0 ← paramstack(plus::OFFSET_STACK_B) -- vbuz1=_stackbyte_vbuc1
|
||||
// [9] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuz1=_stackbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_B,x
|
||||
sta.z b
|
||||
@ -227,16 +229,16 @@ plus: {
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [5] (byte~) main::$0 ← call plus (byte) '0' (byte) 7 [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
|
||||
Statement [8] (byte) plus::a#0 ← paramstack(plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ main::$0 plus::a#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [8] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ main::$0 plus::a#0 ] ) always clobbers reg byte a reg byte x
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::$0 ]
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ main::$0 ]
|
||||
Statement [9] (byte) plus::b#0 ← paramstack(plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ main::$0 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [9] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ main::$0 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ plus::a#0 ]
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:3 [ plus::a#0 ]
|
||||
Statement [10] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ main::$0 plus::return#0 ] ) always clobbers reg byte a
|
||||
Statement [5] (byte~) main::$0 ← call plus (byte) '0' (byte) 7 [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a
|
||||
Statement [8] (byte) plus::a#0 ← paramstack(plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ main::$0 plus::a#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [9] (byte) plus::b#0 ← paramstack(plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ main::$0 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [8] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ main::$0 plus::a#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [9] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ main::$0 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [10] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ main::$0 plus::return#0 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ main::$0 ] : zp ZP_BYTE:2 , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ plus::a#0 ] : zp ZP_BYTE:3 , reg byte y ,
|
||||
@ -248,11 +250,11 @@ Uplift Scope [plus] 4: zp ZP_BYTE:4 [ plus::b#0 ] 2: zp ZP_BYTE:3 [ plus::a#0 ]
|
||||
Uplift Scope [main] 0.5: zp ZP_BYTE:2 [ main::$0 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [plus] best 73 combination reg byte a [ plus::b#0 ] zp ZP_BYTE:3 [ plus::a#0 ] reg byte a [ plus::return#0 ]
|
||||
Uplifting [main] best 70 combination reg byte y [ main::$0 ]
|
||||
Uplifting [] best 70 combination
|
||||
Uplifting [plus] best 81 combination reg byte a [ plus::b#0 ] zp ZP_BYTE:3 [ plus::a#0 ] reg byte a [ plus::return#0 ]
|
||||
Uplifting [main] best 78 combination reg byte y [ main::$0 ]
|
||||
Uplifting [] best 78 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:3 [ plus::a#0 ]
|
||||
Uplifting [plus] best 70 combination zp ZP_BYTE:3 [ plus::a#0 ]
|
||||
Uplifting [plus] best 78 combination zp ZP_BYTE:3 [ plus::a#0 ]
|
||||
Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ plus::a#0 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
@ -289,6 +291,8 @@ main: {
|
||||
lda #7
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
pla
|
||||
// [6] *((const byte*) SCREEN#0) ← (byte~) main::$0 -- _deref_pbuc1=vbuyy
|
||||
sty SCREEN
|
||||
jmp breturn
|
||||
@ -303,11 +307,11 @@ plus: {
|
||||
.const OFFSET_STACK_A = 0
|
||||
.const OFFSET_STACK_B = 1
|
||||
.label a = 2
|
||||
// [8] (byte) plus::a#0 ← paramstack(plus::OFFSET_STACK_A) -- vbuz1=_stackbyte_vbuc1
|
||||
// [8] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_A,x
|
||||
sta.z a
|
||||
// [9] (byte) plus::b#0 ← paramstack(plus::OFFSET_STACK_B) -- vbuaa=_stackbyte_vbuc1
|
||||
// [9] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuaa=_stackbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_B,x
|
||||
// [10] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa
|
||||
@ -370,7 +374,7 @@ reg byte a [ plus::return#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 52
|
||||
Score: 60
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention stack
|
||||
@ -397,6 +401,8 @@ main: {
|
||||
lda #7
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
pla
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
// [6] *((const byte*) SCREEN#0) ← (byte~) main::$0 -- _deref_pbuc1=vbuyy
|
||||
sty SCREEN
|
||||
@ -411,11 +417,11 @@ plus: {
|
||||
.const OFFSET_STACK_A = 0
|
||||
.const OFFSET_STACK_B = 1
|
||||
.label a = 2
|
||||
// [8] (byte) plus::a#0 ← paramstack(plus::OFFSET_STACK_A) -- vbuz1=_stackbyte_vbuc1
|
||||
// [8] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_A,x
|
||||
sta.z a
|
||||
// [9] (byte) plus::b#0 ← paramstack(plus::OFFSET_STACK_B) -- vbuaa=_stackbyte_vbuc1
|
||||
// [9] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuaa=_stackbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_B,x
|
||||
// return a+b;
|
||||
|
Loading…
Reference in New Issue
Block a user