1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +00:00

Added support for multi-level function inlining containing value-lists.

This commit is contained in:
jespergravgaard 2018-05-01 22:37:28 +02:00
parent de8654322f
commit e589373374
10 changed files with 1887 additions and 18 deletions

View File

@ -21,14 +21,12 @@ public class StatementCall extends StatementBase implements StatementLValue {
private String procedureName;
private ProcedureRef procedure;
private List<RValue> parameters;
private boolean parametersByAssignment;
public StatementCall(LValue lValue, String procedureName, List<RValue> parameters) {
super(null);
this.lValue = lValue;
this.procedureName = procedureName;
this.parameters = parameters;
this.parametersByAssignment = false;
}
public LValue getlValue() {
@ -67,17 +65,8 @@ public class StatementCall extends StatementBase implements StatementLValue {
return parameters.get(idx);
}
public boolean isParametersByAssignment() {
return parametersByAssignment;
}
public void setParametersByAssignment(boolean parametersByAssignment) {
this.parametersByAssignment = parametersByAssignment;
}
public void clearParameters() {
this.parameters = null;
this.parametersByAssignment = true;
}
@Override
@ -99,9 +88,6 @@ public class StatementCall extends StatementBase implements StatementLValue {
res.append(parameter.toString(program) + " ");
}
}
if(parametersByAssignment) {
res.append("param-assignment");
}
if(aliveInfo) {
res.append(super.aliveString(program));
}
@ -116,7 +102,6 @@ public class StatementCall extends StatementBase implements StatementLValue {
StatementCall that = (StatementCall) o;
if(parametersByAssignment != that.parametersByAssignment) return false;
if(lValue != null ? !lValue.equals(that.lValue) : that.lValue != null) return false;
if(!procedureName.equals(that.procedureName)) return false;
if(procedure != null ? !procedure.equals(that.procedure) : that.procedure != null) return false;
@ -130,7 +115,6 @@ public class StatementCall extends StatementBase implements StatementLValue {
result = 31 * result + procedureName.hashCode();
result = 31 * result + (procedure != null ? procedure.hashCode() : 0);
result = 31 * result + (parameters != null ? parameters.hashCode() : 0);
result = 31 * result + (parametersByAssignment ? 1 : 0);
return result;
}
}

View File

@ -52,7 +52,6 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
procReturnVarRef = procReturnVar.getRef();
}
StatementCall copyCall = new StatementCall(procReturnVarRef, procedureName, null);
copyCall.setParametersByAssignment(true);
copyCall.setProcedure(procedureRef);
addStatementToCurrentBlock(copyCall);
getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef());

View File

@ -33,7 +33,6 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
Procedure procedure = program.getScope().getProcedure(procedureRef);
String procedureName = origCall.getProcedureName();
StatementCall copyCall = new StatementCall(null, procedureName, null);
copyCall.setParametersByAssignment(true);
copyCall.setProcedure(procedureRef);
addStatementToCurrentBlock(copyCall);
getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef());

View File

@ -8,6 +8,7 @@ import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.*;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
@ -165,6 +166,11 @@ public class Pass1ProcedureInline extends Pass1Base {
if(procStatement instanceof StatementAssignment) {
StatementAssignment procAssignment = (StatementAssignment) procStatement;
inlinedStatement = new StatementAssignment(procAssignment.getlValue(), procAssignment.getrValue1(), procAssignment.getOperator(), procAssignment.getrValue2());
} else if(procStatement instanceof StatementCall) {
StatementCall procCall = (StatementCall) procStatement;
StatementCall inlinedCall = new StatementCall(procCall.getlValue(), procCall.getProcedureName(), new ArrayList<>(procCall.getParameters()));
inlinedCall.setProcedure(procCall.getProcedure());
inlinedStatement = inlinedCall;
} else if(procStatement instanceof StatementConditionalJump) {
StatementConditionalJump procConditional = (StatementConditionalJump) procStatement;
LabelRef procDestinationRef = procConditional.getDestination();
@ -223,6 +229,8 @@ public class Pass1ProcedureInline extends Pass1Base {
replaceable.set(new PointerDereferenceIndexed(((PointerDereferenceIndexed) rValue).getPointer(), ((PointerDereferenceIndexed) rValue).getIndex()));
} else if(rValue instanceof CastValue) {
replaceable.set(new CastValue(((CastValue) rValue).getToType(), ((CastValue) rValue).getValue()));
} else if(rValue instanceof ValueList) {
replaceable.set(new ValueList(new ArrayList<>(((ValueList) rValue).getList())));
}
}
}

View File

@ -44,6 +44,11 @@ public class TestPrograms {
AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false);
}
@Test
public void testInlineFunctionLevel2() throws IOException, URISyntaxException {
compileAndCompare("inline-function-level2");
}
@Test
public void testInlineFunctionPrint() throws IOException, URISyntaxException {
compileAndCompare("inline-function-print");

View File

@ -0,0 +1,26 @@
// Inline functions in two levels
void main() {
for(byte* sc = $400;sc<$400+1000;sc++) *sc = ' ';
line(2, $40, 10, '*');
line(4, $80, 15, '.');
}
byte* cur_line = $400;
inline void line(byte xpos, byte xadd, byte ysize, byte ch) {
cur_line = $400;
word pos = {xpos, 0};
for( byte i=0;i<ysize; i++) {
plot(>pos, ch);
pos += xadd;
cur_line += 40;
}
}
inline void plot(byte xpos, byte ch) {
*(cur_line+xpos) = ch;
}

View File

@ -0,0 +1,115 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label cur_line = 4
jsr main
main: {
.const line1_xpos = 2
.const line1_xadd = $40
.const line1_ysize = $a
.const line1_ch = '*'
.const line2_xpos = 4
.const line2_xadd = $80
.const line2_ysize = $f
.const line2_ch = '.'
.label sc = 2
.label plot1__0 = 6
.label line1_pos = 2
.label plot2__0 = 6
.label line2_pos = 2
lda #<$400
sta sc
lda #>$400
sta sc+1
b1:
lda #' '
ldy #0
sta (sc),y
inc sc
bne !+
inc sc+1
!:
lda sc+1
cmp #>$400+$3e8
bcc b1
bne !+
lda sc
cmp #<$400+$3e8
bcc b1
!:
ldx #0
lda #<$400
sta cur_line
lda #>$400
sta cur_line+1
lda #<line1_xpos*$100+0
sta line1_pos
lda #>line1_xpos*$100+0
sta line1_pos+1
b2:
lda line1_pos+1
clc
adc cur_line
sta plot1__0
lda #0
adc cur_line+1
sta plot1__0+1
lda #line1_ch
ldy #0
sta (plot1__0),y
clc
lda line1_pos
adc #<line1_xadd
sta line1_pos
lda line1_pos+1
adc #>line1_xadd
sta line1_pos+1
lda cur_line
clc
adc #$28
sta cur_line
bcc !+
inc cur_line+1
!:
inx
cpx #line1_ysize
bcc b2
ldx #0
lda #<$400
sta cur_line
lda #>$400
sta cur_line+1
lda #<line2_xpos*$100+0
sta line2_pos
lda #>line2_xpos*$100+0
sta line2_pos+1
b3:
lda line2_pos+1
clc
adc cur_line
sta plot2__0
lda #0
adc cur_line+1
sta plot2__0+1
lda #line2_ch
ldy #0
sta (plot2__0),y
clc
lda line2_pos
adc #<line2_xadd
sta line2_pos
lda line2_pos+1
adc #>line2_xadd
sta line2_pos+1
lda cur_line
clc
adc #$28
sta cur_line
bcc !+
inc cur_line+1
!:
inx
cpx #line2_ysize
bcc b3
rts
}

View File

@ -0,0 +1,59 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@3
@3: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @3
[3] phi() [ ] ( )
main: scope:[main] from @3
[4] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main main::@1
[5] (byte*) main::sc#2 ← phi( main/((byte*))(word/signed word/dword/signed dword) 1024 main::@1/(byte*) main::sc#1 ) [ main::sc#2 ] ( main:2 [ main::sc#2 ] )
[6] *((byte*) main::sc#2) ← (byte) ' ' [ main::sc#2 ] ( main:2 [ main::sc#2 ] )
[7] (byte*) main::sc#1 ← ++ (byte*) main::sc#2 [ main::sc#1 ] ( main:2 [ main::sc#1 ] )
[8] if((byte*) main::sc#1<(word/signed word/dword/signed dword) 1024+(word/signed word/dword/signed dword) 1000) goto main::@1 [ main::sc#1 ] ( main:2 [ main::sc#1 ] )
to:main::line1
main::line1: scope:[main] from main::@1
[9] phi() [ ] ( main:2 [ ] )
to:main::line1_@1
main::line1_@1: scope:[main] from main::@4 main::line1 main::line1_@1
[10] (byte) main::line1_i#2 ← phi( main::@4/(byte) main::line1_i#1 main::line1/(byte/signed byte/word/signed word/dword/signed dword) 0 ) [ main::line1_pos#2 cur_line#13 main::line1_i#2 ] ( main:2 [ main::line1_pos#2 cur_line#13 main::line1_i#2 ] )
[10] (byte*) cur_line#13 ← phi( main::@4/(byte*) cur_line#1 main::line1/((byte*))(word/signed word/dword/signed dword) 1024 ) [ main::line1_pos#2 cur_line#13 main::line1_i#2 ] ( main:2 [ main::line1_pos#2 cur_line#13 main::line1_i#2 ] )
[10] (word) main::line1_pos#2 ← phi( main::@4/(word) main::line1_pos#1 main::line1/(const byte) main::line1_xpos#0*(word/signed word/dword/signed dword) 256+(byte/signed byte/word/signed word/dword/signed dword) 0 ) [ main::line1_pos#2 cur_line#13 main::line1_i#2 ] ( main:2 [ main::line1_pos#2 cur_line#13 main::line1_i#2 ] )
[11] (byte) main::plot1_xpos#0 ← > (word) main::line1_pos#2 [ main::line1_pos#2 cur_line#13 main::line1_i#2 main::plot1_xpos#0 ] ( main:2 [ main::line1_pos#2 cur_line#13 main::line1_i#2 main::plot1_xpos#0 ] )
to:main::plot1
main::plot1: scope:[main] from main::line1_@1
[12] (byte*) main::plot1_$0#0 ← (byte*) cur_line#13 + (byte) main::plot1_xpos#0 [ main::line1_pos#2 cur_line#13 main::line1_i#2 main::plot1_$0#0 ] ( main:2 [ main::line1_pos#2 cur_line#13 main::line1_i#2 main::plot1_$0#0 ] )
[13] *((byte*) main::plot1_$0#0) ← (const byte) main::line1_ch#0 [ main::line1_pos#2 cur_line#13 main::line1_i#2 ] ( main:2 [ main::line1_pos#2 cur_line#13 main::line1_i#2 ] )
to:main::@4
main::@4: scope:[main] from main::plot1
[14] (word) main::line1_pos#1 ← (word) main::line1_pos#2 + (const byte) main::line1_xadd#0 [ cur_line#13 main::line1_i#2 main::line1_pos#1 ] ( main:2 [ cur_line#13 main::line1_i#2 main::line1_pos#1 ] )
[15] (byte*) cur_line#1 ← (byte*) cur_line#13 + (byte/signed byte/word/signed word/dword/signed dword) 40 [ main::line1_i#2 main::line1_pos#1 cur_line#1 ] ( main:2 [ main::line1_i#2 main::line1_pos#1 cur_line#1 ] )
[16] (byte) main::line1_i#1 ← ++ (byte) main::line1_i#2 [ main::line1_pos#1 cur_line#1 main::line1_i#1 ] ( main:2 [ main::line1_pos#1 cur_line#1 main::line1_i#1 ] )
[17] if((byte) main::line1_i#1<(const byte) main::line1_ysize#0) goto main::line1_@1 [ main::line1_pos#1 cur_line#1 main::line1_i#1 ] ( main:2 [ main::line1_pos#1 cur_line#1 main::line1_i#1 ] )
to:main::line2
main::line2: scope:[main] from main::@4
[18] phi() [ ] ( main:2 [ ] )
to:main::line2_@1
main::line2_@1: scope:[main] from main::@6 main::line2 main::line2_@1
[19] (byte) main::line2_i#2 ← phi( main::@6/(byte) main::line2_i#1 main::line2/(byte/signed byte/word/signed word/dword/signed dword) 0 ) [ main::line2_pos#2 cur_line#10 main::line2_i#2 ] ( main:2 [ main::line2_pos#2 cur_line#10 main::line2_i#2 ] )
[19] (byte*) cur_line#10 ← phi( main::@6/(byte*) cur_line#11 main::line2/((byte*))(word/signed word/dword/signed dword) 1024 ) [ main::line2_pos#2 cur_line#10 main::line2_i#2 ] ( main:2 [ main::line2_pos#2 cur_line#10 main::line2_i#2 ] )
[19] (word) main::line2_pos#2 ← phi( main::@6/(word) main::line2_pos#1 main::line2/(const byte) main::line2_xpos#0*(word/signed word/dword/signed dword) 256+(byte/signed byte/word/signed word/dword/signed dword) 0 ) [ main::line2_pos#2 cur_line#10 main::line2_i#2 ] ( main:2 [ main::line2_pos#2 cur_line#10 main::line2_i#2 ] )
[20] (byte) main::plot2_xpos#0 ← > (word) main::line2_pos#2 [ main::line2_pos#2 cur_line#10 main::line2_i#2 main::plot2_xpos#0 ] ( main:2 [ main::line2_pos#2 cur_line#10 main::line2_i#2 main::plot2_xpos#0 ] )
to:main::plot2
main::plot2: scope:[main] from main::line2_@1
[21] (byte*) main::plot2_$0#0 ← (byte*) cur_line#10 + (byte) main::plot2_xpos#0 [ main::line2_pos#2 cur_line#10 main::line2_i#2 main::plot2_$0#0 ] ( main:2 [ main::line2_pos#2 cur_line#10 main::line2_i#2 main::plot2_$0#0 ] )
[22] *((byte*) main::plot2_$0#0) ← (const byte) main::line2_ch#0 [ main::line2_pos#2 cur_line#10 main::line2_i#2 ] ( main:2 [ main::line2_pos#2 cur_line#10 main::line2_i#2 ] )
to:main::@6
main::@6: scope:[main] from main::plot2
[23] (word) main::line2_pos#1 ← (word) main::line2_pos#2 + (const byte) main::line2_xadd#0 [ cur_line#10 main::line2_i#2 main::line2_pos#1 ] ( main:2 [ cur_line#10 main::line2_i#2 main::line2_pos#1 ] )
[24] (byte*) cur_line#11 ← (byte*) cur_line#10 + (byte/signed byte/word/signed word/dword/signed dword) 40 [ main::line2_i#2 main::line2_pos#1 cur_line#11 ] ( main:2 [ main::line2_i#2 main::line2_pos#1 cur_line#11 ] )
[25] (byte) main::line2_i#1 ← ++ (byte) main::line2_i#2 [ main::line2_pos#1 cur_line#11 main::line2_i#1 ] ( main:2 [ main::line2_pos#1 cur_line#11 main::line2_i#1 ] )
[26] if((byte) main::line2_i#1<(const byte) main::line2_ysize#0) goto main::line2_@1 [ main::line2_pos#1 cur_line#11 main::line2_i#1 ] ( main:2 [ main::line2_pos#1 cur_line#11 main::line2_i#1 ] )
to:main::@return
main::@return: scope:[main] from main::@6
[27] return [ ] ( main:2 [ ] )
to:@return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,72 @@
(label) @3
(label) @begin
(label) @end
(byte*) cur_line
(byte*) cur_line#1 cur_line zp ZP_WORD:4 7.333333333333333
(byte*) cur_line#10 cur_line zp ZP_WORD:4 6.6000000000000005
(byte*) cur_line#11 cur_line zp ZP_WORD:4 7.333333333333333
(byte*) cur_line#13 cur_line zp ZP_WORD:4 6.6000000000000005
(void()) main()
(label) main::@1
(label) main::@4
(label) main::@6
(label) main::@return
(label) main::line1
(byte~) main::line1_$0
(bool~) main::line1_$2
(label) main::line1_@1
(byte) main::line1_ch
(const byte) main::line1_ch#0 line1_ch = (byte) '*'
(byte) main::line1_i
(byte) main::line1_i#1 reg byte x 16.5
(byte) main::line1_i#2 reg byte x 3.6666666666666665
(word) main::line1_pos
(word) main::line1_pos#1 line1_pos zp ZP_WORD:2 5.5
(word) main::line1_pos#2 line1_pos zp ZP_WORD:2 30.75
(byte) main::line1_xadd
(const byte) main::line1_xadd#0 line1_xadd = (byte/signed byte/word/signed word/dword/signed dword) 64
(byte) main::line1_xpos
(const byte) main::line1_xpos#0 line1_xpos = (byte/signed byte/word/signed word/dword/signed dword) 2
(byte) main::line1_ysize
(const byte) main::line1_ysize#0 line1_ysize = (byte/signed byte/word/signed word/dword/signed dword) 10
(label) main::line2
(byte~) main::line2_$0
(bool~) main::line2_$2
(label) main::line2_@1
(byte) main::line2_ch
(const byte) main::line2_ch#0 line2_ch = (byte) '.'
(byte) main::line2_i
(byte) main::line2_i#1 reg byte x 16.5
(byte) main::line2_i#2 reg byte x 3.6666666666666665
(word) main::line2_pos
(word) main::line2_pos#1 line2_pos zp ZP_WORD:2 5.5
(word) main::line2_pos#2 line2_pos zp ZP_WORD:2 30.75
(byte) main::line2_xadd
(const byte) main::line2_xadd#0 line2_xadd = (byte/word/signed word/dword/signed dword) 128
(byte) main::line2_xpos
(const byte) main::line2_xpos#0 line2_xpos = (byte/signed byte/word/signed word/dword/signed dword) 4
(byte) main::line2_ysize
(const byte) main::line2_ysize#0 line2_ysize = (byte/signed byte/word/signed word/dword/signed dword) 15
(label) main::plot1
(byte*~) main::plot1_$0
(byte*) main::plot1_$0#0 plot1_$0 zp ZP_WORD:6 22.0
(byte) main::plot1_ch
(byte) main::plot1_xpos
(byte) main::plot1_xpos#0 reg byte a 112.0
(label) main::plot2
(byte*~) main::plot2_$0
(byte*) main::plot2_$0#0 plot2_$0 zp ZP_WORD:6 22.0
(byte) main::plot2_ch
(byte) main::plot2_xpos
(byte) main::plot2_xpos#0 reg byte a 112.0
(byte*) main::sc
(byte*) main::sc#1 sc zp ZP_WORD:2 16.5
(byte*) main::sc#2 sc zp ZP_WORD:2 16.5
zp ZP_WORD:2 [ main::sc#2 main::sc#1 main::line1_pos#2 main::line1_pos#1 main::line2_pos#2 main::line2_pos#1 ]
zp ZP_WORD:4 [ cur_line#13 cur_line#1 cur_line#10 cur_line#11 ]
reg byte x [ main::line1_i#2 main::line1_i#1 ]
reg byte x [ main::line2_i#2 main::line2_i#1 ]
reg byte a [ main::plot1_xpos#0 ]
zp ZP_WORD:6 [ main::plot1_$0#0 main::plot2_$0#0 ]
reg byte a [ main::plot2_xpos#0 ]