/* stabend - emits the symbol table */ static void stabend(Coordinate *cp, Symbol symroot, Coordinate *cpp[], Symbol sp[], Symbol *ignore) { Symbol addresses; int naddresses, nmodule; { /* annotate top-level symbols */ Symbol p; for (p = symroot; p != NULL; p = up(p->up)) symboluid(p); pickle->globals = symboluid(symroot); } { /* emit addresses of top-level and static symbols */ int i, lc = 0, count = Seq_length(statics); addresses = genident(STATIC, array(voidptype, 1, 0), GLOBAL); comment("addresses:\n"); defglobal(addresses, LIT); for (i = 0; i < count; i++) { Symbol p = Seq_get(statics, i); lc = emit_value(lc, voidptype, p); } lc = pad(maxalign, lc); naddresses = lc; Seq_free(&statics); } { /* emit bp count as an alias for the module */ Symbol spoints = mksymbol(AUTO, stringf("_spoints_V%x_%d", uname, Seq_length(pickle->spoints)), array(unsignedtype, 0, 0)); spoints->generated = 1; defglobal(spoints, LIT); } { /* emit module */ int lc; comment("module:\n"); defglobal(module, LIT); lc = emit_value( 0, unsignedtype, (unsigned long)uname); lc = emit_value(lc, voidptype, addresses); lc = pad(maxalign, lc); nmodule = lc; } Seq_free(&locals); #define printit(x) fprintf(stderr, "%7d " #x "\n", n##x); total += n##x { int total = 0; printit(addresses); printit(module); fprintf(stderr, "%7d bytes total\n", total); } #undef printit { /* complete and write symbol-table pickle */ FILE *f = fopen(stringf("%d.pickle", uname), "wb"); sym_write_module(pickle, f); fclose(f); } }
static def_t * get_value_def (ex_value_t *value, etype_t type) { def_t *def; if (type == ev_short) { def = new_def (0, &type_short, 0, sc_extern); def->offset = value->v.short_val; return def; } def = emit_value (value, 0); if (type != def->type->type) return alias_def (def, ev_types[type], 0); return def; }
TEST(syntax, emitting) { CREATE_RUNTIME(); value_t ast = new_heap_literal_ast(runtime, yes()); assembler_t assm; ASSERT_SUCCESS(assembler_init(&assm, runtime, nothing(), scope_get_bottom())); ASSERT_SUCCESS(emit_value(ast, &assm)); assembler_emit_return(&assm); value_t code = assembler_flush(&assm); ASSERT_SUCCESS(code); value_t result = run_code_block_until_condition(ambience, code); ASSERT_VALEQ(yes(), result); assembler_dispose(&assm); DISPOSE_RUNTIME(); }
static int compile_operator(compiletime c) { int operand_count = 0; const char *op = pop_operator(c, &operand_count); if (!strcmp(op, "*")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, multiply_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "**")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, power_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "/")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, divide_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "%")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, modulo_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "=")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, assign_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ";")) { } else if (!strcmp(op, "if")) { const char *val1 = pop_operand(c); emit2(c, if_tc, val1); DEBUG printf("emit '%s' %s\n", val1, op); c->level++; } else if (!strcmp(op, "else")) { c->level--; emit1(c, else_tc); c->level++; DEBUG printf("emit %s\n", op); } else if (!strcmp(op, "fi")) { c->level--; emit1(c, fi_tc); DEBUG printf("emit %s\n", op); } else if (!strcmp(op, "!")) { const char *val1 = pop_operand(c); emit2(c, not_tc, val1); DEBUG printf("emit '%s' %s\n", val1, op); } else if (!strcmp(op, "+")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, add_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "-")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, subtract_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ">")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, gt_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ">=")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, geq_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "<=")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, leq_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "<")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, lt_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "&&")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, and_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "||")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, or_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "^^")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, xor_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "&")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, bit_and_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "|")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, bit_or_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "^")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, bit_xor_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "~")) { const char *val1 = pop_operand(c); emit2(c, bit_negate_tc, val1); DEBUG printf("emit %s %s\n", val1, op); } else if (!strcmp(op, "<<")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, shift_left_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ">>")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, shift_right_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, ">>>")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, logical_shift_right_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "==")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, eq_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "!=")) { const char *val2 = pop_operand(c); const char *val1 = pop_operand(c); emit3(c, neq_tc, val1, val2); DEBUG printf("emit %s %s %s\n", val1, op, val2); } else if (!strcmp(op, "fold-case")) { const char *val1 = pop_operand(c); emit2(c, func_fold_case_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "size")) { const char *val1 = pop_operand(c); emit2(c, func_size_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "print")) { const char *val1 = pop_operand(c); emit2(c, func_print_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "jday")) { const char *val1 = pop_operand(c); emit2(c, func_jday_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "dow")) { const char *val1 = pop_operand(c); emit2(c, func_dow_tc, val1); DEBUG printf("emit %s %s\n", op, val1); } else if (!strcmp(op, "equals")) { emit_code(c, func_eq_tc, operand_count); while (operand_count--) { const char *val1 = pop_operand(c); emit_value(c, val1); DEBUG printf("emit %s '%s'\n", op, val1); } } else if (!strcmp(op, "contains")) { emit_code(c, func_contains_tc, operand_count); while (operand_count--) { const char *val1 = pop_operand(c); emit_value(c, val1); DEBUG printf("emit %s '%s'\n", op, val1); } } else if (!strcmp(op, "begins-with")) { emit_code(c, func_begins_with_tc, operand_count); while (operand_count--) { const char *val1 = pop_operand(c); emit_value(c, val1); DEBUG printf("emit %s '%s'\n", op, val1); } } else if (!strcmp(op, "ends-with")) { emit_code(c, func_ends_with_tc, operand_count); while (operand_count--) { const char *val1 = pop_operand(c); emit_value(c, val1); DEBUG printf("emit %s '%s'\n", op, val1); } } else if (!strcmp(op, "int")) { const char *val1 = pop_operand(c); emit2(c, func_is_int_tc, val1); DEBUG printf("emit %s '%s'\n", op, val1); } else if (!strcmp(op, "real")) { const char *val1 = pop_operand(c); emit2(c, func_is_real_tc, val1); DEBUG printf("emit %s '%s'\n", op, val1); } else if (!strcmp(op, "nan")) { const char *val1 = pop_operand(c); emit2(c, func_is_nan_tc, val1); DEBUG printf("emit %s '%s'\n", op, val1); } else if (!strcmp(op, "string")) { const char *val1 = pop_operand(c); emit2(c, func_is_string_tc, val1); DEBUG printf("emit %s '%s'\n", op, val1); } else if (!strcmp(op, "(")) { return 1; } else if (!strcmp(op, ")")) { return 1; } else { DEBUG printf("bad operator '%s'\n", op); return 0; } push_operand(c, "_STACK"); return 1; }
static void emit3(compiletime c, typecode tc, const char *v1, const char *v2) { emit_code(c, tc, 2); emit_value(c, v1); emit_value(c, v2); }
static void emit2(compiletime c, typecode tc, const char *v1) { emit_code(c, tc, 1); emit_value(c, v1); }