From 979fce13621246b706781035786b5d11a8e2f608 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Mon, 15 Feb 2010 15:55:08 +0000 Subject: [PATCH] cleanup builtin handling and put it into an own file. Also implement a bunch of entities which are just replace 1:1 with C library function calls [r27169] --- ast2firm.c | 55 ++++++---- ast_t.h | 11 ++ entity.c | 44 ++++++++ entity_t.h | 59 +---------- main.c | 12 --- parser.c | 290 +---------------------------------------------------- parser.h | 20 ++++ type.c | 159 ++++++++++++++++++++++------- type.h | 9 ++ type_t.h | 49 +++++++++ types.c | 8 ++ types.h | 4 + 12 files changed, 306 insertions(+), 414 deletions(-) diff --git a/ast2firm.c b/ast2firm.c index 2fbe089..fb00ce7 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -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 --- 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 diff --git a/entity.c b/entity.c index a31b886..748ead0 100644 --- a/entity.c +++ b/entity.c @@ -19,8 +19,12 @@ */ #include +#include + #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; +} diff --git a/entity_t.h b/entity_t.h index bf061b7..02bb014 100644 --- a/entity_t.h +++ b/entity_t.h @@ -25,6 +25,7 @@ #include "entity.h" #include "attribute.h" #include +#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 --- 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, ' '); diff --git a/parser.c b/parser.c index 8abccad..502dcc6 100644 --- 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. */ diff --git a/parser.h b/parser.h index 964799f..f402908 100644 --- a/parser.h +++ b/parser.h @@ -25,11 +25,29 @@ 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 --- 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 --- 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 diff --git a/type_t.h b/type_t.h index fb03da9..a793f7a 100644 --- 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 --- 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 --- 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; -- 2.20.1