+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);
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;
}
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;
{
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) {
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:
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;
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);
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");
#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
#include "ast2firm.h"
#include "adt/error.h"
-#define LINKER "gcc"
+#define PREPROCESSOR "gcc -E"
+#define LINKER "gcc"
static int verbose;
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) {
exit(1);
}
- lexer_open_stream(in, fname);
+ lexer_open_stream(in, input);
translation_unit_t *unit = parse();
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];
}
}
+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)
{
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);
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();
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();
}
typedef enum {
+ CONSTRUCT_INVALID,
CONSTRUCT_POINTER,
CONSTRUCT_FUNCTION,
CONSTRUCT_ARRAY
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;
}
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;
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;
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");
}
}