1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-20 02:32:36 +00:00

Fixed issue with const/label.

This commit is contained in:
jespergravgaard 2019-05-31 01:56:59 +02:00
parent ecf4181ce1
commit 29aa5322b2
7 changed files with 1339 additions and 28 deletions

View File

@ -51,7 +51,7 @@ public class Pass4CodeGeneration {
generateComments(asm, program.getFileComments());
Number programPc;
if(program.getProgramPc()!=null) {
if(program.getProgramPc() != null) {
programPc = program.getProgramPc();
} else {
programPc = 0x080d;
@ -306,40 +306,38 @@ public class Pass4CodeGeneration {
Collection<Integer> constRefStatements = program.getVariableReferenceInfos().getConstRefStatements(constantVar.getRef());
if(constRefStatements != null) {
for(Integer constRefStmtIdx : constRefStatements) {
Statement statement = program.getStatementInfos().getStatement(constRefStmtIdx);
ScopeRef refScope = program.getStatementInfos().getBlock(constRefStmtIdx).getScope();
if(!refScope.equals(scopeRef)) {
Statement statement = program.getStatementInfos().getStatement(constRefStmtIdx);
if(statement instanceof StatementPhiBlock) {
// Const reference in PHI block - examine if the only predecessor is current scope
boolean found = false;
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
RValue phiRRValue = phiRValue.getrValue();
Collection<ConstantRef> phiRValueConstRefs = PassNVariableReferenceInfos.getReferencedConsts(phiRRValue);
for(ConstantRef phiRValueConstRef : phiRValueConstRefs) {
if(phiRValueConstRef.equals(constantVar.getRef())) {
found = true;
// Found the constant
LabelRef pred = phiRValue.getPredecessor();
ControlFlowBlock predBlock = program.getGraph().getBlock(pred);
ScopeRef predScope = predBlock.getScope();
if(!predScope.equals(scopeRef)) {
// Scopes in PHI RValue differs from const scope - generate label
useLabel = true;
}
if(statement instanceof StatementPhiBlock) {
// Const reference in PHI block - examine if the only predecessor is current scope
boolean found = false;
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
RValue phiRRValue = phiRValue.getrValue();
Collection<ConstantRef> phiRValueConstRefs = PassNVariableReferenceInfos.getReferencedConsts(phiRRValue);
for(ConstantRef phiRValueConstRef : phiRValueConstRefs) {
if(phiRValueConstRef.equals(constantVar.getRef())) {
found = true;
// Found the constant
LabelRef pred = phiRValue.getPredecessor();
ControlFlowBlock predBlock = program.getGraph().getBlock(pred);
ScopeRef predScope = predBlock.getScope();
if(!predScope.equals(scopeRef)) {
// Scopes in PHI RValue differs from const scope - generate label
useLabel = true;
}
}
}
}
if(!found) {
// PHI-reference is complex - generate label
program.getLog().append("Warning: Complex PHI-value using constant. Using .label as fallback. " + statement);
useLabel = true;
}
} else {
// Used in a non-PHI statement in another scope - generate label
}
if(!found) {
// PHI-reference is complex - generate label
program.getLog().append("Warning: Complex PHI-value using constant. Using .label as fallback. " + statement);
useLabel = true;
}
} else if(!refScope.equals(scopeRef)) {
// Used in a non-PHI statement in another scope - generate label
useLabel = true;
}
}
}

View File

@ -32,6 +32,11 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testRobozzleLabelProblem() throws IOException, URISyntaxException {
compileAndCompare("robozzle64-label-problem", log());
}
@Test
public void testGlobalPc() throws IOException, URISyntaxException {
compileAndCompare("global-pc");

View File

@ -0,0 +1,11 @@
import "multiply.kc"
void main() {
word* screen = 0x0400;
for( byte y: 0..5) {
word z1 = mul8u(y,40);
*screen++ = z1;
word z2 = mul8u(y,40);
*screen++ = z2;
}
}

View File

@ -0,0 +1,87 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const SIZEOF_WORD = 2
main: {
.label z1 = 5
.label screen = 3
.label z2 = 5
.label y = 2
lda #<$400
sta screen
lda #>$400
sta screen+1
lda #0
sta y
b1:
ldx y
lda #mul8u.b
sta mul8u.mb
lda #0
sta mul8u.mb+1
jsr mul8u
ldy #0
lda z1
sta (screen),y
iny
lda z1+1
sta (screen),y
ldx y
lda #mul8u.b
sta mul8u.mb
lda #0
sta mul8u.mb+1
jsr mul8u
ldy #SIZEOF_WORD
lda z2
sta (screen),y
iny
lda z2+1
sta (screen),y
lda #SIZEOF_WORD+SIZEOF_WORD
clc
adc screen
sta screen
bcc !+
inc screen+1
!:
inc y
lda #6
cmp y
bne b1
rts
}
// Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word
// mul8u(byte register(X) a)
mul8u: {
.label b = $28
.label mb = 7
.label res = 5
.label return = 5
lda #0
sta res
sta res+1
b1:
cpx #0
bne b2
rts
b2:
txa
and #1
cmp #0
beq b3
lda res
clc
adc mb
sta res
lda res+1
adc mb+1
sta res+1
b3:
txa
lsr
tax
asl mb
rol mb+1
jmp b1
}

View File

@ -0,0 +1,61 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@3
[5] (word*) main::screen#1 ← phi( main/(word*) 1024 main::@3/(word*) main::screen#2 )
[5] (byte) main::y#2 ← phi( main/(byte) 0 main::@3/(byte) main::y#1 )
[6] (byte) mul8u::a#1 ← (byte) main::y#2
[7] call mul8u
[8] (word) mul8u::return#2 ← (word) mul8u::res#2
to:main::@2
main::@2: scope:[main] from main::@1
[9] (word) main::z1#0 ← (word) mul8u::return#2
[10] *((word*) main::screen#1) ← (word) main::z1#0
[11] (byte) mul8u::a#2 ← (byte) main::y#2
[12] call mul8u
[13] (word) mul8u::return#3 ← (word) mul8u::res#2
to:main::@3
main::@3: scope:[main] from main::@2
[14] (word) main::z2#0 ← (word) mul8u::return#3
[15] *((word*) main::screen#1 + (const byte) SIZEOF_WORD) ← (word) main::z2#0
[16] (word*) main::screen#2 ← (word*) main::screen#1 + (const byte) SIZEOF_WORD+(const byte) SIZEOF_WORD
[17] (byte) main::y#1 ← ++ (byte) main::y#2
[18] if((byte) main::y#1!=(byte) 6) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
[19] return
to:@return
mul8u: scope:[mul8u] from main::@1 main::@2
[20] (byte) mul8u::a#6 ← phi( main::@1/(byte) mul8u::a#1 main::@2/(byte) mul8u::a#2 )
[20] (word) mul8u::mb#0 ← phi( main::@1/(const byte) mul8u::b#0 main::@2/(const byte) mul8u::b#1 )
to:mul8u::@1
mul8u::@1: scope:[mul8u] from mul8u mul8u::@3
[21] (word) mul8u::mb#2 ← phi( mul8u/(word) mul8u::mb#0 mul8u::@3/(word) mul8u::mb#1 )
[21] (word) mul8u::res#2 ← phi( mul8u/(byte) 0 mul8u::@3/(word) mul8u::res#6 )
[21] (byte) mul8u::a#3 ← phi( mul8u/(byte) mul8u::a#6 mul8u::@3/(byte) mul8u::a#0 )
[22] if((byte) mul8u::a#3!=(byte) 0) goto mul8u::@2
to:mul8u::@return
mul8u::@return: scope:[mul8u] from mul8u::@1
[23] return
to:@return
mul8u::@2: scope:[mul8u] from mul8u::@1
[24] (byte~) mul8u::$1 ← (byte) mul8u::a#3 & (byte) 1
[25] if((byte~) mul8u::$1==(byte) 0) goto mul8u::@3
to:mul8u::@4
mul8u::@4: scope:[mul8u] from mul8u::@2
[26] (word) mul8u::res#1 ← (word) mul8u::res#2 + (word) mul8u::mb#2
to:mul8u::@3
mul8u::@3: scope:[mul8u] from mul8u::@2 mul8u::@4
[27] (word) mul8u::res#6 ← phi( mul8u::@2/(word) mul8u::res#2 mul8u::@4/(word) mul8u::res#1 )
[28] (byte) mul8u::a#0 ← (byte) mul8u::a#3 >> (byte) 1
[29] (word) mul8u::mb#1 ← (word) mul8u::mb#2 << (byte) 1
to:mul8u::@1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
program