From: Matthias Braun Date: Sun, 2 Dec 2007 17:57:58 +0000 (+0000) Subject: updated TODO, improved driver stuff a bit to use more pipes and allow input/output... X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=853c9303530a0f2e68ac923538765f15efea6a90;p=cparser updated TODO, improved driver stuff a bit to use more pipes and allow input/output from stdin/stdout [r18586] --- diff --git a/TODO b/TODO index 491c6cc..37eb859 100644 --- a/TODO +++ b/TODO @@ -1,23 +1,18 @@ Lexer: -- proper support of preprocessor -- octal&hex escape sequences -- wide string constants -- proper handling of different file encodings +- Add preprocessor code +- proper handling of different file encodings, parsing non-ascii strings Parser: - the expect macros abort functions directly. This leads to some functions not resetting the current context properly (parse_for) -- proper handling of function pointer types -- outermost typequalifiers can differ between function declarations and - implementations... -- fix semantic to ignore type qualifiers (const double is the same as double) - label: declaration; is no valid C99 but we parse it anyway - designator support for initializers -- support string literals in intializers +- add constant folding code +- Refactor code, so code to handle number values and strings is + an own module and replacable ast2firm: - output source file positions for panics... -- create strict convs where necessary Coole Warnungen: diff --git a/ast2firm.c b/ast2firm.c index 0551fb7..2104de9 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -39,6 +39,8 @@ static ir_node **imature_blocks; static const declaration_t *current_function_decl; static ir_node *current_function_name; +static struct obstack asm_obst; + typedef enum declaration_type_t { DECLARATION_TYPE_UNKNOWN, DECLARATION_TYPE_FUNCTION, @@ -87,10 +89,12 @@ const char *retrieve_dbg(const dbg_info *dbg, unsigned *line) void init_ast2firm(void) { + obstack_init(&asm_obst); } void exit_ast2firm(void) { + obstack_free(&asm_obst, NULL); } static unsigned unique_id = 0; @@ -2780,6 +2784,101 @@ static void goto_to_firm(const goto_statement_t *statement) set_cur_block(NULL); } +typedef enum modifier_t { + ASM_MODIFIER_WRITE_ONLY = 1 << 0, + ASM_MODIFIER_READ_WRITE = 1 << 1, + ASM_MODIFIER_COMMUTATIVE = 1 << 2, + ASM_MODIFIER_EARLYCLOBBER = 1 << 3, +} modifier_t; + +#if 0 +static void asm_statement_to_firm(const asm_statement_t *statement) +{ + bool needs_memory = false; + + size_t n_clobbers = 0; + asm_clobber_t *clobber = statement->clobbers; + for( ; clobber != NULL; clobber = clobber->next) { + if(strcmp(clobber->clobber, "memory") == 0) { + needs_memory = true; + continue; + } + + ident *id = new_id_from_str(clobber->clobber); + obstack_ptr_grow(&asm_obst, id); + ++n_clobbers; + } + assert(obstack_object_size(&asm_obst) == n_clobbers * sizeof(ident*)); + ident **clobbers = NULL; + if(n_clobbers > 0) { + clobbers = obstack_finish(&asm_obst); + } + + /* find and count input and output constraints */ + asm_constraint_t *constraint = statement->inputs; + for( ; constraint != NULL; constraint = constraint->next) { + int modifiers = 0; + bool supports_memop = false; + for(const char *c = constraint->constraints; *c != 0; ++c) { + /* TODO: improve error messages */ + switch(*c) { + case '?': + case '!': + panic("multiple alternative assembler constraints not " + "supported"); + case 'm': + case 'o': + case 'V': + case '<': + case '>': + case 'X': + supports_memop = true; + obstack_1grow(&asm_obst, *c); + break; + case '=': + if(modifiers & ASM_MODIFIER_READ_WRITE) + panic("inconsistent register constraints"); + modifiers |= ASM_MODIFIER_WRITE_ONLY; + break; + case '+': + if(modifiers & ASM_MODIFIER_WRITE_ONLY) + panic("inconsistent register constraints"); + modifiers |= ASM_MODIFIER_READ_WRITE; + break; + case '&': + modifiers |= ASM_MODIFIER_EARLYCLOBBER; + panic("early clobber assembler constraint not supported yet"); + break; + case '%': + modifiers |= ASM_MODIFIER_COMMUTATIVE; + panic("commutative assembler constraint not supported yet"); + break; + case '#': + /* skip register preferences stuff... */ + while(*c != 0 && *c != ',') + ++c; + break; + case '*': + /* skip register preferences stuff... */ + ++c; + break; + default: + obstack_1grow(&asm_obst, *c); + break; + } + } + obstack_1grow(&asm_obst, '\0'); + const char *constraint_string = obstack_finish(&asm_obst); + + needs_memory |= supports_memop; + if(supports_memop) { + + } + } + +} +#endif + static void statement_to_firm(statement_t *statement) { switch(statement->type) { @@ -2828,7 +2927,9 @@ static void statement_to_firm(statement_t *statement) goto_to_firm(&statement->gotos); return; case STATEMENT_ASM: + //asm_statement_to_firm(&statement->asms); break; + return; } panic("Statement not implemented\n"); } diff --git a/main.c b/main.c index 4bfb5c0..34ee11b 100644 --- a/main.c +++ b/main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #ifndef WITH_LIBCORE @@ -32,6 +33,10 @@ #define LINKER "gcc" #endif +#ifndef ASSEMBLER +#define ASSEMBLER "as" +#endif + #ifdef _WIN32 /* remap some names */ #define popen(cmd, mode) _popen(cmd, mode) @@ -103,6 +108,12 @@ static void get_output_name(char *buf, size_t buflen, const char *inputname, { size_t last_dot = 0xffffffff; size_t i = 0; + + if(inputname == NULL) { + snprintf(buf, buflen, "a%s", newext); + return; + } + for(const char *c = inputname; *c != 0; ++c) { if(*c == '.') last_dot = i; @@ -128,14 +139,8 @@ static translation_unit_t *do_parsing(FILE *const in, const char *const input) return unit; } -static void lextest(const char *fname) +static void lextest(FILE *in, const char *fname) { - FILE *in = fopen(fname, "r"); - if(in == NULL) { - fprintf(stderr, "Couldn't open '%s': %s\n", fname, strerror(errno)); - exit(1); - } - lexer_open_stream(in, fname); do { @@ -143,34 +148,23 @@ static void lextest(const char *fname) print_token(stdout, &lexer_token); puts(""); } while(lexer_token.type != T_EOF); - - fclose(in); } -static void backend(const char *inputname, const char *outname) +static void emit(FILE *out, const char *input_name) { - FILE *out = fopen(outname, "w"); - if(out == NULL) { - fprintf(stderr, "couldn't open '%s' for writing: %s\n", outname, - strerror(errno)); - exit(1); - } - - be_main(out, inputname); - - fclose(out); + be_main(out, input_name); } -static void emit(const char *input_name, const char *out_name) -{ - backend(input_name, out_name); -} - -static FILE* preprocess(const char *in) +static FILE* preprocess(FILE* in, const char *fname) { char buf[4096]; - snprintf(buf, sizeof(buf), PREPROCESSOR " %s", in); + if(in != stdin) { + snprintf(buf, sizeof(buf), PREPROCESSOR " %s", fname); + } else { + /* read from stdin */ + snprintf(buf, sizeof(buf), PREPROCESSOR " -"); + } if(verbose) { puts(buf); @@ -183,7 +177,7 @@ static FILE* preprocess(const char *in) return f; } -static void link(const char *in, const char *out) +static void do_link(const char *out, const char *in) { char buf[4096]; @@ -198,14 +192,15 @@ static void link(const char *in, const char *out) } } -static void assemble(const char *in, const char *out) +static void assemble(const char *out, const char *in) { char buf[4096]; - snprintf(buf, sizeof(buf), "%s %s -c -o %s", LINKER, in, out); + snprintf(buf, sizeof(buf), "%s %s -o %s", ASSEMBLER, in, out); if(verbose) { puts(buf); } + int err = system(buf); if(err != 0) { fprintf(stderr, "assembler reported an error\n"); @@ -213,6 +208,77 @@ static void assemble(const char *in, const char *out) } } +static const char *try_dir(const char *dir) +{ + if(dir == NULL) + return dir; + if(access(dir, R_OK | W_OK | X_OK) == 0) + return dir; + return NULL; +} + +static const char *get_tempdir(void) +{ + static const char *tmpdir = NULL; + + if(tmpdir != NULL) + return tmpdir; + + if(tmpdir == NULL) + tmpdir = try_dir(getenv("TMPDIR")); + if(tmpdir == NULL) + tmpdir = try_dir(getenv("TMP")); + if(tmpdir == NULL) + tmpdir = try_dir(getenv("TEMP")); + +#ifdef P_tmpdir + if(tmpdir == NULL) + tmpdir = try_dir(P_tmpdir); +#endif + + if(tmpdir == NULL) + tmpdir = try_dir("/var/tmp"); + if(tmpdir == NULL) + tmpdir = try_dir("/usr/tmp"); + if(tmpdir == NULL) + tmpdir = try_dir("/tmp"); + + if(tmpdir == NULL) + tmpdir = "."; + + return tmpdir; +} + +/** + * an own version of tmpnam, which: writes in a buffer, appends a user specified + * suffix, emits no warnings during linking (like glibc/gnu ld do for tmpnam)... + */ +static FILE *make_temp_file(char *buffer, size_t buflen, + const char *prefix, const char *suffix) +{ + const char *tempdir = get_tempdir(); + + /* oh well... mkstemp doesn't accept a suffix after XXXXXX... */ + (void) suffix; + suffix = ""; + + snprintf(buffer, buflen, "%s/%sXXXXXX%s", tempdir, prefix, suffix); + + int fd = mkstemp(buffer); + if(fd == -1) { + fprintf(stderr, "couldn't create temporary file: %s\n", + strerror(errno)); + exit(1); + } + FILE *out = fdopen(fd, "w"); + if(out == NULL) { + fprintf(stderr, "couldn't create temporary file FILE*\n"); + exit(1); + } + + return out; +} + static void create_firm_prog(translation_unit_t *unit) { translation_unit_to_firm(unit); @@ -367,9 +433,11 @@ int main(int argc, char **argv) return 1; } } - //firm_be_option(opt); + //be_parse_arg(opt); } else if(arg[0] == '-') { - if (arg[1] == 'D' || + if (arg[1] == '\0') { + input = "-"; + } else if (arg[1] == 'D' || arg[1] == 'O' || arg[1] == 'f' || arg[1] == 'W' || @@ -391,60 +459,108 @@ int main(int argc, char **argv) } } + FILE *out; + char outnamebuf[4096]; + if(outname == NULL) { + switch(mode) { + case PrintAst: + case PrintFluffy: + case LexTest: + break; + case Compile: + get_output_name(outnamebuf, sizeof(outnamebuf), input, ".s"); + outname = outnamebuf; + break; + case CompileAssemble: + get_output_name(outnamebuf, sizeof(outnamebuf), input, ".o"); + outname = outnamebuf; + break; + case CompileAssembleLink: + outname = "a.out"; + break; + } + assert(outname != NULL); + } + + if(strcmp(outname, "-") == 0) { + out = stdout; + } else { + out = fopen(outname, "w"); + if(out == NULL) { + fprintf(stderr, "Couldn't open '%s' for writing: %s\n", outname, + strerror(errno)); + return 1; + } + } + + FILE *in; if(input == NULL) { fprintf(stderr, "%s: no input files\n", argv[0]); return 1; + } else if(strcmp(input, "-") == 0) { + in = stdin; + input = ""; + } else { + in = fopen(input, "r"); + if(in == NULL) { + fprintf(stderr, "Couldn't open '%s': %s\n", input, strerror(errno)); + return 1; + } } if(mode == LexTest) { - lextest(input); + lextest(in, input); + fclose(in); return 0; } - FILE *const in = preprocess(input); - translation_unit_t *const unit = do_parsing(in, input); - pclose(in); + FILE *preprocessed_in = preprocess(in, input); + translation_unit_t *const unit = do_parsing(preprocessed_in, input); + pclose(preprocessed_in); if(unit == NULL) return 1; if(mode == PrintAst) { + ast_set_output(out); print_ast(unit); return 0; } if(mode == PrintFluffy) { - ast_set_output(stdout); - write_fluffy_decls(unit); + write_fluffy_decls(out, unit); } - char outsname[4096]; - const char *sname = NULL; + FILE *asm_out; + char asm_tempfile[1024]; if(mode == Compile) { - sname = outname; - } - if(sname == NULL) { - get_output_name(outsname, sizeof(outsname), input, ".s"); - sname = outsname; + asm_out = out; + } else { + asm_out + = make_temp_file(asm_tempfile, sizeof(asm_tempfile), "cc", ".s"); } create_firm_prog(unit); optimize(); - emit(input, sname); - - if(mode == CompileAssemble) { - char outoname[4096]; - const char *oname = outname; - if(oname == NULL) { - get_output_name(outoname, sizeof(outoname), input, ".o"); - oname = outoname; + emit(asm_out, input); + fclose(asm_out); + + char obj_tfile[1024]; + if(mode == CompileAssemble || mode == CompileAssembleLink) { + const char *obj_outfile; + if(mode == CompileAssemble) { + fclose(out); + obj_outfile = outname; + } else { + FILE *tempf + = make_temp_file(obj_tfile, sizeof(obj_tfile), "cc", ".o"); + fclose(tempf); + obj_outfile = obj_tfile; } - assemble(sname, oname); - } else { - assert(mode == CompileAssembleLink); - if(outname == NULL) - outname = "a.out"; + assemble(obj_outfile, asm_tempfile); + } - link(sname, outname); + if(mode == CompileAssembleLink) { + do_link(outname, obj_tfile); } exit_ast2firm(); diff --git a/write_fluffy.c b/write_fluffy.c index 7ffac47..2956231 100644 --- a/write_fluffy.c +++ b/write_fluffy.c @@ -306,18 +306,12 @@ static void write_function(const declaration_t *declaration) fputc('\n', out); } -void write_fluffy_decls(const translation_unit_t *unit) +void write_fluffy_decls(FILE *output, const translation_unit_t *unit) { -#if 0 - out = fopen("out.fluffy", "w"); - if(out == NULL) { - fprintf(stderr, "Couldn't open out.fluffy: %s\n", strerror(errno)); - exit(1); - } -#endif - out = stdout; + out = output; global_context = &unit->context; + ast_set_output(out); fprintf(out, "/* WARNING: Automatically generated file */\n"); /* write structs,unions + enums */ @@ -368,6 +362,4 @@ void write_fluffy_decls(const translation_unit_t *unit) write_function(declaration); } - - //fclose(out); } diff --git a/write_fluffy.h b/write_fluffy.h index 12cedd6..c623952 100644 --- a/write_fluffy.h +++ b/write_fluffy.h @@ -3,6 +3,6 @@ #include "ast.h" -void write_fluffy_decls(const translation_unit_t *unit); +void write_fluffy_decls(FILE *out, const translation_unit_t *unit); #endif