diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java index c905678d0..9ecdcf26a 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java @@ -92,21 +92,30 @@ public class AsmFragmentManager { synths.add(new FragmentSynthesis("(.*)=(.*)_(band|bor|plus)_(ys?by)", ".*=[axy]s?by_.*", null, "$1=$4_$3_$2", null, null)); synths.add(new FragmentSynthesis("xby=(.*)", null, null, "aby=$1", "tax\n", null)); + synths.add(new FragmentSynthesis("xsby=(.*)", null, null, "asby=$1", "tax\n", null)); synths.add(new FragmentSynthesis("yby=(.*)", null, null, "aby=$1", "tay\n", null)); - synths.add(new FragmentSynthesis("zpby1=(.*)", ".*=.*zps?by1.*", null, "aby=$1", "sta {zpby1}\n", mapZpby)); - synths.add(new FragmentSynthesis("zpsby1=(.*)", ".*=.*zps?by1.*", null, "asby=$1", "sta {zpsby1}\n", mapZpsby)); + synths.add(new FragmentSynthesis("ysby=(.*)", null, null, "asby=$1", "tay\n", null)); + synths.add(new FragmentSynthesis("zpby1=(.*)", ".*=.*zpby1.*", null, "aby=$1", "sta {zpby1}\n", mapZpby)); + synths.add(new FragmentSynthesis("zpsby1=(.*)", ".*=.*zpsby1.*", null, "asby=$1", "sta {zpsby1}\n", mapZpsby)); synths.add(new FragmentSynthesis("_deref_cowo1=(.*)", null, null, "aby=$1", "sta {cowo1}\n", mapConst)); - synths.add(new FragmentSynthesis("_deref_zpptrby1=(.*)", ".*=.*zpptrs?by1.*", null, "aby=$1", "ldy #0\n" + "sta ({zpptrby1}),y\n", mapZpptrby)); + synths.add(new FragmentSynthesis("_deref_zpptrby1=(.*)", ".*=.*zpptrby1.*", null, "aby=$1", "ldy #0\n" + "sta ({zpptrby1}),y\n", mapZpptrby)); synths.add(new FragmentSynthesis("(.*)=xby(.*)", ".*=.*as?by.*", "txa\n", "$1=aby$2", null, null)); synths.add(new FragmentSynthesis("(.*)=yby(.*)", ".*=.*as?by.*", "tya\n", "$1=aby$2", null, null)); - synths.add(new FragmentSynthesis("(.*)=zpby1(.*)", ".*=.*as?by.*|zps?by1=.*", "lda {zpby1}\n", "$1=aby$2", null, mapZpby)); - synths.add(new FragmentSynthesis("(.*)=zpsby1(.*)", ".*=.*as?by.*|zps?by1=.*", "lda {zpsby1}\n", "$1=aby$2", null, mapZpsby)); + synths.add(new FragmentSynthesis("(.*)=zpby1(.*)", ".*=.*as?by.*|zpby1=.*", "lda {zpby1}\n", "$1=aby$2", null, mapZpby)); + synths.add(new FragmentSynthesis("(.*)=zpsby1(.*)", ".*=.*as?by.*|zpsby1=.*", "lda {zpsby1}\n", "$1=aby$2", null, mapZpsby)); synths.add(new FragmentSynthesis("(.*)=_deref_cowo1(.*)", ".*=.*as?by.*", "lda {cowo1}\n", "$1=aby$2", null, mapConst)); synths.add(new FragmentSynthesis("(.*)=_deref_zpptrby1(.*)", ".*=.*as?by.*|.*=.*ys?by.*", "ldy #0\n"+"lda ({zpptrby1}),y\n", "$1=aby$2", null, mapZpptrby)); + synths.add(new FragmentSynthesis("(.*)=(.*)_xby", ".*=[ax]s?by.*xs?by", "txa\n", "$1=$2_aby", null, null)); + synths.add(new FragmentSynthesis("(.*)=(.*)_xsby", ".*=[ax]s?by.*xs?by", "txa\n", "$1=$2_asby", null, null)); + synths.add(new FragmentSynthesis("(.*)=(.*)_yby", ".*=[ay]s?by.*ys?by", "tya\n", "$1=$2_aby", null, null)); + synths.add(new FragmentSynthesis("(.*)=(.*)_ysby", ".*=[ay]s?by.*ys?by", "tya\n", "$1=$2_asby", null, null)); + synths.add(new FragmentSynthesis("(.*)=(.*)_zpby1", ".*=.*as?by.*", "lda {zpby1}\n", "$1=$2_aby", null, mapZpby)); + synths.add(new FragmentSynthesis("(.*)=(.*)_zpsby1", ".*=.*as?by.*", "lda {zpsby1}\n", "$1=$2_asby", null, mapZpsby)); + synths.add(new FragmentSynthesis("zpby1=zpby1(.*)", ".*=.*as?by.*", "lda {zpby1}\n", "aby=aby$1", "sta {zpby1}\n", mapZpby)); - synths.add(new FragmentSynthesis("zpsby1=zpsby1(.*)", ".*=.*as?by.*", "lda {zpsby1}\n", "aby=aby$1", "sta {zpsby1}\n", mapZpby)); + synths.add(new FragmentSynthesis("zpsby1=zpsby1(.*)", ".*=.*as?by.*", "lda {zpsby1}\n", "asby=asby$1", "sta {zpsby1}\n", mapZpby)); synths.add(new FragmentSynthesis("(.*)=(.*)_derefidx_aby", ".*=.*ys?by.*", "tay\n", "$1=$2_derefidx_yby", null, null)); synths.add(new FragmentSynthesis("(.*)=(.*)_derefidx_aby", ".*=.*xs?by.*", "tax\n", "$1=$2_derefidx_xby", null, null)); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java index 0fa427612..55f2d3698 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java @@ -5,19 +5,29 @@ import dk.camelot64.kickc.model.*; import java.util.LinkedHashMap; import java.util.Map; -/** A fragment signature generated from a {@link Statement} used to load/synthesize an AsmFragent for creating ASM code for the statement*/ +/** + * A fragment signature generated from a {@link Statement} used to load/synthesize an AsmFragent for creating ASM code for the statement + */ public class AsmFragmentSignature { - /** The symbol table. */ + /** + * The symbol table. + */ private Program program; - /** The string signature/name of the fragment fragment. */ + /** + * The string signature/name of the fragment fragment. + */ private String signature; - /** Binding of named values in the fragment to values (constants, variables, ...) . */ + /** + * Binding of named values in the fragment to values (constants, variables, ...) . + */ private Map bindings; - /** The scope containing the fragment. Used when referencing symbols defined in other scopes. */ + /** + * The scope containing the fragment. Used when referencing symbols defined in other scopes. + */ private ScopeRef codeScopeRef; public AsmFragmentSignature( @@ -161,68 +171,7 @@ public class AsmFragmentSignature { } private static String getOperatorFragmentName(Operator operator) { - String op = operator.getOperator(); - switch (op) { - case "*": - if(operator.getType().equals(Operator.Type.UNARY)) { - return "_deref_"; - } else { - return "_mul_"; - } - case "*idx": - return "_derefidx_"; - case "+": - return "_plus_"; - case "++": - return "_inc_"; - case "--": - return "_dec_"; - case "-": - return "_minus_"; - case "==": - return "_eq_"; - case "<>": - case "!=": - return "_neq_"; - case "<": - if(operator.getType().equals(Operator.Type.UNARY)) { - return "_lo_"; - } else { - return "_lt_"; - } - case ">": - if(operator.getType().equals(Operator.Type.UNARY)) { - return "_hi_"; - } else { - return "_gt_"; - } - case "<=": - case "=<": - return "_le_"; - case ">=": - case "=>": - return "_ge_"; - case ">>": - return "_ror_"; - case "<<": - return "_rol_"; - case "&": - return "_band_"; - case "|": - return "_bor_"; - case "^": - return "_bxor_"; - case "!": - return "_not_"; - case "~": - return "_bnot_"; - case "lo=": - return "_setlo_"; - case "hi=": - return "_sethi_"; - default: - return op; - } + return operator.getAsmOperator(); } public String getSignature() { @@ -364,7 +313,7 @@ public class AsmFragmentSignature { bindings.put(name, value); return name; } - } else if(value instanceof ConstantValue) { + } else if (value instanceof ConstantValue) { SymbolType type = SymbolTypeInference.inferType(program.getScope(), (ConstantValue) value); if (SymbolTypeBasic.BYTE.equals(type)) { String name = "coby" + nextConstByteIdx++; diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/aby=_byte_asby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=_byte_asby.asm new file mode 100644 index 000000000..505d4e29a --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=_byte_asby.asm @@ -0,0 +1 @@ +// Do nothing: casting signed byte to byte \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/aby=xby_band_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=aby_band_xby.asm similarity index 100% rename from src/main/java/dk/camelot64/kickc/fragment/asm/aby=xby_band_aby.asm rename to src/main/java/dk/camelot64/kickc/fragment/asm/aby=aby_band_xby.asm diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/aby=yby_band_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=aby_band_yby.asm similarity index 100% rename from src/main/java/dk/camelot64/kickc/fragment/asm/aby=yby_band_aby.asm rename to src/main/java/dk/camelot64/kickc/fragment/asm/aby=aby_band_yby.asm diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/aby=coby1_minus_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=coby1_minus_aby.asm new file mode 100644 index 000000000..6f70cd960 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=coby1_minus_aby.asm @@ -0,0 +1,3 @@ +eor #$ff +clc +adc #{coby1}+1 diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/aby=coby1_minus_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=coby1_minus_xby.asm new file mode 100644 index 000000000..7291e54e8 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=coby1_minus_xby.asm @@ -0,0 +1,4 @@ +stx $ff +lda #{coby1} +sec +sbc $ff \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/aby=coby1_minus_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=coby1_minus_yby.asm new file mode 100644 index 000000000..4d2daa02f --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=coby1_minus_yby.asm @@ -0,0 +1,4 @@ +sty $ff +lda #{coby1} +sec +sbc $ff \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_neg_asby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_neg_asby.asm new file mode 100644 index 000000000..9c8b937fb --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_neg_asby.asm @@ -0,0 +1,3 @@ +eor #$ff +clc +adc #$01 \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_sbyte_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_sbyte_aby.asm new file mode 100644 index 000000000..93c22cd75 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_sbyte_aby.asm @@ -0,0 +1 @@ +// casting byte to sbyte - do nothing \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_sbyte_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_sbyte_xby.asm new file mode 100644 index 000000000..403ee3380 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_sbyte_xby.asm @@ -0,0 +1 @@ +txa \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_sbyte_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_sbyte_yby.asm new file mode 100644 index 000000000..8b4b4f7e8 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/asby=_sbyte_yby.asm @@ -0,0 +1 @@ +tya \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/xby=_byte_xsby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/xby=_byte_xsby.asm new file mode 100644 index 000000000..505d4e29a --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/xby=_byte_xsby.asm @@ -0,0 +1 @@ +// Do nothing: casting signed byte to byte \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/xsby=_sbyte_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/xsby=_sbyte_xby.asm new file mode 100644 index 000000000..8b66f4c38 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/xsby=_sbyte_xby.asm @@ -0,0 +1 @@ +// casting - do nothing \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/xsby=_sbyte_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/xsby=_sbyte_zpby1.asm new file mode 100644 index 000000000..269f3a259 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/xsby=_sbyte_zpby1.asm @@ -0,0 +1 @@ +ldx {zpby1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/yby=_byte_ysby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/yby=_byte_ysby.asm new file mode 100644 index 000000000..505d4e29a --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/yby=_byte_ysby.asm @@ -0,0 +1 @@ +// Do nothing: casting signed byte to byte \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/ysby=_sbyte_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/ysby=_sbyte_yby.asm new file mode 100644 index 000000000..8b66f4c38 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/ysby=_sbyte_yby.asm @@ -0,0 +1 @@ +// casting - do nothing \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpsby1=_sbyte_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpsby1=_sbyte_xby.asm new file mode 100644 index 000000000..6e902d6ff --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpsby1=_sbyte_xby.asm @@ -0,0 +1 @@ +stx {zpsby1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpsby1=_sbyte_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpsby1=_sbyte_yby.asm new file mode 100644 index 000000000..4bdedc840 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpsby1=_sbyte_yby.asm @@ -0,0 +1 @@ +sty {zpsby1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/model/Operator.java b/src/main/java/dk/camelot64/kickc/model/Operator.java index 39c933f87..b985ffe72 100644 --- a/src/main/java/dk/camelot64/kickc/model/Operator.java +++ b/src/main/java/dk/camelot64/kickc/model/Operator.java @@ -1,6 +1,8 @@ package dk.camelot64.kickc.model; -/** An Operator. The operation performed on the rvalues in a Statement. */ +/** + * An Operator. The operation performed on the rvalues in a Statement. + */ public class Operator { private String operator; @@ -9,10 +11,13 @@ public class Operator { private Type type; - public Operator(String operator, Type type, int precedence) { + private String asmOperator; + + public Operator(String operator, String asmOperator, Type type, int precedence) { this.operator = operator; this.precedence = precedence; this.type = type; + this.asmOperator = asmOperator; } public static Operator getBinary(String op) { @@ -38,7 +43,7 @@ public class Operator { case ">=": return GE; case "*idx": - return STAR_IDX; + return DEREF_IDX; case "&&": return LOGIC_AND; case "||": @@ -77,7 +82,7 @@ public class Operator { case "~": return BOOL_NOT; case "*": - return STAR; + return DEREF; case "<": return LOWBYTE; case ">": @@ -87,39 +92,58 @@ public class Operator { } } - public static enum Type { + public static Operator getCastUnary(SymbolType castType) { + if (SymbolTypeBasic.BYTE.equals(castType)) { + return CAST_BYTE; + } else if (SymbolTypeBasic.SBYTE.equals(castType)) { + return CAST_SBYTE; + } else if (SymbolTypeBasic.WORD.equals(castType)) { + return CAST_WORD; + } else if (SymbolTypeBasic.SWORD.equals(castType)) { + return CAST_SWORD; + } else { + throw new RuntimeException("Unknown cast type " + castType); + + } + } + + public enum Type { UNARY, BINARY } - public static Operator INCREMENT = new Operator("++", Type.UNARY, 1); - public static Operator DECREMENT = new Operator("--", Type.UNARY, 1); - public static Operator UNARY_PLUS = new Operator("+", Type.UNARY, 2); - public static Operator UNARY_MINUS = new Operator("-", Type.UNARY, 2); - public static Operator BOOL_NOT = new Operator("~", Type.UNARY, 2); - public static Operator NOT = new Operator("!", Type.UNARY, 2); - public static Operator STAR = new Operator("*", Type.UNARY, 2); - public static Operator LOWBYTE = new Operator("<", Type.UNARY, 2); - public static Operator HIBYTE = new Operator(">", Type.UNARY, 2); - public static Operator STAR_IDX = new Operator("*idx", Type.BINARY, 2); - public static Operator SET_LOWBYTE = new Operator("lo=", Type.BINARY, 2); - public static Operator SET_HIBYTE = new Operator("hi=", Type.BINARY, 2); - public static Operator MULTIPLY = new Operator("*", Type.BINARY, 3); - public static Operator DIVIDE = new Operator("/", Type.BINARY, 3); - public static Operator PLUS = new Operator("+", Type.BINARY, 4); - public static Operator MINUS = new Operator("-", Type.BINARY, 4); - public static Operator SHIFT_LEFT = new Operator("<<", Type.BINARY, 5); - public static Operator SHIFT_RIGHT = new Operator(">>", Type.BINARY, 5); - public static Operator LT = new Operator("<", Type.BINARY, 6); - public static Operator LE = new Operator("<=", Type.BINARY, 6); - public static Operator GT = new Operator(">", Type.BINARY, 6); - public static Operator GE = new Operator(">=", Type.BINARY, 6); - public static Operator EQ = new Operator("==", Type.BINARY, 7); - public static Operator NEQ = new Operator("!=", Type.BINARY, 7); - public static Operator BOOL_AND = new Operator("&", Type.BINARY, 8); - public static Operator BOOL_XOR = new Operator("^", Type.BINARY, 9); - public static Operator BOOL_OR = new Operator("|", Type.BINARY, 10); - public static Operator LOGIC_AND = new Operator("&&", Type.BINARY, 11); - public static Operator LOGIC_OR = new Operator("||", Type.BINARY, 12); + public static final Operator INCREMENT = new Operator("++", "_inc_", Type.UNARY, 1); + public static final Operator DECREMENT = new Operator("--", "_dec_", Type.UNARY, 1); + public static final Operator UNARY_PLUS = new Operator("+", "_pos_", Type.UNARY, 2); + public static final Operator UNARY_MINUS = new Operator("-", "_neg_", Type.UNARY, 2); + public static final Operator BOOL_NOT = new Operator("~", "_not_", Type.UNARY, 2); + public static final Operator NOT = new Operator("!", "_not_", Type.UNARY, 2); + public static final Operator DEREF = new Operator("*", "_deref_", Type.UNARY, 2); + public static final Operator LOWBYTE = new Operator("<", "_lo_", Type.UNARY, 2); + public static final Operator HIBYTE = new Operator(">", "_hi_", Type.UNARY, 2); + public static final Operator DEREF_IDX = new Operator("*idx", "_derefidx_", Type.BINARY, 2); + public static final Operator SET_LOWBYTE = new Operator("lo=", "_setlo_", Type.BINARY, 2); + public static final Operator SET_HIBYTE = new Operator("hi=", "_sethi_", Type.BINARY, 2); + public static final Operator CAST_BYTE = new Operator("_byte_", "_byte_", Type.UNARY, 2); + public static final Operator CAST_SBYTE = new Operator("_sbyte_", "_sbyte_", Type.UNARY, 2); + public static final Operator CAST_WORD = new Operator("_word_", "_word_", Type.UNARY, 2); + public static final Operator CAST_SWORD = new Operator("_sword_", "_sword_", Type.UNARY, 2); + public static final Operator MULTIPLY = new Operator("*", "_mul_", Type.BINARY, 3); + public static final Operator DIVIDE = new Operator("/", "_div_", Type.BINARY, 3); + public static final Operator PLUS = new Operator("+", "_plus_", Type.BINARY, 4); + public static final Operator MINUS = new Operator("-", "_minus_", Type.BINARY, 4); + public static final Operator SHIFT_LEFT = new Operator("<<", "_rol_", Type.BINARY, 5); + public static final Operator SHIFT_RIGHT = new Operator(">>", "_ror_", Type.BINARY, 5); + public static final Operator LT = new Operator("<", "_lt_", Type.BINARY, 6); + public static final Operator LE = new Operator("<=", "_le_", Type.BINARY, 6); + public static final Operator GT = new Operator(">", "_gt_", Type.BINARY, 6); + public static final Operator GE = new Operator(">=", "_ge_", Type.BINARY, 6); + public static final Operator EQ = new Operator("==", "_eq_", Type.BINARY, 7); + public static final Operator NEQ = new Operator("!=", "_neq_", Type.BINARY, 7); + public static final Operator BOOL_AND = new Operator("&", "_band_", Type.BINARY, 8); + public static final Operator BOOL_XOR = new Operator("^", "_bxor_", Type.BINARY, 9); + public static final Operator BOOL_OR = new Operator("|", "_bor_", Type.BINARY, 10); + public static final Operator LOGIC_AND = new Operator("&&", "_and_", Type.BINARY, 11); + public static final Operator LOGIC_OR = new Operator("||", "_or_", Type.BINARY, 12); public String getOperator() { return operator; @@ -133,6 +157,10 @@ public class Operator { return type; } + public String getAsmOperator() { + return asmOperator; + } + @Override public String toString() { return operator; diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java index 43f28bc89..f1d1a5c39 100644 --- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java +++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java @@ -10,6 +10,7 @@ public class SymbolTypeBasic implements SymbolType { public static final SymbolTypeBasic SBYTE = new SymbolTypeBasic("signed byte"); public static final SymbolTypeBasic WORD = new SymbolTypeBasic("word"); + public static final SymbolTypeBasic SWORD = new SymbolTypeBasic("signed word"); public static final SymbolTypeBasic STRING = new SymbolTypeBasic("string"); public static final SymbolTypeBasic BOOLEAN = new SymbolTypeBasic("boolean"); @@ -38,6 +39,7 @@ public class SymbolTypeBasic implements SymbolType { case "byte": return BYTE; case "signed byte": return SBYTE; case "word": return WORD; + case "signed word": return SWORD; case "string": return STRING; case "boolean": return BOOLEAN; case "void": return VOID; diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java index 5250504fa..7cab9c4eb 100644 --- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java @@ -1,29 +1,40 @@ package dk.camelot64.kickc.model; -/** Type inference of expressions (rValues & unary/binary operators) */ +/** + * Type inference of expressions (rValues & unary/binary operators) + */ public class SymbolTypeInference { public static SymbolType inferType(Operator operator, SymbolType subType) { - if(operator==null) { + if (operator == null) { return subType; } - String op = operator.getOperator(); - switch (op) { - case "*": - if(subType instanceof SymbolTypePointer) { - return ((SymbolTypePointer) subType).getElementType(); - } else { - throw new RuntimeException("Type error: Dereferencing a non-pointer "+subType); - } - case "<": - case ">": - if(subType instanceof SymbolTypePointer || SymbolTypeBasic.WORD.equals(subType)) { - return SymbolTypeBasic.BYTE; - - } - default: - return subType; + if (Operator.DEREF.equals(operator)) { + if (subType instanceof SymbolTypePointer) { + return ((SymbolTypePointer) subType).getElementType(); + } else { + throw new RuntimeException("Type error: Dereferencing a non-pointer " + subType); + } + } else if (Operator.LOWBYTE.equals(operator)) { + if (subType instanceof SymbolTypePointer || SymbolTypeBasic.WORD.equals(subType)) { + return SymbolTypeBasic.BYTE; + } + } else if (Operator.HIBYTE.equals(operator)) { + if (subType instanceof SymbolTypePointer || SymbolTypeBasic.WORD.equals(subType)) { + return SymbolTypeBasic.BYTE; + } + } else if (Operator.CAST_BYTE.equals(operator)) { + return SymbolTypeBasic.BYTE; + } else if (Operator.CAST_SBYTE.equals(operator)) { + return SymbolTypeBasic.SBYTE; + } else if (Operator.CAST_WORD.equals(operator)) { + return SymbolTypeBasic.WORD; + } else if (Operator.CAST_SWORD.equals(operator)) { + return SymbolTypeBasic.SWORD; + } else { + return subType; } + throw new RuntimeException("Type inference problem unary " + operator + " " + subType); } public static SymbolType inferType(SymbolType type1, Operator operator, SymbolType type2) { @@ -47,8 +58,8 @@ public class SymbolTypeInference { if (type1.equals(SymbolTypeBasic.STRING) && SymbolTypeBasic.BYTE.equals(type2)) { return SymbolTypeBasic.STRING; } else if (type1.equals(SymbolTypeBasic.STRING) && SymbolTypeBasic.STRING.equals(type2)) { - return SymbolTypeBasic.STRING; - } + return SymbolTypeBasic.STRING; + } case "-": // Also continues "+" if (type1 instanceof SymbolTypePointer && (type2.equals(SymbolTypeBasic.BYTE) || type2.equals(SymbolTypeBasic.WORD))) { @@ -68,7 +79,7 @@ public class SymbolTypeInference { } throw new RuntimeException("Type inference case not handled " + type1 + " " + operator + " " + type2); case "*": - if(type1==null && type2 instanceof SymbolTypePointer) { + if (type1 == null && type2 instanceof SymbolTypePointer) { return ((SymbolTypePointer) type2).getElementType(); } if (SymbolTypeBasic.WORD.equals(type1) || SymbolTypeBasic.WORD.equals(type2)) { @@ -80,7 +91,7 @@ public class SymbolTypeInference { } throw new RuntimeException("Type inference case not handled " + type1 + " " + operator + " " + type2); case "*idx": - if(type1 instanceof SymbolTypePointer) { + if (type1 instanceof SymbolTypePointer) { return ((SymbolTypePointer) type1).getElementType(); } throw new RuntimeException("Type inference case not handled " + type1 + " " + operator + " " + type2); @@ -140,12 +151,12 @@ public class SymbolTypeInference { SymbolType leftType = inferType(programScope, constBin.getLeft()); SymbolType rightType = inferType(programScope, constBin.getRight()); return inferType(leftType, constBin.getOperator(), rightType); - } else if(rValue instanceof PointerDereferenceSimple) { + } else if (rValue instanceof PointerDereferenceSimple) { SymbolType pointerType = inferType(programScope, ((PointerDereferenceSimple) rValue).getPointer()); - if(pointerType instanceof SymbolTypePointer) { + if (pointerType instanceof SymbolTypePointer) { return ((SymbolTypePointer) pointerType).getElementType(); } else { - throw new RuntimeException("Cannot infer pointer element type from pointer type "+pointerType); + throw new RuntimeException("Cannot infer pointer element type from pointer type " + pointerType); } } if (type == null) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java index ba459a310..486eebd3e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java @@ -438,7 +438,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public SymbolType visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { - return SymbolTypeBasic.get("signed "+ctx.SIMPLETYPE().getText()); + return SymbolTypeBasic.get("signed " + ctx.SIMPLETYPE().getText()); } @Override @@ -464,8 +464,14 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public RValue visitExprCast(KickCParser.ExprCastContext ctx) { - program.getLog().append("Cast type ignored!"); - return (RValue) visit(ctx.expr()); + RValue child = (RValue) this.visit(ctx.expr()); + SymbolType castType = (SymbolType) this.visit(ctx.typeDecl()); + Operator operator = Operator.getCastUnary(castType); + VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); + VariableRef tmpVarRef = tmpVar.getRef(); + Statement stmt = new StatementAssignment(tmpVarRef, operator, child); + sequence.addStatement(stmt); + return tmpVarRef; } @Override @@ -497,7 +503,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { public RValue visitExprArray(KickCParser.ExprArrayContext ctx) { RValue array = (LValue) visit(ctx.expr(0)); RValue index = (RValue) visit(ctx.expr(1)); - Operator operator = Operator.STAR_IDX; + Operator operator = Operator.DEREF_IDX; VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); VariableRef tmpVarRef = tmpVar.getRef(); Statement stmt = new StatementAssignment(tmpVarRef, array, operator, index); @@ -550,7 +556,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { RValue child = (RValue) this.visit(ctx.expr()); String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText(); Operator operator = Operator.getUnary(op); - if (Operator.STAR.equals(operator)) { + if (Operator.DEREF.equals(operator)) { return new PointerDereferenceSimple(child); } else { VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java index 43de53c69..feb5a393d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java @@ -88,7 +88,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { ConstantValue idxConstant = (ConstantValue) assignment.getrValue2(); ConstantValue newPtr = new ConstantBinary(ptrConstant, Operator.PLUS, idxConstant); assignment.setrValue1(null); - assignment.setOperator(Operator.STAR); + assignment.setOperator(Operator.DEREF); assignment.setrValue2(newPtr); getLog().append("Consolidated referenced array index constant in assignment " + assignment.getlValue()); return true; diff --git a/src/main/java/dk/camelot64/kickc/test/TestPrograms.java b/src/main/java/dk/camelot64/kickc/test/TestPrograms.java index e793545bb..ad3a8f27f 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/main/java/dk/camelot64/kickc/test/TestPrograms.java @@ -24,6 +24,10 @@ public class TestPrograms extends TestCase { helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/"); } + public void testCasting() throws IOException, URISyntaxException { + compileAndCompare("casting"); + } + public void testSignedBytes() throws IOException, URISyntaxException { compileAndCompare("signed-bytes"); } diff --git a/src/main/java/dk/camelot64/kickc/test/casting.kc b/src/main/java/dk/camelot64/kickc/test/casting.kc new file mode 100644 index 000000000..c6e6e7c33 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/casting.kc @@ -0,0 +1,13 @@ +byte* SCREEN = $0400; +byte* SCREEN2 = $0600; + +void main() { + for( byte b: 0..100) { + byte b2 = 100-b; + SCREEN2[b] = b2; + signed byte sb = - (signed byte)b; + SCREEN[b] = (byte)sb; + } + +} +