/**
* 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
*/
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;
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;
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;
}
/* 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) {
* @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);
return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result);
}
-
/**
* Generate an binary-void-return builtin.
*
* @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);
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;
#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
*/
#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)
{
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;
+}
#include "entity.h"
#include "attribute.h"
#include <libfirm/firm_types.h>
+#include "builtins.h"
typedef enum {
ENTITY_INVALID,
} 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;
const char *get_entity_kind_name(entity_kind_t kind);
+entity_t *allocate_entity_zero(entity_kind_t kind);
+
#endif
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, ' ');
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:
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.
*
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;
* 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;
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.
*
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.
*/
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);
void prepare_main_collect2(entity_t *entity);
+entity_t *record_entity(entity_t *entity, bool is_definition);
+
#endif
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.
*/
}
}
-/**
- * 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.
*
*/
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);
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);
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);
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.
*/
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
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
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;
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;
/* 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);
/* 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;
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;
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;