mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-23 23:32:55 +00:00
Fixed problems casting strings to void*. Closes #281
This commit is contained in:
parent
bfe90bdf04
commit
c75e788fd1
@ -1,12 +1,14 @@
|
||||
package dk.camelot64.kickc.model.operators;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||
import dk.camelot64.kickc.model.values.ConstantString;
|
||||
|
||||
/** Unary Cast to a pointer ( type* ) */
|
||||
public class OperatorCastPtr extends OperatorCast {
|
||||
@ -24,8 +26,10 @@ public class OperatorCastPtr extends OperatorCast {
|
||||
return new ConstantPointer(((ConstantInteger) value).getInteger(), pointerType.getElementType());
|
||||
} else if(value instanceof ConstantPointer) {
|
||||
return new ConstantPointer(((ConstantPointer) value).getLocation(), pointerType.getElementType());
|
||||
} else if(value instanceof ConstantString){
|
||||
throw new ConstantNotLiteral("Constant string not literal");
|
||||
}
|
||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + value);
|
||||
throw new InternalError("Calculation not implemented " + getOperator() + " " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,6 +58,16 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
|
||||
getLog().append("Adding pointer type conversion cast to void pointer (" + leftType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
|
||||
binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
|
||||
modified.set(true);
|
||||
} else if((leftType instanceof SymbolTypePointer) && SymbolType.STRING.equals(rightType) && SymbolType.VOID.equals(((SymbolTypePointer) leftType).getElementType())) {
|
||||
if(pass2 || getLog().isVerbosePass1CreateSsa())
|
||||
getLog().append("Adding void pointer type conversion cast (" + leftType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
|
||||
binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
|
||||
modified.set(true);
|
||||
} else if(leftType.equals(SymbolType.STRING) && rightType instanceof SymbolTypePointer && SymbolType.VOID.equals(((SymbolTypePointer) rightType).getElementType())) {
|
||||
if(pass2 || getLog().isVerbosePass1CreateSsa())
|
||||
getLog().append("Adding pointer type conversion cast to void pointer (" + leftType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
|
||||
binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
|
||||
modified.set(true);
|
||||
} else if(SymbolType.WORD.equals(leftType) && isLiteralWordCandidate(right)) {
|
||||
// Detect word literal constructor
|
||||
SymbolType conversionType = SymbolType.WORD;
|
||||
|
@ -377,13 +377,10 @@ public class TestPrograms {
|
||||
compileAndCompare("font-hex-show");
|
||||
}
|
||||
|
||||
// TODO: Fix string not converted to void* properly https://gitlab.com/camelot/kickc/issues/281
|
||||
/*
|
||||
@Test
|
||||
public void testMemcpy1() throws IOException, URISyntaxException {
|
||||
compileAndCompare("memcpy-1", log());
|
||||
compileAndCompare("memcpy-1");
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testMemcpy0() throws IOException, URISyntaxException {
|
||||
|
@ -18,7 +18,6 @@ void main() {
|
||||
*sc2++ = *reigns++;
|
||||
}
|
||||
|
||||
// Not working
|
||||
memcpy(SCREEN+10, CAMELOT, 7);
|
||||
memcpy(SCREEN+50, "rules", 5);
|
||||
|
||||
|
131
src/test/ref/memcpy-1.asm
Normal file
131
src/test/ref/memcpy-1.asm
Normal file
@ -0,0 +1,131 @@
|
||||
// Test memcpy on strings (
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
.label sc = 6
|
||||
.label camelot = 4
|
||||
.label sc2 = 2
|
||||
.label reigns = 8
|
||||
ldx #0
|
||||
lda #<SCREEN
|
||||
sta.z sc
|
||||
lda #>SCREEN
|
||||
sta.z sc+1
|
||||
lda #<CAMELOT
|
||||
sta.z camelot
|
||||
lda #>CAMELOT
|
||||
sta.z camelot+1
|
||||
b1:
|
||||
ldy #0
|
||||
lda (camelot),y
|
||||
sta (sc),y
|
||||
inc.z sc
|
||||
bne !+
|
||||
inc.z sc+1
|
||||
!:
|
||||
inc.z camelot
|
||||
bne !+
|
||||
inc.z camelot+1
|
||||
!:
|
||||
inx
|
||||
cpx #7
|
||||
bne b1
|
||||
ldx #0
|
||||
lda #<SCREEN+$28
|
||||
sta.z sc2
|
||||
lda #>SCREEN+$28
|
||||
sta.z sc2+1
|
||||
lda #<reigns_0
|
||||
sta.z reigns
|
||||
lda #>reigns_0
|
||||
sta.z reigns+1
|
||||
b2:
|
||||
ldy #0
|
||||
lda (reigns),y
|
||||
sta (sc2),y
|
||||
inc.z sc2
|
||||
bne !+
|
||||
inc.z sc2+1
|
||||
!:
|
||||
inc.z reigns
|
||||
bne !+
|
||||
inc.z reigns+1
|
||||
!:
|
||||
inx
|
||||
cpx #6
|
||||
bne b2
|
||||
lda #<7
|
||||
sta.z memcpy.num
|
||||
lda #>7
|
||||
sta.z memcpy.num+1
|
||||
lda #<SCREEN+$a
|
||||
sta.z memcpy.destination
|
||||
lda #>SCREEN+$a
|
||||
sta.z memcpy.destination+1
|
||||
lda #<CAMELOT
|
||||
sta.z memcpy.source
|
||||
lda #>CAMELOT
|
||||
sta.z memcpy.source+1
|
||||
jsr memcpy
|
||||
lda #<5
|
||||
sta.z memcpy.num
|
||||
lda #>5
|
||||
sta.z memcpy.num+1
|
||||
lda #<SCREEN+$32
|
||||
sta.z memcpy.destination
|
||||
lda #>SCREEN+$32
|
||||
sta.z memcpy.destination+1
|
||||
lda #<_8
|
||||
sta.z memcpy.source
|
||||
lda #>_8
|
||||
sta.z memcpy.source+1
|
||||
jsr memcpy
|
||||
rts
|
||||
_8: .text "rules"
|
||||
.byte 0
|
||||
reigns_0: .text "reigns"
|
||||
.byte 0
|
||||
}
|
||||
// Copy block of memory (forwards)
|
||||
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
|
||||
// memcpy(void* zeropage(6) destination, void* zeropage(4) source, word zeropage(8) num)
|
||||
memcpy: {
|
||||
.label src_end = 8
|
||||
.label dst = 6
|
||||
.label src = 4
|
||||
.label source = 4
|
||||
.label destination = 6
|
||||
.label num = 8
|
||||
lda.z src_end
|
||||
clc
|
||||
adc.z source
|
||||
sta.z src_end
|
||||
lda.z src_end+1
|
||||
adc.z source+1
|
||||
sta.z src_end+1
|
||||
b1:
|
||||
lda.z src+1
|
||||
cmp.z src_end+1
|
||||
bne b2
|
||||
lda.z src
|
||||
cmp.z src_end
|
||||
bne b2
|
||||
rts
|
||||
b2:
|
||||
ldy #0
|
||||
lda (src),y
|
||||
sta (dst),y
|
||||
inc.z dst
|
||||
bne !+
|
||||
inc.z dst+1
|
||||
!:
|
||||
inc.z src
|
||||
bne !+
|
||||
inc.z src+1
|
||||
!:
|
||||
jmp b1
|
||||
}
|
||||
CAMELOT: .text "camelot"
|
||||
.byte 0
|
64
src/test/ref/memcpy-1.cfg
Normal file
64
src/test/ref/memcpy-1.cfg
Normal file
@ -0,0 +1,64 @@
|
||||
@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::@1
|
||||
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
|
||||
[5] (byte*) main::sc#2 ← phi( main/(const byte*) SCREEN#0 main::@1/(byte*) main::sc#1 )
|
||||
[5] (byte*) main::camelot#2 ← phi( main/(const byte[]) CAMELOT#0 main::@1/(byte*) main::camelot#1 )
|
||||
[6] *((byte*) main::sc#2) ← *((byte*) main::camelot#2)
|
||||
[7] (byte*) main::sc#1 ← ++ (byte*) main::sc#2
|
||||
[8] (byte*) main::camelot#1 ← ++ (byte*) main::camelot#2
|
||||
[9] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[10] if((byte) main::i#1!=(byte) 7) goto main::@1
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@2
|
||||
[11] (byte) main::i1#2 ← phi( main::@1/(byte) 0 main::@2/(byte) main::i1#1 )
|
||||
[11] (byte*) main::sc2#2 ← phi( main::@1/(const byte*) SCREEN#0+(byte) $28 main::@2/(byte*) main::sc2#1 )
|
||||
[11] (byte*) main::reigns#2 ← phi( main::@1/(const byte*) main::reigns#0 main::@2/(byte*) main::reigns#1 )
|
||||
[12] *((byte*) main::sc2#2) ← *((byte*) main::reigns#2)
|
||||
[13] (byte*) main::sc2#1 ← ++ (byte*) main::sc2#2
|
||||
[14] (byte*) main::reigns#1 ← ++ (byte*) main::reigns#2
|
||||
[15] (byte) main::i1#1 ← ++ (byte) main::i1#2
|
||||
[16] if((byte) main::i1#1!=(byte) 6) goto main::@2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[17] phi()
|
||||
[18] call memcpy
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@3
|
||||
[19] phi()
|
||||
[20] call memcpy
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@4
|
||||
[21] return
|
||||
to:@return
|
||||
memcpy: scope:[memcpy] from main::@3 main::@4
|
||||
[22] (word) memcpy::num#2 ← phi( main::@3/(byte) 7 main::@4/(byte) 5 )
|
||||
[22] (void*) memcpy::destination#2 ← phi( main::@3/(void*)(const byte*) SCREEN#0+(byte) $a main::@4/(void*)(const byte*) SCREEN#0+(byte) $32 )
|
||||
[22] (void*) memcpy::source#2 ← phi( main::@3/(void*)(const byte[]) CAMELOT#0 main::@4/(void*)(const string) main::$8 )
|
||||
[23] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2
|
||||
[24] (byte*~) memcpy::src#4 ← (byte*)(void*) memcpy::source#2
|
||||
[25] (byte*~) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2
|
||||
to:memcpy::@1
|
||||
memcpy::@1: scope:[memcpy] from memcpy memcpy::@2
|
||||
[26] (byte*) memcpy::dst#2 ← phi( memcpy/(byte*~) memcpy::dst#4 memcpy::@2/(byte*) memcpy::dst#1 )
|
||||
[26] (byte*) memcpy::src#2 ← phi( memcpy/(byte*~) memcpy::src#4 memcpy::@2/(byte*) memcpy::src#1 )
|
||||
[27] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2
|
||||
to:memcpy::@return
|
||||
memcpy::@return: scope:[memcpy] from memcpy::@1
|
||||
[28] return
|
||||
to:@return
|
||||
memcpy::@2: scope:[memcpy] from memcpy::@1
|
||||
[29] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2)
|
||||
[30] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2
|
||||
[31] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2
|
||||
to:memcpy::@1
|
1394
src/test/ref/memcpy-1.log
Normal file
1394
src/test/ref/memcpy-1.log
Normal file
File diff suppressed because it is too large
Load Diff
61
src/test/ref/memcpy-1.sym
Normal file
61
src/test/ref/memcpy-1.sym
Normal file
@ -0,0 +1,61 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) CAMELOT
|
||||
(const byte[]) CAMELOT#0 CAMELOT = (string) "camelot"
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(void()) main()
|
||||
(const string) main::$8 $8 = (string) "rules"
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@4
|
||||
(label) main::@return
|
||||
(byte*) main::camelot
|
||||
(byte*) main::camelot#1 camelot zp ZP_WORD:4 7.333333333333333
|
||||
(byte*) main::camelot#2 camelot zp ZP_WORD:4 11.0
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 16.5
|
||||
(byte) main::i#2 reg byte x 5.5
|
||||
(byte) main::i1
|
||||
(byte) main::i1#1 reg byte x 16.5
|
||||
(byte) main::i1#2 reg byte x 5.5
|
||||
(byte*) main::reigns
|
||||
(const byte*) main::reigns#0 reigns#0 = (string) "reigns"
|
||||
(byte*) main::reigns#1 reigns zp ZP_WORD:8 7.333333333333333
|
||||
(byte*) main::reigns#2 reigns zp ZP_WORD:8 11.0
|
||||
(byte*) main::sc
|
||||
(byte*) main::sc#1 sc zp ZP_WORD:6 5.5
|
||||
(byte*) main::sc#2 sc zp ZP_WORD:6 16.5
|
||||
(byte*) main::sc2
|
||||
(byte*) main::sc2#1 sc2 zp ZP_WORD:2 5.5
|
||||
(byte*) main::sc2#2 sc2 zp ZP_WORD:2 16.5
|
||||
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
|
||||
(label) memcpy::@1
|
||||
(label) memcpy::@2
|
||||
(label) memcpy::@return
|
||||
(void*) memcpy::destination
|
||||
(void*) memcpy::destination#2 destination zp ZP_WORD:6
|
||||
(byte*) memcpy::dst
|
||||
(byte*) memcpy::dst#1 dst zp ZP_WORD:6 11.0
|
||||
(byte*) memcpy::dst#2 dst zp ZP_WORD:6 11.666666666666666
|
||||
(byte*~) memcpy::dst#4 dst zp ZP_WORD:6 4.0
|
||||
(word) memcpy::num
|
||||
(word) memcpy::num#2 num zp ZP_WORD:8 2.0
|
||||
(void*) memcpy::return
|
||||
(void*) memcpy::source
|
||||
(void*) memcpy::source#2 source zp ZP_WORD:4
|
||||
(byte*) memcpy::src
|
||||
(byte*) memcpy::src#1 src zp ZP_WORD:4 22.0
|
||||
(byte*) memcpy::src#2 src zp ZP_WORD:4 11.5
|
||||
(byte*~) memcpy::src#4 src zp ZP_WORD:4 2.0
|
||||
(byte*) memcpy::src_end
|
||||
(byte*) memcpy::src_end#0 src_end zp ZP_WORD:8 1.625
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:2 [ main::sc2#2 main::sc2#1 ]
|
||||
reg byte x [ main::i1#2 main::i1#1 ]
|
||||
zp ZP_WORD:4 [ memcpy::source#2 memcpy::src#2 memcpy::src#4 memcpy::src#1 main::camelot#2 main::camelot#1 ]
|
||||
zp ZP_WORD:6 [ memcpy::destination#2 memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 main::sc#2 main::sc#1 ]
|
||||
zp ZP_WORD:8 [ memcpy::num#2 memcpy::src_end#0 main::reigns#2 main::reigns#1 ]
|
Loading…
Reference in New Issue
Block a user