DEADSOFTWARE

JVM: Добавлено больше операторов
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 26 Jul 2017 19:36:35 +0000 (22:36 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 26 Jul 2017 19:36:35 +0000 (22:36 +0300)
src/backends/jvm/generator-jvm.c
src/backends/jvm/generator-jvm.h
src/test.c
tst.java [deleted file]

index c217ccb3d6f37ebb809bf076dcd35e62636d3c5e..b0c54ff1d967aab8a5126d43f1313a344be408f4 100644 (file)
@@ -491,7 +491,7 @@ jvm_alloc_register(struct gen_register_file * rf, oberon_type_t * type)
        else
        {
                assert(i <= MAX_REGISTERS);
-               rf -> num_used += 2;
+               rf -> num_used += 1;
                rf -> reg[i].used = true;
                rf -> reg[i].wide = false;
        }
@@ -754,60 +754,155 @@ push_item(oberon_context_t * ctx, FILE * fp, oberon_item_t * item)
        }
 }
 
+static int
+jvm_new_label_id(oberon_context_t * ctx)
+{
+       gen_context_t * c = ctx -> gen_context;
+       int label_id = c -> label_id;
+       c -> label_id += 1;
+       return label_id;
+}
+
+static char *
+jvm_get_label_name(int label_id)
+{
+       return new_string("L%i", label_id);
+}
+
 static void
-push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper)
+jvm_generate_label(FILE * fp, int label_id)
 {
-       char prefix = get_prefix(ctx, oper -> result);
-       switch(oper -> op)
+       fprintf(fp, "L%i:\n", label_id);
+}
+
+static void
+jvm_generate_logical_not(oberon_context_t * ctx, FILE * fp)
+{
+       int label_true = jvm_new_label_id(ctx);
+       int label_false = jvm_new_label_id(ctx);
+       char * label_name_true = jvm_get_label_name(label_true);
+       char * label_name_false = jvm_get_label_name(label_false);
+
+       fprintf(fp, "ifne %s\n", label_name_false);
+       fprintf(fp, "iconst_1\n");
+       fprintf(fp, "goto %s\n", label_name_true);
+       jvm_generate_label(fp, label_false);
+       fprintf(fp, "iconst_0\n");
+       jvm_generate_label(fp, label_true);
+}
+
+static char
+jvm_get_type_of_prefix(char prefix)
+{
+       switch(prefix)
+       {
+               case 'b':
+                       return 'B';
+               case 'c':
+                       return 'C';
+               case 'd':
+                       return 'D';
+               case 'f':
+                       return 'F';
+               case 'i':
+                       return 'I';
+               case 'l':
+                       return 'J';
+       }
+
+       assert(0);
+}
+
+static void
+jvm_generate_abs(FILE * fp, char prefix)
+{
+       char t = jvm_get_type_of_prefix(prefix);
+       fprintf(fp, "invokestatic java/lang/Math/abs(%c)%c\n", t, t);
+}
+
+static void
+jvm_generate_compare_op(oberon_context_t * ctx, FILE *fp, char prefix, int op)
+{
+       int label_true = jvm_new_label_id(ctx);
+       int label_false = jvm_new_label_id(ctx);
+       char * label_name_true = jvm_get_label_name(label_true);
+       char * label_name_false = jvm_get_label_name(label_false);
+
+       assert(prefix == 'i' || prefix == 'a');
+
+       switch(op)
+       {
+               case OP_EQ:
+                       fprintf(fp, "if_%ccmpeq %s\n", prefix, label_name_true);
+                       break;
+               case OP_NEQ:
+                       fprintf(fp, "if_%ccmpne %s\n", prefix, label_name_true);
+                       break;
+               case OP_LSS:
+                       fprintf(fp, "if_icmplt %s\n", label_name_true);
+                       break;
+               case OP_LEQ:
+                       fprintf(fp, "if_icmple %s\n", label_name_true);
+                       break;
+               case OP_GRT:
+                       fprintf(fp, "if_icmpgt %s\n", label_name_true);
+                       break;
+               case OP_GEQ:
+                       fprintf(fp, "if_icmpge %s\n", label_name_true);
+                       break;
+               default:
+                       oberon_error(ctx, "jvm_generate_compare_op: wat");
+                       break;
+       }
+
+       fprintf(fp, "iconst_0\n");
+       fprintf(fp, "goto %s\n", label_name_false);
+       jvm_generate_label(fp, label_true);
+       fprintf(fp, "iconst_1\n");
+       jvm_generate_label(fp, label_false);
+}
+
+static void
+jvm_generate_operator(oberon_context_t * ctx, FILE *fp, char prefix, int op)
+{
+       switch(op)
        {
                case OP_UNARY_MINUS:
-                       push_expr(ctx, fp, oper -> left);
                        fprintf(fp, "%cneg\n", prefix);
                        break;
                case OP_BITWISE_NOT:
-                       push_expr(ctx, fp, oper -> left);
                        push_int(fp, -1);
                        fprintf(fp, "%cxor\n", prefix);
                        break;
+               case OP_LOGIC_NOT:
+                       jvm_generate_logical_not(ctx, fp);
+                       break;
+               case OP_ABS:
+                       jvm_generate_abs(fp, prefix);
+                       break;
 
                case OP_ADD:
-                       push_expr(ctx, fp, oper -> left);
-                       push_expr(ctx, fp, oper -> right);
                        fprintf(fp, "%cadd\n", prefix);
                        break;
                case OP_SUB:
-                       push_expr(ctx, fp, oper -> left);
-                       push_expr(ctx, fp, oper -> right);
                        fprintf(fp, "%csub\n", prefix);
                        break;
                case OP_MUL:
-                       push_expr(ctx, fp, oper -> left);
-                       push_expr(ctx, fp, oper -> right);
                        fprintf(fp, "%cmul\n", prefix);
                        break;
                case OP_DIV:
-                       push_expr(ctx, fp, oper -> left);
-                       push_expr(ctx, fp, oper -> right);
                        fprintf(fp, "%cdiv\n", prefix);
                        break;
                case OP_MOD:
-                       push_expr(ctx, fp, oper -> left);
-                       push_expr(ctx, fp, oper -> right);
                        fprintf(fp, "%crem\n", prefix);
                        break;
                case OP_BITWISE_AND:
-                       push_expr(ctx, fp, oper -> left);
-                       push_expr(ctx, fp, oper -> right);
                        fprintf(fp, "%cand\n", prefix);
                        break;
                case OP_BITWISE_XOR:
-                       push_expr(ctx, fp, oper -> left);
-                       push_expr(ctx, fp, oper -> right);
                        fprintf(fp, "%cxor\n", prefix);
                        break;
                case OP_BITWISE_OR:
-                       push_expr(ctx, fp, oper -> left);
-                       push_expr(ctx, fp, oper -> right);
                        fprintf(fp, "%cor\n", prefix);
                        break;
 
@@ -817,12 +912,51 @@ push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper)
                case OP_LEQ:
                case OP_GRT:
                case OP_GEQ:
+                       jvm_generate_compare_op(ctx, fp, prefix, op);
+                       break;
+               default:
+                       oberon_error(ctx, "jvm_generate_operator: unk op %i", op);
+                       break;
+       }       
+}
+
+static void
+push_operator(oberon_context_t * ctx, FILE * fp, oberon_oper_t * oper)
+{
+       char prefix = get_prefix(ctx, oper -> result);
+       int op = oper -> op;
+       switch(op)
+       {
+               case OP_UNARY_MINUS:
+               case OP_BITWISE_NOT:
                case OP_LOGIC_NOT:
                case OP_ABS:
-                       oberon_error(ctx, "push_oper: TODO op %i", oper -> op);
+                       push_expr(ctx, fp, oper -> left);
+                       jvm_generate_operator(ctx, fp, prefix, op);
                        break;
+
+               case OP_ADD:
+               case OP_SUB:
+               case OP_MUL:
+               case OP_DIV:
+               case OP_MOD:
+               case OP_BITWISE_AND:
+               case OP_BITWISE_XOR:
+               case OP_BITWISE_OR:
+
+               case OP_EQ:
+               case OP_NEQ:
+               case OP_LSS:
+               case OP_LEQ:
+               case OP_GRT:
+               case OP_GEQ:
+                       push_expr(ctx, fp, oper -> left);
+                       push_expr(ctx, fp, oper -> right);
+                       jvm_generate_operator(ctx, fp, prefix, op);
+                       break;
+
                default:
-                       oberon_error(ctx, "push_oper: unk op %i", oper -> op);
+                       oberon_error(ctx, "push_oper: unk op %i", op);
                        break;
        }
 }
index 01c29ee481785830c6e0e0999be79b179f63f44c..3ccc9f50ac3cbdfd6563aab5d0ef208320e90a27 100644 (file)
@@ -36,6 +36,7 @@ struct gen_context_t
 {
        gen_module_t * m;
        struct gen_register_file * rf;
+       int label_id;
 };
 
 struct gen_module_t
index eb1008c986bb52159572b33fe4f80bd205ab6b91..96e160a7087354a4e07b77900298aacdf9e235ba 100644 (file)
@@ -9,6 +9,7 @@ static char source_test[] =
        "MODULE Test;"
        "VAR"
        "  x : INTEGER;"
+       "  b : BOOLEAN;"
        ""
        "PROCEDURE Tier(x : INTEGER) : INTEGER;"
        "VAR"
@@ -19,7 +20,9 @@ static char source_test[] =
        "END Tier;"
        ""
        "BEGIN;"
-       "  x := Tier(666);"
+       "  x := ABS(-666);"
+       "  x := Tier(x);"
+       "  b := ~TRUE;"
        "END Test."
 ;
 
diff --git a/tst.java b/tst.java
deleted file mode 100644 (file)
index 2dae5b2..0000000
--- a/tst.java
+++ /dev/null
@@ -1,4 +0,0 @@
-public abstract class tst
-{
-       public abstract void invoke();
-}