mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-08-09 04:25:12 +00:00
Merged 181-type-system
This commit is contained in:
2
src/main/fragment/_deref__deref_pptc1=vbuaa.asm
Normal file
2
src/main/fragment/_deref__deref_pptc1=vbuaa.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ldy #0
|
||||||
|
sta ({c1}),y
|
@@ -0,0 +1,5 @@
|
|||||||
|
ldy #0
|
||||||
|
lda {z1}
|
||||||
|
sta !+ +1
|
||||||
|
lda {c1},x
|
||||||
|
!: sta ($ff),y
|
4
src/main/fragment/_deref__deref_pptz1=vbuaa.asm
Normal file
4
src/main/fragment/_deref__deref_pptz1=vbuaa.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
ldy {z1}
|
||||||
|
sty !+ +1
|
||||||
|
ldy #0
|
||||||
|
!: sta ($ff),y
|
8
src/main/fragment/_deref_pduc1=vduz1.asm
Normal file
8
src/main/fragment/_deref_pduc1=vduz1.asm
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
lda {z1}
|
||||||
|
sta {c1}
|
||||||
|
lda {z1}+1
|
||||||
|
sta {c1}+1
|
||||||
|
lda {z1}+2
|
||||||
|
sta {c1}+2
|
||||||
|
lda {z1}+3
|
||||||
|
sta {c1}+3
|
4
src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm
Normal file
4
src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
inc {c1}
|
||||||
|
bne !+
|
||||||
|
inc {c1}+1
|
||||||
|
!:
|
4
src/main/fragment/_deref_pptc1=pbuz1.asm
Normal file
4
src/main/fragment/_deref_pptc1=pbuz1.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
lda {z1}
|
||||||
|
sta {c1}
|
||||||
|
lda {z1}+1
|
||||||
|
sta {c1}+1
|
5
src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm
Normal file
5
src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
ldy #0
|
||||||
|
lda ({z1}),y
|
||||||
|
clc
|
||||||
|
adc #1
|
||||||
|
sta ({z1}),y
|
4
src/main/fragment/pbuz1=_ptr_vwuz2.asm
Normal file
4
src/main/fragment/pbuz1=_ptr_vwuz2.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
lda {z2}
|
||||||
|
sta {z1}
|
||||||
|
lda {z2}+1
|
||||||
|
sta {z1}+1
|
6
src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm
Normal file
6
src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
ldy #{c1}
|
||||||
|
lda {z2}
|
||||||
|
sta ({z1}),y
|
||||||
|
iny
|
||||||
|
lda {z2}+1
|
||||||
|
sta ({z1}),y
|
6
src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm
Normal file
6
src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
ldy #{c1}
|
||||||
|
lda {z2}
|
||||||
|
sta ({z1}),y
|
||||||
|
iny
|
||||||
|
lda {z2}+1
|
||||||
|
sta ({z1}),y
|
5
src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm
Normal file
5
src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
lda {z2}
|
||||||
|
sta ({z1}),y
|
||||||
|
iny
|
||||||
|
lda {z2}+1
|
||||||
|
sta ({z1}),y
|
5
src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm
Normal file
5
src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
lda {z2}
|
||||||
|
sta ({z1}),y
|
||||||
|
iny
|
||||||
|
lda {z2}+1
|
||||||
|
sta ({z1}),y
|
2
src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm
Normal file
2
src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
sta {c1},x
|
||||||
|
|
2
src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm
Normal file
2
src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
sta {c1}+1,x
|
||||||
|
|
2
src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm
Normal file
2
src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
sta {c1},y
|
||||||
|
|
2
src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm
Normal file
2
src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
sta {c1}+1,y
|
||||||
|
|
@@ -0,0 +1,7 @@
|
|||||||
|
lda {c1},x
|
||||||
|
sec
|
||||||
|
sbc {z1}
|
||||||
|
sta {c1},x
|
||||||
|
lda {c1}+1,x
|
||||||
|
sbc {z1}+1
|
||||||
|
sta {c1}+1,x
|
4
src/main/fragment/pwsc1_derefidx_vbuxx=vwsz1.asm
Normal file
4
src/main/fragment/pwsc1_derefidx_vbuxx=vwsz1.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
lda {z1}
|
||||||
|
sta {c1},x
|
||||||
|
lda {z1}+1
|
||||||
|
sta {c1}+1,x
|
@@ -0,0 +1,7 @@
|
|||||||
|
lda {c1},y
|
||||||
|
sec
|
||||||
|
sbc {z1}
|
||||||
|
sta {c1},y
|
||||||
|
lda {c1}+1,y
|
||||||
|
sbc {z1}+1
|
||||||
|
sta {c1}+1,y
|
4
src/main/fragment/pwsc1_derefidx_vbuyy=vwsz1.asm
Normal file
4
src/main/fragment/pwsc1_derefidx_vbuyy=vwsz1.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
lda {z1}
|
||||||
|
sta {c1},y
|
||||||
|
lda {z1}+1
|
||||||
|
sta {c1}+1,y
|
@@ -0,0 +1,8 @@
|
|||||||
|
lda {c1}+1,x
|
||||||
|
cmp {z1}+1
|
||||||
|
bne !+
|
||||||
|
lda {c1},x
|
||||||
|
cmp {z1}
|
||||||
|
beq {la1}
|
||||||
|
!:
|
||||||
|
bcc {la1}
|
3
src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm
Normal file
3
src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
sta {c1},y
|
||||||
|
lda #0
|
||||||
|
sta {c1}+1,y
|
@@ -0,0 +1,8 @@
|
|||||||
|
lda {c1}+1,y
|
||||||
|
cmp {z1}+1
|
||||||
|
bne !+
|
||||||
|
lda {c1},y
|
||||||
|
cmp {z1}
|
||||||
|
beq {la1}
|
||||||
|
!:
|
||||||
|
bcc {la1}
|
3
src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm
Normal file
3
src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
eor #$ff
|
||||||
|
clc
|
||||||
|
adc #$01
|
6
src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm
Normal file
6
src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
sec
|
||||||
|
sbc #{c1}
|
||||||
|
bvc !+
|
||||||
|
eor #$80
|
||||||
|
!:
|
||||||
|
bmi {la1}
|
1
src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm
Normal file
1
src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
lda {c1}
|
1
src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm
Normal file
1
src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
lda {c1}+1
|
1
src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm
Normal file
1
src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
lda {c1},x
|
1
src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm
Normal file
1
src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
lda {c1}+1,x
|
1
src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm
Normal file
1
src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
lda {c1},y
|
1
src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm
Normal file
1
src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
lda {c1}+1,y
|
2
src/main/fragment/vbuaa_le_0_then_la1.asm
Normal file
2
src/main/fragment/vbuaa_le_0_then_la1.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
cmp #0
|
||||||
|
beq {la1}
|
2
src/main/fragment/vbuxx_le_0_then_la1.asm
Normal file
2
src/main/fragment/vbuxx_le_0_then_la1.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
cpx #0
|
||||||
|
beq {la1}
|
2
src/main/fragment/vbuyy_le_0_then_la1.asm
Normal file
2
src/main/fragment/vbuyy_le_0_then_la1.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
cpy #0
|
||||||
|
beq {la1}
|
5
src/main/fragment/vduz1=_dword_vbuaa.asm
Normal file
5
src/main/fragment/vduz1=_dword_vbuaa.asm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
sta {z1}
|
||||||
|
lda #0
|
||||||
|
sta {z1}+1
|
||||||
|
sta {z1}+2
|
||||||
|
sta {z1}+3
|
13
src/main/fragment/vduz1=vduc1_plus_vduz2.asm
Normal file
13
src/main/fragment/vduz1=vduc1_plus_vduz2.asm
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
lda {z2}
|
||||||
|
clc
|
||||||
|
adc #<{c1}
|
||||||
|
sta {z1}
|
||||||
|
lda {z2}+1
|
||||||
|
adc #>{c1}
|
||||||
|
sta {z1}+1
|
||||||
|
lda {z2}+2
|
||||||
|
adc #0
|
||||||
|
sta {z1}+2
|
||||||
|
lda {z2}+3
|
||||||
|
adc #0
|
||||||
|
sta {z1}+3
|
@@ -10,5 +10,4 @@ adc {z2}+2
|
|||||||
sta {z1}+2
|
sta {z1}+2
|
||||||
lda {z1}+3
|
lda {z1}+3
|
||||||
adc {z2}+3
|
adc {z2}+3
|
||||||
sta {z1}+3
|
sta {z1}+3
|
||||||
|
|
@@ -10,5 +10,4 @@ adc #0
|
|||||||
sta {z1}+2
|
sta {z1}+2
|
||||||
lda {z2}+3
|
lda {z2}+3
|
||||||
adc #0
|
adc #0
|
||||||
sta {z1}+3
|
sta {z1}+3
|
||||||
|
|
7
src/main/fragment/vduz1=vwuz2.asm
Normal file
7
src/main/fragment/vduz1=vwuz2.asm
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
lda {z2}
|
||||||
|
sta {z1}
|
||||||
|
lda {z2}+1
|
||||||
|
sta {z1}+1
|
||||||
|
lda #0
|
||||||
|
sta {z1}+2
|
||||||
|
sta {z1}+3
|
@@ -1,8 +1,8 @@
|
|||||||
lda #<{c1}
|
|
||||||
sta {z1}
|
|
||||||
lda #>{c1}
|
|
||||||
sta {z1}+1
|
|
||||||
lda {z2}
|
lda {z2}
|
||||||
sta {z1}+2
|
sta {z1}+2
|
||||||
lda {z2}+1
|
lda {z2}+1
|
||||||
sta {z1}+3
|
sta {z1}+3
|
||||||
|
lda #{c1}
|
||||||
|
sta {z1}
|
||||||
|
lda #0
|
||||||
|
sta {z1}+1
|
||||||
|
8
src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm
Normal file
8
src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
lda #<{c1}
|
||||||
|
sta {z1}
|
||||||
|
lda #>{c1}
|
||||||
|
sta {z1}+1
|
||||||
|
lda {z2}
|
||||||
|
sta {z1}+2
|
||||||
|
lda {z2}+1
|
||||||
|
sta {z1}+3
|
3
src/main/fragment/vssz1=vssf2.asm
Normal file
3
src/main/fragment/vssz1=vssf2.asm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
lda #0
|
||||||
|
sta {z1}
|
||||||
|
sta {z1}+1
|
4
src/main/fragment/vssz1=vssz2.asm
Normal file
4
src/main/fragment/vssz1=vssz2.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
lda {z2}
|
||||||
|
sta {z1}
|
||||||
|
lda {z2}+1
|
||||||
|
sta {z1}+1
|
3
src/main/fragment/vwsz1=_sword_vbuaa.asm
Normal file
3
src/main/fragment/vwsz1=_sword_vbuaa.asm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
sta {z1}
|
||||||
|
lda #0
|
||||||
|
sta {z1}+1
|
11
src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm
Normal file
11
src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
tax
|
||||||
|
clc
|
||||||
|
adc #<{c1}
|
||||||
|
sta {z1}
|
||||||
|
txa
|
||||||
|
ora #$7f
|
||||||
|
bmi !+
|
||||||
|
lda #0
|
||||||
|
!:
|
||||||
|
adc #>{c1}
|
||||||
|
sta {z1}+1
|
7
src/main/fragment/vwsz1=vwsz2_minus_vbsc1.asm
Normal file
7
src/main/fragment/vwsz1=vwsz2_minus_vbsc1.asm
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
lda {z2}
|
||||||
|
sec
|
||||||
|
sbc #{c1}
|
||||||
|
sta {z1}
|
||||||
|
lda {z2}+1
|
||||||
|
sbc #>{c1}
|
||||||
|
sta {z1}+1
|
5
src/main/fragment/vwuz1=vbuaa_rol_1.asm
Normal file
5
src/main/fragment/vwuz1=vbuaa_rol_1.asm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
asl
|
||||||
|
sta {z1}
|
||||||
|
lda #0
|
||||||
|
rol
|
||||||
|
sta {z1}+1
|
@@ -0,0 +1,7 @@
|
|||||||
|
sec
|
||||||
|
lda {z1}
|
||||||
|
sbc {c1},x
|
||||||
|
sta {z1}
|
||||||
|
lda {z1}+1
|
||||||
|
sbc {c1}+1,x
|
||||||
|
sta {z1}+1
|
@@ -0,0 +1,7 @@
|
|||||||
|
sec
|
||||||
|
lda {z1}
|
||||||
|
sbc {c1},y
|
||||||
|
sta {z1}
|
||||||
|
lda {z1}+1
|
||||||
|
sbc {c1}+1,y
|
||||||
|
sta {z1}+1
|
7
src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm
Normal file
7
src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
lda {z1}
|
||||||
|
cmp #<{c1}
|
||||||
|
bne !+
|
||||||
|
lda {z1}+1
|
||||||
|
cmp #>{c1}
|
||||||
|
beq {la1}
|
||||||
|
!:
|
@@ -3,6 +3,6 @@ cmp {z2}+1
|
|||||||
bne !+
|
bne !+
|
||||||
lda {z1}
|
lda {z1}
|
||||||
cmp {z2}
|
cmp {z2}
|
||||||
|
beq {la1}
|
||||||
!:
|
!:
|
||||||
bcc {la1}
|
bcc {la1}
|
||||||
beq {la1}
|
|
@@ -192,7 +192,7 @@ public class CompileLog {
|
|||||||
return verboseSSAOptimize;
|
return verboseSSAOptimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompileLog setVerboseSSAOptimize() {
|
public CompileLog verboseSSAOptimize() {
|
||||||
setVerboseSSAOptimize(true);
|
setVerboseSSAOptimize(true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@@ -153,18 +153,19 @@ public class Compiler {
|
|||||||
new Pass1GenerateControlFlowGraph(program).execute();
|
new Pass1GenerateControlFlowGraph(program).execute();
|
||||||
new Pass1ResolveForwardReferences(program).execute();
|
new Pass1ResolveForwardReferences(program).execute();
|
||||||
new Pass1UnwindBlockScopes(program).execute();
|
new Pass1UnwindBlockScopes(program).execute();
|
||||||
new Pass1TypeInference(program).execute();
|
new Pass1Procedures(program).execute();
|
||||||
new Pass1TypeIdSimplification(program).execute();
|
new PassNTypeInference(program).execute();
|
||||||
|
new PassNTypeIdSimplification(program).execute();
|
||||||
|
|
||||||
if(getLog().isVerbosePass1CreateSsa()) {
|
if(getLog().isVerbosePass1CreateSsa()) {
|
||||||
getLog().append("SYMBOLS");
|
getLog().append("SYMBOLS");
|
||||||
getLog().append(program.getScope().getSymbolTableContents(program));
|
getLog().append(program.getScope().toString(program, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
new Pass1FixLValuesLoHi(program).execute();
|
new Pass1FixLValuesLoHi(program).execute();
|
||||||
new Pass1AssertNoLValueIntermediate(program).execute();
|
new Pass1AssertNoLValueIntermediate(program).execute();
|
||||||
new Pass1PointerSizeofFix(program).execute();
|
new Pass1PointerSizeofFix(program).execute();
|
||||||
new Pass1AddTypePromotions(program).execute();
|
new PassNAddTypeConversionAssignment(program).execute();
|
||||||
new Pass1EarlyConstantIdentification(program).execute();
|
new Pass1EarlyConstantIdentification(program).execute();
|
||||||
new PassNStatementIndices(program).step();
|
new PassNStatementIndices(program).step();
|
||||||
new PassNCallGraphAnalysis(program).step();
|
new PassNCallGraphAnalysis(program).step();
|
||||||
@@ -182,7 +183,7 @@ public class Compiler {
|
|||||||
new Pass1EliminateUncalledProcedures(program).execute();
|
new Pass1EliminateUncalledProcedures(program).execute();
|
||||||
new PassNEliminateUnusedVars(program, false).execute();
|
new PassNEliminateUnusedVars(program, false).execute();
|
||||||
new Pass1ExtractInlineStrings(program).execute();
|
new Pass1ExtractInlineStrings(program).execute();
|
||||||
new Pass1EliminateEmptyBlocks(program).execute();
|
new PassNCullEmptyBlocks(program).execute();
|
||||||
|
|
||||||
new Pass1ModifiedVarsAnalysis(program).execute();
|
new Pass1ModifiedVarsAnalysis(program).execute();
|
||||||
if(getLog().isVerbosePass1CreateSsa()) {
|
if(getLog().isVerbosePass1CreateSsa()) {
|
||||||
@@ -205,7 +206,7 @@ public class Compiler {
|
|||||||
getLog().append(program.getGraph().toString(program));
|
getLog().append(program.getGraph().toString(program));
|
||||||
|
|
||||||
getLog().append("SYMBOL TABLE SSA");
|
getLog().append("SYMBOL TABLE SSA");
|
||||||
getLog().append(program.getScope().getSymbolTableContents(program));
|
getLog().append(program.getScope().toString(program, null));
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
@@ -228,37 +229,50 @@ public class Compiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pass2Optimize() {
|
private List<Pass2SsaOptimization> getPass2Optimizations() {
|
||||||
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
|
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
|
||||||
optimizations.add(new Pass2CullEmptyBlocks(program));
|
optimizations.add(new Pass2FixInlineConstructorsNew(program));
|
||||||
|
|
||||||
|
optimizations.add(new PassNAddNumberTypeConversions(program));
|
||||||
|
optimizations.add(new PassNAddArrayNumberTypeConversions(program));
|
||||||
|
optimizations.add(new Pass2InlineCast(program));
|
||||||
|
//optimizations.add(new Pass2NopCastInlining(program));
|
||||||
|
optimizations.add(new PassNCastSimplification(program));
|
||||||
|
optimizations.add(new PassNFinalizeNumberTypeConversions(program));
|
||||||
|
optimizations.add(new PassNTypeInference(program));
|
||||||
|
optimizations.add(new PassNAddTypeConversionAssignment(program));
|
||||||
|
|
||||||
|
optimizations.add(new PassNTypeIdSimplification(program));
|
||||||
|
optimizations.add(new Pass2SizeOfSimplification(program));
|
||||||
optimizations.add(new PassNStatementIndices(program));
|
optimizations.add(new PassNStatementIndices(program));
|
||||||
optimizations.add(new PassNVariableReferenceInfos(program));
|
optimizations.add(new PassNVariableReferenceInfos(program));
|
||||||
optimizations.add(new Pass2UnaryNotSimplification(program));
|
optimizations.add(new Pass2UnaryNotSimplification(program));
|
||||||
optimizations.add(new Pass2AliasElimination(program));
|
optimizations.add(new Pass2AliasElimination(program));
|
||||||
optimizations.add(new Pass2SelfPhiElimination(program));
|
optimizations.add(new Pass2SelfPhiElimination(program));
|
||||||
optimizations.add(new Pass2RedundantPhiElimination(program));
|
|
||||||
optimizations.add(new Pass2IdenticalPhiElimination(program));
|
optimizations.add(new Pass2IdenticalPhiElimination(program));
|
||||||
|
optimizations.add(new Pass2DuplicateRValueIdentification(program));
|
||||||
optimizations.add(new Pass2ConditionalJumpSimplification(program));
|
optimizations.add(new Pass2ConditionalJumpSimplification(program));
|
||||||
optimizations.add(new Pass2ConditionalAndOrRewriting(program));
|
optimizations.add(new Pass2ConditionalAndOrRewriting(program));
|
||||||
|
optimizations.add(new Pass2ConditionalJumpSequenceImprovement(program));
|
||||||
|
optimizations.add(new Pass2ConstantRValueConsolidation(program));
|
||||||
optimizations.add(new Pass2ConstantIdentification(program));
|
optimizations.add(new Pass2ConstantIdentification(program));
|
||||||
optimizations.add(new PassNStatementIndices(program));
|
optimizations.add(new Pass2ConstantValues(program));
|
||||||
optimizations.add(new PassNVariableReferenceInfos(program));
|
optimizations.add(new Pass2ConstantCallPointerIdentification(program));
|
||||||
optimizations.add(new Pass2ConstantAdditionElimination(program));
|
|
||||||
optimizations.add(new Pass2ConstantIfs(program));
|
optimizations.add(new Pass2ConstantIfs(program));
|
||||||
optimizations.add(new Pass2ConstantStringConsolidation(program));
|
optimizations.add(new Pass2ConstantStringConsolidation(program));
|
||||||
optimizations.add(new Pass2FixInlineConstructors(program));
|
|
||||||
optimizations.add(new Pass2TypeInference(program));
|
|
||||||
optimizations.add(new PassNEliminateUnusedVars(program, true));
|
|
||||||
optimizations.add(new Pass2EliminateRedundantCasts(program));
|
|
||||||
optimizations.add(new Pass2NopCastElimination(program));
|
|
||||||
optimizations.add(new Pass2EliminateUnusedBlocks(program));
|
|
||||||
optimizations.add(new Pass2RangeResolving(program));
|
optimizations.add(new Pass2RangeResolving(program));
|
||||||
optimizations.add(new Pass2ComparisonOptimization(program));
|
optimizations.add(new Pass2ComparisonOptimization(program));
|
||||||
optimizations.add(new Pass2ConstantCallPointerIdentification(program));
|
|
||||||
optimizations.add(new Pass2MultiplyToShiftRewriting(program));
|
|
||||||
optimizations.add(new Pass2SizeOfSimplification(program));
|
|
||||||
optimizations.add(new Pass2InlineDerefIdx(program));
|
optimizations.add(new Pass2InlineDerefIdx(program));
|
||||||
optimizations.add(new Pass2DeInlineWordDerefIdx(program));
|
optimizations.add(new Pass2DeInlineWordDerefIdx(program));
|
||||||
|
optimizations.add(new PassNSimplifyConstantZero(program));
|
||||||
|
optimizations.add(new PassNSimplifyExpressionWithZero(program));
|
||||||
|
optimizations.add(new PassNEliminateUnusedVars(program, true));
|
||||||
|
optimizations.add(new Pass2EliminateUnusedBlocks(program));
|
||||||
|
return optimizations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pass2Optimize() {
|
||||||
|
List<Pass2SsaOptimization> optimizations = getPass2Optimizations();
|
||||||
pass2Execute(optimizations);
|
pass2Execute(optimizations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,13 +305,13 @@ public class Compiler {
|
|||||||
private void pass2InlineConstants() {
|
private void pass2InlineConstants() {
|
||||||
// Constant inlining optimizations - as the last step to ensure that constant identification has been completed
|
// Constant inlining optimizations - as the last step to ensure that constant identification has been completed
|
||||||
List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>();
|
List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>();
|
||||||
|
constantOptimizations.add(new PassNStatementIndices(program));
|
||||||
|
constantOptimizations.add(new PassNVariableReferenceInfos(program));
|
||||||
|
constantOptimizations.add(new Pass2MultiplyToShiftRewriting(program));
|
||||||
constantOptimizations.add(new Pass2ConstantInlining(program));
|
constantOptimizations.add(new Pass2ConstantInlining(program));
|
||||||
constantOptimizations.add(new Pass2ConstantStringConsolidation(program));
|
|
||||||
constantOptimizations.add(new Pass2IdenticalPhiElimination(program));
|
|
||||||
constantOptimizations.add(new Pass2ConstantIdentification(program));
|
|
||||||
constantOptimizations.add(new Pass2ConstantAdditionElimination(program));
|
constantOptimizations.add(new Pass2ConstantAdditionElimination(program));
|
||||||
constantOptimizations.add(new Pass2ConstantSimplification(program));
|
constantOptimizations.add(new Pass2ConstantSimplification(program));
|
||||||
constantOptimizations.add(new Pass2ConstantIfs(program));
|
constantOptimizations.addAll(getPass2Optimizations());
|
||||||
pass2Execute(constantOptimizations);
|
pass2Execute(constantOptimizations);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -351,11 +365,12 @@ public class Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void pass3Analysis() {
|
private void pass3Analysis() {
|
||||||
|
new Pass3AssertNoTypeId(program).check();
|
||||||
new Pass3AssertRValues(program).check();
|
new Pass3AssertRValues(program).check();
|
||||||
|
new Pass3AssertNoNumbers(program).check();
|
||||||
new Pass3AssertConstants(program).check();
|
new Pass3AssertConstants(program).check();
|
||||||
new Pass3AssertArrayLengths(program).check();
|
new Pass3AssertArrayLengths(program).check();
|
||||||
new Pass3AssertNoMulDivMod(program).check();
|
new Pass3AssertNoMulDivMod(program).check();
|
||||||
new PassNBlockSequencePlanner(program).step();
|
|
||||||
// Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes
|
// Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes
|
||||||
new Pass3PhiLifting(program).perform();
|
new Pass3PhiLifting(program).perform();
|
||||||
new PassNBlockSequencePlanner(program).step();
|
new PassNBlockSequencePlanner(program).step();
|
||||||
@@ -382,7 +397,7 @@ public class Compiler {
|
|||||||
|
|
||||||
// Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap
|
// Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap
|
||||||
new Pass3PhiMemCoalesce(program).step();
|
new Pass3PhiMemCoalesce(program).step();
|
||||||
new Pass2CullEmptyBlocks(program).step();
|
new PassNCullEmptyBlocks(program).step();
|
||||||
new PassNRenumberLabels(program).execute();
|
new PassNRenumberLabels(program).execute();
|
||||||
new PassNBlockSequencePlanner(program).step();
|
new PassNBlockSequencePlanner(program).step();
|
||||||
new Pass3AddNopBeforeCallOns(program).generate();
|
new Pass3AddNopBeforeCallOns(program).generate();
|
||||||
@@ -516,7 +531,7 @@ public class Compiler {
|
|||||||
new Pass5FixLongBranches(program).optimize();
|
new Pass5FixLongBranches(program).optimize();
|
||||||
|
|
||||||
getLog().append("\nFINAL SYMBOL TABLE");
|
getLog().append("\nFINAL SYMBOL TABLE");
|
||||||
getLog().append(program.getScope().getSymbolTableContents(program));
|
getLog().append(program.getScope().toString(program, null));
|
||||||
|
|
||||||
getLog().append("\nFINAL ASSEMBLER");
|
getLog().append("\nFINAL ASSEMBLER");
|
||||||
getLog().append("Score: " + Pass4RegisterUpliftCombinations.getAsmScore(program) + "\n");
|
getLog().append("Score: " + Pass4RegisterUpliftCombinations.getAsmScore(program) + "\n");
|
||||||
|
@@ -1,38 +1,61 @@
|
|||||||
package dk.camelot64.kickc;
|
package dk.camelot64.kickc;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
|
|
||||||
/** Parser for converting literal numbers to the corresponding Java Integer/Double */
|
/** Parser for converting literal numbers to the corresponding Java Integer/Double */
|
||||||
public class NumberParser {
|
public class NumberParser {
|
||||||
|
|
||||||
public static Number parseLiteral(String literal) {
|
public static ConstantInteger parseIntegerLiteral(String literal) {
|
||||||
boolean isInt = !literal.contains(".");
|
|
||||||
|
|
||||||
if(isInt) {
|
boolean isInt = !literal.contains(".");
|
||||||
if(literal.startsWith("0x")) {
|
if(!isInt) {
|
||||||
return parseHexInt(literal.substring(2));
|
|
||||||
} else if(literal.startsWith("$")) {
|
|
||||||
return parseHexInt(literal.substring(1));
|
|
||||||
} else if(literal.startsWith("0b")) {
|
|
||||||
return parseBinInt(literal.substring(2));
|
|
||||||
} else if(literal.startsWith("%")) {
|
|
||||||
return parseBinInt(literal.substring(1));
|
|
||||||
} else {
|
|
||||||
return parseDecInt(literal);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new NumberFormatException("Not Implemented: non-integer parsing. " + literal);
|
throw new NumberFormatException("Not Implemented: non-integer parsing. " + literal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolType type = SymbolType.NUMBER;
|
||||||
|
if(literal.endsWith("ub") || literal.endsWith("uc")) {
|
||||||
|
type = SymbolType.BYTE;
|
||||||
|
literal = literal.substring(0, literal.length()-2);
|
||||||
|
} else if(literal.endsWith("sb") || literal.endsWith("sc")) {
|
||||||
|
type = SymbolType.SBYTE;
|
||||||
|
literal = literal.substring(0, literal.length()-2);
|
||||||
|
} else if(literal.endsWith("uw") || literal.endsWith("ui")|| literal.endsWith("us")) {
|
||||||
|
type = SymbolType.WORD;
|
||||||
|
literal = literal.substring(0, literal.length()-2);
|
||||||
|
} else if(literal.endsWith("sw") || literal.endsWith("si")|| literal.endsWith("ss")) {
|
||||||
|
type = SymbolType.SWORD;
|
||||||
|
literal = literal.substring(0, literal.length()-2);
|
||||||
|
} else if(literal.endsWith("ud") || literal.endsWith("ul")) {
|
||||||
|
type = SymbolType.DWORD;
|
||||||
|
literal = literal.substring(0, literal.length()-2);
|
||||||
|
} else if(literal.endsWith("sd") || literal.endsWith("sl")) {
|
||||||
|
type = SymbolType.SDWORD;
|
||||||
|
literal = literal.substring(0, literal.length()-2);
|
||||||
|
} else if(literal.endsWith("l")) {
|
||||||
|
type = SymbolType.SDWORD;
|
||||||
|
literal = literal.substring(0, literal.length()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Long value;
|
||||||
|
if(literal.startsWith("0x")) {
|
||||||
|
value = Long.parseLong(literal.substring(2), 16);
|
||||||
|
} else if(literal.startsWith("$")) {
|
||||||
|
value = Long.parseLong(literal.substring(1), 16);
|
||||||
|
} else if(literal.startsWith("0b")) {
|
||||||
|
value = Long.parseLong(literal.substring(2), 2);
|
||||||
|
} else if(literal.startsWith("%")) {
|
||||||
|
value = Long.parseLong(literal.substring(1), 2);
|
||||||
|
} else {
|
||||||
|
value = Long.parseLong(literal);
|
||||||
|
}
|
||||||
|
return new ConstantInteger(value, type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Long parseHexInt(String literal) {
|
public static Number parseLiteral(String literal) {
|
||||||
return Long.parseLong(literal, 16);
|
ConstantInteger constantInteger = parseIntegerLiteral(literal);
|
||||||
}
|
return constantInteger.getValue();
|
||||||
|
|
||||||
private static Long parseBinInt(String literal) {
|
|
||||||
return Long.parseLong(literal, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Long parseDecInt(String literal) {
|
|
||||||
return Long.parseLong(literal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -7,9 +7,7 @@ import dk.camelot64.kickc.model.symbols.ConstantVar;
|
|||||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||||
import dk.camelot64.kickc.model.symbols.Symbol;
|
import dk.camelot64.kickc.model.symbols.Symbol;
|
||||||
import dk.camelot64.kickc.model.symbols.Variable;
|
import dk.camelot64.kickc.model.symbols.Variable;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.*;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
|
||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
/** Formatting of numbers, constants, names and more for KickAssembler */
|
/** Formatting of numbers, constants, names and more for KickAssembler */
|
||||||
@@ -61,7 +59,7 @@ public class AsmFormat {
|
|||||||
} else if(symbol instanceof Procedure) {
|
} else if(symbol instanceof Procedure) {
|
||||||
return getAsmParamName((Procedure) symbol, codeScope);
|
return getAsmParamName((Procedure) symbol, codeScope);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Unhandled symbol type "+symbol);
|
throw new RuntimeException("Unhandled symbol type " + symbol);
|
||||||
}
|
}
|
||||||
} else if(value instanceof ConstantCastValue) {
|
} else if(value instanceof ConstantCastValue) {
|
||||||
ConstantCastValue castValue = (ConstantCastValue) value;
|
ConstantCastValue castValue = (ConstantCastValue) value;
|
||||||
@@ -75,6 +73,7 @@ public class AsmFormat {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get ASM for a binary constant expression
|
* Get ASM for a binary constant expression
|
||||||
|
*
|
||||||
* @param program The program
|
* @param program The program
|
||||||
* @param left The left operand of the expression
|
* @param left The left operand of the expression
|
||||||
* @param operator The binary operator
|
* @param operator The binary operator
|
||||||
@@ -85,12 +84,12 @@ public class AsmFormat {
|
|||||||
private static String getAsmConstantBinary(Program program, ConstantValue left, OperatorBinary operator, ConstantValue right, ScopeRef codeScope) {
|
private static String getAsmConstantBinary(Program program, ConstantValue left, OperatorBinary operator, ConstantValue right, ScopeRef codeScope) {
|
||||||
if(Operators.MODULO.equals(operator)) {
|
if(Operators.MODULO.equals(operator)) {
|
||||||
// Remainder operator % not supported by KickAss - use modulo function instead
|
// Remainder operator % not supported by KickAss - use modulo function instead
|
||||||
return "mod("+
|
return "mod(" +
|
||||||
getAsmConstant(program, left, operator.getPrecedence(), codeScope) +
|
getAsmConstant(program, left, operator.getPrecedence(), codeScope) +
|
||||||
"," +
|
"," +
|
||||||
getAsmConstant(program, right, operator.getPrecedence(), codeScope)+
|
getAsmConstant(program, right, operator.getPrecedence(), codeScope) +
|
||||||
")";
|
")";
|
||||||
} else {
|
} else {
|
||||||
return getAsmConstant(program, left, operator.getPrecedence(), codeScope) +
|
return getAsmConstant(program, left, operator.getPrecedence(), codeScope) +
|
||||||
operator.getOperator() +
|
operator.getOperator() +
|
||||||
getAsmConstant(program, right, operator.getPrecedence(), codeScope);
|
getAsmConstant(program, right, operator.getPrecedence(), codeScope);
|
||||||
@@ -109,64 +108,95 @@ public class AsmFormat {
|
|||||||
private static String getAsmConstantUnary(Program program, ScopeRef codeScope, Operator operator, ConstantValue operand, int outerPrecedence) {
|
private static String getAsmConstantUnary(Program program, ScopeRef codeScope, Operator operator, ConstantValue operand, int outerPrecedence) {
|
||||||
if(Operators.CAST_BYTE.equals(operator) || Operators.CAST_SBYTE.equals(operator)) {
|
if(Operators.CAST_BYTE.equals(operator) || Operators.CAST_SBYTE.equals(operator)) {
|
||||||
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
||||||
if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
|
if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
|
||||||
// No cast needed
|
// No cast needed
|
||||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
} else {
|
|
||||||
return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)0xff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
|
|
||||||
}
|
}
|
||||||
} else if(operator instanceof OperatorCastPtr || Operators.CAST_WORD.equals(operator) || Operators.CAST_SWORD.equals(operator) ) {
|
ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope());
|
||||||
|
if(constantLiteral instanceof ConstantInteger && Operators.CAST_BYTE.equals(operator) && SymbolType.BYTE.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||||
|
// No cast needed
|
||||||
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
|
}
|
||||||
|
if(constantLiteral instanceof ConstantInteger && Operators.CAST_SBYTE.equals(operator) && SymbolType.SBYTE.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||||
|
// No cast needed
|
||||||
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
|
}
|
||||||
|
// Cast is needed
|
||||||
|
return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
|
||||||
|
} else if(operator instanceof OperatorCastPtr || Operators.CAST_WORD.equals(operator) || Operators.CAST_SWORD.equals(operator)) {
|
||||||
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
||||||
if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || SymbolType.isByte(operandType) || SymbolType.isSByte(operandType) || operandType instanceof SymbolTypePointer) {
|
if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType) || operandType instanceof SymbolTypePointer) {
|
||||||
// No cast needed
|
// No cast needed
|
||||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
} else {
|
|
||||||
return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)0xffff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
|
|
||||||
}
|
}
|
||||||
|
ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope());
|
||||||
|
if(constantLiteral instanceof ConstantInteger && Operators.CAST_WORD.equals(operator)&& SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||||
|
// No cast needed
|
||||||
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
|
}
|
||||||
|
if(constantLiteral instanceof ConstantInteger && Operators.CAST_SWORD.equals(operator)&& SymbolType.SWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||||
|
// No cast needed
|
||||||
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
|
}
|
||||||
|
if(constantLiteral instanceof ConstantInteger && (operator instanceof OperatorCastPtr) && SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||||
|
// No cast needed
|
||||||
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
|
}
|
||||||
|
// Cast is needed
|
||||||
|
return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
|
||||||
} else if(Operators.CAST_DWORD.equals(operator) || Operators.CAST_SDWORD.equals(operator)) {
|
} else if(Operators.CAST_DWORD.equals(operator) || Operators.CAST_SDWORD.equals(operator)) {
|
||||||
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
||||||
if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
|
if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType) || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType) || operandType instanceof SymbolTypePointer) {
|
||||||
// No cast needed
|
// No cast needed
|
||||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
} else {
|
|
||||||
return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
|
|
||||||
}
|
}
|
||||||
|
ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope());
|
||||||
|
if(constantLiteral instanceof ConstantInteger && Operators.CAST_DWORD.equals(operator)&& SymbolType.DWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||||
|
// No cast needed
|
||||||
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
|
}
|
||||||
|
if(constantLiteral instanceof ConstantInteger && Operators.CAST_SDWORD.equals(operator)&& SymbolType.SDWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
|
||||||
|
// No cast needed
|
||||||
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
|
}
|
||||||
|
// Cast is needed
|
||||||
|
return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
|
||||||
} else if(Operators.LOWBYTE.equals(operator)) {
|
} else if(Operators.LOWBYTE.equals(operator)) {
|
||||||
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
||||||
if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
|
if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
|
||||||
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
return getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
} else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
|
} else if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
|
||||||
return "<" + getAsmConstant(program, operand, outerPrecedence, codeScope);
|
return "<" + getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
} else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
|
} else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
|
||||||
return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_AND, new ConstantInteger((long)0xffff)), outerPrecedence, codeScope);
|
return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_AND, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope);
|
||||||
} else {
|
} else {
|
||||||
throw new CompileError("Unhandled type "+operand);
|
throw new CompileError("Unhandled type " + operand);
|
||||||
}
|
}
|
||||||
} else if(Operators.HIBYTE.equals(operator)) {
|
} else if(Operators.HIBYTE.equals(operator)) {
|
||||||
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
||||||
if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
|
if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
|
||||||
return getAsmConstant(program, new ConstantInteger(0l), outerPrecedence, codeScope);
|
return getAsmConstant(program, new ConstantInteger(0l), outerPrecedence, codeScope);
|
||||||
} else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
|
} else if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
|
||||||
return ">" + getAsmConstant(program, operand, outerPrecedence, codeScope);
|
return ">" + getAsmConstant(program, operand, outerPrecedence, codeScope);
|
||||||
} else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
|
} else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
|
||||||
return getAsmConstant(program, new ConstantBinary(operand, Operators.SHIFT_RIGHT, new ConstantInteger((long)16)), outerPrecedence, codeScope);
|
return getAsmConstant(program, new ConstantBinary(operand, Operators.SHIFT_RIGHT, new ConstantInteger((long) 16)), outerPrecedence, codeScope);
|
||||||
} else {
|
} else {
|
||||||
throw new CompileError("Unhandled type "+operand);
|
throw new CompileError("Unhandled type " + operand);
|
||||||
}
|
}
|
||||||
} else if(Operators.INCREMENT.equals(operator)) {
|
} else if(Operators.INCREMENT.equals(operator)) {
|
||||||
return getAsmConstant(program, new ConstantBinary(operand, Operators.PLUS, new ConstantInteger((long)1)), outerPrecedence, codeScope);
|
return getAsmConstant(program, new ConstantBinary(operand, Operators.PLUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope);
|
||||||
} else if(Operators.DECREMENT.equals(operator)) {
|
} else if(Operators.DECREMENT.equals(operator)) {
|
||||||
return getAsmConstant(program, new ConstantBinary(operand, Operators.MINUS, new ConstantInteger((long)1)), outerPrecedence, codeScope);
|
return getAsmConstant(program, new ConstantBinary(operand, Operators.MINUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope);
|
||||||
} else if(Operators.BOOL_NOT.equals(operator)) {
|
} else if(Operators.BOOL_NOT.equals(operator)) {
|
||||||
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
|
||||||
if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
|
if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
|
||||||
return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long)0xff)), outerPrecedence, codeScope);
|
return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xff)), outerPrecedence, codeScope);
|
||||||
} else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
|
} else if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
|
||||||
return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long)0xffff)), outerPrecedence, codeScope);
|
return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope);
|
||||||
} else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
|
} else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
|
||||||
return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long)0xffffffff)), outerPrecedence, codeScope);
|
return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffffffff)), outerPrecedence, codeScope);
|
||||||
} else {
|
} else {
|
||||||
throw new CompileError("Unhandled type "+operand);
|
throw new CompileError("Unhandled type " + operand);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return operator.getOperator() +
|
return operator.getOperator() +
|
||||||
@@ -200,7 +230,11 @@ public class AsmFormat {
|
|||||||
if(number.longValue() >= 0L && number.longValue() <= 255L) {
|
if(number.longValue() >= 0L && number.longValue() <= 255L) {
|
||||||
return SHORT_ASM_NUMBERS[number.intValue()];
|
return SHORT_ASM_NUMBERS[number.intValue()];
|
||||||
} else {
|
} else {
|
||||||
return String.format("$%x", number.longValue());
|
if(number.longValue()<0) {
|
||||||
|
return "-"+getAsmNumber(-number.longValue());
|
||||||
|
} else {
|
||||||
|
return String.format("$%x", number.longValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Unsupported number type " + number);
|
throw new RuntimeException("Unsupported number type " + number);
|
||||||
@@ -208,6 +242,7 @@ public class AsmFormat {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the ASM code for a boolean value
|
* Get the ASM code for a boolean value
|
||||||
|
*
|
||||||
* @param bool the boolean vallue
|
* @param bool the boolean vallue
|
||||||
* @return "0" / "1"
|
* @return "0" / "1"
|
||||||
*/
|
*/
|
||||||
|
@@ -3,14 +3,12 @@ package dk.camelot64.kickc.fragment;
|
|||||||
import dk.camelot64.kickc.NumberParser;
|
import dk.camelot64.kickc.NumberParser;
|
||||||
import dk.camelot64.kickc.asm.*;
|
import dk.camelot64.kickc.asm.*;
|
||||||
import dk.camelot64.kickc.model.*;
|
import dk.camelot64.kickc.model.*;
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
||||||
import dk.camelot64.kickc.model.values.ConstantValue;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||||
import dk.camelot64.kickc.model.symbols.Label;
|
import dk.camelot64.kickc.model.symbols.Label;
|
||||||
import dk.camelot64.kickc.model.symbols.Variable;
|
import dk.camelot64.kickc.model.symbols.Variable;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.values.ScopeRef;
|
|
||||||
import dk.camelot64.kickc.model.values.Value;
|
|
||||||
import dk.camelot64.kickc.parser.KickCBaseVisitor;
|
import dk.camelot64.kickc.parser.KickCBaseVisitor;
|
||||||
import dk.camelot64.kickc.parser.KickCParser;
|
import dk.camelot64.kickc.parser.KickCParser;
|
||||||
|
|
||||||
@@ -97,6 +95,16 @@ public class AsmFragmentInstance {
|
|||||||
} else if(boundValue instanceof Label) {
|
} else if(boundValue instanceof Label) {
|
||||||
String param = ((Label) boundValue).getLocalName().replace('@', 'b').replace(':', '_').replace("$", "_");
|
String param = ((Label) boundValue).getLocalName().replace('@', 'b').replace(':', '_').replace("$", "_");
|
||||||
return new AsmParameter(param, false);
|
return new AsmParameter(param, false);
|
||||||
|
} else if(boundValue instanceof StructMemberRef) {
|
||||||
|
StructMemberRef structMemberRef = (StructMemberRef) boundValue;
|
||||||
|
StructDefinition structDefinition = program.getScope().getStructDefinition(structMemberRef);
|
||||||
|
Variable structMember = structDefinition.getMember(structMemberRef.getMemberName());
|
||||||
|
int memberByteOffset = structDefinition.getMemberByteOffset(structMember);
|
||||||
|
VariableRef struct = (VariableRef) structMemberRef.getStruct();
|
||||||
|
Variable structVar = program.getScope().getVariable( struct);
|
||||||
|
Registers.RegisterZpStruct structRegister = (Registers.RegisterZpStruct) structVar.getAllocation();
|
||||||
|
// TODO Use STRUCT_OFFSET constants instead of hardcoded constants
|
||||||
|
return new AsmParameter(AsmFormat.getAsmParamName(structVar, codeScopeRef)+"+"+memberByteOffset,true);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Bound Value Type not implemented " + boundValue);
|
throw new RuntimeException("Bound Value Type not implemented " + boundValue);
|
||||||
}
|
}
|
||||||
@@ -300,8 +308,7 @@ public class AsmFragmentInstance {
|
|||||||
@Override
|
@Override
|
||||||
public AsmParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) {
|
public AsmParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) {
|
||||||
Number number = NumberParser.parseLiteral(ctx.NUMBER().getText());
|
Number number = NumberParser.parseLiteral(ctx.NUMBER().getText());
|
||||||
ConstantInteger intVal = new ConstantInteger(number.longValue());
|
boolean isZp = SymbolType.BYTE.contains(number.longValue()) || SymbolType.SBYTE.contains(number.longValue());
|
||||||
boolean isZp = SymbolType.isByte(intVal.getType()) || SymbolType.isSByte(intVal.getType());
|
|
||||||
String param = AsmFormat.getAsmNumber(number);
|
String param = AsmFormat.getAsmNumber(number);
|
||||||
return new AsmParameter(param, isZp);
|
return new AsmParameter(param, isZp);
|
||||||
}
|
}
|
||||||
|
@@ -3,11 +3,8 @@ package dk.camelot64.kickc.fragment;
|
|||||||
import dk.camelot64.kickc.model.Program;
|
import dk.camelot64.kickc.model.Program;
|
||||||
import dk.camelot64.kickc.model.statements.Statement;
|
import dk.camelot64.kickc.model.statements.Statement;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeMulti;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
import dk.camelot64.kickc.model.values.ConstantValue;
|
|
||||||
import dk.camelot64.kickc.model.values.ScopeRef;
|
|
||||||
import dk.camelot64.kickc.model.values.Value;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -38,6 +35,7 @@ public class AsmFragmentInstanceSpec {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an asm fragment instance specification.
|
* Creates an asm fragment instance specification.
|
||||||
|
*
|
||||||
* @param program The symbol table
|
* @param program The symbol table
|
||||||
* @param signature The fragment signature.
|
* @param signature The fragment signature.
|
||||||
* @param bindings Binding of named values in the fragment to values (constants, variables, ...)
|
* @param bindings Binding of named values in the fragment to values (constants, variables, ...)
|
||||||
@@ -50,6 +48,7 @@ public class AsmFragmentInstanceSpec {
|
|||||||
this.codeScopeRef = codeScopeRef;
|
this.codeScopeRef = codeScopeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getSignature() {
|
public String getSignature() {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
@@ -70,7 +69,7 @@ public class AsmFragmentInstanceSpec {
|
|||||||
private ConstantValue variationConstant;
|
private ConstantValue variationConstant;
|
||||||
|
|
||||||
/** When iterating variations this is iterates the potential types for the constant value. */
|
/** When iterating variations this is iterates the potential types for the constant value. */
|
||||||
private Iterator<SymbolType> variationIterator;
|
private Iterator<SymbolTypeIntegerFixed> variationIterator;
|
||||||
|
|
||||||
/** The name of the current variation in the bindings. */
|
/** The name of the current variation in the bindings. */
|
||||||
private String variationCurrentName;
|
private String variationCurrentName;
|
||||||
@@ -82,10 +81,11 @@ public class AsmFragmentInstanceSpec {
|
|||||||
* Does any more variations of the ASM fragment instance specification exist?
|
* Does any more variations of the ASM fragment instance specification exist?
|
||||||
* Variations are used for finding the right fragment to use for constant numbers.
|
* Variations are used for finding the right fragment to use for constant numbers.
|
||||||
* For instance the number 1000 can be represented as several different types (unsigned/signed word/dword).
|
* For instance the number 1000 can be represented as several different types (unsigned/signed word/dword).
|
||||||
|
*
|
||||||
* @return true if more variations exits
|
* @return true if more variations exits
|
||||||
*/
|
*/
|
||||||
public boolean hasNextVariation() {
|
public boolean hasNextVariation() {
|
||||||
if(variationIterator==null) {
|
if(variationIterator == null) {
|
||||||
// Look for variations
|
// Look for variations
|
||||||
// TODO Currently only one iterable constant value is handled - add support for multiple iterable constant values!
|
// TODO Currently only one iterable constant value is handled - add support for multiple iterable constant values!
|
||||||
for(String name : bindings.keySet()) {
|
for(String name : bindings.keySet()) {
|
||||||
@@ -93,9 +93,9 @@ public class AsmFragmentInstanceSpec {
|
|||||||
// Found a constant value that may be multi-typed
|
// Found a constant value that may be multi-typed
|
||||||
Value value = bindings.get(name);
|
Value value = bindings.get(name);
|
||||||
if(value instanceof ConstantValue) {
|
if(value instanceof ConstantValue) {
|
||||||
SymbolType symbolType = SymbolTypeInference.inferType(program.getScope(), (ConstantValue) value);
|
ConstantLiteral constantLiteral = ((ConstantValue) value).calculateLiteral(program.getScope());
|
||||||
if(symbolType instanceof SymbolTypeMulti) {
|
if(constantLiteral instanceof ConstantInteger) {
|
||||||
Collection<SymbolType> types = ((SymbolTypeMulti) symbolType).getTypes();
|
List<SymbolTypeIntegerFixed> types = getVariationTypes(((ConstantInteger) constantLiteral).getValue());
|
||||||
if(types.size() > 1) {
|
if(types.size() > 1) {
|
||||||
// Found constant value with multiple types
|
// Found constant value with multiple types
|
||||||
variationConstant = (ConstantValue) value;
|
variationConstant = (ConstantValue) value;
|
||||||
@@ -111,13 +111,29 @@ public class AsmFragmentInstanceSpec {
|
|||||||
}
|
}
|
||||||
// If no variations exist add empty iterator
|
// If no variations exist add empty iterator
|
||||||
if(variationIterator == null) {
|
if(variationIterator == null) {
|
||||||
List<SymbolType> empty = new ArrayList<>();
|
List<SymbolTypeIntegerFixed> empty = new ArrayList<>();
|
||||||
variationIterator = empty.iterator();
|
variationIterator = empty.iterator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return variationIterator.hasNext();
|
return variationIterator.hasNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find any fixed integer types that can contain the passed integer value
|
||||||
|
* @param value the value to examine
|
||||||
|
* @return All fixed size integer types capable of representing the passed value
|
||||||
|
*/
|
||||||
|
public static List<SymbolTypeIntegerFixed> getVariationTypes(Long value) {
|
||||||
|
ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>();
|
||||||
|
for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) {
|
||||||
|
if(typeInteger.contains(value)) {
|
||||||
|
potentialTypes.add(typeInteger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return potentialTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the ASM fragment instance specification to the next available variation.
|
* Updates the ASM fragment instance specification to the next available variation.
|
||||||
* If no more variations exist the ASM fragment instance specification will become unusable.
|
* If no more variations exist the ASM fragment instance specification will become unusable.
|
||||||
@@ -126,7 +142,7 @@ public class AsmFragmentInstanceSpec {
|
|||||||
if(hasNextVariation()) {
|
if(hasNextVariation()) {
|
||||||
SymbolType nextVariationValue = variationIterator.next();
|
SymbolType nextVariationValue = variationIterator.next();
|
||||||
// Find the next name
|
// Find the next name
|
||||||
String variationConstName = "c"+variationCurrentName.substring(variationCurrentName.length() - 1);
|
String variationConstName = "c" + variationCurrentName.substring(variationCurrentName.length() - 1);
|
||||||
String variationNextName = AsmFragmentInstanceSpecFactory.getTypePrefix(nextVariationValue) + variationConstName;
|
String variationNextName = AsmFragmentInstanceSpecFactory.getTypePrefix(nextVariationValue) + variationConstName;
|
||||||
// Update bindings
|
// Update bindings
|
||||||
Value constValue = bindings.get(variationCurrentName);
|
Value constValue = bindings.get(variationCurrentName);
|
||||||
@@ -136,7 +152,7 @@ public class AsmFragmentInstanceSpec {
|
|||||||
this.signature = signature.replace(variationCurrentName, variationNextName);
|
this.signature = signature.replace(variationCurrentName, variationNextName);
|
||||||
variationCurrentName = variationNextName;
|
variationCurrentName = variationNextName;
|
||||||
variationCurrentValue = nextVariationValue;
|
variationCurrentValue = nextVariationValue;
|
||||||
} else {
|
} else {
|
||||||
this.signature = "no-more-variations";
|
this.signature = "no-more-variations";
|
||||||
this.bindings = new LinkedHashMap<>();
|
this.bindings = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
|
@@ -1,23 +1,17 @@
|
|||||||
package dk.camelot64.kickc.fragment;
|
package dk.camelot64.kickc.fragment;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
import dk.camelot64.kickc.model.*;
|
||||||
import dk.camelot64.kickc.model.ControlFlowGraph;
|
|
||||||
import dk.camelot64.kickc.model.Program;
|
|
||||||
import dk.camelot64.kickc.model.Registers;
|
|
||||||
import dk.camelot64.kickc.model.operators.Operator;
|
import dk.camelot64.kickc.model.operators.Operator;
|
||||||
|
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
||||||
|
import dk.camelot64.kickc.model.operators.Operators;
|
||||||
import dk.camelot64.kickc.model.statements.Statement;
|
import dk.camelot64.kickc.model.statements.Statement;
|
||||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||||
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
||||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
import dk.camelot64.kickc.model.symbols.*;
|
||||||
import dk.camelot64.kickc.model.symbols.Label;
|
import dk.camelot64.kickc.model.types.*;
|
||||||
import dk.camelot64.kickc.model.symbols.Symbol;
|
|
||||||
import dk.camelot64.kickc.model.symbols.Variable;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeProcedure;
|
|
||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
|
import java.lang.InternalError;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -87,6 +81,7 @@ public class AsmFragmentInstanceSpecFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the created ASM fragment instance specification
|
* Get the created ASM fragment instance specification
|
||||||
|
*
|
||||||
* @return The ASM fragment instance specification
|
* @return The ASM fragment instance specification
|
||||||
*/
|
*/
|
||||||
public AsmFragmentInstanceSpec getAsmFragmentInstanceSpec() {
|
public AsmFragmentInstanceSpec getAsmFragmentInstanceSpec() {
|
||||||
@@ -226,15 +221,56 @@ public class AsmFragmentInstanceSpecFactory {
|
|||||||
public String bind(Value value, SymbolType castType) {
|
public String bind(Value value, SymbolType castType) {
|
||||||
|
|
||||||
if(value instanceof CastValue) {
|
if(value instanceof CastValue) {
|
||||||
CastValue castVal = (CastValue) value;
|
CastValue cast = (CastValue) value;
|
||||||
SymbolType toType = castVal.getToType();
|
SymbolType toType = cast.getToType();
|
||||||
value = castVal.getValue();
|
OperatorUnary castUnary = Operators.getCastUnary(toType);
|
||||||
return bind(value, toType);
|
RValue castValue = cast.getValue();
|
||||||
|
SymbolType castValueType = SymbolTypeInference.inferType(this.program.getScope(), castValue);
|
||||||
|
if(castValueType.getSizeBytes() == toType.getSizeBytes()) {
|
||||||
|
return bind(castValue, toType);
|
||||||
|
} else {
|
||||||
|
return getOperatorFragmentName(castUnary) + bind(castValue);
|
||||||
|
}
|
||||||
} else if(value instanceof ConstantCastValue) {
|
} else if(value instanceof ConstantCastValue) {
|
||||||
ConstantCastValue castVal = (ConstantCastValue) value;
|
ConstantCastValue castVal = (ConstantCastValue) value;
|
||||||
SymbolType toType = castVal.getToType();
|
ConstantValue val = castVal.getValue();
|
||||||
value = castVal.getValue();
|
if(castType == null) {
|
||||||
return bind(value, toType);
|
SymbolType toType = castVal.getToType();
|
||||||
|
// If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff )
|
||||||
|
|
||||||
|
if(toType instanceof SymbolTypeIntegerFixed) {
|
||||||
|
SymbolTypeIntegerFixed integerFixed = (SymbolTypeIntegerFixed) toType;
|
||||||
|
ConstantLiteral constantLiteral;
|
||||||
|
Long integerValue;
|
||||||
|
try {
|
||||||
|
constantLiteral = val.calculateLiteral(program.getScope());
|
||||||
|
if(constantLiteral instanceof ConstantInteger) {
|
||||||
|
integerValue = ((ConstantInteger) constantLiteral).getValue();
|
||||||
|
} else if(constantLiteral instanceof ConstantPointer) {
|
||||||
|
integerValue = ((ConstantPointer) constantLiteral).getValue();
|
||||||
|
} else {
|
||||||
|
throw new InternalError("Not implemented " + constantLiteral);
|
||||||
|
}
|
||||||
|
} catch(ConstantNotLiteral e) {
|
||||||
|
// Assume it is a word
|
||||||
|
integerValue = 0xffffL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!integerFixed.contains(integerValue)) {
|
||||||
|
if(toType.getSizeBytes() == 1) {
|
||||||
|
val = new ConstantBinary(new ConstantInteger(0xffL, SymbolType.BYTE), Operators.BOOL_AND, val);
|
||||||
|
} else if(toType.getSizeBytes() == 2) {
|
||||||
|
val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val);
|
||||||
|
} else {
|
||||||
|
throw new InternalError("Not implemented " + toType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bind(val, toType);
|
||||||
|
} else {
|
||||||
|
return bind(val, castType);
|
||||||
|
}
|
||||||
} else if(value instanceof PointerDereference) {
|
} else if(value instanceof PointerDereference) {
|
||||||
PointerDereference deref = (PointerDereference) value;
|
PointerDereference deref = (PointerDereference) value;
|
||||||
SymbolType ptrType = null;
|
SymbolType ptrType = null;
|
||||||
@@ -267,6 +303,27 @@ public class AsmFragmentInstanceSpecFactory {
|
|||||||
String name = "la" + nextLabelIdx++;
|
String name = "la" + nextLabelIdx++;
|
||||||
bind(name, value);
|
bind(name, value);
|
||||||
return name;
|
return name;
|
||||||
|
} else if(value instanceof StructZero) {
|
||||||
|
return "vssf" + ((StructZero) value).getTypeStruct().getSizeBytes();
|
||||||
|
} else if(value instanceof StructMemberRef) {
|
||||||
|
StructMemberRef structMemberRef = (StructMemberRef) value;
|
||||||
|
StructDefinition structDefinition = program.getScope().getStructDefinition(structMemberRef);
|
||||||
|
Variable structMember = structDefinition.getMember(structMemberRef.getMemberName());
|
||||||
|
int memberByteOffset = structDefinition.getMemberByteOffset(structMember);
|
||||||
|
|
||||||
|
RValue struct = structMemberRef.getStruct();
|
||||||
|
if(struct instanceof VariableRef) {
|
||||||
|
Variable structVar = program.getScope().getVariable((VariableRef) struct);
|
||||||
|
if(structVar.getAllocation() instanceof Registers.RegisterZpStruct) {
|
||||||
|
Registers.RegisterZpStruct structRegister = (Registers.RegisterZpStruct) structVar.getAllocation();
|
||||||
|
Registers.RegisterZpStructMember memberRegister = structRegister.getMemberRegister(memberByteOffset);
|
||||||
|
String name = getTypePrefix(structMember.getType()) + getRegisterName(memberRegister);
|
||||||
|
bind(name, structMemberRef);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return bind(struct) + "_mbr_" + memberByteOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Binding of value type not supported " + value);
|
throw new RuntimeException("Binding of value type not supported " + value);
|
||||||
}
|
}
|
||||||
@@ -288,35 +345,37 @@ public class AsmFragmentInstanceSpecFactory {
|
|||||||
* @return The type name
|
* @return The type name
|
||||||
*/
|
*/
|
||||||
static String getTypePrefix(SymbolType type) {
|
static String getTypePrefix(SymbolType type) {
|
||||||
if(SymbolType.isByte(type)) {
|
if(SymbolType.BYTE.equals(type)) {
|
||||||
return "vbu";
|
return "vbu";
|
||||||
} else if(SymbolType.isSByte(type)) {
|
} else if(SymbolType.SBYTE.equals(type)) {
|
||||||
return "vbs";
|
return "vbs";
|
||||||
} else if(SymbolType.isWord(type)) {
|
} else if(SymbolType.WORD.equals(type)) {
|
||||||
return "vwu";
|
return "vwu";
|
||||||
} else if(SymbolType.isSWord(type)) {
|
} else if(SymbolType.SWORD.equals(type)) {
|
||||||
return "vws";
|
return "vws";
|
||||||
} else if(SymbolType.isDWord(type)) {
|
} else if(SymbolType.DWORD.equals(type)) {
|
||||||
return "vdu";
|
return "vdu";
|
||||||
} else if(SymbolType.isSDWord(type)) {
|
} else if(SymbolType.SDWORD.equals(type)) {
|
||||||
return "vds";
|
return "vds";
|
||||||
} else if(SymbolType.STRING.equals(type)) {
|
} else if(SymbolType.STRING.equals(type)) {
|
||||||
return "pbu";
|
return "pbu";
|
||||||
} else if(SymbolType.BOOLEAN.equals(type)) {
|
} else if(SymbolType.BOOLEAN.equals(type)) {
|
||||||
return "vbo";
|
return "vbo";
|
||||||
|
} else if(type instanceof SymbolTypeStruct) {
|
||||||
|
return "vss";
|
||||||
} else if(type instanceof SymbolTypePointer) {
|
} else if(type instanceof SymbolTypePointer) {
|
||||||
SymbolType elementType = ((SymbolTypePointer) type).getElementType();
|
SymbolType elementType = ((SymbolTypePointer) type).getElementType();
|
||||||
if(SymbolType.isByte(elementType)) {
|
if(SymbolType.BYTE.equals(elementType)) {
|
||||||
return "pbu";
|
return "pbu";
|
||||||
} else if(SymbolType.isSByte(elementType)) {
|
} else if(SymbolType.SBYTE.equals(elementType)) {
|
||||||
return "pbs";
|
return "pbs";
|
||||||
} else if(SymbolType.isWord(elementType)) {
|
} else if(SymbolType.WORD.equals(elementType)) {
|
||||||
return "pwu";
|
return "pwu";
|
||||||
} else if(SymbolType.isSWord(elementType)) {
|
} else if(SymbolType.SWORD.equals(elementType)) {
|
||||||
return "pws";
|
return "pws";
|
||||||
} else if(SymbolType.isDWord(elementType)) {
|
} else if(SymbolType.DWORD.equals(elementType)) {
|
||||||
return "pdu";
|
return "pdu";
|
||||||
} else if(SymbolType.isSDWord(elementType)) {
|
} else if(SymbolType.SDWORD.equals(elementType)) {
|
||||||
return "pds";
|
return "pds";
|
||||||
} else if(SymbolType.BOOLEAN.equals(elementType)) {
|
} else if(SymbolType.BOOLEAN.equals(elementType)) {
|
||||||
return "pbo";
|
return "pbo";
|
||||||
@@ -324,6 +383,8 @@ public class AsmFragmentInstanceSpecFactory {
|
|||||||
return "ppr";
|
return "ppr";
|
||||||
} else if(elementType instanceof SymbolTypePointer) {
|
} else if(elementType instanceof SymbolTypePointer) {
|
||||||
return "ppt";
|
return "ppt";
|
||||||
|
} else if(elementType instanceof SymbolTypeStruct) {
|
||||||
|
return "pss";
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Not implemented " + type);
|
throw new RuntimeException("Not implemented " + type);
|
||||||
}
|
}
|
||||||
@@ -344,8 +405,9 @@ public class AsmFragmentInstanceSpecFactory {
|
|||||||
Registers.RegisterType.ZP_BOOL.equals(register.getType()) ||
|
Registers.RegisterType.ZP_BOOL.equals(register.getType()) ||
|
||||||
Registers.RegisterType.ZP_BYTE.equals(register.getType()) ||
|
Registers.RegisterType.ZP_BYTE.equals(register.getType()) ||
|
||||||
Registers.RegisterType.ZP_WORD.equals(register.getType()) ||
|
Registers.RegisterType.ZP_WORD.equals(register.getType()) ||
|
||||||
Registers.RegisterType.ZP_DWORD.equals(register.getType())
|
Registers.RegisterType.ZP_DWORD.equals(register.getType()) ||
|
||||||
) {
|
Registers.RegisterType.ZP_STRUCT.equals(register.getType())
|
||||||
|
) {
|
||||||
// Examine if the ZP register is already bound
|
// Examine if the ZP register is already bound
|
||||||
Registers.RegisterZp registerZp = (Registers.RegisterZp) register;
|
Registers.RegisterZp registerZp = (Registers.RegisterZp) register;
|
||||||
String zpNameIdx = null;
|
String zpNameIdx = null;
|
||||||
|
24
src/main/java/dk/camelot64/kickc/model/InternalError.java
Normal file
24
src/main/java/dk/camelot64/kickc/model/InternalError.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package dk.camelot64.kickc.model;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.statements.Statement;
|
||||||
|
import dk.camelot64.kickc.model.statements.StatementSource;
|
||||||
|
|
||||||
|
/** Signals an internal error in the compiler. Should be reported to the author. */
|
||||||
|
public class InternalError extends RuntimeException {
|
||||||
|
|
||||||
|
public InternalError(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InternalError(String message, StatementSource source) {
|
||||||
|
super(message+"\n"+source.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public InternalError(String message, Statement statement) {
|
||||||
|
this(message, statement.getSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
public InternalError(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
@@ -45,6 +45,7 @@ public class Registers {
|
|||||||
ZP_BYTE,
|
ZP_BYTE,
|
||||||
ZP_WORD,
|
ZP_WORD,
|
||||||
ZP_DWORD,
|
ZP_DWORD,
|
||||||
|
ZP_STRUCT,
|
||||||
ZP_BOOL,
|
ZP_BOOL,
|
||||||
CONSTANT
|
CONSTANT
|
||||||
}
|
}
|
||||||
@@ -104,6 +105,7 @@ public class Registers {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return zp;
|
return zp;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -150,6 +152,38 @@ public class Registers {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Zero page addresses used as a register for a struct variable. */
|
||||||
|
public static class RegisterZpStruct extends RegisterZp {
|
||||||
|
|
||||||
|
public RegisterZpStruct(int zp) {
|
||||||
|
super(zp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegisterZpStructMember getMemberRegister(int memberByteOffset) {
|
||||||
|
return new RegisterZpStructMember(getZp()+memberByteOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RegisterType getType() {
|
||||||
|
return RegisterType.ZP_STRUCT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Zero page addresses used as a register for a struct member variable. */
|
||||||
|
public static class RegisterZpStructMember extends RegisterZp {
|
||||||
|
|
||||||
|
public RegisterZpStructMember(int zp) {
|
||||||
|
super(zp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RegisterType getType() {
|
||||||
|
return RegisterType.ZP_STRUCT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** A zero page address used as a register for a boolean variable. */
|
/** A zero page address used as a register for a boolean variable. */
|
||||||
public static class RegisterZpBool extends RegisterZp {
|
public static class RegisterZpBool extends RegisterZp {
|
||||||
|
@@ -224,9 +224,11 @@ public class VariableReferenceInfos {
|
|||||||
public Collection<Integer> getConstRefStatements(ConstantRef constRef) {
|
public Collection<Integer> getConstRefStatements(ConstantRef constRef) {
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
||||||
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
||||||
refs.stream()
|
if(refs!=null) {
|
||||||
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
refs.stream()
|
||||||
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
||||||
|
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
||||||
|
}
|
||||||
return stmts;
|
return stmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,9 +241,11 @@ public class VariableReferenceInfos {
|
|||||||
public Collection<Integer> getVarRefStatements(VariableRef varRef) {
|
public Collection<Integer> getVarRefStatements(VariableRef varRef) {
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
|
||||||
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
||||||
refs.stream()
|
if(refs!=null) {
|
||||||
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
refs.stream()
|
||||||
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
||||||
|
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
||||||
|
}
|
||||||
return stmts;
|
return stmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,10 +258,12 @@ public class VariableReferenceInfos {
|
|||||||
public Collection<Integer> getVarUseStatements(VariableRef varRef) {
|
public Collection<Integer> getVarUseStatements(VariableRef varRef) {
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
|
||||||
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
||||||
refs.stream()
|
if(refs!=null) {
|
||||||
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
refs.stream()
|
||||||
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE == referenceToSymbolVar.getReferenceType())
|
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
||||||
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE == referenceToSymbolVar.getReferenceType())
|
||||||
|
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
||||||
|
}
|
||||||
return stmts;
|
return stmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,10 +277,12 @@ public class VariableReferenceInfos {
|
|||||||
public Collection<SymbolVariableRef> getSymbolRefConsts(ConstantRef constRef) {
|
public Collection<SymbolVariableRef> getSymbolRefConsts(ConstantRef constRef) {
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
||||||
LinkedHashSet<SymbolVariableRef> constRefs = new LinkedHashSet<>();
|
LinkedHashSet<SymbolVariableRef> constRefs = new LinkedHashSet<>();
|
||||||
refs.stream()
|
if(refs!=null) {
|
||||||
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()))
|
refs.stream()
|
||||||
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol)
|
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()))
|
||||||
.forEach(referenceToSymbolVar -> constRefs.add(((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol()));
|
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol)
|
||||||
|
.forEach(referenceToSymbolVar -> constRefs.add(((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol()));
|
||||||
|
}
|
||||||
return constRefs;
|
return constRefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
package dk.camelot64.kickc.model.iterator;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.operators.Operator;
|
||||||
|
import dk.camelot64.kickc.model.values.Value;
|
||||||
|
|
||||||
|
/** A unary or binary operator expression.
|
||||||
|
* Iterable using {@link ProgramExpressionIterator}.
|
||||||
|
* */
|
||||||
|
public interface ProgramExpression {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the operator
|
||||||
|
*
|
||||||
|
* @return the operator
|
||||||
|
*/
|
||||||
|
Operator getOperator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the unary/binary expression with a new value.
|
||||||
|
*
|
||||||
|
* Throws an exception if replacement is not possible
|
||||||
|
*
|
||||||
|
* @param value The new value.
|
||||||
|
*/
|
||||||
|
void set(Value value);
|
||||||
|
}
|
@@ -0,0 +1,406 @@
|
|||||||
|
package dk.camelot64.kickc.model.iterator;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.Comment;
|
||||||
|
import dk.camelot64.kickc.model.InternalError;
|
||||||
|
import dk.camelot64.kickc.model.operators.OperatorBinary;
|
||||||
|
import dk.camelot64.kickc.model.operators.Operators;
|
||||||
|
import dk.camelot64.kickc.model.statements.Statement;
|
||||||
|
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||||
|
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
||||||
|
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||||
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
|
import dk.camelot64.kickc.model.symbols.Scope;
|
||||||
|
import dk.camelot64.kickc.model.symbols.Variable;
|
||||||
|
import dk.camelot64.kickc.model.symbols.VariableIntermediate;
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||||
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A binary expression in the program being iterated by {@link ProgramExpressionIterator}
|
||||||
|
*/
|
||||||
|
public interface ProgramExpressionBinary extends ProgramExpression {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the left operand
|
||||||
|
*
|
||||||
|
* @return The left operand
|
||||||
|
*/
|
||||||
|
RValue getLeft();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the binary operator
|
||||||
|
*
|
||||||
|
* @return the operator
|
||||||
|
*/
|
||||||
|
OperatorBinary getOperator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the right operand
|
||||||
|
*
|
||||||
|
* @return The right operand
|
||||||
|
*/
|
||||||
|
RValue getRight();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a cast to the left operand
|
||||||
|
*
|
||||||
|
* @param toType The toType to cast to
|
||||||
|
*/
|
||||||
|
void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a cast to the right operand
|
||||||
|
*
|
||||||
|
* @param toType The toType to cast to
|
||||||
|
*/
|
||||||
|
void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols);
|
||||||
|
|
||||||
|
|
||||||
|
/** Binary expression assignment rvalue. */
|
||||||
|
class ProgramExpressionBinaryAssignmentRValue implements ProgramExpressionBinary {
|
||||||
|
|
||||||
|
private final StatementAssignment assignment;
|
||||||
|
|
||||||
|
ProgramExpressionBinaryAssignmentRValue(StatementAssignment assignment) {
|
||||||
|
this.assignment = assignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getLeft() {
|
||||||
|
return assignment.getrValue1();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorBinary getOperator() {
|
||||||
|
return (OperatorBinary) assignment.getOperator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getRight() {
|
||||||
|
return assignment.getrValue2();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
assignment.setrValue2((RValue) value);
|
||||||
|
assignment.setOperator(null);
|
||||||
|
assignment.setrValue1(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
if(assignment.getrValue1() instanceof ConstantValue) {
|
||||||
|
assignment.setrValue1(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue1()));
|
||||||
|
} else {
|
||||||
|
Scope blockScope = symbols.getScope(currentScope);
|
||||||
|
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
|
||||||
|
tmpVar.setTypeInferred(toType);
|
||||||
|
StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||||
|
assignment.setrValue1(tmpVar.getRef());
|
||||||
|
stmtIt.previous();
|
||||||
|
stmtIt.add(newAssignment);
|
||||||
|
stmtIt.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
if(assignment.getrValue2() instanceof ConstantValue) {
|
||||||
|
assignment.setrValue2(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue2()));
|
||||||
|
} else {
|
||||||
|
Scope blockScope = symbols.getScope(currentScope);
|
||||||
|
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
|
||||||
|
tmpVar.setTypeInferred(toType);
|
||||||
|
StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||||
|
assignment.setrValue2(tmpVar.getRef());
|
||||||
|
stmtIt.previous();
|
||||||
|
stmtIt.add(newAssignment);
|
||||||
|
stmtIt.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Binary expression - assignment lvalue and the "total" rvalue. */
|
||||||
|
class ProgramExpressionBinaryAssignmentLValue implements ProgramExpressionBinary {
|
||||||
|
private final StatementAssignment assignment;
|
||||||
|
|
||||||
|
ProgramExpressionBinaryAssignmentLValue(StatementAssignment assignment) {
|
||||||
|
this.assignment = assignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getLeft() {
|
||||||
|
return assignment.getlValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorBinary getOperator() {
|
||||||
|
return Operators.ASSIGNMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getRight() {
|
||||||
|
if(assignment.getrValue1() == null && assignment.getOperator() == null) {
|
||||||
|
return assignment.getrValue2();
|
||||||
|
} else {
|
||||||
|
return new AssignmentRValue(assignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
throw new InternalError("Updating an entire assignment is not allowed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
if(assignment.getlValue() instanceof VariableRef) {
|
||||||
|
Variable variable = symbols.getVariable((VariableRef) assignment.getlValue());
|
||||||
|
if(variable.isInferredType())
|
||||||
|
variable.setTypeInferred(toType);
|
||||||
|
else
|
||||||
|
throw new InternalError("Cannot cast declared type!" + variable.toString());
|
||||||
|
} else {
|
||||||
|
Scope blockScope = symbols.getScope(currentScope);
|
||||||
|
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
|
||||||
|
SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
|
||||||
|
tmpVar.setTypeInferred(rightType);
|
||||||
|
StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||||
|
assignment.setlValue(tmpVar.getRef());
|
||||||
|
stmtIt.add(newAssignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
if(assignment.getrValue1() == null && assignment.getOperator() == null) {
|
||||||
|
assignment.setOperator(Operators.getCastUnary(toType));
|
||||||
|
} else {
|
||||||
|
Scope blockScope = symbols.getScope(currentScope);
|
||||||
|
VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
|
||||||
|
SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
|
||||||
|
tmpVar.setTypeInferred(rightType);
|
||||||
|
StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
|
||||||
|
assignment.setlValue(tmpVar.getRef());
|
||||||
|
stmtIt.add(newAssignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Binary expression conditional jump. */
|
||||||
|
class ProgramExpressionBinaryConditionalJump implements ProgramExpressionBinary {
|
||||||
|
private final StatementConditionalJump conditionalJump;
|
||||||
|
|
||||||
|
ProgramExpressionBinaryConditionalJump(StatementConditionalJump assignment) {
|
||||||
|
this.conditionalJump = assignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getLeft() {
|
||||||
|
return conditionalJump.getrValue1();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorBinary getOperator() {
|
||||||
|
return (OperatorBinary) conditionalJump.getOperator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getRight() {
|
||||||
|
return conditionalJump.getrValue2();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
conditionalJump.setrValue2((RValue) value);
|
||||||
|
conditionalJump.setOperator(null);
|
||||||
|
conditionalJump.setrValue1(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
if(conditionalJump.getrValue1() instanceof ConstantValue) {
|
||||||
|
conditionalJump.setrValue1(new ConstantCastValue(toType, (ConstantValue) conditionalJump.getrValue1()));
|
||||||
|
} else {
|
||||||
|
throw new InternalError("Not implemented!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
if(conditionalJump.getrValue2() instanceof ConstantValue) {
|
||||||
|
conditionalJump.setrValue2(new ConstantCastValue(toType, (ConstantValue) conditionalJump.getrValue2()));
|
||||||
|
} else {
|
||||||
|
throw new InternalError("Not implemented!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Binary expression as part of a constant expression. */
|
||||||
|
class ProgramExpressionBinaryConstant implements ProgramExpressionBinary {
|
||||||
|
/** A program value containing a {@link ConstantBinary}. */
|
||||||
|
private ProgramValue programValue;
|
||||||
|
|
||||||
|
public ProgramExpressionBinaryConstant(ProgramValue programValue) {
|
||||||
|
this.programValue = programValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstantBinary getConstantBinary() {
|
||||||
|
return (ConstantBinary) programValue.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getLeft() {
|
||||||
|
return getConstantBinary().getLeft();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorBinary getOperator() {
|
||||||
|
return getConstantBinary().getOperator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getRight() {
|
||||||
|
return getConstantBinary().getRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
programValue.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
getConstantBinary().setLeft(new ConstantCastValue(toType, getConstantBinary().getLeft()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
getConstantBinary().setRight(new ConstantCastValue(toType, getConstantBinary().getRight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Binary expression that is an indexed dereference of a pointer eg. ptr[i] or *(ptr+i). */
|
||||||
|
class ProgramExpressionBinaryPointerDereferenceIndexed implements ProgramExpressionBinary {
|
||||||
|
/** A program value containing a {@link ConstantBinary}. */
|
||||||
|
private ProgramValue programValue;
|
||||||
|
|
||||||
|
public ProgramExpressionBinaryPointerDereferenceIndexed(ProgramValue programValue) {
|
||||||
|
this.programValue = programValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PointerDereferenceIndexed getPointerDereferenceIndexed() {
|
||||||
|
return (PointerDereferenceIndexed) programValue.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getLeft() {
|
||||||
|
return getPointerDereferenceIndexed().getPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorBinary getOperator() {
|
||||||
|
return Operators.PLUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getRight() {
|
||||||
|
return getPointerDereferenceIndexed().getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
programValue.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
if(getPointerDereferenceIndexed().getPointer() instanceof ConstantValue) {
|
||||||
|
getPointerDereferenceIndexed().setPointer(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getPointer()));
|
||||||
|
} else {
|
||||||
|
// Try to use CastValue - may later have to be supported!
|
||||||
|
getPointerDereferenceIndexed().setPointer(new CastValue(toType, getPointerDereferenceIndexed().getPointer()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
if(getPointerDereferenceIndexed().getIndex() instanceof ConstantValue) {
|
||||||
|
getPointerDereferenceIndexed().setIndex(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getIndex()));
|
||||||
|
} else if( getPointerDereferenceIndexed().getIndex() instanceof VariableRef) {
|
||||||
|
Variable variable = symbols.getVariable((VariableRef) getPointerDereferenceIndexed().getIndex());
|
||||||
|
if(variable.isInferredType())
|
||||||
|
variable.setTypeInferred(toType);
|
||||||
|
else
|
||||||
|
throw new InternalError("Cannot cast declared type!" + variable.toString());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Try to use CastValue - may later have to be supported!
|
||||||
|
getPointerDereferenceIndexed().setIndex(new CastValue(toType, getPointerDereferenceIndexed().getIndex()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Assignment of a phi value to a phi variable. */
|
||||||
|
class ProgramExpressionBinaryPhiValueAssignemnt implements ProgramExpressionBinary {
|
||||||
|
|
||||||
|
private final StatementPhiBlock.PhiVariable phiVariable;
|
||||||
|
private final StatementPhiBlock.PhiRValue value;
|
||||||
|
|
||||||
|
public ProgramExpressionBinaryPhiValueAssignemnt(StatementPhiBlock.PhiVariable phiVariable, StatementPhiBlock.PhiRValue value) {
|
||||||
|
this.phiVariable = phiVariable;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getLeft() {
|
||||||
|
return phiVariable.getVariable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorBinary getOperator() {
|
||||||
|
return Operators.ASSIGNMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getRight() {
|
||||||
|
return value.getrValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
Variable variable = symbols.getVariable(phiVariable.getVariable());
|
||||||
|
if(variable.isInferredType())
|
||||||
|
variable.setTypeInferred(toType);
|
||||||
|
else
|
||||||
|
throw new InternalError("Cannot cast declared type!" + variable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
|
||||||
|
if(getRight() instanceof VariableRef) {
|
||||||
|
Variable variable = symbols.getVariable((VariableRef) getRight());
|
||||||
|
if(variable.isInferredType())
|
||||||
|
variable.setTypeInferred(toType);
|
||||||
|
} else if(getRight() instanceof ConstantValue) {
|
||||||
|
value.setrValue(new ConstantCastValue(toType, (ConstantValue) getRight()));
|
||||||
|
} else {
|
||||||
|
value.setrValue(new CastValue(toType, getRight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
throw new InternalError("Not supported!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,26 @@
|
|||||||
|
package dk.camelot64.kickc.model.iterator;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||||
|
import dk.camelot64.kickc.model.statements.Statement;
|
||||||
|
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
/** A handler that performs some action for unary/binary expressions in the program.
|
||||||
|
* A {@link ProgramExpressionIterator} can be used to iterate all unary/binary expressions in a part of the program.
|
||||||
|
* The Handler then receives all unary/binary expressions one at a time.
|
||||||
|
* The Handler has the option of modifying the expression. After the handler is executed all sub-values are recursed.
|
||||||
|
* The execute() method furthermore receives some extra parameters with information about the context of the passed value.
|
||||||
|
*/
|
||||||
|
public interface ProgramExpressionHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a single expression
|
||||||
|
*
|
||||||
|
* @param programExpression The expression
|
||||||
|
* @param currentStmt The statement iterator - just past the current statement that the value is a part of. Current statment can be retrieved by calling
|
||||||
|
* @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block.
|
||||||
|
* @param currentBlock The current block that the value is a part of
|
||||||
|
*/
|
||||||
|
void execute(ProgramExpression programExpression, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,75 @@
|
|||||||
|
package dk.camelot64.kickc.model.iterator;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||||
|
import dk.camelot64.kickc.model.Program;
|
||||||
|
import dk.camelot64.kickc.model.statements.Statement;
|
||||||
|
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||||
|
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
||||||
|
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||||
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capable of iterating the different structures of a Program (graph, block, statement, symboltable, symbol).
|
||||||
|
* Creates appropriate BinaryExpressions and passes them to a ProgramExpressionHandler.
|
||||||
|
* Iteration might be guided (eg. filtering some types of the structure to iterate at call-time)
|
||||||
|
*/
|
||||||
|
public class ProgramExpressionIterator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a handler on all values in the entire program (both in the control flow graph and the symbol table.)
|
||||||
|
*
|
||||||
|
* @param program The program
|
||||||
|
* @param handler The handler to execute
|
||||||
|
*/
|
||||||
|
public static void execute(Program program, ProgramExpressionHandler handler) {
|
||||||
|
// Iterate all symbols
|
||||||
|
ProgramValueHandler programValueHandler = (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||||
|
if(programValue.get() instanceof ConstantBinary) {
|
||||||
|
handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), currentStmt, stmtIt, currentBlock);
|
||||||
|
} else if(programValue.get() instanceof ConstantUnary) {
|
||||||
|
handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), currentStmt, stmtIt, currentBlock);
|
||||||
|
} else if(programValue.get() instanceof PointerDereferenceIndexed) {
|
||||||
|
handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), currentStmt, stmtIt, currentBlock);
|
||||||
|
} else if(programValue.get() instanceof ConstantCastValue) {
|
||||||
|
handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstantCast(programValue), currentStmt, stmtIt, currentBlock);
|
||||||
|
} else if(programValue.get() instanceof CastValue) {
|
||||||
|
handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), currentStmt, stmtIt, currentBlock);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ProgramValueIterator.execute(program.getScope(), programValueHandler);
|
||||||
|
|
||||||
|
// Iterate all blocks/statements
|
||||||
|
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||||
|
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
|
||||||
|
while(stmtIt.hasNext()) {
|
||||||
|
Statement stmt = stmtIt.next();
|
||||||
|
if(stmt instanceof StatementAssignment) {
|
||||||
|
StatementAssignment assignment = (StatementAssignment) stmt;
|
||||||
|
if(assignment.getrValue1() != null && assignment.getOperator() != null && assignment.getrValue2() != null) {
|
||||||
|
handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryAssignmentRValue(assignment), stmt, stmtIt, block);
|
||||||
|
} else if(assignment.getrValue1() == null && assignment.getOperator() != null && assignment.getrValue2() != null) {
|
||||||
|
handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryAssignmentRValue(assignment), stmt, stmtIt, block);
|
||||||
|
}
|
||||||
|
handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue(assignment), stmt, stmtIt, block);
|
||||||
|
} else if(stmt instanceof StatementConditionalJump) {
|
||||||
|
StatementConditionalJump condJump = (StatementConditionalJump) stmt;
|
||||||
|
if(condJump.getrValue1() != null && condJump.getOperator() != null && condJump.getrValue2() != null) {
|
||||||
|
handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConditionalJump(condJump), stmt, stmtIt, block);
|
||||||
|
}
|
||||||
|
} else if(stmt instanceof StatementPhiBlock) {
|
||||||
|
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) stmt).getPhiVariables()) {
|
||||||
|
for(StatementPhiBlock.PhiRValue value : phiVariable.getValues()) {
|
||||||
|
handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPhiValueAssignemnt(phiVariable, value), stmt, stmtIt, block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Iterate all statement values
|
||||||
|
ProgramValueIterator.execute(stmt, programValueHandler, stmtIt, block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,146 @@
|
|||||||
|
package dk.camelot64.kickc.model.iterator;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
||||||
|
import dk.camelot64.kickc.model.operators.Operators;
|
||||||
|
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||||
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A binary expression in the program being iterated by {@link ProgramExpressionIterator}
|
||||||
|
*/
|
||||||
|
public interface ProgramExpressionUnary extends ProgramExpression {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the unary operator
|
||||||
|
*
|
||||||
|
* @return the operator
|
||||||
|
*/
|
||||||
|
OperatorUnary getOperator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the right operand
|
||||||
|
*
|
||||||
|
* @return The right operand
|
||||||
|
*/
|
||||||
|
RValue getOperand();
|
||||||
|
|
||||||
|
/** Unary expression assignment rvalue. */
|
||||||
|
class ProgramExpressionUnaryAssignmentRValue implements ProgramExpressionUnary {
|
||||||
|
private final StatementAssignment assignment;
|
||||||
|
|
||||||
|
ProgramExpressionUnaryAssignmentRValue(StatementAssignment assignment) {
|
||||||
|
this.assignment = assignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorUnary getOperator() {
|
||||||
|
return (OperatorUnary) assignment.getOperator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getOperand() {
|
||||||
|
return assignment.getrValue2();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
assignment.setrValue2((RValue) value);
|
||||||
|
assignment.setOperator(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unary expression as part of a constant expression. */
|
||||||
|
class ProgramExpressionUnaryConstant implements ProgramExpressionUnary {
|
||||||
|
|
||||||
|
/** A ProgramValue containing a {@link ConstantUnary}. */
|
||||||
|
private ProgramValue programValue;
|
||||||
|
|
||||||
|
ProgramExpressionUnaryConstant(ProgramValue programValue) {
|
||||||
|
this.programValue = programValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstantUnary getConstantUnary() {
|
||||||
|
return (ConstantUnary) programValue.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorUnary getOperator() {
|
||||||
|
return (getConstantUnary()).getOperator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getOperand() {
|
||||||
|
return getConstantUnary().getOperand();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
programValue.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unary cast expression {@link ConstantCastValue} as part of a constant expression. */
|
||||||
|
class ProgramExpressionUnaryConstantCast implements ProgramExpressionUnary {
|
||||||
|
|
||||||
|
/** A ProgramValue containing a {@link ConstantCastValue}. */
|
||||||
|
private ProgramValue programValue;
|
||||||
|
|
||||||
|
ProgramExpressionUnaryConstantCast(ProgramValue programValue) {
|
||||||
|
this.programValue = programValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstantCastValue getConstantUnary() {
|
||||||
|
return (ConstantCastValue) programValue.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorUnary getOperator() {
|
||||||
|
return Operators.getCastUnary(getConstantUnary().getToType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getOperand() {
|
||||||
|
return getConstantUnary().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
programValue.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unary cast expression {@link CastValue} as part of a constant expression. */
|
||||||
|
class ProgramExpressionUnaryCast implements ProgramExpressionUnary {
|
||||||
|
|
||||||
|
/** A ProgramValue containing a {@link CastValue}. */
|
||||||
|
private ProgramValue programValue;
|
||||||
|
|
||||||
|
ProgramExpressionUnaryCast(ProgramValue programValue) {
|
||||||
|
this.programValue = programValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CastValue getConstantUnary() {
|
||||||
|
return (CastValue) programValue.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorUnary getOperator() {
|
||||||
|
return Operators.getCastUnary(getConstantUnary().getToType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getOperand() {
|
||||||
|
return getConstantUnary().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
programValue.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@@ -50,10 +50,10 @@ public class ProgramValueIterator {
|
|||||||
*/
|
*/
|
||||||
public static void execute(SymbolVariable symbolVariable, ProgramValueHandler programValueHandler) {
|
public static void execute(SymbolVariable symbolVariable, ProgramValueHandler programValueHandler) {
|
||||||
if(symbolVariable.getType() instanceof SymbolTypeArray) {
|
if(symbolVariable.getType() instanceof SymbolTypeArray) {
|
||||||
execute(new ProgramValue.TypeArraySize((SymbolTypeArray) symbolVariable.getType()), programValueHandler, null, null, null);
|
execute(new ProgramValue.ProgramValueTypeArraySize((SymbolTypeArray) symbolVariable.getType()), programValueHandler, null, null, null);
|
||||||
}
|
}
|
||||||
if(symbolVariable instanceof ConstantVar) {
|
if(symbolVariable instanceof ConstantVar) {
|
||||||
execute(new ProgramValue.ConstantVariableValue((ConstantVar) symbolVariable), programValueHandler, null, null, null);
|
execute(new ProgramValue.ProgramValueConstantVar((ConstantVar) symbolVariable), programValueHandler, null, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ public class ProgramValueIterator {
|
|||||||
// The sequence RValue1, RValue2, LValue is important - as it is essential for {@link dk.camelot64.kickc.passes.Pass1GenerateSingleStaticAssignmentForm} to create the correct SSA
|
// The sequence RValue1, RValue2, LValue is important - as it is essential for {@link dk.camelot64.kickc.passes.Pass1GenerateSingleStaticAssignmentForm} to create the correct SSA
|
||||||
execute(new ProgramValue.RValue1((StatementAssignment) statement), handler, statement, statementsIt, block);
|
execute(new ProgramValue.RValue1((StatementAssignment) statement), handler, statement, statementsIt, block);
|
||||||
execute(new ProgramValue.RValue2((StatementAssignment) statement), handler, statement, statementsIt, block);
|
execute(new ProgramValue.RValue2((StatementAssignment) statement), handler, statement, statementsIt, block);
|
||||||
execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
||||||
} else if(statement instanceof StatementCall) {
|
} else if(statement instanceof StatementCall) {
|
||||||
StatementCall call = (StatementCall) statement;
|
StatementCall call = (StatementCall) statement;
|
||||||
if(call.getParameters() != null) {
|
if(call.getParameters() != null) {
|
||||||
@@ -107,7 +107,7 @@ public class ProgramValueIterator {
|
|||||||
execute(new ProgramValue.CallParameter(call, i), handler, statement, statementsIt, block);
|
execute(new ProgramValue.CallParameter(call, i), handler, statement, statementsIt, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
||||||
} else if(statement instanceof StatementCallPointer) {
|
} else if(statement instanceof StatementCallPointer) {
|
||||||
StatementCallPointer call = (StatementCallPointer) statement;
|
StatementCallPointer call = (StatementCallPointer) statement;
|
||||||
execute(new ProgramValue.CallPointerProcedure((StatementCallPointer) statement), handler, statement, statementsIt, block);
|
execute(new ProgramValue.CallPointerProcedure((StatementCallPointer) statement), handler, statement, statementsIt, block);
|
||||||
@@ -117,7 +117,7 @@ public class ProgramValueIterator {
|
|||||||
execute(new ProgramValue.CallPointerParameter(call, i), handler, statement, statementsIt, block);
|
execute(new ProgramValue.CallPointerParameter(call, i), handler, statement, statementsIt, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
||||||
} else if(statement instanceof StatementConditionalJump) {
|
} else if(statement instanceof StatementConditionalJump) {
|
||||||
execute(new ProgramValue.CondRValue1((StatementConditionalJump) statement), handler, statement, statementsIt, block);
|
execute(new ProgramValue.CondRValue1((StatementConditionalJump) statement), handler, statement, statementsIt, block);
|
||||||
execute(new ProgramValue.CondRValue2((StatementConditionalJump) statement), handler, statement, statementsIt, block);
|
execute(new ProgramValue.CondRValue2((StatementConditionalJump) statement), handler, statement, statementsIt, block);
|
||||||
@@ -137,15 +137,15 @@ public class ProgramValueIterator {
|
|||||||
StatementKickAsm statementKickAsm = (StatementKickAsm) statement;
|
StatementKickAsm statementKickAsm = (StatementKickAsm) statement;
|
||||||
RValue location = statementKickAsm.getLocation();
|
RValue location = statementKickAsm.getLocation();
|
||||||
if(location!=null) {
|
if(location!=null) {
|
||||||
execute(new ProgramValue.KickAsmLocation(statementKickAsm), handler, statement, statementsIt, block);
|
execute(new ProgramValue.ProgramValueKickAsmLocation(statementKickAsm), handler, statement, statementsIt, block);
|
||||||
}
|
}
|
||||||
RValue bytes = statementKickAsm.getLocation();
|
RValue bytes = statementKickAsm.getLocation();
|
||||||
if(bytes!=null) {
|
if(bytes!=null) {
|
||||||
execute(new ProgramValue.KickAsmBytes(statementKickAsm), handler, statement, statementsIt, block);
|
execute(new ProgramValue.ProgramValueKickAsmBytes(statementKickAsm), handler, statement, statementsIt, block);
|
||||||
}
|
}
|
||||||
RValue cycles = statementKickAsm.getLocation();
|
RValue cycles = statementKickAsm.getLocation();
|
||||||
if(cycles!=null) {
|
if(cycles!=null) {
|
||||||
execute(new ProgramValue.KickAsmCycles(statementKickAsm), handler, statement, statementsIt, block);
|
execute(new ProgramValue.ProgramValueKickAsmCycles(statementKickAsm), handler, statement, statementsIt, block);
|
||||||
}
|
}
|
||||||
List<SymbolVariableRef> uses = statementKickAsm.getUses();
|
List<SymbolVariableRef> uses = statementKickAsm.getUses();
|
||||||
for(int i = 0; i < uses.size(); i++) {
|
for(int i = 0; i < uses.size(); i++) {
|
||||||
@@ -155,7 +155,7 @@ public class ProgramValueIterator {
|
|||||||
StatementAsm statementAsm = (StatementAsm) statement;
|
StatementAsm statementAsm = (StatementAsm) statement;
|
||||||
Map<String, SymbolVariableRef> referenced = statementAsm.getReferenced();
|
Map<String, SymbolVariableRef> referenced = statementAsm.getReferenced();
|
||||||
for(String label : referenced.keySet()) {
|
for(String label : referenced.keySet()) {
|
||||||
execute(new ProgramValue.AsmReferenced(statementAsm, label), handler, statement, statementsIt, block);
|
execute(new ProgramValue.ProgramValueAsmReferenced(statementAsm, label), handler, statement, statementsIt, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,47 +182,50 @@ public class ProgramValueIterator {
|
|||||||
private static Collection<ProgramValue> getSubValues(Value value) {
|
private static Collection<ProgramValue> getSubValues(Value value) {
|
||||||
ArrayList<ProgramValue> subValues = new ArrayList<>();
|
ArrayList<ProgramValue> subValues = new ArrayList<>();
|
||||||
if(value instanceof PointerDereferenceIndexed) {
|
if(value instanceof PointerDereferenceIndexed) {
|
||||||
subValues.add(new ProgramValue.Pointer((PointerDereference) value));
|
subValues.add(new ProgramValue.ProgramValuePointer((PointerDereference) value));
|
||||||
subValues.add(new ProgramValue.PointerIndex((PointerDereferenceIndexed) value));
|
subValues.add(new ProgramValue.ProgramValuePointerIndex((PointerDereferenceIndexed) value));
|
||||||
} else if(value instanceof PointerDereferenceSimple) {
|
} else if(value instanceof PointerDereferenceSimple) {
|
||||||
subValues.add(new ProgramValue.Pointer((PointerDereference) value));
|
subValues.add(new ProgramValue.ProgramValuePointer((PointerDereference) value));
|
||||||
|
} else if(value instanceof StructMemberRef) {
|
||||||
|
subValues.add(new ProgramValue.ProgramValueStruct((StructMemberRef) value));
|
||||||
} else if(value instanceof ValueList) {
|
} else if(value instanceof ValueList) {
|
||||||
ValueList valueList = (ValueList) value;
|
ValueList valueList = (ValueList) value;
|
||||||
int size = valueList.getList().size();
|
int size = valueList.getList().size();
|
||||||
for(int i = 0; i < size; i++) {
|
for(int i = 0; i < size; i++) {
|
||||||
subValues.add(new ProgramValue.ListElement(valueList, i));
|
subValues.add(new ProgramValue.ProgramValueListElement(valueList, i));
|
||||||
}
|
}
|
||||||
} else if(value instanceof ConstantArrayList) {
|
} else if(value instanceof ConstantArrayList) {
|
||||||
ConstantArrayList constantArrayList = (ConstantArrayList) value;
|
ConstantArrayList constantArrayList = (ConstantArrayList) value;
|
||||||
int size = constantArrayList.getElements().size();
|
int size = constantArrayList.getElements().size();
|
||||||
for(int i = 0; i < size; i++) {
|
for(int i = 0; i < size; i++) {
|
||||||
subValues.add(new ProgramValue.ConstantArrayElement(constantArrayList, i));
|
subValues.add(new ProgramValue.ProgramValueConstantArrayElement(constantArrayList, i));
|
||||||
}
|
}
|
||||||
} else if(value instanceof CastValue) {
|
} else if(value instanceof CastValue) {
|
||||||
subValues.add(new ProgramValue.CastValue((CastValue) value));
|
subValues.add(new ProgramValue.ProgramValueCastValue((CastValue) value));
|
||||||
} else if(value instanceof ConstantCastValue) {
|
} else if(value instanceof ConstantCastValue) {
|
||||||
subValues.add(new ProgramValue.ConstantCastValue((ConstantCastValue) value));
|
subValues.add(new ProgramValue.ProgramValueConstantCastValue((ConstantCastValue) value));
|
||||||
} else if(value instanceof ConstantSymbolPointer) {
|
} else if(value instanceof ConstantSymbolPointer) {
|
||||||
subValues.add(new ProgramValue.ConstantSymbolPointerTo((ConstantSymbolPointer) value));
|
subValues.add(new ProgramValue.ProgramValueConstantSymbolPointerTo((ConstantSymbolPointer) value));
|
||||||
} else if(value instanceof RangeValue) {
|
} else if(value instanceof RangeValue) {
|
||||||
subValues.add(new ProgramValue.RangeFirst((RangeValue) value));
|
subValues.add(new ProgramValue.ProgramValueRangeFirst((RangeValue) value));
|
||||||
subValues.add(new ProgramValue.RangeLast((RangeValue) value));
|
subValues.add(new ProgramValue.ProgramValueRangeLast((RangeValue) value));
|
||||||
} else if(value instanceof ConstantBinary) {
|
} else if(value instanceof ConstantBinary) {
|
||||||
subValues.add(new ProgramValue.ConstantBinaryLeft((ConstantBinary) value));
|
subValues.add(new ProgramValue.ProgramValueConstantBinaryLeft((ConstantBinary) value));
|
||||||
subValues.add(new ProgramValue.ConstantBinaryRight((ConstantBinary) value));
|
subValues.add(new ProgramValue.ProgramValueConstantBinaryRight((ConstantBinary) value));
|
||||||
} else if(value instanceof ConstantUnary) {
|
} else if(value instanceof ConstantUnary) {
|
||||||
subValues.add(new ProgramValue.ConstantUnaryValue((ConstantUnary) value));
|
subValues.add(new ProgramValue.ProgramValueConstantUnaryValue((ConstantUnary) value));
|
||||||
} else if(value instanceof ArrayFilled) {
|
} else if(value instanceof ArrayFilled) {
|
||||||
subValues.add(new ProgramValue.ArrayFilledSize((ArrayFilled) value));
|
subValues.add(new ProgramValue.ProgramValueArrayFilledSize((ArrayFilled) value));
|
||||||
} else if(value instanceof ConstantArrayFilled) {
|
} else if(value instanceof ConstantArrayFilled) {
|
||||||
subValues.add(new ProgramValue.ConstantArrayFilledSize((ConstantArrayFilled) value));
|
subValues.add(new ProgramValue.ProgramValueConstantArrayFilledSize((ConstantArrayFilled) value));
|
||||||
} else if(value instanceof LvalueIntermediate) {
|
} else if(value instanceof LvalueIntermediate) {
|
||||||
subValues.add(new ProgramValue.LValueIntermediateVariable((LvalueIntermediate) value));
|
subValues.add(new ProgramValue.ProgramValueLValueIntermediateVariable((LvalueIntermediate) value));
|
||||||
} else if(value == null ||
|
} else if(value == null ||
|
||||||
value instanceof VariableRef ||
|
value instanceof VariableRef ||
|
||||||
value instanceof ProcedureRef ||
|
value instanceof ProcedureRef ||
|
||||||
value instanceof ConstantLiteral ||
|
value instanceof ConstantLiteral ||
|
||||||
value instanceof ConstantRef ||
|
value instanceof ConstantRef ||
|
||||||
|
value instanceof StructZero ||
|
||||||
value instanceof LabelRef
|
value instanceof LabelRef
|
||||||
) {
|
) {
|
||||||
// No sub values
|
// No sub values
|
||||||
|
@@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.ConstantNotLiteral;
|
|||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
/** Unary Address-of Operator (&p) */
|
/** Unary Address-of Operator (&p) */
|
||||||
@@ -20,7 +19,7 @@ public class OperatorAddressOf extends OperatorUnary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return new SymbolTypePointer(operandType);
|
return new SymbolTypePointer(operandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,25 @@
|
|||||||
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
|
/** Binary assignment operator ( x = y ) */
|
||||||
|
public class OperatorAssignment extends OperatorBinary {
|
||||||
|
|
||||||
|
public OperatorAssignment(int precedence) {
|
||||||
|
super("=", "_assign_", precedence);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConstantLiteral calculateLiteral(ConstantLiteral left, ConstantLiteral right) {
|
||||||
|
throw new CompileError("Calculation not implemented " + left + " " + getOperator() + " " + right);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1,7 +1,6 @@
|
|||||||
package dk.camelot64.kickc.model.operators;
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
/** A binary expression operator */
|
/** A binary expression operator */
|
||||||
@@ -25,6 +24,6 @@ public abstract class OperatorBinary extends Operator {
|
|||||||
* @param right The type of the right operand
|
* @param right The type of the right operand
|
||||||
* @return The type resulting from applying the operator to the operands
|
* @return The type resulting from applying the operator to the operands
|
||||||
*/
|
*/
|
||||||
public abstract SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right);
|
public abstract SymbolType inferType(SymbolType left, SymbolType right);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,7 @@
|
|||||||
package dk.camelot64.kickc.model.operators;
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.*;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeInteger;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
@@ -24,7 +21,7 @@ public class OperatorBitwiseAnd extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) {
|
public SymbolType inferType(SymbolType type1, SymbolType type2) {
|
||||||
// Handle pointers as words
|
// Handle pointers as words
|
||||||
if(type1 instanceof SymbolTypePointer) {
|
if(type1 instanceof SymbolTypePointer) {
|
||||||
type1 = SymbolType.WORD;
|
type1 = SymbolType.WORD;
|
||||||
@@ -32,16 +29,12 @@ public class OperatorBitwiseAnd extends OperatorBinary {
|
|||||||
if(type2 instanceof SymbolTypePointer) {
|
if(type2 instanceof SymbolTypePointer) {
|
||||||
type2 = SymbolType.WORD;
|
type2 = SymbolType.WORD;
|
||||||
}
|
}
|
||||||
// Find smallest bitwise type
|
// Handle numeric types
|
||||||
if(type1 instanceof SymbolTypeInteger && type2 instanceof SymbolTypeInteger) {
|
if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
|
||||||
|
if(type1.getSizeBytes()<type2.getSizeBytes())
|
||||||
for(SymbolTypeInteger candidate : SymbolType.getIntegerTypes()) {
|
return type1;
|
||||||
boolean match1 = ((SymbolTypeInteger) type1).getBits() <= candidate.getBits();
|
else
|
||||||
boolean match2 = ((SymbolTypeInteger) type2).getBits() <= candidate.getBits();
|
return type2;
|
||||||
if(!candidate.isSigned() && (match1 || match2)) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
|
throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
|
||||||
|
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
@@ -23,7 +22,7 @@ public class OperatorBitwiseNot extends OperatorUnary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return operandType;
|
return operandType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,10 +1,7 @@
|
|||||||
package dk.camelot64.kickc.model.operators;
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.*;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeInteger;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
@@ -24,7 +21,7 @@ public class OperatorBitwiseOr extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) {
|
public SymbolType inferType(SymbolType type1, SymbolType type2) {
|
||||||
// Handle pointers as words
|
// Handle pointers as words
|
||||||
if(type1 instanceof SymbolTypePointer) {
|
if(type1 instanceof SymbolTypePointer) {
|
||||||
type1 = SymbolType.WORD;
|
type1 = SymbolType.WORD;
|
||||||
@@ -32,9 +29,9 @@ public class OperatorBitwiseOr extends OperatorBinary {
|
|||||||
if(type2 instanceof SymbolTypePointer) {
|
if(type2 instanceof SymbolTypePointer) {
|
||||||
type2 = SymbolType.WORD;
|
type2 = SymbolType.WORD;
|
||||||
}
|
}
|
||||||
// Handle numeric types through proper promotion
|
// Handle numeric types
|
||||||
if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
|
if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
|
||||||
return SymbolType.promotedBitwiseType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
|
return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
|
||||||
}
|
}
|
||||||
throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
|
throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,7 @@
|
|||||||
package dk.camelot64.kickc.model.operators;
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.*;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeInteger;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
@@ -24,7 +21,7 @@ public class OperatorBitwiseXor extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) {
|
public SymbolType inferType(SymbolType type1, SymbolType type2) {
|
||||||
// Handle pointers as words
|
// Handle pointers as words
|
||||||
if(type1 instanceof SymbolTypePointer) {
|
if(type1 instanceof SymbolTypePointer) {
|
||||||
type1 = SymbolType.WORD;
|
type1 = SymbolType.WORD;
|
||||||
@@ -32,9 +29,9 @@ public class OperatorBitwiseXor extends OperatorBinary {
|
|||||||
if(type2 instanceof SymbolTypePointer) {
|
if(type2 instanceof SymbolTypePointer) {
|
||||||
type2 = SymbolType.WORD;
|
type2 = SymbolType.WORD;
|
||||||
}
|
}
|
||||||
// Handle numeric types through proper promotion
|
// Handle numeric types
|
||||||
if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
|
if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
|
||||||
return SymbolType.promotedBitwiseType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
|
return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
|
||||||
}
|
}
|
||||||
throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
|
throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,18 @@
|
|||||||
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
|
||||||
|
/** Abstract cast operator. */
|
||||||
|
public abstract class OperatorCast extends OperatorUnary {
|
||||||
|
|
||||||
|
private SymbolType toType;
|
||||||
|
|
||||||
|
public OperatorCast(String operator, String asmOperator, int precedence, SymbolType toType) {
|
||||||
|
super(operator, asmOperator, precedence);
|
||||||
|
this.toType = toType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SymbolType getToType() {
|
||||||
|
return toType;
|
||||||
|
}
|
||||||
|
}
|
@@ -3,16 +3,15 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||||
|
|
||||||
/** Unary Cast to boolean operator ( (boolean) x ) */
|
/** Unary Cast to boolean operator ( (boolean) x ) */
|
||||||
public class OperatorCastBool extends OperatorUnary {
|
public class OperatorCastBool extends OperatorCast {
|
||||||
|
|
||||||
public OperatorCastBool(int precedence) {
|
public OperatorCastBool(int precedence) {
|
||||||
super("((bool))", "_bool_", precedence);
|
super("((bool))", "_bool_", precedence, SymbolType.BOOLEAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -26,7 +25,7 @@ public class OperatorCastBool extends OperatorUnary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return SymbolType.BOOLEAN;
|
return SymbolType.BOOLEAN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,30 +3,29 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||||
|
|
||||||
/** Unary Cast to byte operator ( (byte) x ) */
|
/** Unary Cast to byte operator ( (byte) x ) */
|
||||||
public class OperatorCastByte extends OperatorUnary {
|
public class OperatorCastByte extends OperatorCast {
|
||||||
|
|
||||||
public OperatorCastByte(int precedence) {
|
public OperatorCastByte(int precedence) {
|
||||||
super("((byte))", "_byte_", precedence);
|
super("((byte))", "_byte_", precedence, SymbolType.BYTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
||||||
if(value instanceof ConstantInteger) {
|
if(value instanceof ConstantInteger) {
|
||||||
return new ConstantInteger(0xff & ((ConstantInteger) value).getValue());
|
return new ConstantInteger(0xff & ((ConstantInteger) value).getValue(), SymbolType.BYTE);
|
||||||
} else if(value instanceof ConstantPointer) {
|
} else if(value instanceof ConstantPointer) {
|
||||||
return new ConstantInteger(0xff & ((ConstantPointer) value).getLocation());
|
return new ConstantInteger(0xff & ((ConstantPointer) value).getLocation(), SymbolType.BYTE);
|
||||||
}
|
}
|
||||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return SymbolType.BYTE;
|
return SymbolType.BYTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,32 +3,31 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||||
|
|
||||||
/** Unary Cast to double word operator ( (dword) x ) */
|
/** Unary Cast to double word operator ( (dword) x ) */
|
||||||
public class OperatorCastDWord extends OperatorUnary {
|
public class OperatorCastDWord extends OperatorCast {
|
||||||
|
|
||||||
public OperatorCastDWord(int precedence) {
|
public OperatorCastDWord(int precedence) {
|
||||||
super("((dword))", "_dword_", precedence);
|
super("((dword))", "_dword_", precedence, SymbolType.DWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
||||||
if(value instanceof ConstantInteger) {
|
if(value instanceof ConstantInteger) {
|
||||||
return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue());
|
return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue(), SymbolType.DWORD);
|
||||||
}
|
}
|
||||||
if(value instanceof ConstantPointer) {
|
if(value instanceof ConstantPointer) {
|
||||||
return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation());
|
return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation(), SymbolType.DWORD);
|
||||||
}
|
}
|
||||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return SymbolType.DWORD;
|
return SymbolType.DWORD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,18 +4,17 @@ import dk.camelot64.kickc.model.CompileError;
|
|||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||||
|
|
||||||
/** Unary Cast to a pointer ( type* ) */
|
/** Unary Cast to a pointer ( type* ) */
|
||||||
public class OperatorCastPtr extends OperatorUnary {
|
public class OperatorCastPtr extends OperatorCast {
|
||||||
|
|
||||||
private final SymbolType elementType;
|
private final SymbolType elementType;
|
||||||
|
|
||||||
public OperatorCastPtr(int precedence, SymbolType elementType) {
|
public OperatorCastPtr(int precedence, SymbolType elementType) {
|
||||||
super("((" + elementType.toString() + "*))", "_ptr_", precedence);
|
super("((" + elementType.toString() + "*))", "_ptr_", precedence, new SymbolTypePointer(elementType));
|
||||||
this.elementType = elementType;
|
this.elementType = elementType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +32,7 @@ public class OperatorCastPtr extends OperatorUnary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return new SymbolTypePointer(elementType);
|
return new SymbolTypePointer(elementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,27 +3,26 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
/** Unary Cast to signed byte operator ( (signed byte) x ) */
|
/** Unary Cast to signed byte operator ( (signed byte) x ) */
|
||||||
public class OperatorCastSByte extends OperatorUnary {
|
public class OperatorCastSByte extends OperatorCast {
|
||||||
|
|
||||||
public OperatorCastSByte(int precedence) {
|
public OperatorCastSByte(int precedence) {
|
||||||
super("((signed byte))", "_sbyte_", precedence);
|
super("((signed byte))", "_sbyte_", precedence, SymbolType.SBYTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
||||||
if(value instanceof ConstantInteger) {
|
if(value instanceof ConstantInteger) {
|
||||||
return new ConstantInteger(0xff & ((ConstantInteger) value).getValue());
|
return new ConstantInteger(0xff & ((ConstantInteger) value).getValue(), SymbolType.SBYTE);
|
||||||
}
|
}
|
||||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return SymbolType.SBYTE;
|
return SymbolType.SBYTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,27 +3,26 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
/** Unary Cast to signed double word operator ( (signed dword) x ) */
|
/** Unary Cast to signed double word operator ( (signed dword) x ) */
|
||||||
public class OperatorCastSDWord extends OperatorUnary {
|
public class OperatorCastSDWord extends OperatorCast {
|
||||||
|
|
||||||
public OperatorCastSDWord(int precedence) {
|
public OperatorCastSDWord(int precedence) {
|
||||||
super("((signed dword))", "_sdword_", precedence);
|
super("((signed dword))", "_sdword_", precedence, SymbolType.SDWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
||||||
if(value instanceof ConstantInteger) {
|
if(value instanceof ConstantInteger) {
|
||||||
return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue());
|
return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue(), SymbolType.SDWORD);
|
||||||
}
|
}
|
||||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return SymbolType.SDWORD;
|
return SymbolType.SDWORD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,27 @@
|
|||||||
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
|
/** Unary Cast to signed number operator ( (snumber) x ) */
|
||||||
|
public class OperatorCastSNumber extends OperatorCast {
|
||||||
|
|
||||||
|
public OperatorCastSNumber(int precedence) {
|
||||||
|
super("((snumber))", "_snumber_", precedence, SymbolType.SNUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
||||||
|
if(value instanceof ConstantInteger)
|
||||||
|
return new ConstantInteger(((ConstantInteger) value).getValue(), SymbolType.SNUMBER);
|
||||||
|
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
|
return SymbolType.SNUMBER;
|
||||||
|
}
|
||||||
|
}
|
@@ -3,27 +3,26 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
/** Unary Cast to signed word operator ( (signed word) x ) */
|
/** Unary Cast to signed word operator ( (signed word) x ) */
|
||||||
public class OperatorCastSWord extends OperatorUnary {
|
public class OperatorCastSWord extends OperatorCast {
|
||||||
|
|
||||||
public OperatorCastSWord(int precedence) {
|
public OperatorCastSWord(int precedence) {
|
||||||
super("((signed word))", "_sword_", precedence);
|
super("((signed word))", "_sword_", precedence, SymbolType.SWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
||||||
if(value instanceof ConstantInteger) {
|
if(value instanceof ConstantInteger) {
|
||||||
return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue());
|
return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue(), SymbolType.SWORD);
|
||||||
}
|
}
|
||||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return SymbolType.SWORD;
|
return SymbolType.SWORD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,27 @@
|
|||||||
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
|
/** Unary Cast to unsigned number operator ( (unumber) x ) */
|
||||||
|
public class OperatorCastUNumber extends OperatorCast {
|
||||||
|
|
||||||
|
public OperatorCastUNumber(int precedence) {
|
||||||
|
super("((unumber))", "_unumber_", precedence, SymbolType.UNUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
||||||
|
if(value instanceof ConstantInteger)
|
||||||
|
return new ConstantInteger(((ConstantInteger) value).getValue(), SymbolType.UNUMBER);
|
||||||
|
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
|
return SymbolType.UNUMBER;
|
||||||
|
}
|
||||||
|
}
|
@@ -3,31 +3,30 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||||
|
|
||||||
/** Unary Cast to word operator ( (word) x ) */
|
/** Unary Cast to word operator ( (word) x ) */
|
||||||
public class OperatorCastWord extends OperatorUnary {
|
public class OperatorCastWord extends OperatorCast {
|
||||||
|
|
||||||
public OperatorCastWord(int precedence) {
|
public OperatorCastWord(int precedence) {
|
||||||
super("((word))", "_word_", precedence);
|
super("((word))", "_word_", precedence, SymbolType.WORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
|
||||||
if(value instanceof ConstantInteger) {
|
if(value instanceof ConstantInteger) {
|
||||||
return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue());
|
return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue(), SymbolType.WORD);
|
||||||
}
|
}
|
||||||
if(value instanceof ConstantPointer) {
|
if(value instanceof ConstantPointer) {
|
||||||
return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation());
|
return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation(), SymbolType.WORD);
|
||||||
}
|
}
|
||||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return SymbolType.WORD;
|
return SymbolType.WORD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.CompileError;
|
|||||||
import dk.camelot64.kickc.model.types.NoMatchingType;
|
import dk.camelot64.kickc.model.types.NoMatchingType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@ public class OperatorDWord extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
|
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||||
// Handle pointers as words
|
// Handle pointers as words
|
||||||
if(left instanceof SymbolTypePointer) {
|
if(left instanceof SymbolTypePointer) {
|
||||||
left = SymbolType.WORD;
|
left = SymbolType.WORD;
|
||||||
@@ -32,13 +31,13 @@ public class OperatorDWord extends OperatorBinary {
|
|||||||
if(right instanceof SymbolTypePointer) {
|
if(right instanceof SymbolTypePointer) {
|
||||||
right = SymbolType.WORD;
|
right = SymbolType.WORD;
|
||||||
}
|
}
|
||||||
if(SymbolType.isByte(left)) {
|
if(SymbolType.BYTE.equals(left)) {
|
||||||
left = SymbolType.WORD;
|
left = SymbolType.WORD;
|
||||||
}
|
}
|
||||||
if(SymbolType.isByte(right)) {
|
if(SymbolType.BYTE.equals(right)) {
|
||||||
right = SymbolType.WORD;
|
right = SymbolType.WORD;
|
||||||
}
|
}
|
||||||
if(SymbolType.isWord(left) && SymbolType.isWord(right)) {
|
if(SymbolType.WORD.equals(left) && SymbolType.WORD.equals(right)) {
|
||||||
return SymbolType.DWORD;
|
return SymbolType.DWORD;
|
||||||
}
|
}
|
||||||
throw new NoMatchingType("DWord constructor cannot use " + left + " " + getOperator() + " " + right);
|
throw new NoMatchingType("DWord constructor cannot use " + left + " " + getOperator() + " " + right);
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
package dk.camelot64.kickc.model.operators;
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
@@ -19,11 +18,11 @@ public class OperatorDecrement extends OperatorUnary {
|
|||||||
if(operand instanceof ConstantInteger ) {
|
if(operand instanceof ConstantInteger ) {
|
||||||
return new ConstantInteger(((ConstantInteger) operand).getInteger() -1);
|
return new ConstantInteger(((ConstantInteger) operand).getInteger() -1);
|
||||||
}
|
}
|
||||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + operand );
|
throw new ConstantNotLiteral("Calculation not literal " + getOperator() + " " + operand );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return operandType;
|
return operandType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.CompileError;
|
|||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
/** Unary Pointer Dereference Operator (*p) */
|
/** Unary Pointer Dereference Operator (*p) */
|
||||||
@@ -20,7 +19,7 @@ public class OperatorDeref extends OperatorUnary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
if(operandType instanceof SymbolTypePointer) {
|
if(operandType instanceof SymbolTypePointer) {
|
||||||
return ((SymbolTypePointer) operandType).getElementType();
|
return ((SymbolTypePointer) operandType).getElementType();
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
|
|
||||||
/** Binary Pointer Dereference with an index Operator ( p[i] / *(p+i) ) */
|
/** Binary Pointer Dereference with an index Operator ( p[i] / *(p+i) ) */
|
||||||
@@ -19,7 +18,7 @@ public class OperatorDerefIdx extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
|
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||||
if(left instanceof SymbolTypePointer) {
|
if(left instanceof SymbolTypePointer) {
|
||||||
return ((SymbolTypePointer) left).getElementType();
|
return ((SymbolTypePointer) left).getElementType();
|
||||||
}
|
}
|
||||||
|
@@ -27,18 +27,17 @@ public class OperatorDivide extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
|
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||||
if(left instanceof SymbolTypePointer) {
|
if(left instanceof SymbolTypePointer) {
|
||||||
if(SymbolType.isByte(right) || SymbolType.isWord(right)) {
|
if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)|| SymbolType.UNUMBER.equals(right)|| SymbolType.SNUMBER.equals(right)) {
|
||||||
return left;
|
return left;
|
||||||
} else {
|
} else {
|
||||||
throw new NoMatchingType("Cannot divide pointer by "+right.toString());
|
throw new NoMatchingType("Cannot divide pointer by "+right.toString());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Handle numeric types through proper promotion
|
// Handle numeric types through proper promotion
|
||||||
if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
|
if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
|
||||||
return SymbolType.promotedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
|
return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right);
|
throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right);
|
||||||
|
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantBool;
|
import dk.camelot64.kickc.model.values.ConstantBool;
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
@@ -25,7 +24,7 @@ public class OperatorEqual extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
|
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||||
return SymbolType.BOOLEAN;
|
return SymbolType.BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,7 +5,6 @@ import dk.camelot64.kickc.model.ConstantNotLiteral;
|
|||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||||
@@ -22,10 +21,14 @@ public class OperatorGetHigh extends OperatorUnary {
|
|||||||
public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
|
public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
|
||||||
if(operand instanceof ConstantInteger) {
|
if(operand instanceof ConstantInteger) {
|
||||||
ConstantInteger operandInt = (ConstantInteger) operand;
|
ConstantInteger operandInt = (ConstantInteger) operand;
|
||||||
if(SymbolType.isWord(operandInt.getType()) || SymbolType.isSWord(operandInt.getType())) {
|
if(SymbolType.WORD.equals(operandInt.getType()) || SymbolType.SWORD.equals(operandInt.getType())) {
|
||||||
return new ConstantInteger(operandInt.getInteger()>>8);
|
return new ConstantInteger(operandInt.getInteger()>>8);
|
||||||
} else if(SymbolType.isDWord(operandInt.getType()) || SymbolType.isSDWord(operandInt.getType())) {
|
} else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) {
|
||||||
return new ConstantInteger(operandInt.getInteger()>>16);
|
return new ConstantInteger(operandInt.getInteger()>>16);
|
||||||
|
} else if(SymbolType.BYTE.equals(operandInt.getType()) || SymbolType.SBYTE.equals(operandInt.getType())) {
|
||||||
|
return new ConstantInteger(0L, SymbolType.BYTE);
|
||||||
|
} else if(SymbolType.NUMBER.equals(operandInt.getType())) {
|
||||||
|
throw new ConstantNotLiteral("Operand not resolved "+operand);
|
||||||
}
|
}
|
||||||
} else if(operand instanceof ConstantPointer) {
|
} else if(operand instanceof ConstantPointer) {
|
||||||
return new ConstantInteger(((ConstantPointer) operand).getLocation()>>8);
|
return new ConstantInteger(((ConstantPointer) operand).getLocation()>>8);
|
||||||
@@ -36,13 +39,21 @@ public class OperatorGetHigh extends OperatorUnary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
if(operandType instanceof SymbolTypePointer || SymbolType.isWord(operandType) || SymbolType.isSWord(operandType)) {
|
if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) {
|
||||||
return SymbolType.BYTE;
|
return SymbolType.BYTE;
|
||||||
} else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
|
} else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
|
||||||
return SymbolType.WORD;
|
return SymbolType.WORD;
|
||||||
|
} else if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
|
||||||
|
return SymbolType.BYTE;
|
||||||
} else if(SymbolType.STRING.equals(operandType)) {
|
} else if(SymbolType.STRING.equals(operandType)) {
|
||||||
return SymbolType.BYTE;
|
return SymbolType.BYTE;
|
||||||
|
} else if(SymbolType.NUMBER.equals(operandType)) {
|
||||||
|
return SymbolType.NUMBER;
|
||||||
|
} else if(SymbolType.UNUMBER.equals(operandType)) {
|
||||||
|
return SymbolType.UNUMBER;
|
||||||
|
} else if(SymbolType.SNUMBER.equals(operandType)) {
|
||||||
|
return SymbolType.UNUMBER;
|
||||||
}
|
}
|
||||||
throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
|
throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,6 @@ import dk.camelot64.kickc.model.ConstantNotLiteral;
|
|||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||||
@@ -22,27 +21,39 @@ public class OperatorGetLow extends OperatorUnary {
|
|||||||
public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
|
public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
|
||||||
if(operand instanceof ConstantInteger) {
|
if(operand instanceof ConstantInteger) {
|
||||||
ConstantInteger operandInt = (ConstantInteger) operand;
|
ConstantInteger operandInt = (ConstantInteger) operand;
|
||||||
if(SymbolType.isWord(operandInt.getType()) || SymbolType.isSWord(operandInt.getType())) {
|
if(SymbolType.WORD.equals(operandInt.getType()) || SymbolType.SWORD.equals(operandInt.getType())) {
|
||||||
return new ConstantInteger(operandInt.getInteger()&0xff);
|
return new ConstantInteger(operandInt.getInteger()&0xff);
|
||||||
} else if(SymbolType.isDWord(operandInt.getType()) || SymbolType.isSDWord(operandInt.getType())) {
|
} else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) {
|
||||||
return new ConstantInteger(operandInt.getInteger()&0xffff);
|
return new ConstantInteger(operandInt.getInteger()&0xffff);
|
||||||
|
} else if(SymbolType.BYTE.equals(operandInt.getType()) || SymbolType.SBYTE.equals(operandInt.getType())) {
|
||||||
|
return operandInt;
|
||||||
|
} else if(SymbolType.NUMBER.equals(operandInt.getType())) {
|
||||||
|
throw new ConstantNotLiteral("Operand not resolved "+operand);
|
||||||
}
|
}
|
||||||
} else if(operand instanceof ConstantPointer) {
|
} else if(operand instanceof ConstantPointer) {
|
||||||
return new ConstantInteger(((ConstantPointer) operand).getLocation()&0xff);
|
return new ConstantInteger(((ConstantPointer) operand).getLocation()&0xff);
|
||||||
} else if(operand instanceof ConstantString) {
|
} else if(operand instanceof ConstantString) {
|
||||||
throw new ConstantNotLiteral("address of string is not literal");
|
throw new ConstantNotLiteral("address of string is not literal");
|
||||||
}
|
}
|
||||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + operand );
|
throw new ConstantNotLiteral("Calculation not implemented " + getOperator() + " " + operand );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
if(operandType instanceof SymbolTypePointer || SymbolType.isWord(operandType) || SymbolType.isSWord(operandType)) {
|
if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) {
|
||||||
return SymbolType.BYTE;
|
return SymbolType.BYTE;
|
||||||
} else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
|
} else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
|
||||||
return SymbolType.WORD;
|
return SymbolType.WORD;
|
||||||
|
} else if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
|
||||||
|
return SymbolType.BYTE;
|
||||||
} else if(SymbolType.STRING.equals(operandType)) {
|
} else if(SymbolType.STRING.equals(operandType)) {
|
||||||
return SymbolType.BYTE;
|
return SymbolType.BYTE;
|
||||||
|
} else if(SymbolType.NUMBER.equals(operandType)) {
|
||||||
|
return SymbolType.NUMBER;
|
||||||
|
} else if(SymbolType.UNUMBER.equals(operandType)) {
|
||||||
|
return SymbolType.UNUMBER;
|
||||||
|
} else if(SymbolType.SNUMBER.equals(operandType)) {
|
||||||
|
return SymbolType.UNUMBER;
|
||||||
}
|
}
|
||||||
throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
|
throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantBool;
|
import dk.camelot64.kickc.model.values.ConstantBool;
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
@@ -23,7 +22,7 @@ public class OperatorGreaterThan extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
|
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||||
return SymbolType.BOOLEAN;
|
return SymbolType.BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantBool;
|
import dk.camelot64.kickc.model.values.ConstantBool;
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
@@ -23,7 +22,7 @@ public class OperatorGreaterThanEqual extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
|
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||||
return SymbolType.BOOLEAN;
|
return SymbolType.BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
package dk.camelot64.kickc.model.operators;
|
package dk.camelot64.kickc.model.operators;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||||
@@ -22,11 +21,11 @@ public class OperatorIncrement extends OperatorUnary {
|
|||||||
} else if(operand instanceof ConstantPointer) {
|
} else if(operand instanceof ConstantPointer) {
|
||||||
return new ConstantPointer(((ConstantPointer) operand).getLocation()+1, ((ConstantPointer) operand).getElementType());
|
return new ConstantPointer(((ConstantPointer) operand).getLocation()+1, ((ConstantPointer) operand).getElementType());
|
||||||
}
|
}
|
||||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + operand );
|
throw new ConstantNotLiteral("Calculation not literal " + getOperator() + " " + operand );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple operandType) {
|
public SymbolType inferType(SymbolType operandType) {
|
||||||
return operandType;
|
return operandType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
|
|||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.types.SymbolType;
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
|
|
||||||
import dk.camelot64.kickc.model.values.ConstantBool;
|
import dk.camelot64.kickc.model.values.ConstantBool;
|
||||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||||
@@ -23,7 +22,7 @@ public class OperatorLessThan extends OperatorBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
|
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||||
return SymbolType.BOOLEAN;
|
return SymbolType.BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user