convert ast types to firm types
authorMatthias Braun <matze@braunis.de>
Mon, 12 Nov 2007 19:47:57 +0000 (19:47 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 12 Nov 2007 19:47:57 +0000 (19:47 +0000)
[r18371]

ast2firm.c [new file with mode: 0644]
ast_t.h
type_t.h

diff --git a/ast2firm.c b/ast2firm.c
new file mode 100644 (file)
index 0000000..b125728
--- /dev/null
@@ -0,0 +1,530 @@
+#include <config.h>
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <libfirm/firm.h>
+#include <libfirm/adt/obst.h>
+
+#include "adt/error.h"
+#include "token_t.h"
+#include "type_t.h"
+#include "ast_t.h"
+
+static ir_type *ir_type_const_char;
+static ir_type *ir_type_void;
+static ir_type *ir_type_int;
+static ir_type *ir_type_void_ptr;
+
+static type_t *type_const_char;
+static type_t *type_void;
+static type_t *type_int;
+
+typedef struct type2firm_env_t type2firm_env_t;
+struct type2firm_env_t {
+       int can_cache;       /* nonzero if type can safely be cached because
+                               no typevariables are in the hierarchy */
+};
+
+static ir_type *_get_ir_type(type2firm_env_t *env, type_t *type);
+static ir_type *get_ir_type(type_t *type);
+
+ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos)
+{
+       (void) pos;
+#if 0
+       const declaration_t *declaration = & value_numbers[pos]->declaration;
+
+       print_warning_prefix(declaration->source_position);
+       fprintf(stderr, "variable '%s' might be used uninitialized\n",
+                       declaration->symbol->string);
+#endif
+       fprintf(stderr, "Some variable might be used uninitialized\n");
+       return new_r_Unknown(irg, mode);
+}
+
+unsigned dbg_snprint(char *buf, unsigned len, const dbg_info *dbg)
+{
+       const source_position_t *pos = (const source_position_t*) dbg;
+       if(pos == NULL)
+               return 0;
+       return (unsigned) snprintf(buf, len, "%s:%u", pos->input_name,
+                                  pos->linenr);
+}
+
+const char *retrieve_dbg(const dbg_info *dbg, unsigned *line)
+{
+       const source_position_t *pos = (const source_position_t*) dbg;
+       if(pos == NULL)
+               return NULL;
+       if(line != NULL)
+               *line = pos->linenr;
+       return pos->input_name;
+}
+
+void init_ast2firm(void)
+{
+       type_const_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST);
+       type_void       = make_atomic_type(ATOMIC_TYPE_VOID, 0);
+       type_int        = make_atomic_type(ATOMIC_TYPE_INT, 0);
+
+       ir_type_const_char = get_ir_type(type_const_char);
+       ir_type_void       = get_ir_type(type_void);
+       ir_type_void_ptr   = new_type_pointer(new_id_from_str("void_ptr"),
+                                             ir_type_void, mode_P_data);
+       ir_type_int        = get_ir_type(type_int);
+}
+
+void exit_ast2firm(void)
+{
+}
+
+static unsigned unique_id = 0;
+
+static ident *unique_ident(const char *tag)
+{
+       char buf[256];
+
+       snprintf(buf, sizeof(buf), "%s.%d", tag, unique_id);
+       unique_id++;
+       return new_id_from_str(buf);
+}
+
+#if 0
+static symbol_t *unique_symbol(const char *tag)
+{
+       obstack_printf(&symbol_obstack, "%s.%d", tag, unique_id);
+       unique_id++;
+
+       const char *string = obstack_finish(&symbol_obstack);
+       symbol_t   *symbol = symbol_table_insert(string);
+
+       assert(symbol->string == string);
+
+       return symbol;
+}
+#endif
+
+static type_t *skip_typeref(type_t *type)
+{
+       while(1) {
+               switch(type->type) {
+               case TYPE_TYPEDEF: {
+                       const typedef_type_t *typedef_type = (const typedef_type_t*) type;
+                       type = typedef_type->declaration->type;
+                       continue;
+               }
+               case TYPE_TYPEOF: {
+                       const typeof_type_t *typeof_type = (const typeof_type_t *) type;
+                       if(typeof_type->typeof_type != NULL) {
+                               type = typeof_type->typeof_type;
+                       } else {
+                               type = typeof_type->expression->datatype;
+                       }
+                       continue;
+               }
+               default:
+                       break;
+               }
+               break;
+       }
+
+       return type;
+}
+
+static ir_mode *get_atomic_mode(const atomic_type_t* atomic_type)
+{
+       switch(atomic_type->atype) {
+       case ATOMIC_TYPE_SCHAR:
+       case ATOMIC_TYPE_CHAR:
+               return mode_Bs;
+       case ATOMIC_TYPE_UCHAR:
+               return mode_Bu;
+       case ATOMIC_TYPE_SHORT:
+               return mode_Hs;
+       case ATOMIC_TYPE_USHORT:
+               return mode_Hu;
+       case ATOMIC_TYPE_LONG:
+       case ATOMIC_TYPE_INT:
+               return mode_Is;
+       case ATOMIC_TYPE_ULONG:
+       case ATOMIC_TYPE_UINT:
+               return mode_Iu;
+       case ATOMIC_TYPE_LONGLONG:
+               return mode_Ls;
+       case ATOMIC_TYPE_ULONGLONG:
+               return mode_Lu;
+       case ATOMIC_TYPE_FLOAT:
+               return mode_F;
+       case ATOMIC_TYPE_DOUBLE:
+               return mode_D;
+       case ATOMIC_TYPE_LONG_DOUBLE:
+               return mode_E;
+       case ATOMIC_TYPE_BOOL:
+               return mode_b;
+#ifdef PROVIDE_COMPLEX
+       case ATOMIC_TYPE_FLOAT_COMPLEX:
+       case ATOMIC_TYPE_DOUBLE_COMPLEX:
+       case ATOMIC_TYPE_LONG_DOUBLE_COMPLEX:
+               panic("complex lowering not implemented yet");
+               break;
+       case ATOMIC_TYPE_FLOAT_IMAGINARY:
+       case ATOMIC_TYPE_DOUBLE_IMAGINARY:
+       case ATOMIC_TYPE_LONG_DOUBLE_IMAGINARY:
+               panic("imaginary lowering not implemented yet");
+               break;
+#endif
+       case ATOMIC_TYPE_VOID:
+               panic("tried to get mode from void type");
+               break;
+       case ATOMIC_TYPE_INVALID:
+               break;
+       }
+       panic("Encountered unknown atomic type");
+}
+
+
+static unsigned get_type_size(type_t *type);
+
+static unsigned get_atomic_type_size(const atomic_type_t *type)
+{
+       switch(type->atype) {
+       case ATOMIC_TYPE_CHAR:
+       case ATOMIC_TYPE_SCHAR:
+       case ATOMIC_TYPE_UCHAR:
+               return 1;
+
+       case ATOMIC_TYPE_SHORT:
+       case ATOMIC_TYPE_USHORT:
+               return 2;
+
+       case ATOMIC_TYPE_BOOL:
+       case ATOMIC_TYPE_INT:
+       case ATOMIC_TYPE_UINT:
+       case ATOMIC_TYPE_LONG:
+       case ATOMIC_TYPE_ULONG:
+       case ATOMIC_TYPE_FLOAT:
+               return 4;
+
+       case ATOMIC_TYPE_LONGLONG:
+       case ATOMIC_TYPE_ULONGLONG:
+       case ATOMIC_TYPE_DOUBLE:
+               return 8;
+
+       case ATOMIC_TYPE_LONG_DOUBLE:
+               return 12;
+
+       case ATOMIC_TYPE_VOID:
+               return 1;
+
+       case ATOMIC_TYPE_INVALID:
+               break;
+       }
+       panic("Trying to determine size of invalid atomic type");
+}
+
+static unsigned get_compound_type_size(compound_type_t *type)
+{
+       ir_type *irtype = get_ir_type(&type->type);
+       return get_type_size_bytes(irtype);
+}
+
+static unsigned get_array_type_size(array_type_t *type)
+{
+       ir_type *irtype = get_ir_type(&type->type);
+       return get_type_size_bytes(irtype);
+}
+
+static unsigned get_type_size(type_t *type)
+{
+       type = skip_typeref(type);
+
+       switch(type->type) {
+       case TYPE_ATOMIC:
+               return get_atomic_type_size((const atomic_type_t*) type);
+       case TYPE_ENUM:
+               return get_mode_size_bytes(mode_Is);
+       case TYPE_COMPOUND_UNION:
+       case TYPE_COMPOUND_STRUCT:
+               return get_compound_type_size((compound_type_t*) type);
+       case TYPE_METHOD:
+               /* just a pointer to the method */
+               return get_mode_size_bytes(mode_P_code);
+       case TYPE_POINTER:
+               return get_mode_size_bytes(mode_P_data);
+       case TYPE_ARRAY:
+               return get_array_type_size((array_type_t*) type);
+       case TYPE_BUILTIN:
+       case TYPE_TYPEDEF:
+       case TYPE_TYPEOF:
+       case TYPE_INVALID:
+               break;
+       }
+       panic("Trying to determine size of invalid type");
+}
+
+static unsigned count_parameters(const method_type_t *method_type)
+{
+       unsigned count = 0;
+
+       method_parameter_t *parameter = method_type->parameters;
+       for ( ; parameter != NULL; parameter = parameter->next) {
+               ++count;
+       }
+
+       return count;
+}
+
+
+
+
+static ir_type *get_atomic_type(type2firm_env_t *env, const atomic_type_t *type)
+{
+       (void) env;
+       ir_mode *mode   = get_atomic_mode(type);
+       ident   *id     = get_mode_ident(mode);
+       ir_type *irtype = new_type_primitive(id, mode);
+
+       return irtype;
+}
+
+static ir_type *get_method_type(type2firm_env_t *env,
+                                const method_type_t *method_type)
+{
+       type_t  *result_type  = method_type->result_type;
+
+       ident   *id           = unique_ident("methodtype");
+       int      n_parameters = count_parameters(method_type);
+       int      n_results    = result_type == type_void ? 0 : 1;
+       ir_type *irtype       = new_type_method(id, n_parameters, n_results);
+
+       if(result_type != type_void) {
+               ir_type *restype = _get_ir_type(env, result_type);
+               set_method_res_type(irtype, 0, restype);
+       }
+
+       method_parameter_t *parameter = method_type->parameters;
+       int                 n         = 0;
+       for( ; parameter != NULL; parameter = parameter->next) {
+               ir_type *p_irtype = _get_ir_type(env, parameter->type);
+               set_method_param_type(irtype, n, p_irtype);
+               ++n;
+       }
+
+       if(method_type->variadic) {
+               set_method_variadicity(irtype, variadicity_variadic);
+       }
+
+       return irtype;
+}
+
+static ir_type *get_pointer_type(type2firm_env_t *env, pointer_type_t *type)
+{
+       type_t  *points_to = type->points_to;
+       ir_type *ir_points_to;
+       /* Avoid endless recursion if the points_to type contains this poiner type
+        * again (might be a struct). We therefore first create a void* pointer
+        * and then set the real points_to type
+        */
+       ir_type *ir_type_void = get_ir_type(type_void);
+       ir_type *ir_type      = new_type_pointer(unique_ident("pointer"),
+                                             ir_type_void, mode_P_data);
+       type->type.firm_type  = ir_type;
+
+       ir_points_to = _get_ir_type(env, points_to);
+       set_pointer_points_to_type(ir_type, ir_points_to);
+
+       return ir_type;
+}
+
+static ir_type *get_array_type(type2firm_env_t *env, array_type_t *type)
+{
+       type_t  *element_type    = type->element_type;
+       ir_type *ir_element_type = _get_ir_type(env, element_type);
+
+       /* TODO... */
+       int n_elements = 0;
+       panic("TODO arraytpye size not implemented yet");
+
+       ir_type *ir_type = new_type_array(unique_ident("array"), 1, ir_element_type);
+       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);
+       }
+       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;
+}
+
+#define INVALID_TYPE ((ir_type_ptr)-1)
+
+static ir_type *get_struct_type(type2firm_env_t *env, compound_type_t *type)
+{
+       symbol_t *symbol = type->declaration->symbol;
+       ident    *id;
+       if(symbol != NULL) {
+               id = unique_ident(symbol->string);
+       } else {
+               id = unique_ident("__anonymous_struct");
+       }
+       ir_type *ir_type = new_type_struct(id);
+
+       type->type.firm_type = ir_type;
+
+       int align_all = 1;
+       int offset    = 0;
+       declaration_t *entry = type->declaration->context.declarations;
+       for( ; entry != NULL; entry = entry->next) {
+               ident       *ident         = new_id_from_str(entry->symbol->string);
+               ir_type_ptr  entry_ir_type = _get_ir_type(env, entry->type);
+
+               int entry_size      = get_type_size_bytes(entry_ir_type);
+               int entry_alignment = get_type_alignment_bytes(entry_ir_type);
+               int misalign = offset % entry_alignment;
+               offset += misalign;
+
+               ir_entity *entity = new_entity(ir_type, ident, entry_ir_type);
+               set_entity_offset(entity, offset);
+               add_struct_member(ir_type, entity);
+               entry->entity = entity;
+
+               offset += entry_size;
+               if(entry_alignment > align_all) {
+                       if(entry_alignment % align_all != 0) {
+                               panic("Uneven alignments not supported yet");
+                       }
+                       align_all = entry_alignment;
+               }
+       }
+
+       int misalign = offset % align_all;
+       offset += misalign;
+       set_type_alignment_bytes(ir_type, align_all);
+       set_type_size_bytes(ir_type, offset);
+       set_type_state(ir_type, layout_fixed);
+
+       return ir_type;
+}
+
+static ir_type *get_union_type(type2firm_env_t *env, compound_type_t *type)
+{
+       declaration_t *declaration = type->declaration;
+       symbol_t      *symbol      = declaration->symbol;
+       ident         *id;
+       if(symbol != NULL) {
+               id = unique_ident(symbol->string);
+       } else {
+               id = unique_ident("__anonymous_union");
+       }
+       ir_type  *ir_type = new_type_union(id);
+
+       type->type.firm_type = ir_type;
+
+       int align_all = 1;
+       int size      = 0;
+       declaration_t *entry = declaration->context.declarations;
+       for( ; entry != NULL; entry = entry->next) {
+               ident       *ident         = new_id_from_str(entry->symbol->string);
+               ir_type_ptr  entry_ir_type = _get_ir_type(env, entry->type);
+
+               int entry_size      = get_type_size_bytes(entry_ir_type);
+               int entry_alignment = get_type_alignment_bytes(entry_ir_type);
+
+               ir_entity *entity = new_entity(ir_type, ident, entry_ir_type);
+               add_union_member(ir_type, entity);
+               set_entity_offset(entity, 0);
+               entry->entity = entity;
+
+               if(entry_size > size) {
+                       size = entry_size;
+               }
+               if(entry_alignment > align_all) {
+                       if(entry_alignment % align_all != 0) {
+                               panic("Uneven alignments not supported yet");
+                       }
+                       align_all = entry_alignment;
+               }
+       }
+
+       set_type_alignment_bytes(ir_type, align_all);
+       set_type_size_bytes(ir_type, size);
+       set_type_state(ir_type, layout_fixed);
+
+       return ir_type;
+}
+
+static ir_type *_get_ir_type(type2firm_env_t *env, type_t *type)
+{
+       assert(type != NULL);
+
+       type = skip_typeref(type);
+
+       if(type->firm_type != NULL) {
+               assert(type->firm_type != INVALID_TYPE);
+               return type->firm_type;
+       }
+
+       ir_type *firm_type = NULL;
+       switch(type->type) {
+       case TYPE_ATOMIC:
+               firm_type = get_atomic_type(env, (atomic_type_t*) type);
+               break;
+       case TYPE_METHOD:
+               firm_type = get_method_type(env, (method_type_t*) type);
+               break;
+       case TYPE_POINTER:
+               firm_type = get_pointer_type(env, (pointer_type_t*) type);
+               break;
+       case TYPE_ARRAY:
+               firm_type = get_array_type(env, (array_type_t*) type);
+               break;
+       case TYPE_COMPOUND_STRUCT:
+               firm_type = get_struct_type(env, (compound_type_t*) type);
+               break;
+       case TYPE_COMPOUND_UNION:
+               firm_type = get_union_type(env, (compound_type_t*) type);
+               break;
+       case TYPE_ENUM:
+               firm_type = ir_type_int;
+               break;
+       case TYPE_BUILTIN:
+       case TYPE_TYPEOF:
+       case TYPE_TYPEDEF:
+       case TYPE_INVALID:
+               break;
+       }
+       if(firm_type == NULL)
+               panic("unknown type found");
+
+       if(env->can_cache) {
+               type->firm_type = firm_type;
+       }
+       return firm_type;
+
+}
+
+static ir_type *get_ir_type(type_t *type)
+{
+       type2firm_env_t env;
+       env.can_cache = 1;
+
+       return _get_ir_type(&env, type);
+}
+
+static inline ir_mode *get_ir_mode(type_t *type)
+{
+       ir_type *irtype = get_ir_type(type);
+       ir_mode *mode   = get_type_mode(irtype);
+       assert(mode != NULL);
+       return mode;
+}
+
+int dummy(void)
+{
+       return get_type_size(type_int);
+}
diff --git a/ast_t.h b/ast_t.h
index ee01174..5d40c57 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -1,6 +1,8 @@
 #ifndef AST_T_H
 #define AST_T_H
 
+#include <libfirm/firm_types.h>
+
 #include "ast.h"
 #include "symbol.h"
 #include "token_t.h"
@@ -237,6 +239,8 @@ struct declaration_t {
        declaration_t      *context_next;
        /** next declaration with same symbol */
        declaration_t      *next;
+
+       ir_entity          *entity;
 };
 
 typedef enum {
index 17b90e1..eb072e6 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -3,6 +3,8 @@
 
 #include <stdbool.h>
 
+#include <libfirm/firm_types.h>
+
 #include "type.h"
 #include "symbol.h"
 #include "token_t.h"
@@ -65,6 +67,8 @@ typedef enum {
 struct type_t {
        type_type_t       type;
        type_qualifier_t  qualifiers;
+
+       ir_type          *firm_type;
 };
 
 struct atomic_type_t {
@@ -75,6 +79,7 @@ struct atomic_type_t {
 struct builtin_type_t {
        type_t    type;
        symbol_t *symbol;
+       type_t   *real_type;
 };
 
 struct pointer_type_t {