📄 idelasm.c
字号:
compile_number (void){ int value; if (parse_number (&value)) gen2 (PUSH, value, absolute); else { stub (string_dup (token_text)); gen_insn (CALL, 0, text_segment, find (&globals, token_text)); }}static void compile_token (void){ const Symbol *e = find (&locals, token_text); if (e && e->opcode != unbound) gen2 (LOCAL, locals.size - 1 - e->index, absolute); else { const Symbol *e = find (&globals, token_text); if (e == NULL) compile_number (); else switch (e->opcode) { case CALL: gen_insn (CALL, 0, e->segment, e); break; case PUSH: gen2 (PUSH, e->index, e->segment); break; case LOCAL: unreachable (); break; default: gen (e->opcode); break; } }}static intseeing (const char *string){ return 0 == strcmp (token_text, string);}static voidexpect (const char *string){ if (!seeing (string)) syntax_error ("Missing `%s'", string);}static voideat (const char *string){ expect (string); advance ();}static intsee_locals (void){ int before = locals.size; for (;;) { advance (); if (seeing ("--")) break; else if (seeing ("}")) syntax_error ("Missing `--'"); else define_local (token_text); } return locals.size - before;}static voidnest (void){ for (;;) { advance (); if (seeing ("{")) { int count = see_locals (); if (count != 0) gen (BEGIN); nest (); expect ("}"); if (count != 0) gen2 (DROP, count, absolute); unbind (&locals, count); } else if (seeing ("}")) break; else if (seeing ("if")) { gen (BEGIN); nest (); if (seeing ("else")) { gen (ELSE); nest (); } expect ("then"); gen (THEN); } else if (seeing ("else")) break; else if (seeing ("then")) break; else if (seeing (";")) break; else if (seeing ("")) break; else compile_token (); }}static u32parse_stack_effect (void){ int popping, pushing; advance (); if (!parse_number (&popping)) syntax_error ("Number expected (pushing)"); advance (); if (!parse_number (&pushing)) syntax_error ("Number expected (popping)"); return interleave_bits (popping, pushing);}static voidcolon (void){ u32 se = parse_stack_effect (); advance (); if (seeing ("")) syntax_error ("Name expected"); { const char *name = string_dup (token_text); create (name, se); nest (); eat (";"); created (name); }}static voidcompile_bytes (void){ int token_value; while (parse_number (&token_value)) { emit_byte (token_value); advance (); }}static voidcompile_ints (void){ int token_value; while (parse_number (&token_value)) { emit_int (token_value); advance (); }}static voidparse_bytes (void){ advance (); if (seeing ("")) syntax_error ("Name expected"); { const char *name = string_dup (token_text); new_header (&globals, name, PUSH, data_ptr, data_segment, 0); advance (); compile_bytes (); eat (";bytes"); }}static voidparse_ints (void){ advance (); if (seeing ("")) syntax_error ("Name expected"); { const char *name = string_dup (token_text); data_ptr = word_align (data_ptr); new_header (&globals, name, PUSH, data_ptr, data_segment, 0); advance (); compile_ints (); eat (";ints"); }}static voidcompile_string_constant (void){ skip_preprocessor (); if (ch != '"') syntax_error ("Expected a string constant"); next (); for (; ch != '"'; next ()) if (ch == '\0') syntax_error ("Unterminated string constant"); else if (ch == '\\') emit_byte (scan_escape ()); else emit_byte (ch); next ();}static voidparse_string (void){ advance (); if (seeing ("")) syntax_error ("Name expected"); { const char *addr_name = string_cat (token_text, ".addr"); const char *size_name = string_cat (token_text, ".size"); int start = data_ptr; new_header (&globals, addr_name, PUSH, start, data_segment, 0); compile_string_constant (); new_header (&globals, size_name, PUSH, data_ptr - start, data_segment, 0); advance (); }}static voidparse_bss_data (void){ int value; advance (); if (seeing ("")) syntax_error ("Name expected"); { const char *name = string_dup (token_text); new_header (&globals, name, PUSH, bss_ptr, bss_segment, 0); advance (); if (!parse_number (&value)) syntax_error ("Integer expected"); if (value < 0) syntax_error ("Negative count"); advance (); if (bss_ptr + value < bss_ptr) syntax_error ("BSS space overflow"); bss_ptr += value; }}static voidcompile_program (void){ scan = program; ch = *scan; start_line (); advance (); while (!seeing ("")) { if (seeing ("def")) colon (); else if (seeing ("bytes:")) parse_bytes (); else if (seeing ("ints:")) parse_ints (); else if (seeing ("string:")) parse_string (); else if (seeing ("bss-data:")) parse_bss_data (); else syntax_error ("Definition expected"); }}/* Output */static voidpush_insn (OW *ow, const Insn *insn, int this_index){ int op = insn->opcode; switch (op) { case DROP: case LOCAL: push_u32 (ow, insn->operand); break; case PUSH: if (insn->segment == bss_segment) push_i32 (ow, bss_start + insn->operand); else push_i32 (ow, insn->operand); break; case CALL: if (insn->symbol->index == -1) { the_place = insn->place; syntax_error ("Unresolved reference to %s", insn->symbol->name); } push_i32 (ow, insn->symbol->index - this_index); break; } push_u8 (ow, op);}static voidpush_defn (OW *ow, const Symbol *e){ int mark = start_subfile (ow); int i; for (i = e->start; i < e->end; ++i) push_insn (ow, &text[i], e->index); end_subfile (ow, mark);}static Symbol **defns_fill (void){ int d, i; Symbol **defn_symbol = allot (current_index * sizeof defn_symbol[0]); for (d = 0; d < current_index; ++d) defn_symbol[d] = NULL; for (i = 0; i < globals.size; ++i) { Symbol *e = globals.stack[i]; if (e->opcode == CALL && e->index != -1) { assert (0 <= e->index && e->index < current_index); defn_symbol[e->index] = e; } } return defn_symbol;} static Symbol *defns_ref (Symbol **defn_symbol, int i){ assert (0 <= i && i < current_index); if (defn_symbol[i] == NULL) die ("Unresolved defn"); /* This can't happen (right?) */ return defn_symbol[i];}static voidpush_defns (OW *ow){ int mark = start_subfile (ow); Symbol **defn_symbol = defns_fill (); int i; for (i = current_index - 1; 0 <= i; --i) push_defn (ow, defns_ref (defn_symbol, i)); for (i = current_index - 1; 0 <= i; --i) push_u32 (ow, defns_ref (defn_symbol, i)->stack_effect); free (defn_symbol); push_u32 (ow, current_index); end_subfile (ow, mark); push_tag (ow, tag_defns);}static voidpush_int_run (OW *ow, int top, int bottom){ int mark = start_subfile (ow); while (bottom < top) { top -= word_size; push_i32 (ow, *(i32 *)(data + top)); } end_subfile (ow, mark); push_tag (ow, tag_ints);}static voidpush_byte_run (OW *ow, int top, int bottom){ int mark = start_subfile (ow); while (bottom < top) { top -= 1; push_u8 (ow, data[endianness ^ top]); } end_subfile (ow, mark); push_tag (ow, tag_bytes);}static voidpush_run (OW *ow, int top, int bottom, int int_encoded_size){ if (int_encoded_size < top - bottom) push_int_run (ow, top, bottom); else push_byte_run (ow, top, bottom);}static intblock_size (int byte_count){ return 1 + u32_encoded_size (byte_count) + byte_count;}static boolshould_join (int top, int bot1, int size1, int bot2, int size2){ if (size1 < top - bot1) return size2 < block_size (bot1 - bot2); else return bot1 - bot2 < block_size (size2);}/* Traverse the run of data words ending at index `top' whose sizes when int-encoded are either all >= word_size or all <= word_size. Set *bottom to the index of the start of the run, and *int_encoded_size to the size as encoded. Pre: `top' points to a word boundary > 0. */static voidfind_run (int *bottom, int *int_encoded_size, int top){ int bot = top; int sum = 0; /* sum of the sizes from bot to top */ int L, variety; /* Go through any initial run of size=word_size words */ do { bot -= word_size; L = i32_encoded_size (*(i32 *)(data + bot)); sum += L; } while (0 < bot && word_size != L); /* Now we know which variety of run we're looking for */ variety = (L <= word_size); /* So go through the ensuing run of that type, and we're done */ while (0 < bot) { L = i32_encoded_size (*(i32 *)(data + bot - word_size)); if (variety != (L <= word_size)) break; bot -= word_size, sum += L; } *bottom = bot; *int_encoded_size = sum;}/* Push a Zeroes block if needed to pad out to the total space, and return the address of the top of the nonzero data. */static intpush_zeroes (OW *ow){ int top = word_align (data_ptr); int space = top + word_align (bss_ptr); /* Skip down over any zeroes at the top of the data segment */ while (0 < top && 0 == *(i32 *)(data + top - 4)) top -= 4; if (top < space) { int mark = start_subfile (ow); push_i32 (ow, space - top); end_subfile (ow, mark); push_tag (ow, tag_zeroes); } return top;}/* Push all the static data onto `ow'. Produces a combination of int and byte sections for space efficiency -- it's essentially doing run-length encoding on the int-encoded sizes of the data words. This lets us encode both arrays of small integers and arrays of random bytes with reasonable efficiency. */static voidpush_data (OW *ow){ int top = push_zeroes (ow); int bot1, size1; int bot2, size2; if (top == 0) return; find_run (&bot1, &size1, top); while (0 < bot1) { find_run (&bot2, &size2, bot1); /* There's a run-boundary at bot1 now. If switching the run type is too expensive we instead join the following two runs into the topmost one. */ if (should_join (top, bot1, size1, bot2, size2)) { bot1 = bot2, size1 += size2; if (0 < bot1) { find_run (&bot2, &size2, bot1); bot1 = bot2, size1 += size2; } } else { push_run (ow, top, bot1, size1); top = bot1, bot1 = bot2, size1 = size2; } } push_run (ow, top, bot1, size1);}static voidwrite_program (const char *comment){ OW *ow = ow_make (); bss_start = word_align (data_ptr); push_data (ow); push_defns (ow); push_header (ow, comment); ow_write (stdout, ow); ow_unmake (ow);}/* The main program */static voidprocess_file (const char *filename){ int size; FILE *input = open_file (filename, "r"); the_place.filename = (input == stdin ? NULL : filename); the_place.line = the_place.column = 0; read_file (&program, &size, input); fclose (input); compile_program (); free (program);}static voidshow_version (void){ printf ("idelasm version %s\n", idel_version_string); exit (0);}static voidshow_help (void){ printf ("Usage: %s [option]... [file]...\n", program_name); printf ("where the legal options are:\n"" -comment <string>\n"" -help\n"" -version\n"); exit (0);}static const char *parse_comment (const char *comment){ if (strchr (comment, '\n')) die ("Comment contains a newline: %s", comment); return comment;}const char *program_name;intmain (int argc, char **argv){ const char *comment = NULL; program_name = argv[0]; setup_dictionaries (); setup_primitives (); setup_insns (); setup_data_space (); /* Parse command-line options */ for (;;) { if (1 < argc) { if (0 == strcmp ("-version", argv[1])) show_version (); if (0 == strcmp ("-help", argv[1])) show_help (); } if (2 < argc) { if (0 == strcmp ("-comment", argv[1])) comment = parse_comment (argv[2]); else break; argc -= 2, argv += 2; } else break; } if (argc == 1) process_file ("-"); else for (; 1 < argc; ++argv, --argc) process_file (argv[1]); write_program (comment); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -