improve array support, start doing some driver stuff
authorMatthias Braun <matze@braunis.de>
Fri, 16 Nov 2007 13:44:04 +0000 (13:44 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 16 Nov 2007 13:44:04 +0000 (13:44 +0000)
[r18410]

ast2firm.c
main.c
parser.c

index df44b68..8e3b3ac 100644 (file)
@@ -256,6 +256,8 @@ static unsigned count_parameters(const function_type_t *function_type)
 
 
 
+static long fold_constant(const expression_t *expression);
+
 static ir_type *create_atomic_type(const atomic_type_t *type)
 {
        ir_mode *mode   = get_atomic_mode(type);
@@ -317,21 +319,23 @@ static ir_type *create_array_type(array_type_t *type)
        type_t  *element_type    = type->element_type;
        ir_type *ir_element_type = get_ir_type(element_type);
 
-       /* TODO... */
-       int n_elements = 0;
-       panic("TODO arraytpye size not implemented yet");
+       ident   *id      = unique_ident("array");
+       ir_type *ir_type = new_type_array(id, 1, ir_element_type);
+
+       if(type->size != NULL) {
+               int n_elements = fold_constant(type->size);
 
-       ir_type *ir_type = new_type_array(unique_ident("array"), 1, ir_element_type);
-       set_array_bounds_int(ir_type, 0, 0, n_elements);
+               set_array_bounds_int(ir_type, 0, 0, n_elements);
 
-       size_t elemsize = get_type_size_bytes(ir_element_type);
-       int align = get_type_alignment_bytes(ir_element_type);
-       if(elemsize % align > 0) {
-               elemsize += align - (elemsize % align);
+               size_t elemsize = get_type_size_bytes(ir_element_type);
+               int align = get_type_alignment_bytes(ir_element_type);
+               if(elemsize % align > 0) {
+                       elemsize += align - (elemsize % align);
+               }
+               set_type_size_bytes(ir_type, n_elements * elemsize);
+               set_type_alignment_bytes(ir_type, align);
+               set_type_state(ir_type, layout_fixed);
        }
-       set_type_size_bytes(ir_type, n_elements * elemsize);
-       set_type_alignment_bytes(ir_type, align);
-       set_type_state(ir_type, layout_fixed);
 
        return ir_type;
 }
@@ -491,6 +495,12 @@ static ir_type *get_ir_type(type_t *type)
 static inline ir_mode *get_ir_mode(type_t *type)
 {
        ir_type *irtype = get_ir_type(type);
+
+       /* firm doesn't report a mode for arrays somehow... */
+       if(is_Array_type(irtype)) {
+               return mode_P;
+       }
+
        ir_mode *mode   = get_type_mode(irtype);
        assert(mode != NULL);
        return mode;
@@ -612,7 +622,7 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
 {
        dbg_info      *dbgi        = get_dbg_info(&ref->expression.source_position);
        declaration_t *declaration = ref->declaration;
-       type_t        *type        = declaration->type;
+       type_t        *type        = skip_typeref(declaration->type);
        ir_mode       *mode        = get_ir_mode(type);
 
        switch((declaration_type_t) declaration->declaration_type) {
@@ -626,7 +636,12 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
        case DECLARATION_TYPE_GLOBAL_VARIABLE: {
                ir_entity *entity   = declaration->v.entity;
                ir_node   *symconst = create_symconst(dbgi, entity);
-               return load_from_expression_addr(type, symconst, dbgi);
+
+               if(type->type == TYPE_ARRAY) {
+                       return symconst;
+               } else {
+                       return load_from_expression_addr(type, symconst, dbgi);
+               }
        }
        case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY:
        case DECLARATION_TYPE_COMPOUND_MEMBER:
@@ -1148,7 +1163,6 @@ static ir_node *array_access_addr(const array_access_expression_t *expression)
 static ir_node *array_access_to_firm(
                const array_access_expression_t *expression)
 {
-
        dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
        ir_node  *addr = array_access_addr(expression);
        type_t   *type = expression->expression.datatype;
@@ -1674,6 +1688,26 @@ static void switch_statement_to_firm(const switch_statement_t *statement)
        set_cur_block(break_block);
 }
 
+static long fold_constant(const expression_t *expression)
+{
+       ir_graph *old_current_ir_graph = current_ir_graph;
+       current_ir_graph = get_const_code_irg();
+
+       ir_node *cnst = expression_to_firm(expression);
+       if(!is_Const(cnst)) {
+               panic("couldn't fold constantl");
+       }
+       tarval *tv = get_Const_tarval(cnst);
+       if(!tarval_is_long(tv)) {
+               panic("folded constant not an integer");
+       }
+
+       long res = get_tarval_long(tv);
+
+       current_ir_graph = old_current_ir_graph;
+       return res;
+}
+
 static void case_label_to_firm(const case_label_statement_t *statement)
 {
        dbg_info *dbgi = get_dbg_info(&statement->statement.source_position);
@@ -1683,16 +1717,7 @@ static void case_label_to_firm(const case_label_statement_t *statement)
        ir_node *proj;
        set_cur_block(get_nodes_block(current_switch_cond));
        if(statement->expression) {
-               ir_node *cnst = expression_to_firm(statement->expression);
-               if(!is_Const(cnst)) {
-                       panic("couldn't fold constant for case label");
-               }
-               tarval *tv = get_Const_tarval(cnst);
-               if(!mode_is_int(get_tarval_mode(tv))) {
-                       panic("case label not an integer");
-               }
-
-               long pn = get_tarval_long(tv);
+               long pn = fold_constant(statement->expression);
                if(pn == MAGIC_DEFAULT_PN_NUMBER) {
                        /* oops someone detected our cheating... */
                        panic("magic default pn used");
diff --git a/main.c b/main.c
index 0f442a1..802eb35 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,9 +1,10 @@
 #include <config.h>
 
-#include <stdlib.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <string.h>
+#include <assert.h>
 
 #ifndef WITH_LIBCORE
 #define WITH_LIBCORE
@@ -19,7 +20,8 @@
 #include "ast2firm.h"
 #include "adt/error.h"
 
-#define LINKER "gcc"
+#define PREPROCESSOR "gcc -E"
+#define LINKER       "gcc"
 
 static int verbose;
 
@@ -107,7 +109,7 @@ static void get_output_name(char *buf, size_t buflen, const char *inputname,
        memcpy(buf+last_dot, newext, extlen);
 }
 
-static translation_unit_t *do_parsing(const char *fname)
+static translation_unit_t *do_parsing(const char *fname, const char *input)
 {
        FILE *in = fopen(fname, "r");
        if(in == NULL) {
@@ -115,7 +117,7 @@ static translation_unit_t *do_parsing(const char *fname)
                exit(1);
        }
 
-       lexer_open_stream(in, fname);
+       lexer_open_stream(in, input);
 
        translation_unit_t *unit = parse();
 
@@ -162,6 +164,21 @@ static void emit(const char *input_name, const char *out_name)
        backend(input_name, out_name);
 }
 
+static void preprocess(const char *in, const char *out)
+{
+       char buf[4096];
+
+       snprintf(buf, sizeof(buf), "%s %s -o %s", PREPROCESSOR, in, out);
+       if(verbose) {
+               puts(buf);
+       }
+       int err = system(buf);
+       if(err != 0) {
+               fprintf(stderr, "preprocessor reported an error\n");
+               exit(1);
+       }
+}
+
 static void link(const char *in, const char *out)
 {
        char buf[4096];
@@ -177,7 +194,20 @@ static void link(const char *in, const char *out)
        }
 }
 
+static void assemble(const char *in, const char *out)
+{
+       char buf[4096];
 
+       snprintf(buf, sizeof(buf), "%s %s -c -o %s", LINKER, in, out);
+       if(verbose) {
+               puts(buf);
+       }
+       int err = system(buf);
+       if(err != 0) {
+               fprintf(stderr, "assembler reported an error\n");
+               exit(1);
+       }
+}
 
 static void create_firm_prog(translation_unit_t *unit)
 {
@@ -192,6 +222,15 @@ static void create_firm_prog(translation_unit_t *unit)
 
 static void optimize(void)
 {
+       int         arr_len;
+       ir_entity **keep_methods;
+
+       cgana(&arr_len, &keep_methods);
+       gc_irgs(arr_len, keep_methods);
+       free(keep_methods);
+
+       optimize_funccalls(0);
+
        for(int i = 0; i < get_irp_n_irgs(); ++i) {
                ir_graph *irg = get_irp_irg(i);
                place_code(irg);
@@ -205,6 +244,20 @@ static void optimize(void)
 
 void write_fluffy_decls(translation_unit_t *unit);
 
+typedef enum compile_mode_t {
+       Compile,
+       CompileAssemble,
+       CompileAssembleLink,
+       LexTest,
+       PrintAst,
+       PrintFluffy
+} compile_mode_t;
+
+static void usage(const char *argv0)
+{
+       fprintf(stderr, "Usage %s input [-o output] [-c]\n", argv0);
+}
+
 int main(int argc, char **argv)
 {
        initialize_firm();
@@ -218,41 +271,100 @@ int main(int argc, char **argv)
        init_parser();
        init_ast2firm();
 
-       if(argc > 2 && strcmp(argv[1], "--lextest") == 0) {
-               lextest(argv[2]);
-               return 0;
-       }
+       const char *input   = NULL;
+       const char *outname = NULL;
+       compile_mode_t mode = CompileAssembleLink;
 
-       if(argc > 2 && strcmp(argv[1], "--print-ast") == 0) {
-               translation_unit_t *unit = do_parsing(argv[2]);
-               ast_set_output(stdout);
-               if(unit != NULL) {
-                       print_ast(unit);
+       for(int i = 1; i < argc; ++i) {
+               const char *arg = argv[i];
+               if(strcmp(arg, "-o") == 0) {
+                       ++i;
+                       if(i >= argc) {
+                               usage(argv[0]);
+                               return 1;
+                       }
+                       outname = argv[i];
+               } else if(strcmp(arg, "-c") == 0) {
+                       mode = CompileAssemble;
+               } else if(strcmp(arg, "-S") == 0) {
+                       mode = Compile;
+               } else if(strcmp(arg, "--lextest") == 0) {
+                       mode = LexTest;
+               } else if(strcmp(arg, "--print-ast") == 0) {
+                       mode = PrintAst;
+               } else if(strcmp(arg, "--print-fluffy") == 0) {
+                       mode = PrintFluffy;
+               } else if(strcmp(arg, "-v") == 0) {
+                       verbose = 1;
+               } else if(arg[0] == '-') {
+                       usage(argv[0]);
+                       return 1;
+               } else {
+                       if(input != NULL) {
+                               fprintf(stderr, "Error: multiple input files specified\n");
+                               usage(argv[0]);
+                               return 1;
+                       } else {
+                               input = arg;
+                       }
                }
+       }
+
+       if(input == NULL) {
+               fprintf(stderr, "%s: no input files\n", argv[0]);
+               return 1;
+       }
+
+       if(mode == LexTest) {
+               lextest(input);
                return 0;
        }
 
-       if(argc > 2 && strcmp(argv[1], "--print-fluffy") == 0) {
-               translation_unit_t *unit = do_parsing(argv[2]);
+       const char *tmpfile = tmpnam(NULL);
+       preprocess(input, tmpfile);
+
+       translation_unit_t *unit = do_parsing(tmpfile, input);
+       if(unit == NULL)
+               return 1;
+
+       if(mode == PrintAst) {
+               print_ast(unit);
+               return 0;
+       }
+       if(mode == PrintFluffy) {
                ast_set_output(stdout);
                write_fluffy_decls(unit);
-               return 0;
        }
 
-       for(int i = 1; i < argc; ++i) {
-               const char *input = argv[i];
-               char        outfname[4096];
+       char outsname[4096];
+       const char *sname = NULL;
+       if(mode == Compile) {
+               sname = outname;
+       }
+       if(sname == NULL) {
+               get_output_name(outsname, sizeof(outsname), input, ".s");
+               sname = outsname;
+       }
 
-               get_output_name(outfname, sizeof(outfname), input, ".s");
+       create_firm_prog(unit);
+       optimize();
+       emit(input, sname);
 
-               translation_unit_t *unit = do_parsing(input);
-               if(unit == NULL) {
-                       return 1;
+       if(mode == CompileAssemble) {
+               char outoname[4096];
+               const char *oname = outname;
+               if(oname == NULL) {
+                       get_output_name(outoname, sizeof(outoname), input, ".o");
+                       oname = outoname;
                }
-               create_firm_prog(unit);
-               optimize();
-               emit(input, outfname);
-               link(outfname, "a.out");
+               assemble(sname, oname);
+       } else {
+               assert(mode == CompileAssembleLink);
+
+               if(outname == NULL)
+                       outname = "a.out";
+
+               link(sname, outname);
        }
 
        exit_ast2firm();
index eba409d..0ec8867 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1475,6 +1475,7 @@ static declaration_t *parse_parameters(function_type_t *type)
 }
 
 typedef enum {
+       CONSTRUCT_INVALID,
        CONSTRUCT_POINTER,
        CONSTRUCT_FUNCTION,
        CONSTRUCT_ARRAY
@@ -1519,7 +1520,8 @@ static construct_type_t *parse_pointer_declarator(void)
 
        parsed_pointer_t *pointer = obstack_alloc(&temp_obst, sizeof(pointer[0]));
        memset(pointer, 0, sizeof(pointer[0]));
-       pointer->type_qualifiers = parse_type_qualifiers();
+       pointer->construct_type.type = CONSTRUCT_POINTER;
+       pointer->type_qualifiers     = parse_type_qualifiers();
 
        return (construct_type_t*) pointer;
 }
@@ -1530,6 +1532,7 @@ static construct_type_t *parse_array_declarator(void)
 
        parsed_array_t *array = obstack_alloc(&temp_obst, sizeof(array[0]));
        memset(array, 0, sizeof(array[0]));
+       array->construct_type.type = CONSTRUCT_ARRAY;
 
        if(token.type == T_static) {
                array->is_static = true;
@@ -1672,6 +1675,8 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
                array_type_t              *array_type;
 
                switch(iter->type) {
+               case CONSTRUCT_INVALID:
+                       panic("invalid type construction found");
                case CONSTRUCT_FUNCTION:
                        construct_function_type = (construct_function_type_t*) iter;
                        function_type           = construct_function_type->function_type;
@@ -2349,15 +2354,18 @@ static expression_t *parse_array_expression(unsigned precedence,
        array_access->array_ref           = array_ref;
        array_access->index               = parse_expression();
 
-       type_t *array_type = array_ref->datatype;
-       if(array_type != NULL) {
-               if(array_type->type == TYPE_POINTER) {
-                       pointer_type_t *pointer           = (pointer_type_t*) array_type;
+       type_t *type = array_ref->datatype;
+       if(type != NULL) {
+               if(type->type == TYPE_POINTER) {
+                       pointer_type_t *pointer           = (pointer_type_t*) type;
                        array_access->expression.datatype = pointer->points_to;
+               } else if(type->type == TYPE_ARRAY) {
+                       array_type_t *array_type          = (array_type_t*) type;
+                       array_access->expression.datatype = array_type->element_type;
                } else {
                        parser_print_error_prefix();
                        fprintf(stderr, "array access on object with non-pointer type ");
-                       print_type(array_type);
+                       print_type(type);
                        fprintf(stderr, "\n");
                }
        }