Removed EXPR_BUILTIN_SYMBOL: Builtins are now predefined functions
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Sat, 27 Dec 2008 00:26:19 +0000 (00:26 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Sat, 27 Dec 2008 00:26:19 +0000 (00:26 +0000)
with a builtin_kind != bk_none.
This simplifies parsing and allows to have "different" builtin-sets (enable MS builtins for instance)

[r24902]

ast.c
ast.h
ast2firm.c
ast_t.h
entity_t.h
parser.c
tokens.inc
walk_statements.c

diff --git a/ast.c b/ast.c
index 613da53..7fd934b 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -114,7 +114,6 @@ static unsigned get_expression_precedence(expression_kind_t kind)
                [EXPR_ALIGNOF]                    = PREC_UNARY,
 
                [EXPR_FUNCNAME]                   = PREC_PRIMARY,
-               [EXPR_BUILTIN_SYMBOL]             = PREC_PRIMARY,
                [EXPR_BUILTIN_CONSTANT_P]         = PREC_PRIMARY,
                [EXPR_BUILTIN_TYPES_COMPATIBLE_P] = PREC_PRIMARY,
                [EXPR_OFFSETOF]                   = PREC_PRIMARY,
@@ -584,16 +583,6 @@ static void print_typeprop_expression(const typeprop_expression_t *expression)
        }
 }
 
-/**
- * Prints an builtin symbol.
- *
- * @param expression   the builtin symbol expression
- */
-static void print_builtin_symbol(const builtin_symbol_expression_t *expression)
-{
-       fputs(expression->symbol->string, out);
-}
-
 /**
  * Prints a builtin constant expression.
  *
@@ -812,9 +801,6 @@ static void print_expression_prec(const expression_t *expression, unsigned top_p
        case EXPR_ALIGNOF:
                print_typeprop_expression(&expression->typeprop);
                break;
-       case EXPR_BUILTIN_SYMBOL:
-               print_builtin_symbol(&expression->builtin_symbol);
-               break;
        case EXPR_BUILTIN_CONSTANT_P:
                print_builtin_constant(&expression->builtin_constant);
                break;
@@ -1757,23 +1743,27 @@ bool is_address_constant(const expression_t *expression)
        }
 }
 
+/**
+ * Check if the given expression is a call to a builtin function
+ * returning a constant result.
+ */
 static bool is_builtin_const_call(const expression_t *expression)
 {
        expression_t *function = expression->call.function;
-       if (function->kind != EXPR_BUILTIN_SYMBOL) {
+       if (function->kind != EXPR_REFERENCE)
+               return false;
+       reference_expression_t *ref = &function->reference;
+       if (ref->entity->kind != ENTITY_FUNCTION)
                return false;
-       }
-
-       symbol_t *symbol = function->builtin_symbol.symbol;
 
-       switch (symbol->ID) {
-       case T___builtin_huge_val:
-       case T___builtin_inf:
-       case T___builtin_inff:
-       case T___builtin_infl:
-       case T___builtin_nan:
-       case T___builtin_nanf:
-       case T___builtin_nanl:
+       switch (ref->entity->function.btk) {
+       case bk_gnu_builtin_huge_val:
+       case bk_gnu_builtin_inf:
+       case bk_gnu_builtin_inff:
+       case bk_gnu_builtin_infl:
+       case bk_gnu_builtin_nan:
+       case bk_gnu_builtin_nanf:
+       case bk_gnu_builtin_nanl:
                return true;
        }
 
@@ -1854,7 +1844,6 @@ bool is_constant_expression(const expression_t *expression)
                return true;
        }
 
-       case EXPR_BUILTIN_SYMBOL:
        case EXPR_SELECT:
        case EXPR_VA_START:
        case EXPR_VA_ARG:
diff --git a/ast.h b/ast.h
index bf200b2..e13e601 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -48,7 +48,6 @@ typedef struct designator_t                          designator_t;
 typedef struct offsetof_expression_t                 offsetof_expression_t;
 typedef struct va_start_expression_t                 va_start_expression_t;
 typedef struct va_arg_expression_t                   va_arg_expression_t;
-typedef struct builtin_symbol_expression_t           builtin_symbol_expression_t;
 typedef struct builtin_constant_expression_t         builtin_constant_expression_t;
 typedef struct builtin_types_compatible_expression_t builtin_types_compatible_expression_t;
 typedef struct classify_type_expression_t            classify_type_expression_t;
index 67cbad6..8ab912f 100644 (file)
@@ -1444,6 +1444,21 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
        }
        case DECLARATION_KIND_FUNCTION: {
                ir_mode *const mode = get_ir_mode_storage(type);
+
+               if (entity->function.btk != bk_none) {
+                       /* for gcc compatibility we have to produce (dummy) addresses for some
+                        * builtins */
+                       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);
+
+                       return res;
+               }
                return create_symconst(dbgi, mode, entity->function.entity);
        }
        case DECLARATION_KIND_INNER_FUNCTION: {
@@ -1549,9 +1564,10 @@ static ir_node *gen_unary_builtin(ir_builtin_kind kind, expression_t *op, type_t
        in[0] = expression_to_firm(op);
 
        ir_type *tp  = get_ir_type(function_type);
+       ir_type *res = get_method_res_type(tp, 0);
        ir_node *irn = new_d_Builtin(db, get_irg_no_mem(current_ir_graph), kind, 1, in, tp);
        set_irn_pinned(irn, op_pin_state_floats);
-       return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
+       return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result);
 }
 
 /**
@@ -1561,17 +1577,16 @@ static ir_node *process_builtin_call(const call_expression_t *call)
 {
        dbg_info *dbgi = get_dbg_info(&call->base.source_position);
 
-       assert(call->function->kind == EXPR_BUILTIN_SYMBOL);
-       builtin_symbol_expression_t *builtin = &call->function->builtin_symbol;
+       assert(call->function->kind == EXPR_REFERENCE);
+       reference_expression_t *builtin = &call->function->reference;
 
        type_t *type = skip_typeref(builtin->base.type);
        assert(is_type_pointer(type));
 
        type_t   *function_type = skip_typeref(type->pointer.points_to);
-       symbol_t *symbol        = builtin->symbol;
 
-       switch(symbol->ID) {
-       case T___builtin_alloca: {
+       switch (builtin->entity->function.btk) {
+       case bk_gnu_builtin_alloca: {
                if (call->arguments == NULL || call->arguments->next != NULL) {
                        panic("invalid number of parameters on __builtin_alloca");
                }
@@ -1588,19 +1603,19 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                return res;
        }
 
-       case T___builtin_huge_val:
-       case T___builtin_inf:
-       case T___builtin_inff:
-       case T___builtin_infl: {
+       case bk_gnu_builtin_huge_val:
+       case bk_gnu_builtin_inf:
+       case bk_gnu_builtin_inff:
+       case bk_gnu_builtin_infl: {
                type_t  *type = function_type->function.return_type;
                ir_mode *mode = get_ir_mode_arithmetic(type);
                tarval  *tv   = get_mode_infinite(mode);
                ir_node *res  = new_d_Const(dbgi, tv);
                return   res;
        }
-       case T___builtin_nan:
-       case T___builtin_nanf:
-       case T___builtin_nanl: {
+       case bk_gnu_builtin_nan:
+       case bk_gnu_builtin_nanf:
+       case bk_gnu_builtin_nanl: {
                /* Ignore string for now... */
                assert(is_type_function(function_type));
                type_t  *type = function_type->function.return_type;
@@ -1609,15 +1624,15 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                ir_node *res  = new_d_Const(dbgi, tv);
                return res;
        }
-       case T___builtin_expect: {
+       case bk_gnu_builtin_expect: {
                expression_t *argument = call->arguments->expression;
                return _expression_to_firm(argument);
        }
-       case T___builtin_va_end:
+       case bk_gnu_builtin_va_end:
                /* evaluate the argument of va_end for its side effects */
                _expression_to_firm(call->arguments->expression);
                return NULL;
-       case T___builtin_frame_address: {
+       case bk_gnu_builtin_frame_address: {
                expression_t *const expression = call->arguments->expression;
                long val = fold_constant(expression);
                if (val == 0) {
@@ -1634,7 +1649,7 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                        return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
                }
        }
-       case T___builtin_return_address: {
+       case bk_gnu_builtin_return_address: {
                expression_t *const expression = call->arguments->expression;
                ir_node *in[2];
 
@@ -1644,17 +1659,18 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                ir_node *irn = new_d_Builtin(dbgi, get_irg_no_mem(current_ir_graph), ir_bk_return_address, 2, in, tp);
                return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
        }
-       case T___builtin_ffs:
+       case bk_gnu_builtin_ffs:
                 return gen_unary_builtin(ir_bk_ffs,      call->arguments->expression, function_type, dbgi);
-       case T___builtin_clz:
+       case bk_gnu_builtin_clz:
                 return gen_unary_builtin(ir_bk_clz,      call->arguments->expression, function_type, dbgi);
-       case T___builtin_ctz:
+       case bk_gnu_builtin_ctz:
                 return gen_unary_builtin(ir_bk_ctz,      call->arguments->expression, function_type, dbgi);
-       case T___builtin_popcount:
+       case bk_gnu_builtin_popcount:
+       case bk_ms__popcount:
                 return gen_unary_builtin(ir_bk_popcount, call->arguments->expression, function_type, dbgi);
-       case T___builtin_parity:
+       case bk_gnu_builtin_parity:
                 return gen_unary_builtin(ir_bk_parity,   call->arguments->expression, function_type, dbgi);
-       case T___builtin_prefetch: {
+       case bk_gnu_builtin_prefetch: {
                call_argument_t *const args = call->arguments;
                expression_t *const addr    = args->expression;
                ir_node *in[3];
@@ -1681,12 +1697,30 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                set_store(new_Proj(irn, mode_M, pn_Builtin_M));
                return NULL;
        }
-       case T___builtin_trap: {
+       case bk_gnu_builtin_trap:
+       case bk_ms__ud2:
+       {
                ir_type *tp  = get_ir_type(function_type);
                ir_node *irn = new_d_Builtin(dbgi, get_store(), ir_bk_trap, 0, NULL, tp);
                set_store(new_Proj(irn, mode_M, pn_Builtin_M));
                return NULL;
        }
+       case bk_ms__debugbreak: {
+               ir_type *tp  = get_ir_type(function_type);
+               ir_node *irn = new_d_Builtin(dbgi, get_store(), ir_bk_debugbreak, 0, NULL, tp);
+               set_store(new_Proj(irn, mode_M, pn_Builtin_M));
+               return NULL;
+       }
+       case bk_ms_ReturnAddress: {
+               expression_t *const expression = call->arguments->expression;
+               ir_node *in[2];
+
+               in[0] = new_Const_long(mode_int, 0);
+               in[1] = get_irg_frame(current_ir_graph);
+               ir_type *tp  = get_ir_type(function_type);
+               ir_node *irn = new_d_Builtin(dbgi, get_irg_no_mem(current_ir_graph), ir_bk_return_address, 2, in, tp);
+               return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
+       }
        default:
                panic("unsupported builtin found");
        }
@@ -1705,13 +1739,15 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
        assert(get_cur_block() != NULL);
 
        expression_t *function = call->function;
-       if (function->kind == EXPR_BUILTIN_SYMBOL) {
-               return process_builtin_call(call);
-       }
        if (function->kind == EXPR_REFERENCE) {
                const reference_expression_t *ref    = &function->reference;
                entity_t                     *entity = ref->entity;
 
+               if (ref->entity->kind == ENTITY_FUNCTION &&
+                   ref->entity->function.btk != bk_none) {
+                       return process_builtin_call(call);
+               }
+
                if (entity->kind == ENTITY_FUNCTION
                                && entity->function.entity == rts_entities[rts_alloca]) {
                        /* handle alloca() call */
@@ -3231,23 +3267,6 @@ static ir_node *label_address_to_firm(
        return new_SymConst(mode_P_code, value, symconst_label);
 }
 
-static ir_node *builtin_symbol_to_firm(
-               const builtin_symbol_expression_t *expression)
-{
-       /* for gcc compatibility we have to produce (dummy) addresses for some
-        * builtins */
-       if (warning.other) {
-               warningf(&expression->base.source_position,
-                                "taking address of builtin '%Y'", expression->symbol);
-       }
-
-       /* 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;
-}
-
 /**
  * creates firm nodes for an expression. The difference between this function
  * and expression_to_firm is, that this version might produce mode_b nodes
@@ -3303,8 +3322,6 @@ static ir_node *_expression_to_firm(const expression_t *expression)
                return va_start_expression_to_firm(&expression->va_starte);
        case EXPR_VA_ARG:
                return va_arg_expression_to_firm(&expression->va_arge);
-       case EXPR_BUILTIN_SYMBOL:
-               return builtin_symbol_to_firm(&expression->builtin_symbol);
        case EXPR_BUILTIN_CONSTANT_P:
                return builtin_constant_to_firm(&expression->builtin_constant);
        case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
@@ -3323,15 +3340,20 @@ static ir_node *_expression_to_firm(const expression_t *expression)
        panic("invalid expression found");
 }
 
+/**
+ * Check if a given expression is a GNU __builtin_expect() call.
+ */
 static bool is_builtin_expect(const expression_t *expression)
 {
        if (expression->kind != EXPR_CALL)
                return false;
 
        expression_t *function = expression->call.function;
-       if (function->kind != EXPR_BUILTIN_SYMBOL)
+       if (function->kind != EXPR_REFERENCE)
                return false;
-       if (function->builtin_symbol.symbol->ID != T___builtin_expect)
+       reference_expression_t *ref = &function->reference;
+       if (ref->entity->kind == ENTITY_FUNCTION &&
+           ref->entity->function.btk != bk_gnu_builtin_expect)
                return false;
 
        return true;
@@ -5633,6 +5655,10 @@ static void scope_to_firm(scope_t *scope)
                        continue;
 
                if (entity->kind == ENTITY_FUNCTION) {
+                       if (entity->function.btk != bk_none) {
+                               /* builtins have no representation */
+                               continue;
+                       }
                        get_function_entity(entity);
                } else if (entity->kind == ENTITY_VARIABLE) {
                        create_global_variable(entity);
@@ -5646,6 +5672,10 @@ static void scope_to_firm(scope_t *scope)
                        continue;
 
                if (entity->kind == ENTITY_FUNCTION) {
+                       if (entity->function.btk != bk_none) {
+                               /* builtins have no representation */
+                               continue;
+                       }
                        create_function(entity);
                } else if (entity->kind == ENTITY_VARIABLE) {
                        assert(entity->declaration.kind
diff --git a/ast_t.h b/ast_t.h
index 0a98d02..1c0141d 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -81,7 +81,6 @@ typedef enum expression_kind_t {
        EXPR_ALIGNOF,
 
        EXPR_FUNCNAME,
-       EXPR_BUILTIN_SYMBOL,
        EXPR_BUILTIN_CONSTANT_P,
        EXPR_BUILTIN_TYPES_COMPATIBLE_P,
        EXPR_OFFSETOF,
@@ -273,11 +272,6 @@ struct compound_literal_expression_t {
        initializer_t     *initializer;
 };
 
-struct builtin_symbol_expression_t {
-       expression_base_t  base;
-       symbol_t          *symbol;
-};
-
 struct builtin_constant_expression_t {
        expression_base_t  base;
        expression_t      *value;
@@ -389,7 +383,6 @@ union expression_t {
        string_literal_expression_t           string;
        wide_string_literal_expression_t      wide_string;
        compound_literal_expression_t         compound_literal;
-       builtin_symbol_expression_t           builtin_symbol;
        builtin_constant_expression_t         builtin_constant;
        builtin_types_compatible_expression_t builtin_types_compatible;
        reference_expression_t                reference;
index 03cfd7a..3081d77 100644 (file)
@@ -232,12 +232,44 @@ 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_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__debugbreak,             /**< MS __debugbreak */
+       bk_ms_ReturnAddress,           /**< MS _ReturnAddress */
+       bk_ms__popcount,               /**< MS __popcount */
+       bk_ms__ud2,                    /**< MS __ud2 */
+} builtin_kind_t;
+
 struct function_t {
        declaration_t  base;
        bool           is_inline     : 1;
        bool           need_closure  : 1;  /**< Inner function needs closure. */
        bool           goto_to_outer : 1;  /**< Inner function has goto to outer function. */
 
+       builtin_kind_t btk;
        scope_t        parameters;
        statement_t   *statement;
 
index 8e365d4..238422a 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -206,6 +206,9 @@ 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:
@@ -288,36 +291,17 @@ static void semantic_comparison(binary_expression_t *expression);
        case T___FUNCTION__:             \
        case T___PRETTY_FUNCTION__:      \
        case T___alignof__:              \
-       case T___builtin_alloca:         \
        case T___builtin_classify_type:  \
        case T___builtin_constant_p:     \
-       case T___builtin_expect:         \
-       case T___builtin_huge_val:       \
-       case T___builtin_inf:            \
-       case T___builtin_inff:           \
-       case T___builtin_infl:           \
        case T___builtin_isgreater:      \
        case T___builtin_isgreaterequal: \
        case T___builtin_isless:         \
        case T___builtin_islessequal:    \
        case T___builtin_islessgreater:  \
        case T___builtin_isunordered:    \
-       case T___builtin_nan:            \
-       case T___builtin_nanf:           \
-       case T___builtin_nanl:           \
        case T___builtin_offsetof:       \
-       case T___builtin_prefetch:       \
        case T___builtin_va_arg:         \
-       case T___builtin_va_end:         \
        case T___builtin_va_start:       \
-       case T___builtin_return_address: \
-       case T___builtin_frame_address:  \
-       case T___builtin_ffs:            \
-       case T___builtin_clz:            \
-       case T___builtin_ctz:            \
-       case T___builtin_popcount:       \
-       case T___builtin_parity:         \
-       case T___builtin_trap:           \
        case T___func__:                 \
        case T___noop:                   \
        case T__assume:                  \
@@ -436,7 +420,6 @@ static size_t get_expression_struct_size(expression_kind_t kind)
                [EXPR_ALIGNOF]                    = sizeof(typeprop_expression_t),
                [EXPR_CLASSIFY_TYPE]              = sizeof(classify_type_expression_t),
                [EXPR_FUNCNAME]                   = sizeof(funcname_expression_t),
-               [EXPR_BUILTIN_SYMBOL]             = sizeof(builtin_symbol_expression_t),
                [EXPR_BUILTIN_CONSTANT_P]         = sizeof(builtin_constant_expression_t),
                [EXPR_BUILTIN_TYPES_COMPATIBLE_P] = sizeof(builtin_types_compatible_expression_t),
                [EXPR_OFFSETOF]                   = sizeof(offsetof_expression_t),
@@ -2145,7 +2128,6 @@ unary:
                case EXPR_CLASSIFY_TYPE:
                case EXPR_ALIGNOF:
                case EXPR_FUNCNAME:
-               case EXPR_BUILTIN_SYMBOL:
                case EXPR_BUILTIN_CONSTANT_P:
                case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
                case EXPR_OFFSETOF:
@@ -5762,7 +5744,6 @@ static bool expression_returns(expression_t const *const expr)
                case EXPR_SIZEOF: // TODO handle obscure VLA case
                case EXPR_ALIGNOF:
                case EXPR_FUNCNAME:
-               case EXPR_BUILTIN_SYMBOL:
                case EXPR_BUILTIN_CONSTANT_P:
                case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
                case EXPR_OFFSETOF:
@@ -6943,52 +6924,20 @@ static type_t *make_function_0_type(type_t *return_type)
 }
 
 /**
- * Creates a function type for some function like builtins.
+ * Creates a NO_RETURN return_type (func)(void) function type if not
+ * already exists.
  *
- * @param symbol   the symbol describing the builtin
- */
-static type_t *get_builtin_symbol_type(symbol_t *symbol)
-{
-       switch (symbol->ID) {
-       case T___builtin_alloca:
-               return make_function_1_type(type_void_ptr, type_size_t);
-       case T___builtin_huge_val:
-               return make_function_0_type(type_double);
-       case T___builtin_inf:
-               return make_function_0_type(type_double);
-       case T___builtin_inff:
-               return make_function_0_type(type_float);
-       case T___builtin_infl:
-               return make_function_0_type(type_long_double);
-       case T___builtin_nan:
-               return make_function_1_type(type_double, type_char_ptr);
-       case T___builtin_nanf:
-               return make_function_1_type(type_float, type_char_ptr);
-       case T___builtin_nanl:
-               return make_function_1_type(type_long_double, type_char_ptr);
-       case T___builtin_va_end:
-               return make_function_1_type(type_void, type_valist);
-       case T___builtin_expect:
-               return make_function_2_type(type_long, type_long, type_long);
-       case T___builtin_return_address:
-       case T___builtin_frame_address:
-               return make_function_1_type(type_void_ptr, type_unsigned_int);
-       case T___builtin_ffs:
-       case T___builtin_clz:
-       case T___builtin_ctz:
-       case T___builtin_popcount:
-       case T___builtin_parity:
-               return make_function_1_type(type_int, type_unsigned_int);
-       case T___builtin_prefetch:
-               return make_function_1_type_variadic(type_float, type_void_ptr);
-       case T___builtin_trap: {
-               type_t *type = make_function_0_type(type_void);
-               type->function.base.modifiers |= DM_NORETURN;
-               return type;
-       }
-       default:
-               internal_errorf(HERE, "not implemented builtin identifier found");
-       }
+ * @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.base.modifiers |= DM_NORETURN;
+       return type;
+
+       return identify_new_type(type);
 }
 
 /**
@@ -7048,9 +6997,6 @@ type_t *revert_automatic_type_conversion(const expression_t *expression)
                        return type->pointer.points_to;
                }
 
-               case EXPR_BUILTIN_SYMBOL:
-                       return get_builtin_symbol_type(expression->builtin_symbol.symbol);
-
                case EXPR_ARRAY_ACCESS: {
                        const expression_t *array_ref = expression->array_access.array_ref;
                        type_t             *type_left = skip_typeref(array_ref->base.type);
@@ -7550,22 +7496,6 @@ end_error:
        return create_invalid_expression();
 }
 
-static expression_t *parse_builtin_symbol(void)
-{
-       expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_SYMBOL);
-
-       symbol_t *symbol = token.v.symbol;
-
-       expression->builtin_symbol.symbol = symbol;
-       next_token();
-
-       type_t *type = get_builtin_symbol_type(symbol);
-       type = automatic_type_conversion(type);
-
-       expression->base.type = type;
-       return expression;
-}
-
 /**
  * Parses a __builtin_constant_p() expression.
  */
@@ -7841,25 +7771,6 @@ static expression_t *parse_primary_expression(void)
                case T___builtin_offsetof:           return parse_offsetof();
                case T___builtin_va_start:           return parse_va_start();
                case T___builtin_va_arg:             return parse_va_arg();
-               case T___builtin_expect:
-               case T___builtin_alloca:
-               case T___builtin_inf:
-               case T___builtin_inff:
-               case T___builtin_infl:
-               case T___builtin_nan:
-               case T___builtin_nanf:
-               case T___builtin_nanl:
-               case T___builtin_huge_val:
-               case T___builtin_va_end:
-               case T___builtin_return_address:
-               case T___builtin_frame_address:
-               case T___builtin_ffs:
-               case T___builtin_clz:
-               case T___builtin_ctz:
-               case T___builtin_popcount:
-               case T___builtin_parity:
-               case T___builtin_prefetch:
-               case T___builtin_trap:               return parse_builtin_symbol();
                case T___builtin_isgreater:
                case T___builtin_isgreaterequal:
                case T___builtin_isless:
@@ -8155,20 +8066,20 @@ static void check_call_argument(const function_parameter_t *parameter,
  * Handle the semantic restrictions of builtin calls
  */
 static void handle_builtin_argument_restrictions(call_expression_t *call) {
-       switch (call->function->builtin_symbol.symbol->ID) {
-               case T___builtin_return_address:
-               case T___builtin_frame_address: {
+       switch (call->function->reference.entity->function.btk) {
+               case bk_gnu_builtin_return_address:
+               case bk_gnu_builtin_frame_address: {
                        /* argument must be constant */
                        call_argument_t *argument = call->arguments;
 
                        if (! is_constant_expression(argument->expression)) {
                                errorf(&call->base.source_position,
                                       "argument of '%Y' must be a constant expression",
-                                      call->function->builtin_symbol.symbol);
+                                      call->function->reference.entity->base.symbol);
                        }
                        break;
                }
-               case T___builtin_prefetch: {
+               case bk_gnu_builtin_prefetch: {
                        /* second and third argument must be constant if existent */
                        call_argument_t *rw = call->arguments->next;
                        call_argument_t *locality = NULL;
@@ -8177,7 +8088,7 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) {
                                if (! is_constant_expression(rw->expression)) {
                                        errorf(&call->base.source_position,
                                               "second argument of '%Y' must be a constant expression",
-                                              call->function->builtin_symbol.symbol);
+                                              call->function->reference.entity->base.symbol);
                                }
                                locality = rw->next;
                        }
@@ -8185,7 +8096,7 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) {
                                if (! is_constant_expression(locality->expression)) {
                                        errorf(&call->base.source_position,
                                               "third argument of '%Y' must be a constant expression",
-                                              call->function->builtin_symbol.symbol);
+                                              call->function->reference.entity->base.symbol);
                                }
                                locality = rw->next;
                        }
@@ -8288,8 +8199,11 @@ static expression_t *parse_call_expression(expression_t *expression)
                         "function call has aggregate value");
        }
 
-       if (call->function->kind == EXPR_BUILTIN_SYMBOL) {
-               handle_builtin_argument_restrictions(&result->call);
+       if (call->function->kind == EXPR_REFERENCE) {
+               reference_expression_t *reference = &call->function->reference;
+               if (reference->entity->kind == ENTITY_FUNCTION &&
+                   reference->entity->function.btk != bk_none)
+                       handle_builtin_argument_restrictions(call);
        }
 
 end_error:
@@ -9434,13 +9348,13 @@ static bool expression_has_effect(const expression_t *const expr)
 
                case EXPR_CALL: {
                        const call_expression_t *const call = &expr->call;
-                       if (call->function->kind != EXPR_BUILTIN_SYMBOL)
+                       if (call->function->kind != EXPR_REFERENCE)
                                return true;
 
-                       switch (call->function->builtin_symbol.symbol->ID) {
-                               case T___builtin_prefetch:
-                               case T___builtin_va_end:   return true;
-                               default:                   return false;
+                       switch (call->function->reference.entity->function.btk) {
+                               case bk_gnu_builtin_prefetch:
+                               case bk_gnu_builtin_va_end:   return true;
+                               default:                      return false;
                        }
                }
 
@@ -9461,7 +9375,6 @@ static bool expression_has_effect(const expression_t *const expr)
                case EXPR_ALIGNOF:                    return false;
 
                case EXPR_FUNCNAME:                   return false;
-               case EXPR_BUILTIN_SYMBOL:             break; /* handled in EXPR_CALL */
                case EXPR_BUILTIN_CONSTANT_P:         return false;
                case EXPR_BUILTIN_TYPES_COMPATIBLE_P: return false;
                case EXPR_OFFSETOF:                   return false;
@@ -11456,6 +11369,10 @@ void start_parsing(void)
 
        assert(current_scope == NULL);
        scope_push(&unit->scope);
+
+       create_gnu_builtins();
+       if (c_mode & _MS)
+               create_microsoft_intrinsics();
 }
 
 translation_unit_t *finish_parsing(void)
@@ -11519,6 +11436,84 @@ 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 _STR(a)              #a
+#define STR(a)               _STR(a)
+#define CONCAT(a,b)          a##b
+#define GNU_BUILTIN_NAME(a)  STR(CONCAT(__builtin_, a))
+#define GNU_BUILTIN(a, b)    create_builtin_function(CONCAT(bk_gnu_builtin_, a), GNU_BUILTIN_NAME(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(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
+#undef GNU_BUILTIN_NAME
+#undef CONCAT
+#undef STR
+#undef _STR
+}
+
+/**
+ * Create predefined MS intrinsics.
+ */
+static void create_microsoft_intrinsics(void) {
+#define _STR(a)              #a
+#define STR(a)               _STR(a)
+#define CONCAT(a,b)          a##b
+#define MS_BUILTIN(a, b)  create_builtin_function(CONCAT(bk_ms, a), STR(a), b)
+
+       MS_BUILTIN(__debugbreak,    make_function_0_type(type_void));
+       MS_BUILTIN(_ReturnAddress,  make_function_0_type(type_void_ptr));
+       MS_BUILTIN(__popcount,      make_function_1_type(type_unsigned_int, type_unsigned_int));
+       MS_BUILTIN(__ud2,           make_function_0_type_noreturn(type_void));
+
+#undef MS_BUILTIN
+#undef CONCAT
+#undef STR
+#undef _STR
+}
+
 /**
  * Initialize the parser.
  */
index 607e3e2..d4741e4 100644 (file)
@@ -89,35 +89,16 @@ S(_ALL, __thread)
 S(_ALL, __extension__)
 S(_ALL, __builtin_classify_type)
 S(_ALL, __builtin_va_list)
-S(_ALL, __builtin_expect)
 S(_ALL, __builtin_offsetof)
 S(_ALL, __builtin_va_arg)
-S(_ALL, __builtin_va_end)
-S(_ALL, __builtin_alloca)
-S(_ALL, __builtin_inf)
-S(_ALL, __builtin_inff)
-S(_ALL, __builtin_infl)
-S(_ALL, __builtin_nan)
-S(_ALL, __builtin_nanf)
-S(_ALL, __builtin_nanl)
+S(_ALL, __builtin_constant_p)
+S(_ALL, __builtin_types_compatible_p)
 S(_ALL, __builtin_isgreater)
 S(_ALL, __builtin_isgreaterequal)
 S(_ALL, __builtin_isless)
 S(_ALL, __builtin_islessequal)
 S(_ALL, __builtin_islessgreater)
 S(_ALL, __builtin_isunordered)
-S(_ALL, __builtin_constant_p)
-S(_ALL, __builtin_prefetch)
-S(_ALL, __builtin_huge_val)
-S(_ALL, __builtin_return_address)
-S(_ALL, __builtin_frame_address)
-S(_ALL, __builtin_ffs)
-S(_ALL, __builtin_clz)
-S(_ALL, __builtin_ctz)
-S(_ALL, __builtin_popcount)
-S(_ALL, __builtin_parity)
-S(_ALL, __builtin_trap)
-S(_ALL, __builtin_types_compatible_p)
 S(_ALL, __PRETTY_FUNCTION__)
 S(_ALL, __FUNCTION__)
 S(_ALL, __label__)
index ff26889..1201dd7 100644 (file)
@@ -85,7 +85,6 @@ static void walk_expression(expression_t const *const expr,
        case EXPR_STRING_LITERAL:
        case EXPR_WIDE_STRING_LITERAL:
        case EXPR_FUNCNAME:
-       case EXPR_BUILTIN_SYMBOL:
        case EXPR_VA_START:
        case EXPR_VA_ARG:
        case EXPR_LABEL_ADDRESS: