cleanup builtin handling and put it into an own file. Also implement a bunch of entit...
authorMatthias Braun <matze@braunis.de>
Mon, 15 Feb 2010 15:55:08 +0000 (15:55 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 15 Feb 2010 15:55:08 +0000 (15:55 +0000)
[r27169]

12 files changed:
ast2firm.c
ast_t.h
entity.c
entity_t.h
main.c
parser.c
parser.h
type.c
type.h
type_t.h
types.c
types.h

index 2fbe089..fb00ce7 100644 (file)
@@ -926,7 +926,7 @@ static bool is_main(entity_t *entity)
 /**
  * Creates an entity representing a function.
  *
- * @param declaration  the function declaration
+ * @param entity       the function declaration/definition
  * @param owner_type   the owner type of this function, NULL
  *                     for global functions
  */
@@ -937,6 +937,13 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
                return entity->function.irentity;
        }
 
+       entity_t *original_entity = entity;
+       if (entity->function.btk != bk_none) {
+               entity = get_builtin_replacement(entity);
+               if (entity == NULL)
+                       return NULL;
+       }
+
        if (is_main(entity)) {
                /* force main to C linkage */
                type_t *type = entity->declaration.type;
@@ -952,7 +959,6 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
        symbol_t *symbol = entity->base.symbol;
        ident    *id     = new_id_from_str(symbol->string);
 
-
        /* already an entity defined? */
        ir_entity *irentity = entitymap_get(&entitymap, symbol);
        bool const has_body = entity->function.statement != NULL;
@@ -1031,8 +1037,8 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
        entitymap_insert(&entitymap, symbol, irentity);
 
 entity_created:
-       entity->declaration.kind  = DECLARATION_KIND_FUNCTION;
-       entity->function.irentity = irentity;
+       original_entity->declaration.kind  = DECLARATION_KIND_FUNCTION;
+       original_entity->function.irentity = irentity;
 
        return irentity;
 }
@@ -1445,19 +1451,23 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
        /* make sure the type is constructed */
        (void) get_ir_type(type);
 
-       /* for gcc compatibility we have to produce (dummy) addresses for some
-        * builtins */
        if (entity->kind == ENTITY_FUNCTION && entity->function.btk != bk_none) {
-               if (warning.other) {
-                       warningf(&ref->base.source_position,
-                                       "taking address of builtin '%Y'", ref->entity->base.symbol);
-               }
+               ir_entity *irentity = get_function_entity(entity, NULL);
+               /* for gcc compatibility we have to produce (dummy) addresses for some
+                * builtins which don't have entities */
+               if (irentity == NULL) {
+                       if (warning.other) {
+                               warningf(&ref->base.source_position,
+                                               "taking address of builtin '%Y'",
+                                               ref->entity->base.symbol);
+                       }
 
-               /* simply create a NULL pointer */
-               ir_mode  *mode = get_ir_mode_arithmetic(type_void_ptr);
-               ir_node  *res  = new_Const_long(mode, 0);
+                       /* simply create a NULL pointer */
+                       ir_mode  *mode = get_ir_mode_arithmetic(type_void_ptr);
+                       ir_node  *res  = new_Const_long(mode, 0);
 
-               return res;
+                       return res;
+               }
        }
 
        switch ((declaration_kind_t) entity->declaration.kind) {
@@ -1606,7 +1616,8 @@ static ir_node *gen_unary_builtin(ir_builtin_kind kind, expression_t *op, type_t
  * @param function_type  the function type for the GNU builtin routine
  * @param db             debug info
  */
-static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op, type_t *function_type, dbg_info *db)
+static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op,
+                                         type_t *function_type, dbg_info *db)
 {
        ir_node *in[1];
        in[0] = expression_to_firm(op);
@@ -1619,7 +1630,6 @@ static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op,
        return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result);
 }
 
-
 /**
  * Generate an binary-void-return builtin.
  *
@@ -1629,8 +1639,9 @@ static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op,
  * @param function_type  the function type for the GNU builtin routine
  * @param db             debug info
  */
-static ir_node *gen_binary_builtin_mem(ir_builtin_kind kind, expression_t *op1, expression_t *op2,
-                                                                          type_t *function_type, dbg_info *db)
+static ir_node *gen_binary_builtin_mem(ir_builtin_kind kind, expression_t *op1,
+                                       expression_t *op2, type_t *function_type,
+                                                                          dbg_info *db)
 {
        ir_node *in[2];
        in[0] = expression_to_firm(op1);
@@ -1848,14 +1859,14 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
                entity_t                     *entity = ref->entity;
 
                if (entity->kind == ENTITY_FUNCTION) {
-                       if (entity->function.btk != bk_none) {
-                               return process_builtin_call(call);
-                       }
-
                        ir_entity *irentity = entity->function.irentity;
                        if (irentity == NULL)
                                irentity = get_function_entity(entity, NULL);
 
+                       if (irentity == NULL && entity->function.btk != bk_none) {
+                               return process_builtin_call(call);
+                       }
+
                        if (irentity == rts_entities[rts_alloca]) {
                                /* handle alloca() call */
                                expression_t *argument = call->arguments->expression;
diff --git a/ast_t.h b/ast_t.h
index cb8d4e9..e1611fb 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -676,4 +676,15 @@ static inline bool is_invalid_statement(statement_t *statement)
 
 #define allocate_ast(size)                 _allocate_ast(size)
 
+/**
+ * Allocate an AST node with given size and
+ * initialize all fields with zero.
+ */
+static inline void *allocate_ast_zero(size_t size)
+{
+       void *res = allocate_ast(size);
+       memset(res, 0, size);
+       return res;
+}
+
 #endif
index a31b886..748ead0 100644 (file)
--- a/entity.c
+++ b/entity.c
  */
 #include <config.h>
 
+#include <assert.h>
+
 #include "entity_t.h"
+#include "ast_t.h"
 #include "adt/error.h"
+#include "adt/util.h"
 
 const char *get_entity_kind_name(entity_kind_t kind)
 {
@@ -43,3 +47,43 @@ const char *get_entity_kind_name(entity_kind_t kind)
 
        panic("Invalid entity kind encountered in get_entity_kind_name");
 }
+
+/**
+ * Returns the size of an entity node.
+ *
+ * @param kind  the entity kind
+ */
+static size_t get_entity_struct_size(entity_kind_t kind)
+{
+       static const size_t sizes[] = {
+               [ENTITY_VARIABLE]        = sizeof(variable_t),
+               [ENTITY_PARAMETER]       = sizeof(parameter_t),
+               [ENTITY_COMPOUND_MEMBER] = sizeof(compound_member_t),
+               [ENTITY_FUNCTION]        = sizeof(function_t),
+               [ENTITY_TYPEDEF]         = sizeof(typedef_t),
+               [ENTITY_STRUCT]          = sizeof(compound_t),
+               [ENTITY_UNION]           = sizeof(compound_t),
+               [ENTITY_ENUM]            = sizeof(enum_t),
+               [ENTITY_ENUM_VALUE]      = sizeof(enum_value_t),
+               [ENTITY_LABEL]           = sizeof(label_t),
+               [ENTITY_LOCAL_LABEL]     = sizeof(label_t),
+               [ENTITY_NAMESPACE]       = sizeof(namespace_t)
+       };
+       assert(kind < lengthof(sizes));
+       assert(sizes[kind] != 0);
+       return sizes[kind];
+}
+
+/**
+ * Allocate an entity of given kind and initialize all
+ * fields with zero.
+ *
+ * @param kind   the kind of the entity to allocate
+ */
+entity_t *allocate_entity_zero(entity_kind_t kind)
+{
+       size_t    size   = get_entity_struct_size(kind);
+       entity_t *entity = allocate_ast_zero(size);
+       entity->kind     = kind;
+       return entity;
+}
index bf061b7..02bb014 100644 (file)
@@ -25,6 +25,7 @@
 #include "entity.h"
 #include "attribute.h"
 #include <libfirm/firm_types.h>
+#include "builtins.h"
 
 typedef enum {
        ENTITY_INVALID,
@@ -240,62 +241,6 @@ struct parameter_t {
        } v;
 };
 
-/**
- * GNU builtin or MS intrinsic functions.
- */
-typedef enum builtin_kind_t {
-       bk_none = 0,                   /**< no builtin */
-       bk_gnu_builtin_alloca,         /**< GNU __builtin_alloca */
-       bk_gnu_builtin_huge_val,       /**< GNU __builtin_huge_val */
-       bk_gnu_builtin_huge_valf,      /**< GNU __builtin_huge_valf */
-       bk_gnu_builtin_huge_vall,      /**< GNU __builtin_huge_vall */
-       bk_gnu_builtin_inf,            /**< GNU __builtin_inf */
-       bk_gnu_builtin_inff,           /**< GNU __builtin_inff */
-       bk_gnu_builtin_infl,           /**< GNU __builtin_infl */
-       bk_gnu_builtin_nan,            /**< GNU __builtin_nan */
-       bk_gnu_builtin_nanf,           /**< GNU __builtin_nanf */
-       bk_gnu_builtin_nanl,           /**< GNU __builtin_nanl */
-       bk_gnu_builtin_va_end,         /**< GNU __builtin_va_end */
-       bk_gnu_builtin_expect,         /**< GNU __builtin_expect */
-       bk_gnu_builtin_return_address, /**< GNU __builtin_return_address */
-       bk_gnu_builtin_frame_address,  /**< GNU __builtin_frame_address */
-       bk_gnu_builtin_ffs,            /**< GNU __builtin_ffs */
-       bk_gnu_builtin_clz,            /**< GNU __builtin_clz */
-       bk_gnu_builtin_ctz,            /**< GNU __builtin_ctz */
-       bk_gnu_builtin_popcount,       /**< GNU __builtin_popcount */
-       bk_gnu_builtin_parity,         /**< GNU __builtin_parity */
-       bk_gnu_builtin_prefetch,       /**< GNU __builtin_prefetch */
-       bk_gnu_builtin_trap,           /**< GNU __builtin_trap */
-
-       bk_ms_rotl,                    /**< MS _rotl */
-       bk_ms_rotr,                    /**< MS _rotr */
-       bk_ms_rotl64,                  /**< MS _rotl64 */
-       bk_ms_rotr64,                  /**< MS _rotr64 */
-       bk_ms_byteswap_ushort,         /**< MS _byteswap_ushort */
-       bk_ms_byteswap_ulong,          /**< MS _byteswap_ulong */
-       bk_ms_byteswap_uint64,         /**< MS _byteswap_uint64 */
-
-       bk_ms__debugbreak,             /**< MS __debugbreak */
-       bk_ms_ReturnAddress,           /**< MS _ReturnAddress */
-       bk_ms_AddressOfReturnAddress,  /**< MS _AddressOfReturnAddress */
-       bk_ms__popcount,               /**< MS __popcount */
-       bk_ms_enable,                  /**< MS _enable */
-       bk_ms_disable,                 /**< MS _disable */
-       bk_ms__inbyte,                 /**< MS __inbyte */
-       bk_ms__inword,                 /**< MS __inword */
-       bk_ms__indword,                /**< MS __indword */
-       bk_ms__outbyte,                /**< MS __outbyte */
-       bk_ms__outword,                /**< MS __outword */
-       bk_ms__outdword,               /**< MS __outdword */
-       bk_ms__ud2,                    /**< MS __ud2 */
-       bk_ms_BitScanForward,          /**< MS _BitScanForward */
-       bk_ms_BitScanReverse,          /**< MS _BitScanReverse */
-       bk_ms_InterlockedExchange,     /**< MS _InterlockedExchange */
-       bk_ms_InterlockedExchange64,   /**< MS _InterlockedExchange64 */
-       bk_ms__readeflags,             /**< MS __readflags */
-       bk_ms__writeeflags,            /**< MS __writeflags */
-} builtin_kind_t;
-
 struct function_t {
        declaration_t  base;
        bool           is_inline     : 1;
@@ -349,4 +294,6 @@ static inline bool is_declaration(const entity_t *entity)
 
 const char *get_entity_kind_name(entity_kind_t kind);
 
+entity_t *allocate_entity_zero(entity_kind_t kind);
+
 #endif
diff --git a/main.c b/main.c
index 77bf0c6..c8b5878 100644 (file)
--- a/main.c
+++ b/main.c
@@ -317,18 +317,6 @@ static FILE *preprocess(const char *fname, filetype_t filetype)
                add_flag(&cppflags_obst, "-U__VERSION__");
                add_flag(&cppflags_obst, "-D__VERSION__=\"%s\"", cparser_REVISION);
 
-               /* TODO hack... */
-               add_flag(&cppflags_obst, "-D__builtin_abort=abort");
-               add_flag(&cppflags_obst, "-D__builtin_abs=abs");
-               add_flag(&cppflags_obst, "-D__builtin_exit=exit");
-               add_flag(&cppflags_obst, "-D__builtin_malloc=malloc");
-               add_flag(&cppflags_obst, "-D__builtin_memcmp=memcmp");
-               add_flag(&cppflags_obst, "-D__builtin_memcpy=memcpy");
-               add_flag(&cppflags_obst, "-D__builtin_memset=memset");
-               add_flag(&cppflags_obst, "-D__builtin_strlen=strlen");
-               add_flag(&cppflags_obst, "-D__builtin_strcmp=strcmp");
-               add_flag(&cppflags_obst, "-D__builtin_strcpy=strcpy");
-
                if (flags[0] != '\0') {
                        size_t len = strlen(flags);
                        obstack_1grow(&cppflags_obst, ' ');
index 8abccad..502dcc6 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -151,13 +151,8 @@ typedef enum declarator_flags_t {
 static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                                   declarator_flags_t flags);
 
-static entity_t *record_entity(entity_t *entity, bool is_definition);
-
 static void semantic_comparison(binary_expression_t *expression);
 
-static void create_gnu_builtins(void);
-static void create_microsoft_intrinsics(void);
-
 #define STORAGE_CLASSES       \
        STORAGE_CLASSES_NO_EXTERN \
        case T_extern:
@@ -266,57 +261,6 @@ static void create_microsoft_intrinsics(void);
        case T_throw:                    \
        case T_true:
 
-/**
- * Allocate an AST node with given size and
- * initialize all fields with zero.
- */
-static void *allocate_ast_zero(size_t size)
-{
-       void *res = allocate_ast(size);
-       memset(res, 0, size);
-       return res;
-}
-
-/**
- * Returns the size of an entity node.
- *
- * @param kind  the entity kind
- */
-static size_t get_entity_struct_size(entity_kind_t kind)
-{
-       static const size_t sizes[] = {
-               [ENTITY_VARIABLE]        = sizeof(variable_t),
-               [ENTITY_PARAMETER]       = sizeof(parameter_t),
-               [ENTITY_COMPOUND_MEMBER] = sizeof(compound_member_t),
-               [ENTITY_FUNCTION]        = sizeof(function_t),
-               [ENTITY_TYPEDEF]         = sizeof(typedef_t),
-               [ENTITY_STRUCT]          = sizeof(compound_t),
-               [ENTITY_UNION]           = sizeof(compound_t),
-               [ENTITY_ENUM]            = sizeof(enum_t),
-               [ENTITY_ENUM_VALUE]      = sizeof(enum_value_t),
-               [ENTITY_LABEL]           = sizeof(label_t),
-               [ENTITY_LOCAL_LABEL]     = sizeof(label_t),
-               [ENTITY_NAMESPACE]       = sizeof(namespace_t)
-       };
-       assert(kind < lengthof(sizes));
-       assert(sizes[kind] != 0);
-       return sizes[kind];
-}
-
-/**
- * Allocate an entity of given kind and initialize all
- * fields with zero.
- *
- * @param kind   the kind of the entity to allocate
- */
-static entity_t *allocate_entity_zero(entity_kind_t kind)
-{
-       size_t    size   = get_entity_struct_size(kind);
-       entity_t *entity = allocate_ast_zero(size);
-       entity->kind     = kind;
-       return entity;
-}
-
 /**
  * Returns the size of a statement node.
  *
@@ -455,53 +399,10 @@ static statement_t *create_empty_statement(void)
        return allocate_statement_zero(STATEMENT_EMPTY);
 }
 
-/**
- * Returns the size of a type node.
- *
- * @param kind  the type kind
- */
-static size_t get_type_struct_size(type_kind_t kind)
-{
-       static const size_t sizes[] = {
-               [TYPE_ATOMIC]          = sizeof(atomic_type_t),
-               [TYPE_COMPLEX]         = sizeof(complex_type_t),
-               [TYPE_IMAGINARY]       = sizeof(imaginary_type_t),
-               [TYPE_BITFIELD]        = sizeof(bitfield_type_t),
-               [TYPE_COMPOUND_STRUCT] = sizeof(compound_type_t),
-               [TYPE_COMPOUND_UNION]  = sizeof(compound_type_t),
-               [TYPE_ENUM]            = sizeof(enum_type_t),
-               [TYPE_FUNCTION]        = sizeof(function_type_t),
-               [TYPE_POINTER]         = sizeof(pointer_type_t),
-               [TYPE_ARRAY]           = sizeof(array_type_t),
-               [TYPE_BUILTIN]         = sizeof(builtin_type_t),
-               [TYPE_TYPEDEF]         = sizeof(typedef_type_t),
-               [TYPE_TYPEOF]          = sizeof(typeof_type_t),
-       };
-       assert(lengthof(sizes) == (int)TYPE_TYPEOF + 1);
-       assert(kind <= TYPE_TYPEOF);
-       assert(sizes[kind] != 0);
-       return sizes[kind];
-}
-
-/**
- * Allocate a type node of given kind and initialize all
- * fields with zero.
- *
- * @param kind             type kind to allocate
- */
-static type_t *allocate_type_zero(type_kind_t kind)
-{
-       size_t  size = get_type_struct_size(kind);
-       type_t *res  = obstack_alloc(type_obst, size);
-       memset(res, 0, size);
-       res->base.kind = kind;
-
-       return res;
-}
-
 static function_parameter_t *allocate_parameter(type_t *const type)
 {
-       function_parameter_t *const param = obstack_alloc(type_obst, sizeof(*param));
+       function_parameter_t *const param
+               = obstack_alloc(type_obst, sizeof(*param));
        memset(param, 0, sizeof(*param));
        param->type = type;
        return param;
@@ -4220,7 +4121,7 @@ static void merge_in_attributes(declaration_t *decl, attribute_t *attributes)
  * record entities for the NAMESPACE_NORMAL, and produce error messages/warnings
  * for various problems that occur for multiple definitions
  */
-static entity_t *record_entity(entity_t *entity, const bool is_definition)
+entity_t *record_entity(entity_t *entity, const bool is_definition)
 {
        const symbol_t *const    symbol  = entity->base.symbol;
        const namespace_tag_t    namespc = (namespace_tag_t)entity->base.namespc;
@@ -6218,91 +6119,6 @@ static entity_t *create_implicit_function(symbol_t *symbol,
        return entity;
 }
 
-/**
- * Creates a return_type (func)(argument_type) function type if not
- * already exists.
- */
-static type_t *make_function_2_type(type_t *return_type, type_t *argument_type1,
-                                    type_t *argument_type2)
-{
-       function_parameter_t *const parameter2 = allocate_parameter(argument_type2);
-       function_parameter_t *const parameter1 = allocate_parameter(argument_type1);
-       parameter1->next = parameter2;
-
-       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
-       type->function.return_type = return_type;
-       type->function.parameters  = parameter1;
-
-       return identify_new_type(type);
-}
-
-/**
- * Creates a return_type (func)(argument_type) function type if not
- * already exists.
- *
- * @param return_type    the return type
- * @param argument_type  the argument type
- */
-static type_t *make_function_1_type(type_t *return_type, type_t *argument_type)
-{
-       function_parameter_t *const parameter = allocate_parameter(argument_type);
-
-       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
-       type->function.return_type = return_type;
-       type->function.parameters  = parameter;
-
-       return identify_new_type(type);
-}
-
-/**
- * Creates a return_type (func)(argument_type, ...) function type if not
- * already exists.
- *
- * @param return_type    the return type
- * @param argument_type  the argument type
- */
-static type_t *make_function_1_type_variadic(type_t *return_type, type_t *argument_type)
-{
-       function_parameter_t *const parameter = allocate_parameter(argument_type);
-
-       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
-       type->function.return_type = return_type;
-       type->function.parameters  = parameter;
-       type->function.variadic    = true;
-
-       return identify_new_type(type);
-}
-
-/**
- * Creates a return_type (func)(void) function type if not
- * already exists.
- *
- * @param return_type    the return type
- */
-static type_t *make_function_0_type(type_t *return_type)
-{
-       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
-       type->function.return_type = return_type;
-       type->function.parameters  = NULL;
-
-       return identify_new_type(type);
-}
-
-/**
- * Creates a NO_RETURN return_type (func)(void) function type if not
- * already exists.
- *
- * @param return_type    the return type
- */
-static type_t *make_function_0_type_noreturn(type_t *return_type)
-{
-       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
-       type->function.return_type = return_type;
-       type->function.parameters  = NULL;
-       type->function.modifiers  |= DM_NORETURN;
-       return identify_new_type(type);
-}
-
 /**
  * Performs automatic type cast as described in ยง6.3.2.1.
  *
@@ -10923,106 +10739,6 @@ void parse(void)
        incomplete_arrays = NULL;
 }
 
-/**
- * create a builtin function.
- */
-static entity_t *create_builtin_function(builtin_kind_t kind, const char *name, type_t *function_type)
-{
-       symbol_t *symbol = symbol_table_insert(name);
-       entity_t *entity = allocate_entity_zero(ENTITY_FUNCTION);
-       entity->declaration.storage_class          = STORAGE_CLASS_EXTERN;
-       entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
-       entity->declaration.type                   = function_type;
-       entity->declaration.implicit               = true;
-       entity->base.symbol                        = symbol;
-       entity->base.source_position               = builtin_source_position;
-
-       entity->function.btk                       = kind;
-
-       record_entity(entity, /*is_definition=*/false);
-       return entity;
-}
-
-
-/**
- * Create predefined gnu builtins.
- */
-static void create_gnu_builtins(void)
-{
-#define GNU_BUILTIN(a, b) create_builtin_function(bk_gnu_builtin_##a, "__builtin_" #a, b)
-
-       GNU_BUILTIN(alloca,         make_function_1_type(type_void_ptr, type_size_t));
-       GNU_BUILTIN(huge_val,       make_function_0_type(type_double));
-       GNU_BUILTIN(huge_valf,      make_function_0_type(type_float));
-       GNU_BUILTIN(huge_vall,      make_function_0_type(type_long_double));
-       GNU_BUILTIN(inf,            make_function_0_type(type_double));
-       GNU_BUILTIN(inff,           make_function_0_type(type_float));
-       GNU_BUILTIN(infl,           make_function_0_type(type_long_double));
-       GNU_BUILTIN(nan,            make_function_1_type(type_double, type_char_ptr));
-       GNU_BUILTIN(nanf,           make_function_1_type(type_float, type_char_ptr));
-       GNU_BUILTIN(nanl,           make_function_1_type(type_long_double, type_char_ptr));
-       GNU_BUILTIN(va_end,         make_function_1_type(type_void, type_valist));
-       GNU_BUILTIN(expect,         make_function_2_type(type_long, type_long, type_long));
-       GNU_BUILTIN(return_address, make_function_1_type(type_void_ptr, type_unsigned_int));
-       GNU_BUILTIN(frame_address,  make_function_1_type(type_void_ptr, type_unsigned_int));
-       GNU_BUILTIN(ffs,            make_function_1_type(type_int, type_unsigned_int));
-       GNU_BUILTIN(clz,            make_function_1_type(type_int, type_unsigned_int));
-       GNU_BUILTIN(ctz,            make_function_1_type(type_int, type_unsigned_int));
-       GNU_BUILTIN(popcount,       make_function_1_type(type_int, type_unsigned_int));
-       GNU_BUILTIN(parity,         make_function_1_type(type_int, type_unsigned_int));
-       GNU_BUILTIN(prefetch,       make_function_1_type_variadic(type_float, type_void_ptr));
-       GNU_BUILTIN(trap,           make_function_0_type_noreturn(type_void));
-
-#undef GNU_BUILTIN
-}
-
-/**
- * Create predefined MS intrinsics.
- */
-static void create_microsoft_intrinsics(void)
-{
-#define MS_BUILTIN(a, b) create_builtin_function(bk_ms##a, #a, b)
-
-       /* intrinsics for all architectures */
-       MS_BUILTIN(_rotl,                  make_function_2_type(type_unsigned_int,   type_unsigned_int, type_int));
-       MS_BUILTIN(_rotr,                  make_function_2_type(type_unsigned_int,   type_unsigned_int, type_int));
-       MS_BUILTIN(_rotl64,                make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int));
-       MS_BUILTIN(_rotr64,                make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int));
-       MS_BUILTIN(_byteswap_ushort,       make_function_1_type(type_unsigned_short, type_unsigned_short));
-       MS_BUILTIN(_byteswap_ulong,        make_function_1_type(type_unsigned_long,  type_unsigned_long));
-       MS_BUILTIN(_byteswap_uint64,       make_function_1_type(type_unsigned_int64, type_unsigned_int64));
-
-       MS_BUILTIN(__debugbreak,            make_function_0_type(type_void));
-       MS_BUILTIN(_ReturnAddress,          make_function_0_type(type_void_ptr));
-       MS_BUILTIN(_AddressOfReturnAddress, make_function_0_type(type_void_ptr));
-       MS_BUILTIN(__popcount,              make_function_1_type(type_unsigned_int, type_unsigned_int));
-
-       /* x86/x64 only */
-       MS_BUILTIN(_enable,                make_function_0_type(type_void));
-       MS_BUILTIN(_disable,               make_function_0_type(type_void));
-       MS_BUILTIN(__inbyte,               make_function_1_type(type_unsigned_char, type_unsigned_short));
-       MS_BUILTIN(__inword,               make_function_1_type(type_unsigned_short, type_unsigned_short));
-       MS_BUILTIN(__indword,              make_function_1_type(type_unsigned_long, type_unsigned_short));
-       MS_BUILTIN(__outbyte,              make_function_2_type(type_void, type_unsigned_short, type_unsigned_char));
-       MS_BUILTIN(__outword,              make_function_2_type(type_void, type_unsigned_short, type_unsigned_short));
-       MS_BUILTIN(__outdword,             make_function_2_type(type_void, type_unsigned_short, type_unsigned_long));
-       MS_BUILTIN(__ud2,                  make_function_0_type_noreturn(type_void));
-       MS_BUILTIN(_BitScanForward,        make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long));
-       MS_BUILTIN(_BitScanReverse,        make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long));
-       MS_BUILTIN(_InterlockedExchange,   make_function_2_type(type_long, type_long_ptr, type_long));
-       MS_BUILTIN(_InterlockedExchange64, make_function_2_type(type_int64, type_int64_ptr, type_int64));
-
-       if (machine_size <= 32) {
-               MS_BUILTIN(__readeflags,           make_function_0_type(type_unsigned_int));
-               MS_BUILTIN(__writeeflags,          make_function_1_type(type_void, type_unsigned_int));
-       } else {
-               MS_BUILTIN(__readeflags,           make_function_0_type(type_unsigned_int64));
-               MS_BUILTIN(__writeeflags,          make_function_1_type(type_void, type_unsigned_int64));
-       }
-
-#undef MS_BUILTIN
-}
-
 /**
  * Initialize the parser.
  */
index 964799f..f402908 100644 (file)
--- a/parser.h
+++ b/parser.h
 
 typedef struct environment_entry_t environment_entry_t;
 
+/**
+ * Initialize parser. Should be called once when the program starts
+ */
 void init_parser(void);
+/**
+ * Frees resources occupied by parser. Should be called once before the program
+ * exits.
+ */
 void exit_parser(void);
 
+/**
+ * Start parsing a new compilation unit
+ */
 void start_parsing(void);
+
+/**
+ * Parse input. The source of the input is determined by the lexer module
+ */
 void parse(void);
+
+/**
+ * Finish parsing a complete compilation unit and return the AST.
+ */
 translation_unit_t *finish_parsing(void);
 
 type_t   *revert_automatic_type_conversion(const expression_t *expression);
@@ -37,4 +55,6 @@ entity_t *expression_is_variable(const expression_t *expression);
 
 void prepare_main_collect2(entity_t *entity);
 
+entity_t *record_entity(entity_t *entity, bool is_definition);
+
 #endif
diff --git a/type.c b/type.c
index de4738d..27ec551 100644 (file)
--- a/type.c
+++ b/type.c
@@ -52,6 +52,44 @@ struct atomic_type_properties_t {
        unsigned   flags;             /**< type flags from atomic_type_flag_t */
 };
 
+/**
+ * Returns the size of a type node.
+ *
+ * @param kind  the type kind
+ */
+static size_t get_type_struct_size(type_kind_t kind)
+{
+       static const size_t sizes[] = {
+               [TYPE_ATOMIC]          = sizeof(atomic_type_t),
+               [TYPE_COMPLEX]         = sizeof(complex_type_t),
+               [TYPE_IMAGINARY]       = sizeof(imaginary_type_t),
+               [TYPE_BITFIELD]        = sizeof(bitfield_type_t),
+               [TYPE_COMPOUND_STRUCT] = sizeof(compound_type_t),
+               [TYPE_COMPOUND_UNION]  = sizeof(compound_type_t),
+               [TYPE_ENUM]            = sizeof(enum_type_t),
+               [TYPE_FUNCTION]        = sizeof(function_type_t),
+               [TYPE_POINTER]         = sizeof(pointer_type_t),
+               [TYPE_ARRAY]           = sizeof(array_type_t),
+               [TYPE_BUILTIN]         = sizeof(builtin_type_t),
+               [TYPE_TYPEDEF]         = sizeof(typedef_type_t),
+               [TYPE_TYPEOF]          = sizeof(typeof_type_t),
+       };
+       assert(lengthof(sizes) == (int)TYPE_TYPEOF + 1);
+       assert(kind <= TYPE_TYPEOF);
+       assert(sizes[kind] != 0);
+       return sizes[kind];
+}
+
+type_t *allocate_type_zero(type_kind_t kind)
+{
+       size_t  size = get_type_struct_size(kind);
+       type_t *res  = obstack_alloc(type_obst, size);
+       memset(res, 0, size);
+       res->base.kind = kind;
+
+       return res;
+}
+
 /**
  * Properties of atomic types.
  */
@@ -752,34 +790,6 @@ void print_type_ext(const type_t *const type, const symbol_t *symbol,
        }
 }
 
-/**
- * Return the size of a type AST node.
- *
- * @param type  The type.
- */
-static size_t get_type_struct_size(const type_t *type)
-{
-       switch(type->kind) {
-       case TYPE_ATOMIC:          return sizeof(atomic_type_t);
-       case TYPE_COMPLEX:         return sizeof(complex_type_t);
-       case TYPE_IMAGINARY:       return sizeof(imaginary_type_t);
-       case TYPE_COMPOUND_STRUCT:
-       case TYPE_COMPOUND_UNION:  return sizeof(compound_type_t);
-       case TYPE_ENUM:            return sizeof(enum_type_t);
-       case TYPE_FUNCTION:        return sizeof(function_type_t);
-       case TYPE_POINTER:         return sizeof(pointer_type_t);
-       case TYPE_REFERENCE:       return sizeof(reference_type_t);
-       case TYPE_ARRAY:           return sizeof(array_type_t);
-       case TYPE_BUILTIN:         return sizeof(builtin_type_t);
-       case TYPE_TYPEDEF:         return sizeof(typedef_type_t);
-       case TYPE_TYPEOF:          return sizeof(typeof_type_t);
-       case TYPE_BITFIELD:        return sizeof(bitfield_type_t);
-       case TYPE_ERROR:           panic("error type found");
-       case TYPE_INVALID:         panic("invalid type found");
-       }
-       panic("unknown type found");
-}
-
 /**
  * Duplicates a type.
  *
@@ -790,7 +800,7 @@ static size_t get_type_struct_size(const type_t *type)
  */
 type_t *duplicate_type(const type_t *type)
 {
-       size_t size = get_type_struct_size(type);
+       size_t size = get_type_struct_size(type->kind);
 
        type_t *copy = obstack_alloc(type_obst, size);
        memcpy(copy, type, size);
@@ -1725,10 +1735,6 @@ static entity_t *pack_bitfield_members(il_size_t *struct_offset,
        return member;
 }
 
-/**
- * Finish the construction of a struct type by calculating its size, offsets,
- * alignment.
- */
 void layout_struct_type(compound_type_t *type)
 {
        assert(type->compound != NULL);
@@ -1805,10 +1811,6 @@ void layout_struct_type(compound_type_t *type)
        compound->layouted  = true;
 }
 
-/**
- * Finish the construction of an union type by calculating
- * its size and alignment.
- */
 void layout_union_type(compound_type_t *type)
 {
        assert(type->compound != NULL);
@@ -1843,6 +1845,89 @@ void layout_union_type(compound_type_t *type)
        compound->alignment = alignment;
 }
 
+static function_parameter_t *allocate_parameter(type_t *const type)
+{
+       function_parameter_t *const param
+               = obstack_alloc(type_obst, sizeof(*param));
+       memset(param, 0, sizeof(*param));
+       param->type = type;
+       return param;
+}
+
+type_t *make_function_2_type(type_t *return_type, type_t *argument_type1,
+                             type_t *argument_type2)
+{
+       function_parameter_t *const parameter2 = allocate_parameter(argument_type2);
+       function_parameter_t *const parameter1 = allocate_parameter(argument_type1);
+       parameter1->next = parameter2;
+
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.parameters  = parameter1;
+       type->function.linkage     = LINKAGE_C;
+
+       return identify_new_type(type);
+}
+
+type_t *make_function_1_type(type_t *return_type, type_t *argument_type)
+{
+       function_parameter_t *const parameter = allocate_parameter(argument_type);
+
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.parameters  = parameter;
+       type->function.linkage     = LINKAGE_C;
+
+       return identify_new_type(type);
+}
+
+type_t *make_function_1_type_variadic(type_t *return_type,
+                                      type_t *argument_type)
+{
+       function_parameter_t *const parameter = allocate_parameter(argument_type);
+
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.parameters  = parameter;
+       type->function.variadic    = true;
+       type->function.linkage     = LINKAGE_C;
+
+       return identify_new_type(type);
+}
+
+type_t *make_function_0_type(type_t *return_type)
+{
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.parameters  = NULL;
+       type->function.linkage     = LINKAGE_C;
+
+       return identify_new_type(type);
+}
+
+type_t *make_function_type(type_t *return_type, int n_types,
+                           type_t *const *argument_types,
+                                                  decl_modifiers_t modifiers)
+{
+       type_t *type               = allocate_type_zero(TYPE_FUNCTION);
+       type->function.return_type = return_type;
+       type->function.modifiers  |= modifiers;
+       type->function.linkage     = LINKAGE_C;
+
+       function_parameter_t *last  = NULL;
+       for (int i = 0; i < n_types; ++i) {
+               function_parameter_t *parameter = allocate_parameter(argument_types[i]);
+               if (last == NULL) {
+                       type->function.parameters = parameter;
+               } else {
+                       last->next = parameter;
+               }
+               last = parameter;
+       }
+
+       return identify_new_type(type);
+}
+
 /**
  * Debug helper. Prints the given type to stdout.
  */
diff --git a/type.h b/type.h
index cf8730f..de382d6 100644 (file)
--- a/type.h
+++ b/type.h
@@ -211,7 +211,16 @@ atomic_type_kind_t find_unsigned_int_atomic_type_kind_for_size(unsigned size);
 
 const char *get_atomic_kind_name(atomic_type_kind_t kind);
 
+/**
+ * Finish the construction of a struct type by calculating its size, offsets,
+ * alignment.
+ */
 void layout_struct_type(compound_type_t *type);
+
+/**
+ * Finish the construction of an union type by calculating
+ * its size and alignment.
+ */
 void layout_union_type(compound_type_t *type);
 
 #endif
index fb03da9..a793f7a 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -288,4 +288,53 @@ static inline bool is_type_valid(const type_t *type)
        return type->kind != TYPE_ERROR;
 }
 
+/**
+ * Allocate a type node of given kind and initialize all
+ * fields with zero.
+ *
+ * @param kind             type kind to allocate
+ */
+type_t *allocate_type_zero(type_kind_t kind);
+
+/**
+ * Creates a return_type (func)(void) function type if not
+ * already exists.
+ *
+ * @param return_type    the return type
+ */
+type_t *make_function_0_type(type_t *return_type);
+
+/**
+ * Creates a return_type (func)(argument_type) function type if not
+ * already exists.
+ *
+ * @param return_type    the return type
+ * @param argument_type  the argument type
+ */
+type_t *make_function_1_type(type_t *return_type, type_t *argument_type1);
+
+
+/**
+ * Creates a return_type (func)(argument_type1,argument_type2) function type
+ * if not already exists.
+ */
+type_t *make_function_2_type(type_t *return_type, type_t *argument_type1,
+                             type_t *argument_type2);
+
+/**
+ * Creates a return_type (func)(argument_type, ...) function type if not
+ * already exists.
+ *
+ * @param return_type    the return type
+ * @param argument_type  the argument type
+ */
+type_t *make_function_1_type_variadic(type_t *return_type, type_t *argument_type);
+
+/**
+ * Create a function type with n parameters
+ */
+type_t *make_function_type(type_t *return_type, int n_types,
+                           type_t *const *argument_types,
+                                                  decl_modifiers_t modifiers);
+
 #endif
diff --git a/types.c b/types.c
index 0f25245..0c71f81 100644 (file)
--- a/types.c
+++ b/types.c
@@ -44,7 +44,9 @@ type_t *type_unsigned_long;
 type_t *type_void;
 
 type_t *type_char_ptr;
+type_t *type_char_ptr_restrict;
 type_t *type_const_char_ptr;
+type_t *type_const_char_ptr_restrict;
 type_t *type_int_ptr;
 type_t *type_long_long_ptr;
 type_t *type_long_ptr;
@@ -52,6 +54,8 @@ type_t *type_unsigned_long_ptr;
 type_t *type_short_ptr;
 type_t *type_signed_char_ptr;
 type_t *type_void_ptr;
+type_t *type_const_void_ptr;
+type_t *type_void_ptr_restrict;
 
 type_t *type_char_ptr_ptr;
 
@@ -143,7 +147,10 @@ void init_basic_types(void)
 
        /* pointer types */
        type_void_ptr           = make_pointer_type(type_void,              TYPE_QUALIFIER_NONE);
+       type_const_void_ptr     = make_pointer_type(type_void,              TYPE_QUALIFIER_CONST);
+       type_void_ptr_restrict  = make_pointer_type(type_void,              TYPE_QUALIFIER_RESTRICT);
        type_char_ptr           = make_pointer_type(type_char,              TYPE_QUALIFIER_NONE);
+       type_char_ptr_restrict  = make_pointer_type(type_char,              TYPE_QUALIFIER_RESTRICT);
        type_signed_char_ptr    = make_pointer_type(type_signed_char,       TYPE_QUALIFIER_NONE);
        type_short_ptr          = make_pointer_type(type_short,             TYPE_QUALIFIER_NONE);
        type_int_ptr            = make_pointer_type(type_int,               TYPE_QUALIFIER_NONE);
@@ -156,6 +163,7 @@ void init_basic_types(void)
        /* const character types */
        type_const_char         = make_atomic_type(ATOMIC_TYPE_CHAR,        TYPE_QUALIFIER_CONST);
        type_const_char_ptr     = make_pointer_type(type_const_char,        TYPE_QUALIFIER_NONE);
+       type_const_char_ptr_restrict = make_pointer_type(type_const_char,        TYPE_QUALIFIER_RESTRICT);
 
        /* other types */
        type_intmax_t    = type_long_long;
diff --git a/types.h b/types.h
index 10785de..ca61283 100644 (file)
--- a/types.h
+++ b/types.h
@@ -43,7 +43,9 @@ extern type_t *type_unsigned_long;
 extern type_t *type_void;
 
 extern type_t *type_char_ptr;
+extern type_t *type_char_ptr_restrict;
 extern type_t *type_const_char_ptr;
+extern type_t *type_const_char_ptr_restrict;
 extern type_t *type_int_ptr;
 extern type_t *type_long_long_ptr;
 extern type_t *type_long_ptr;
@@ -51,6 +53,8 @@ extern type_t *type_unsigned_long_ptr;
 extern type_t *type_short_ptr;
 extern type_t *type_signed_char_ptr;
 extern type_t *type_void_ptr;
+extern type_t *type_const_void_ptr;
+extern type_t *type_void_ptr_restrict;
 
 extern type_t *type_char_ptr_ptr;