1
0
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:
jespergravgaard
2019-05-30 17:55:53 +02:00
419 changed files with 23206 additions and 5956 deletions

View File

@@ -0,0 +1,2 @@
ldy #0
sta ({c1}),y

View File

@@ -0,0 +1,5 @@
ldy #0
lda {z1}
sta !+ +1
lda {c1},x
!: sta ($ff),y

View File

@@ -0,0 +1,4 @@
ldy {z1}
sty !+ +1
ldy #0
!: sta ($ff),y

View 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

View File

@@ -0,0 +1,4 @@
inc {c1}
bne !+
inc {c1}+1
!:

View File

@@ -0,0 +1,4 @@
lda {z1}
sta {c1}
lda {z1}+1
sta {c1}+1

View File

@@ -0,0 +1,5 @@
ldy #0
lda ({z1}),y
clc
adc #1
sta ({z1}),y

View File

@@ -0,0 +1,4 @@
lda {z2}
sta {z1}
lda {z2}+1
sta {z1}+1

View File

@@ -0,0 +1,6 @@
ldy #{c1}
lda {z2}
sta ({z1}),y
iny
lda {z2}+1
sta ({z1}),y

View File

@@ -0,0 +1,6 @@
ldy #{c1}
lda {z2}
sta ({z1}),y
iny
lda {z2}+1
sta ({z1}),y

View File

@@ -0,0 +1,5 @@
lda {z2}
sta ({z1}),y
iny
lda {z2}+1
sta ({z1}),y

View File

@@ -0,0 +1,5 @@
lda {z2}
sta ({z1}),y
iny
lda {z2}+1
sta ({z1}),y

View File

@@ -0,0 +1,2 @@
sta {c1},x

View File

@@ -0,0 +1,2 @@
sta {c1}+1,x

View File

@@ -0,0 +1,2 @@
sta {c1},y

View File

@@ -0,0 +1,2 @@
sta {c1}+1,y

View File

@@ -0,0 +1,7 @@
lda {c1},x
sec
sbc {z1}
sta {c1},x
lda {c1}+1,x
sbc {z1}+1
sta {c1}+1,x

View File

@@ -0,0 +1,4 @@
lda {z1}
sta {c1},x
lda {z1}+1
sta {c1}+1,x

View File

@@ -0,0 +1,7 @@
lda {c1},y
sec
sbc {z1}
sta {c1},y
lda {c1}+1,y
sbc {z1}+1
sta {c1}+1,y

View File

@@ -0,0 +1,4 @@
lda {z1}
sta {c1},y
lda {z1}+1
sta {c1}+1,y

View File

@@ -0,0 +1,8 @@
lda {c1}+1,x
cmp {z1}+1
bne !+
lda {c1},x
cmp {z1}
beq {la1}
!:
bcc {la1}

View File

@@ -0,0 +1,3 @@
sta {c1},y
lda #0
sta {c1}+1,y

View File

@@ -0,0 +1,8 @@
lda {c1}+1,y
cmp {z1}+1
bne !+
lda {c1},y
cmp {z1}
beq {la1}
!:
bcc {la1}

View File

@@ -0,0 +1,3 @@
eor #$ff
clc
adc #$01

View File

@@ -0,0 +1,6 @@
sec
sbc #{c1}
bvc !+
eor #$80
!:
bmi {la1}

View File

@@ -0,0 +1 @@
lda {c1}

View File

@@ -0,0 +1 @@
lda {c1}+1

View File

@@ -0,0 +1 @@
lda {c1},x

View File

@@ -0,0 +1 @@
lda {c1}+1,x

View File

@@ -0,0 +1 @@
lda {c1},y

View File

@@ -0,0 +1 @@
lda {c1}+1,y

View File

@@ -0,0 +1,2 @@
cmp #0
beq {la1}

View File

@@ -0,0 +1,2 @@
cpx #0
beq {la1}

View File

@@ -0,0 +1,2 @@
cpy #0
beq {la1}

View File

@@ -0,0 +1,5 @@
sta {z1}
lda #0
sta {z1}+1
sta {z1}+2
sta {z1}+3

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,7 @@
lda {z2}
sta {z1}
lda {z2}+1
sta {z1}+1
lda #0
sta {z1}+2
sta {z1}+3

View File

@@ -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

View 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

View File

@@ -0,0 +1,3 @@
lda #0
sta {z1}
sta {z1}+1

View File

@@ -0,0 +1,4 @@
lda {z2}
sta {z1}
lda {z2}+1
sta {z1}+1

View File

@@ -0,0 +1,3 @@
sta {z1}
lda #0
sta {z1}+1

View File

@@ -0,0 +1,11 @@
tax
clc
adc #<{c1}
sta {z1}
txa
ora #$7f
bmi !+
lda #0
!:
adc #>{c1}
sta {z1}+1

View File

@@ -0,0 +1,7 @@
lda {z2}
sec
sbc #{c1}
sta {z1}
lda {z2}+1
sbc #>{c1}
sta {z1}+1

View File

@@ -0,0 +1,5 @@
asl
sta {z1}
lda #0
rol
sta {z1}+1

View File

@@ -0,0 +1,7 @@
sec
lda {z1}
sbc {c1},x
sta {z1}
lda {z1}+1
sbc {c1}+1,x
sta {z1}+1

View File

@@ -0,0 +1,7 @@
sec
lda {z1}
sbc {c1},y
sta {z1}
lda {z1}+1
sbc {c1}+1,y
sta {z1}+1

View File

@@ -0,0 +1,7 @@
lda {z1}
cmp #<{c1}
bne !+
lda {z1}+1
cmp #>{c1}
beq {la1}
!:

View File

@@ -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}

View File

@@ -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;
} }

View File

@@ -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");

View File

@@ -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);
} }

View File

@@ -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"
*/ */

View File

@@ -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);
} }

View File

@@ -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<>();
} }

View File

@@ -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;

View 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);
}
}

View File

@@ -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 {

View File

@@ -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;
} }

View File

@@ -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);
}

View File

@@ -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!");
}
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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);
} }
} }

View File

@@ -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;
}
}

View File

@@ -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);
} }

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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);
} }

View File

@@ -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);
} }

View File

@@ -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;
}
}

View File

@@ -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;
} }
} }

View File

@@ -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;
} }
} }

View File

@@ -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;
} }
} }

View File

@@ -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);
} }

View File

@@ -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;
} }
} }

View File

@@ -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;
} }
} }

View File

@@ -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;
}
}

View File

@@ -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;
} }
} }

View File

@@ -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;
}
}

View File

@@ -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;
} }
} }

View File

@@ -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);

View File

@@ -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;
} }
} }

View File

@@ -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();
} }

View File

@@ -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();
} }

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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);
} }

View File

@@ -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);
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }
} }

View File

@@ -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