1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-04-09 21:37:31 +00:00

Removed FilledArray. Fixed unary plus. Closes #339

This commit is contained in:
jespergravgaard 2019-11-19 08:28:54 +01:00
parent c60ab5fc7d
commit 397680ea9c
14 changed files with 417 additions and 78 deletions

View File

@ -202,6 +202,8 @@ public class AsmFormat {
} else {
throw new CompileError("Unhandled type " + operand);
}
} else if(Operators.POS.equals(operator)) {
return getAsmConstant(program, operand, outerPrecedence, codeScope);
} else {
return operator.getOperator() +
getAsmConstant(program, operand, operator.getPrecedence(), codeScope);

View File

@ -392,26 +392,6 @@ public interface ProgramValue {
}
/** Value inside a array filled expression. */
class ProgramValueArrayFilledSize implements ProgramValue {
private final ArrayFilled array;
ProgramValueArrayFilledSize(ArrayFilled array) {
this.array = array;
}
@Override
public Value get() {
return array.getSize();
}
@Override
public void set(Value val) {
array.setSize((RValue) val);
}
}
/** A variable/constant referenced inside inline ASM. */
class ProgramValueAsmReferenced implements ProgramValue {
private StatementAsm statementAsm;

View File

@ -233,8 +233,6 @@ public class ProgramValueIterator {
subValues.add(new ProgramValue.ProgramValueConstantBinaryRight((ConstantBinary) value));
} else if(value instanceof ConstantUnary) {
subValues.add(new ProgramValue.ProgramValueConstantUnaryValue((ConstantUnary) value));
} else if(value instanceof ArrayFilled) {
subValues.add(new ProgramValue.ProgramValueArrayFilledSize((ArrayFilled) value));
} else if(value instanceof ConstantArrayFilled) {
subValues.add(new ProgramValue.ProgramValueConstantArrayFilledSize((ConstantArrayFilled) value));
} else if(value instanceof ConstantArrayKickAsm) {

View File

@ -53,8 +53,6 @@ public class SymbolTypeInference {
return new SymbolTypePointer(((ConstantArrayList) rValue).getElementType());
} else if(rValue instanceof ConstantArrayKickAsm) {
return new SymbolTypePointer(((ConstantArrayKickAsm) rValue).getElementType());
} else if(rValue instanceof ArrayFilled) {
return new SymbolTypePointer(((ArrayFilled) rValue).getElementType());
} else if(rValue instanceof ConstantArrayFilled) {
return new SymbolTypePointer(((ConstantArrayFilled) rValue).getElementType());
} else if(rValue instanceof ConstantSymbolPointer) {

View File

@ -1,47 +0,0 @@
package dk.camelot64.kickc.model.values;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.types.SymbolType;
/**
* An zero-filled array. The size of the array is currently non-constant, but must be resolved to a constant before pass 3.
* The array is allocated in the code memory (as a .fill() ).
*/
public class ArrayFilled implements RValue {
private RValue size;
private SymbolType elementType;
public ArrayFilled(SymbolType elementType, RValue size) {
this.size = size;
this.elementType = elementType;
}
public SymbolType getElementType() {
return elementType;
}
public RValue getSize() {
return size;
}
public void setSize(RValue size) {
this.size = size;
}
@Override
public String toString() {
return toString(null);
}
@Override
public String toString(Program program) {
StringBuilder out = new StringBuilder();
out.append("{ fill( ");
out.append(size.toString());
out.append(", 0) }");
return out.toString();
}
}

View File

@ -1682,7 +1682,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return null;
}
/**
* RValues that have not yet been output as part of a statement.
* The expression visitor methods updates this so that the surrounding

View File

@ -224,11 +224,6 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
if(castConstant != null) {
return new ConstantCastValue(castValue.getToType(), castConstant);
}
} else if(rValue instanceof ArrayFilled) {
ArrayFilled arrayFilled = (ArrayFilled) rValue;
if(arrayFilled.getSize() instanceof ConstantValue) {
return new ConstantArrayFilled(arrayFilled.getElementType(), (ConstantValue) arrayFilled.getSize());
}
}
return null;
}

View File

@ -486,7 +486,7 @@ public class Pass4CodeGeneration {
asm.addDataAlignment(alignment);
}
ConstantValue constantValue = constantVar.getConstantValue();
if(constantValue instanceof ConstantArrayList || constantValue instanceof ConstantArrayFilled || constantValue instanceof ConstantArrayKickAsm || constantValue instanceof ConstantString) {
if(constantValue instanceof ConstantArray || constantValue instanceof ConstantString) {
AsmDataChunk asmDataChunk = new AsmDataChunk();
addChunkData(asmDataChunk, constantValue, constantVar.getType(), constantVar.isArray(), constantVar.getArraySize(), scopeRef);
asmDataChunk.addToAsm(AsmFormat.asmFix(asmName), asm);

View File

@ -37,6 +37,11 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testUnaryPlus() throws IOException, URISyntaxException {
compileAndCompare("unary-plus");
}
@Test
public void testConstDeclaration() throws IOException, URISyntaxException {
compileAndCompare("const-declaration");

17
src/test/kc/unary-plus.kc Normal file
View File

@ -0,0 +1,17 @@
// Test unary plus
void main() {
char* SCREEN = 0x0400;
int* SCREEN2 = 0x0428;
char i = +3;
SCREEN[0] = i;
SCREEN[1] = +3;
int j = +3;
SCREEN2[0] = j;
SCREEN2[1] = +3;
}

View File

@ -0,0 +1,24 @@
// Test unary plus
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const SIZEOF_SIGNED_WORD = 2
main: {
.label SCREEN = $400
.label SCREEN2 = $428
.const i = 3
.const j = 3
lda #i
sta SCREEN
lda #3
sta SCREEN+1
lda #<j
sta SCREEN2
lda #>j
sta SCREEN2+1
lda #<3
sta SCREEN2+1*SIZEOF_SIGNED_WORD
lda #>3
sta SCREEN2+1*SIZEOF_SIGNED_WORD+1
rts
}

View File

@ -0,0 +1,20 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) main::i
[5] *((const byte*) main::SCREEN+(byte) 1) ← (byte)+(number) 3
[6] *((const signed word*) main::SCREEN2) ← (const signed word) main::j
[7] *((const signed word*) main::SCREEN2+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed byte)+(number) 3
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return

337
src/test/ref/unary-plus.log Normal file
View File

@ -0,0 +1,337 @@
Fixing pointer array-indexing *((signed word*) main::SCREEN2 + (number) 0)
Fixing pointer array-indexing *((signed word*) main::SCREEN2 + (number) 1)
Identified constant variable (byte*) main::SCREEN
Identified constant variable (signed word*) main::SCREEN2
Identified constant variable (byte) main::i
Identified constant variable (signed word) main::j
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @1
*((const byte*) main::SCREEN + (number) 0) ← (const byte) main::i
*((const byte*) main::SCREEN + (number) 1) ← +(number) 3
(number~) main::$0 ← (number) 0 * (const byte) SIZEOF_SIGNED_WORD
*((const signed word*) main::SCREEN2 + (number~) main::$0) ← (const signed word) main::j
(number~) main::$1 ← (number) 1 * (const byte) SIZEOF_SIGNED_WORD
*((const signed word*) main::SCREEN2 + (number~) main::$1) ← +(number) 3
to:main::@return
main::@return: scope:[main] from main
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte) SIZEOF_SIGNED_WORD = (byte) 2
(void()) main()
(number~) main::$0
(number~) main::$1
(label) main::@return
(const byte*) main::SCREEN = (byte*)(number) $400
(const signed word*) main::SCREEN2 = (signed word*)(number) $428
(const byte) main::i = (byte)+(number) 3
(const signed word) main::j = (signed word)+(number) 3
Adding number conversion cast (unumber) 0 in *((const byte*) main::SCREEN + (number) 0) ← (const byte) main::i
Adding number conversion cast (unumber) +3 in *((const byte*) main::SCREEN + (number) 1) ← +(number) 3
Adding number conversion cast (unumber) 1 in *((const byte*) main::SCREEN + (number) 1) ← ((unumber)) +(number) 3
Adding number conversion cast (unumber) 0 in (number~) main::$0 ← (number) 0 * (const byte) SIZEOF_SIGNED_WORD
Adding number conversion cast (unumber) main::$0 in (number~) main::$0 ← (unumber)(number) 0 * (const byte) SIZEOF_SIGNED_WORD
Adding number conversion cast (unumber) 1 in (number~) main::$1 ← (number) 1 * (const byte) SIZEOF_SIGNED_WORD
Adding number conversion cast (unumber) main::$1 in (number~) main::$1 ← (unumber)(number) 1 * (const byte) SIZEOF_SIGNED_WORD
Adding number conversion cast (snumber) +3 in *((const signed word*) main::SCREEN2 + (unumber~) main::$1) ← +(number) 3
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast *((const byte*) main::SCREEN + (unumber)(number) 1) ← (unumber)+(number) 3
Inlining cast *((const signed word*) main::SCREEN2 + (unumber~) main::$1) ← (snumber)+(number) 3
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant pointer cast (signed word*) 1064
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in (unumber~) main::$0 ← (byte) 0 * (const byte) SIZEOF_SIGNED_WORD
Inferred type updated to byte in (unumber~) main::$1 ← (byte) 1 * (const byte) SIZEOF_SIGNED_WORD
Constant right-side identified [1] *((const byte*) main::SCREEN + (byte) 1) ← (unumber)+(number) 3
Constant right-side identified [2] (byte~) main::$0 ← (byte) 0 * (const byte) SIZEOF_SIGNED_WORD
Constant right-side identified [4] (byte~) main::$1 ← (byte) 1 * (const byte) SIZEOF_SIGNED_WORD
Constant right-side identified [5] *((const signed word*) main::SCREEN2 + (byte~) main::$1) ← (snumber)+(number) 3
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::$0 = 0*SIZEOF_SIGNED_WORD
Constant (const byte) main::$1 = 1*SIZEOF_SIGNED_WORD
Successful SSA optimization Pass2ConstantIdentification
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_SIGNED_WORD in
Successful SSA optimization PassNSimplifyConstantZero
Simplifying expression containing zero main::SCREEN in [0] *((const byte*) main::SCREEN + (byte) 0) ← (const byte) main::i
Simplifying expression containing zero main::SCREEN2 in [3] *((const signed word*) main::SCREEN2 + (const byte) main::$0) ← (const signed word) main::j
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) main::$0
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$1 = (byte) 1*(const byte) SIZEOF_SIGNED_WORD
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(main::SCREEN+1)
Consolidated array index constant in *(main::SCREEN2+1*SIZEOF_SIGNED_WORD)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
CALL GRAPH
Calls in [] to main:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
(void()) main()
main: scope:[main] from @1
[4] *((const byte*) main::SCREEN) ← (const byte) main::i
[5] *((const byte*) main::SCREEN+(byte) 1) ← (byte)+(number) 3
[6] *((const signed word*) main::SCREEN2) ← (const signed word) main::j
[7] *((const signed word*) main::SCREEN2+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed byte)+(number) 3
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test unary plus
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_SIGNED_WORD = 2
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label SCREEN = $400
.label SCREEN2 = $428
.const i = 3
.const j = 3
// [4] *((const byte*) main::SCREEN) ← (const byte) main::i -- _deref_pbuc1=vbuc2
lda #i
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (byte)+(number) 3 -- _deref_pbuc1=vbuc2
lda #3
sta SCREEN+1
// [6] *((const signed word*) main::SCREEN2) ← (const signed word) main::j -- _deref_pwsc1=vwsc2
lda #<j
sta SCREEN2
lda #>j
sta SCREEN2+1
// [7] *((const signed word*) main::SCREEN2+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed byte)+(number) 3 -- _deref_pwsc1=vwsc2
lda #<3
sta SCREEN2+1*SIZEOF_SIGNED_WORD
lda #>3
sta SCREEN2+1*SIZEOF_SIGNED_WORD+1
jmp __breturn
// main::@return
__breturn:
// [8] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((const byte*) main::SCREEN) ← (const byte) main::i [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← (byte)+(number) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] *((const signed word*) main::SCREEN2) ← (const signed word) main::j [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const signed word*) main::SCREEN2+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed byte)+(number) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 57 combination
Uplifting [] best 57 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test unary plus
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_SIGNED_WORD = 2
// @begin
__bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
// @1
__b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
jmp __bend
// @end
__bend:
// main
main: {
.label SCREEN = $400
.label SCREEN2 = $428
.const i = 3
.const j = 3
// [4] *((const byte*) main::SCREEN) ← (const byte) main::i -- _deref_pbuc1=vbuc2
lda #i
sta SCREEN
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (byte)+(number) 3 -- _deref_pbuc1=vbuc2
lda #3
sta SCREEN+1
// [6] *((const signed word*) main::SCREEN2) ← (const signed word) main::j -- _deref_pwsc1=vwsc2
lda #<j
sta SCREEN2
lda #>j
sta SCREEN2+1
// [7] *((const signed word*) main::SCREEN2+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed byte)+(number) 3 -- _deref_pwsc1=vwsc2
lda #<3
sta SCREEN2+1*SIZEOF_SIGNED_WORD
lda #>3
sta SCREEN2+1*SIZEOF_SIGNED_WORD+1
jmp __breturn
// main::@return
__breturn:
// [8] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) SIZEOF_SIGNED_WORD = (byte) 2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(const signed word*) main::SCREEN2 = (signed word*) 1064
(const byte) main::i = (byte)+(number) 3
(const signed word) main::j = (signed word)+(number) 3
FINAL ASSEMBLER
Score: 42
// File Comments
// Test unary plus
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_SIGNED_WORD = 2
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label SCREEN = $400
.label SCREEN2 = $428
.const i = 3
.const j = 3
// SCREEN[0] = i
// [4] *((const byte*) main::SCREEN) ← (const byte) main::i -- _deref_pbuc1=vbuc2
lda #i
sta SCREEN
// SCREEN[1] = +3
// [5] *((const byte*) main::SCREEN+(byte) 1) ← (byte)+(number) 3 -- _deref_pbuc1=vbuc2
lda #3
sta SCREEN+1
// SCREEN2[0] = j
// [6] *((const signed word*) main::SCREEN2) ← (const signed word) main::j -- _deref_pwsc1=vwsc2
lda #<j
sta SCREEN2
lda #>j
sta SCREEN2+1
// SCREEN2[1] = +3
// [7] *((const signed word*) main::SCREEN2+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed byte)+(number) 3 -- _deref_pwsc1=vwsc2
lda #<3
sta SCREEN2+1*SIZEOF_SIGNED_WORD
lda #>3
sta SCREEN2+1*SIZEOF_SIGNED_WORD+1
// main::@return
// }
// [8] return
rts
}
// File Data

View File

@ -0,0 +1,11 @@
(label) @1
(label) @begin
(label) @end
(const byte) SIZEOF_SIGNED_WORD = (byte) 2
(void()) main()
(label) main::@return
(const byte*) main::SCREEN = (byte*) 1024
(const signed word*) main::SCREEN2 = (signed word*) 1064
(const byte) main::i = (byte)+(number) 3
(const signed word) main::j = (signed word)+(number) 3