index d609ed8de96c216a30ac4ec9bceda90ec230583e..ca0f88565536d1ae11ce2022c4713099fb9bcf0c 100644 (file)
}
}
+static void
+jvm_generate_push_string(gen_proc_t * p, char * str, int char_size)
+{
+ assert(char_size == 1);
+ int len = strlen(str);
+
+ jvm_generate_push_int(p, len + 1);
+ jvm_generate(p, 1, 1, "newarray byte");
+
+ for(int i = 0; i < len; i++)
+ {
+ jvm_generate(p, 1, 2, "dup");
+ jvm_generate_push_int(p, i);
+ jvm_generate_push_int(p, str[i]);
+ jvm_generate(p, 3, 0, "bastore");
+ }
+}
+
static gen_var_t *
oberon_generator_new_var()
{
* Входящие параметры заграблены.
* Теперь генерируем эквивалентный код:
* int i = 0;
- * int len = dst.length
+ * int len = src.length
* while(i < len)
* {
* ...
jvm_generate(p, 0, 1, "iconst_0");
jvm_generate(p, 1, 0, "istore %i", loop[i].index -> reg);
- jvm_generate_load(p, arr, dst);
+ jvm_generate_load(p, arr, src);
jvm_generate(p, 1, 1, "arraylength");
jvm_generate(p, 1, 0, "istore %i", loop[i].length -> reg);
case OBERON_TYPE_ARRAY:
case OBERON_TYPE_REAL:
case OBERON_TYPE_CHAR:
+ case OBERON_TYPE_STRING:
break;
case OBERON_TYPE_RECORD:
;
}
}
+void
+oberon_generator_init_temp_var(oberon_context_t * ctx, oberon_object_t * var)
+{
+ assert(var -> class == OBERON_CLASS_VAR);
+
+ gen_var_t * v = oberon_generator_new_var();
+ var -> gen_var = v;
+
+ gen_module_t * m;
+ m = ctx -> mod -> gen_mod;
+
+ gen_proc_t * p;
+ p = m -> class -> p;
+
+ bool wide;
+ wide = jvm_is_wide_type(var -> type);
+
+ jvm_generate_and_init_local_var(v, p, wide);
+}
+
void
oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
{
jvm_generate_function_end(p);
}
+gen_label_t *
+oberon_generator_reserve_label(oberon_context_t * ctx)
+{
+ gen_module_t * m;
+ gen_proc_t * p;
+ gen_label_t * l;
+
+ m = ctx -> mod -> gen_mod;
+ p = m -> class -> p;
+
+ l = GC_MALLOC(sizeof *l);
+ memset(l, 0, sizeof *l);
+
+ l -> id = jvm_new_label_id(p);
+ return l;
+}
+
+void
+oberon_generate_label(oberon_context_t * ctx, gen_label_t * l)
+{
+ gen_module_t * m;
+ gen_proc_t * p;
+
+ m = ctx -> mod -> gen_mod;
+ p = m -> class -> p;
+
+ jvm_generate_label(p, l -> id);
+}
+
+void
+oberon_generate_goto(oberon_context_t * ctx, gen_label_t * l)
+{
+ gen_module_t * m;
+ gen_proc_t * p;
+
+ m = ctx -> mod -> gen_mod;
+ p = m -> class -> p;
+
+ jvm_generate(p, 0, 0, "goto L%i", l -> id);
+}
+
+void
+oberon_generate_branch(oberon_context_t * ctx, oberon_expr_t * cond, bool gotoif, gen_label_t * l)
+{
+ gen_module_t * m;
+ gen_proc_t * p;
+
+ m = ctx -> mod -> gen_mod;
+ p = m -> class -> p;
+
+ push_expr(p, cond);
+
+ if(gotoif == false)
+ {
+ /* переход если false */
+ jvm_generate(p, 1, 0, "ifeq L%i", l -> id);
+ }
+ else
+ {
+ /* переход если true */
+ jvm_generate(p, 1, 0, "ifne L%i", l -> id);
+ }
+}
+
static void
jvm_generate_call_proc(gen_proc_t * p, oberon_item_t * desig)
{
case MODE_REAL:
jvm_generate_push_float(p, item -> real, item -> result -> size);
break;
+ case MODE_STRING:
+ jvm_generate_push_string(p, item -> string, item -> result -> size);
+ break;
default:
gen_error("push_item: unk mode %i", item -> mode);
break;
jvm_generate(p, cell_size, cell_size, "invokestatic java/lang/Math/abs(%c)%c", t, t);
}
-static void
-jvm_generate_compare_op(gen_proc_t * p, char prefix, int op)
+static char *
+jvm_get_compare_postfix(int op)
{
- int label_true = jvm_new_label_id(p);
- int label_done = jvm_new_label_id(p);
- char * label_name_true = jvm_get_label_name(label_true);
- char * label_name_done = jvm_get_label_name(label_done);
- int cell_size = 2 * jvm_cell_size_for_postfix(prefix);
-
- assert(prefix == 'i' || prefix == 'a');
-
- const char * cmpop = "";
+ char * cmpop = "";
switch(op)
{
case OP_EQ:
gen_error("jvm_generate_compare_op: wat");
break;
}
+ return cmpop;
+}
+
+static void
+jvm_generate_compare_op(gen_proc_t * p, oberon_type_t * t, int op)
+{
+ char prefix = jvm_get_prefix(t);
+ int label_true = jvm_new_label_id(p);
+ int label_done = jvm_new_label_id(p);
+ int cell_size = jvm_cell_size_for_type(t);
+ char * cmpop = jvm_get_compare_postfix(op);
+
+ if(prefix == 'l')
+ {
+ jvm_generate(p, 2 * cell_size, 1, "lcmp");
+ jvm_generate(p, 1, 1, "if%s L%i", cmpop, label_true);
+ }
+ else if(prefix == 'f' || prefix == 'd')
+ {
+ char fop;
+ if(op == OP_EQ || op == OP_NEQ || op == OP_GRT || op == OP_GEQ)
+ {
+ fop = 'l';
+ }
+ else
+ {
+ fop = 'g';
+ }
+ jvm_generate(p, 2 * cell_size, 1, "%ccmp%c", prefix, fop);
+ jvm_generate(p, 1, 1, "if%s L%i", cmpop, label_true);
+ }
+ else
+ {
+ jvm_generate(p, 2 * cell_size, 0, "if_%ccmp%s L%i", prefix, cmpop, label_true);
+ }
- jvm_generate(p, cell_size, 0, "if_%ccmp%s %s", prefix, cmpop, label_name_true);
jvm_generate(p, 0, 1, "iconst_0");
- jvm_generate(p, 0, 0, "goto %s", label_name_done);
+ jvm_generate(p, 0, 0, "goto L%i", label_done);
jvm_generate_label(p, label_true);
jvm_generate(p, 0, 1, "iconst_1");
jvm_generate_label(p, label_done);
}
static void
-jvm_generate_operator(gen_proc_t * p, char prefix, int op)
+jvm_generate_operator(gen_proc_t * p, oberon_type_t * t, char prefix, int op)
{
int cell_size = jvm_cell_size_for_postfix(prefix);
switch(op)
case OP_LEQ:
case OP_GRT:
case OP_GEQ:
- jvm_generate_compare_op(p, prefix, op);
+ jvm_generate_compare_op(p, t, op);
break;
default:
gen_error("jvm_generate_operator: unk op %i", op);
@@ -1580,6 +1712,7 @@ jvm_generate_logical_and(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b)
static void
push_operator(gen_proc_t * p, oberon_oper_t * oper)
{
+ oberon_type_t * preq = oper -> left -> result;
char prefix = jvm_get_prefix(oper -> result);
int op = oper -> op;
switch(op)
case OP_LOGIC_NOT:
case OP_ABS:
push_expr(p, oper -> left);
- jvm_generate_operator(p, prefix, op);
+ jvm_generate_operator(p, preq, prefix, op);
break;
case OP_ADD:
case OP_GEQ:
push_expr(p, oper -> left);
push_expr(p, oper -> right);
- jvm_generate_operator(p, prefix, op);
+ jvm_generate_operator(p, preq, prefix, op);
break;
case OP_LOGIC_OR: