From 04feb28c906b3bcabac9075a8e44c7d730527a1e Mon Sep 17 00:00:00 2001 From: Christoph Mallon Date: Sun, 18 Nov 2007 13:56:38 +0000 Subject: [PATCH] Implement the GCC insani^Wextension __builtin_classify_type. [r18485] --- ast.c | 11 ++++++ ast.h | 1 + ast2firm.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ast_t.h | 6 +++ parser.c | 19 ++++++++++ tokens.inc | 1 + 6 files changed, 147 insertions(+) diff --git a/ast.c b/ast.c index 692de23..d61ff38 100644 --- a/ast.c +++ b/ast.c @@ -234,6 +234,14 @@ static void print_select(const select_expression_t *expression) fputs(expression->symbol->string, out); } +static void print_classify_type_expression( + const classify_type_expression_t *const expr) +{ + fputs("__builtin_classify_type(", out); + print_expression(expr->type_expression); + fputc(')', out); +} + void print_expression(const expression_t *expression) { switch(expression->type) { @@ -279,6 +287,9 @@ void print_expression(const expression_t *expression) case EXPR_SELECT: print_select((const select_expression_t*) expression); break; + case EXPR_CLASSIFY_TYPE: + print_classify_type_expression((const classify_type_expression_t*)expression); + break; case EXPR_OFFSETOF: case EXPR_STATEMENT: diff --git a/ast.h b/ast.h index 7751563..1b1f8d6 100644 --- a/ast.h +++ b/ast.h @@ -26,6 +26,7 @@ typedef struct designator_t designator_t; typedef struct offsetof_expression_t offsetof_expression_t; typedef struct va_arg_expression_t va_arg_expression_t; typedef struct builtin_symbol_expression_t builtin_symbol_expression_t; +typedef struct classify_type_expression_t classify_type_expression_t; typedef struct initializer_t initializer_t; typedef struct declaration_t declaration_t; diff --git a/ast2firm.c b/ast2firm.c index 3f90847..7bfe53d 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -1333,6 +1333,113 @@ static ir_node *select_to_firm(const select_expression_t *expression) return deref_address(type, addr, dbgi); } +/* Values returned by __builtin_classify_type. */ +typedef enum gcc_type_class +{ + no_type_class = -1, + void_type_class, + integer_type_class, + char_type_class, + enumeral_type_class, + boolean_type_class, + pointer_type_class, + reference_type_class, + offset_type_class, + real_type_class, + complex_type_class, + function_type_class, + method_type_class, + record_type_class, + union_type_class, + array_type_class, + string_type_class, + set_type_class, + file_type_class, + lang_type_class +} gcc_type_class; + +static ir_node *classify_type_to_firm(const classify_type_expression_t *const expr) +{ + const type_t *const type = expr->type_expression->datatype; + + gcc_type_class tc; + switch (type->type) + { + case TYPE_ATOMIC: { + const atomic_type_t *const atomic_type = (const atomic_type_t*)type; + switch (atomic_type->atype) { + // should not be reached + case ATOMIC_TYPE_INVALID: + tc = no_type_class; + break; + + // gcc cannot do that + case ATOMIC_TYPE_VOID: + tc = void_type_class; + break; + + case ATOMIC_TYPE_CHAR: // gcc handles this as integer + case ATOMIC_TYPE_SCHAR: // gcc handles this as integer + case ATOMIC_TYPE_UCHAR: // gcc handles this as integer + case ATOMIC_TYPE_SHORT: + case ATOMIC_TYPE_USHORT: + case ATOMIC_TYPE_INT: + case ATOMIC_TYPE_UINT: + case ATOMIC_TYPE_LONG: + case ATOMIC_TYPE_ULONG: + case ATOMIC_TYPE_LONGLONG: + case ATOMIC_TYPE_ULONGLONG: + case ATOMIC_TYPE_BOOL: // gcc handles this as integer + tc = integer_type_class; + break; + + case ATOMIC_TYPE_FLOAT: + case ATOMIC_TYPE_DOUBLE: + case ATOMIC_TYPE_LONG_DOUBLE: + tc = real_type_class; + break; + +#ifdef PROVIDE_COMPLEX + case ATOMIC_TYPE_FLOAT_COMPLEX: + case ATOMIC_TYPE_DOUBLE_COMPLEX: + case ATOMIC_TYPE_LONG_DOUBLE_COMPLEX: + tc = complex_type_class; + break; +#endif + +#ifdef PROVIDE_IMAGINARY + case ATOMIC_TYPE_FLOAT_IMAGINARY: + case ATOMIC_TYPE_DOUBLE_IMAGINARY: + case ATOMIC_TYPE_LONG_DOUBLE_IMAGINARY: + tc = complex_type_class; + break; +#endif + + default: + panic("Unimplemented case in classify_type_to_firm()."); + } + break; + } + + case TYPE_ARRAY: // gcc handles this as pointer + case TYPE_FUNCTION: // gcc handles this as pointer + case TYPE_POINTER: tc = pointer_type_class; break; + case TYPE_COMPOUND_STRUCT: tc = record_type_class; break; + case TYPE_COMPOUND_UNION: tc = union_type_class; break; + + // gcc handles this as integer + case TYPE_ENUM: tc = integer_type_class; break; + + default: + panic("Unimplemented case in classify_type_to_firm()."); + } + + dbg_info *const dbgi = get_dbg_info(&expr->expression.source_position); + ir_mode *const mode = mode_Is; + tarval *const tv = new_tarval_from_long(tc, mode); + return new_d_Const(dbgi, mode, tv); +} + static ir_node *dereference_addr(const unary_expression_t *const expression) { assert(expression->type == UNEXPR_DEREFERENCE); @@ -1388,6 +1495,8 @@ static ir_node *_expression_to_firm(const expression_t *expression) return conditional_to_firm((const conditional_expression_t*)expression); case EXPR_SELECT: return select_to_firm((const select_expression_t*) expression); + case EXPR_CLASSIFY_TYPE: + return classify_type_to_firm((const classify_type_expression_t*)expression); case EXPR_FUNCTION: case EXPR_OFFSETOF: case EXPR_PRETTY_FUNCTION: diff --git a/ast_t.h b/ast_t.h index 94c96a1..7d3fc37 100644 --- a/ast_t.h +++ b/ast_t.h @@ -24,6 +24,7 @@ typedef enum { EXPR_SELECT, EXPR_ARRAY_ACCESS, EXPR_SIZEOF, + EXPR_CLASSIFY_TYPE, EXPR_FUNCTION, EXPR_PRETTY_FUNCTION, @@ -190,6 +191,11 @@ struct statement_expression_t { statement_t *statement; }; +struct classify_type_expression_t { + expression_t expression; + expression_t *type_expression; +}; + typedef enum { STORAGE_CLASS_NONE, STORAGE_CLASS_TYPEDEF, diff --git a/parser.c b/parser.c index f030107..1d9a9a7 100644 --- a/parser.c +++ b/parser.c @@ -2851,6 +2851,23 @@ static expression_t *parse_extension(unsigned precedence) return parse_sub_expression(precedence); } +static expression_t *parse_builtin_classify_type(const unsigned precedence) +{ + eat(T___builtin_classify_type); + + classify_type_expression_t *const classify_type_expr = + allocate_ast_zero(sizeof(classify_type_expr[0])); + classify_type_expr->expression.type = EXPR_CLASSIFY_TYPE; + classify_type_expr->expression.datatype = type_int; + + expect('('); + expression_t *const expression = parse_sub_expression(precedence); + expect(')'); + classify_type_expr->type_expression = expression; + + return (expression_t*)classify_type_expr; +} + static void semantic_incdec(unary_expression_t *expression) { type_t *orig_type = expression->value->datatype; @@ -3540,6 +3557,8 @@ static void init_expression_parsers(void) register_expression_parser(parse_UNEXPR_PREFIX_DECREMENT, T_MINUSMINUS, 25); register_expression_parser(parse_sizeof, T_sizeof, 25); register_expression_parser(parse_extension, T___extension__, 25); + register_expression_parser(parse_builtin_classify_type, + T___builtin_classify_type, 25); } diff --git a/tokens.inc b/tokens.inc index 4209c2d..bed58e0 100644 --- a/tokens.inc +++ b/tokens.inc @@ -45,6 +45,7 @@ S(_Imaginary) S(__thread) S(__extension__) S(__attribute__) +S(__builtin_classify_type) S(__builtin_va_list) S(__builtin_expect) S(__builtin_offsetof) -- 2.20.1