with a builtin_kind != bk_none.
This simplifies parsing and allows to have "different" builtin-sets (enable MS builtins for instance)
[r24902]
[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,
}
}
-/**
- * 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.
*
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;
}
}
+/**
+ * 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;
}
return true;
}
- case EXPR_BUILTIN_SYMBOL:
case EXPR_SELECT:
case EXPR_VA_START:
case EXPR_VA_ARG:
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;
}
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: {
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);
}
/**
{
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");
}
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;
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) {
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];
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];
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");
}
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 */
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
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:
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;
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);
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
EXPR_ALIGNOF,
EXPR_FUNCNAME,
- EXPR_BUILTIN_SYMBOL,
EXPR_BUILTIN_CONSTANT_P,
EXPR_BUILTIN_TYPES_COMPATIBLE_P,
EXPR_OFFSETOF,
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;
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;
} 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;
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___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: \
[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),
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:
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:
}
/**
- * 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);
}
/**
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);
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.
*/
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:
* 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;
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;
}
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;
}
"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:
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;
}
}
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;
assert(current_scope == NULL);
scope_push(&unit->scope);
+
+ create_gnu_builtins();
+ if (c_mode & _MS)
+ create_microsoft_intrinsics();
}
translation_unit_t *finish_parsing(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.
*/
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__)
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: