static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
{
assert(entity->kind == ENTITY_FUNCTION);
- if (entity->function.irentity != NULL) {
+ if (entity->function.irentity != NULL)
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;
+ switch (entity->function.btk) {
+ case BUILTIN_NONE:
+ case BUILTIN_LIBC:
+ case BUILTIN_LIBC_CHECK:
+ break;
+ default:
+ return NULL;
}
if (is_main(entity)) {
nested_function = true;
dbg_info *const dbgi = get_dbg_info(&entity->base.source_position);
- irentity = new_d_entity(owner_type, id, ir_type_method, dbgi);
+ irentity = new_d_entity(owner_type, id, ir_type_method, dbgi);
ident *ld_id;
if (nested_function)
entitymap_insert(&entitymap, symbol, irentity);
entity_created:
- original_entity->declaration.kind = DECLARATION_KIND_FUNCTION;
- original_entity->function.irentity = irentity;
+ entity->declaration.kind = DECLARATION_KIND_FUNCTION;
+ entity->function.irentity = irentity;
return irentity;
}
/* make sure the type is constructed */
(void) get_ir_type(type);
- if (entity->kind == ENTITY_FUNCTION && entity->function.btk != bk_none) {
+ if (entity->kind == ENTITY_FUNCTION
+ && entity->function.btk != BUILTIN_NONE) {
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 */
panic("reference to declaration with unknown type found");
}
-/**
- * Generate an unary builtin.
- *
- * @param kind the builtin kind to generate
- * @param op the operand
- * @param function_type the function type for the GNU builtin routine
- * @param db debug info
- */
-static ir_node *gen_unary_builtin(ir_builtin_kind kind, expression_t *op, type_t *function_type, dbg_info *db)
-{
- ir_node *in[1];
- 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), 1, in, kind, tp);
- set_irn_pinned(irn, op_pin_state_floats);
- return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result);
-}
-
-/**
- * Generate a pinned unary builtin.
- *
- * @param kind the builtin kind to generate
- * @param op the operand
- * @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)
-{
- ir_node *in[1];
- 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 *mem = get_store();
- ir_node *irn = new_d_Builtin(db, mem, 1, in, kind, tp);
- set_store(new_Proj(irn, mode_M, pn_Builtin_M));
- return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result);
-}
-
-/**
- * Generate an binary-void-return builtin.
- *
- * @param kind the builtin kind to generate
- * @param op1 the first operand
- * @param op2 the second operand
- * @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)
-{
- ir_node *in[2];
- in[0] = expression_to_firm(op1);
- in[1] = expression_to_firm(op2);
-
- ir_type *tp = get_ir_type(function_type);
- ir_node *mem = get_store();
- ir_node *irn = new_d_Builtin(db, mem, 2, in, kind, tp);
- set_store(new_Proj(irn, mode_M, pn_Builtin_M));
- return NULL;
-}
-
/**
* Transform calls to builtin functions.
*/
type_t *function_type = skip_typeref(expr_type->pointer.points_to);
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");
- }
+ case BUILTIN_NONE:
+ break;
+ case BUILTIN_ALLOCA: {
expression_t *argument = call->arguments->expression;
ir_node *size = expression_to_firm(argument);
return res;
}
-
- case bk_gnu_builtin_huge_val:
- case bk_gnu_builtin_huge_valf:
- case bk_gnu_builtin_huge_vall:
- case bk_gnu_builtin_inf:
- case bk_gnu_builtin_inff:
- case bk_gnu_builtin_infl: {
+ case BUILTIN_INF: {
type_t *type = function_type->function.return_type;
ir_mode *mode = get_ir_mode_arithmetic(type);
ir_tarval *tv = get_mode_infinite(mode);
ir_node *res = new_d_Const(dbgi, tv);
return res;
}
- case bk_gnu_builtin_nan:
- case bk_gnu_builtin_nanf:
- case bk_gnu_builtin_nanl: {
+ case BUILTIN_NAN: {
/* 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 bk_gnu_builtin_expect: {
+ case BUILTIN_EXPECT: {
expression_t *argument = call->arguments->expression;
return _expression_to_firm(argument);
}
- case bk_gnu_builtin_va_end:
+ case BUILTIN_VA_END:
/* evaluate the argument of va_end for its side effects */
_expression_to_firm(call->arguments->expression);
return NULL;
- case bk_gnu_builtin_frame_address: {
- expression_t *const expression = call->arguments->expression;
- bool val = fold_constant_to_bool(expression);
- if (!val) {
- /* the nice case */
- return get_irg_frame(current_ir_graph);
- } else {
- /* get the argument */
- ir_node *in[2];
-
- in[0] = expression_to_firm(expression);
- 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), 2, in, ir_bk_frame_address, tp);
- return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
- }
- }
- case bk_gnu_builtin_return_address: {
- expression_t *const expression = call->arguments->expression;
- ir_node *in[2];
-
- in[0] = expression_to_firm(expression);
- 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), 2, in, ir_bk_return_address, tp);
- return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
- }
- case bk_gnu_builtin_ffs:
- return gen_unary_builtin(ir_bk_ffs, call->arguments->expression, function_type, dbgi);
- case bk_gnu_builtin_clz:
- case bk_gnu_builtin_clzl:
- case bk_gnu_builtin_clzll:
- return gen_unary_builtin(ir_bk_clz, call->arguments->expression, function_type, dbgi);
- case bk_gnu_builtin_ctz:
- case bk_gnu_builtin_ctzl:
- case bk_gnu_builtin_ctzll:
- return gen_unary_builtin(ir_bk_ctz, call->arguments->expression, function_type, dbgi);
- case bk_gnu_builtin_popcount:
- case bk_gnu_builtin_popcountl:
- case bk_gnu_builtin_popcountll:
- case bk_ms__popcount:
- return gen_unary_builtin(ir_bk_popcount, call->arguments->expression, function_type, dbgi);
- case bk_gnu_builtin_parity:
- return gen_unary_builtin(ir_bk_parity, call->arguments->expression, function_type, dbgi);
- case bk_gnu_builtin_prefetch: {
- call_argument_t *const args = call->arguments;
- expression_t *const addr = args->expression;
- ir_node *in[3];
-
- in[0] = _expression_to_firm(addr);
- if (args->next != NULL) {
- expression_t *const rw = args->next->expression;
-
- in[1] = _expression_to_firm(rw);
-
- if (args->next->next != NULL) {
- expression_t *const locality = args->next->next->expression;
-
- in[2] = expression_to_firm(locality);
- } else {
- in[2] = new_Const_long(mode_int, 3);
- }
- } else {
- in[1] = new_Const_long(mode_int, 0);
- in[2] = new_Const_long(mode_int, 3);
- }
- ir_type *tp = get_ir_type(function_type);
- ir_node *irn = new_d_Builtin(dbgi, get_store(), 3, in, ir_bk_prefetch, tp);
- set_store(new_Proj(irn, mode_M, pn_Builtin_M));
- return NULL;
- }
- case bk_gnu_builtin_object_size: {
+ case BUILTIN_OBJECT_SIZE: {
/* determine value of "type" */
expression_t *type_expression = call->arguments->next->expression;
long type_val = fold_constant_to_int(type_expression);
return new_d_Const(dbgi, result);
}
- 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(), 0, NULL, ir_bk_trap, 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(), 0, NULL, ir_bk_debugbreak, tp);
- set_store(new_Proj(irn, mode_M, pn_Builtin_M));
- return NULL;
- }
- case bk_ms_ReturnAddress: {
- ir_node *in[2];
-
- in[0] = new_Const(get_mode_null(mode_int));
- 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), 2, in, ir_bk_return_address, tp);
- return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
- }
- case bk_ms_rotl:
- case bk_ms_rotl64: {
+ case BUILTIN_ROTL: {
ir_node *val = expression_to_firm(call->arguments->expression);
ir_node *shf = expression_to_firm(call->arguments->next->expression);
ir_mode *mode = get_irn_mode(val);
return new_d_Rotl(dbgi, val, create_conv(dbgi, shf, mode_uint), mode);
}
- case bk_ms_rotr:
- case bk_ms_rotr64: {
+ case BUILTIN_ROTR: {
ir_node *val = expression_to_firm(call->arguments->expression);
ir_node *shf = expression_to_firm(call->arguments->next->expression);
ir_mode *mode = get_irn_mode(val);
ir_node *sub = new_d_Sub(dbgi, c, create_conv(dbgi, shf, mode_uint), mode_uint);
return new_d_Rotl(dbgi, val, sub, mode);
}
- case bk_ms_byteswap_ushort:
- case bk_ms_byteswap_ulong:
- case bk_ms_byteswap_uint64:
- return gen_unary_builtin(ir_bk_bswap, call->arguments->expression, function_type, dbgi);
- case bk_ms__inbyte:
- case bk_ms__inword:
- case bk_ms__indword:
- return gen_unary_builtin_pinned(ir_bk_inport, call->arguments->expression, function_type, dbgi);
- case bk_ms__outbyte:
- case bk_ms__outword:
- case bk_ms__outdword:
- return gen_binary_builtin_mem(ir_bk_outport, call->arguments->expression,
- call->arguments->next->expression, function_type, dbgi);
- default:
- panic("unsupported builtin found");
+ case BUILTIN_FIRM:
+ break;
+ case BUILTIN_LIBC:
+ case BUILTIN_LIBC_CHECK:
+ panic("builtin did not produce an entity");
}
+ panic("invalid builtin found");
}
/**
dbg_info *const dbgi = get_dbg_info(&call->base.source_position);
assert(currently_reachable());
- expression_t *function = call->function;
+ expression_t *function = call->function;
+ ir_node *callee = NULL;
+ bool firm_builtin = false;
+ ir_builtin_kind firm_builtin_kind = ir_bk_trap;
if (function->kind == EXPR_REFERENCE) {
const reference_expression_t *ref = &function->reference;
entity_t *entity = ref->entity;
if (entity->kind == ENTITY_FUNCTION) {
- ir_entity *irentity = entity->function.irentity;
- if (irentity == NULL)
- irentity = get_function_entity(entity, NULL);
-
- if (irentity == NULL && entity->function.btk != bk_none) {
+ builtin_kind_t builtin = entity->function.btk;
+ if (builtin == BUILTIN_FIRM) {
+ firm_builtin = true;
+ firm_builtin_kind = entity->function.b.firm_builtin_kind;
+ } else if (builtin != BUILTIN_NONE && builtin != BUILTIN_LIBC
+ && builtin != BUILTIN_LIBC_CHECK) {
return process_builtin_call(call);
}
-
-#if 0
- if (irentity == rts_entities[rts_alloca]) {
- /* handle alloca() call */
- expression_t *argument = call->arguments->expression;
- ir_node *size = expression_to_firm(argument);
- ir_mode *mode = get_ir_mode_arithmetic(type_size_t);
-
- size = create_conv(dbgi, size, mode);
-
- ir_node *store = get_store();
- ir_node *alloca = new_d_Alloc(dbgi, store, size,
- firm_unknown_type, stack_alloc);
- ir_node *proj_m = new_Proj(alloca, mode_M, pn_Alloc_M);
- set_store(proj_m);
- ir_node *res = new_Proj(alloca, mode_P_data, pn_Alloc_res);
-
- return res;
- }
-#endif
}
}
- ir_node *callee = expression_to_firm(function);
+ if (!firm_builtin)
+ callee = expression_to_firm(function);
type_t *type = skip_typeref(function->base.type);
assert(is_type_pointer(type));
assert(is_type_function(points_to));
function_type_t *function_type = &points_to->function;
- int n_parameters = 0;
+ int n_parameters = 0;
ir_type *ir_method_type = get_ir_type((type_t*) function_type);
ir_type *new_method_type = NULL;
if (function_type->variadic || function_type->unspecified_parameters) {
argument = argument->next;
}
- ir_node *store = get_store();
- ir_node *node = new_d_Call(dbgi, store, callee, n_parameters, in,
- ir_method_type);
- ir_node *mem = new_d_Proj(dbgi, node, mode_M, pn_Call_M);
- set_store(mem);
+ ir_node *store;
+ if (function_type->modifiers & DM_CONST) {
+ store = get_irg_no_mem(current_ir_graph);
+ } else {
+ store = get_store();
+ }
+ ir_node *node;
type_t *return_type = skip_typeref(function_type->return_type);
ir_node *result = NULL;
+ if (firm_builtin) {
+ node = new_d_Builtin(dbgi, store, n_parameters, in, firm_builtin_kind,
+ ir_method_type);
+ if (! (function_type->modifiers & DM_CONST)) {
+ ir_node *mem = new_Proj(node, mode_M, pn_Builtin_M);
+ set_store(mem);
+ }
- if (!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
- ir_node *resproj = new_d_Proj(dbgi, node, mode_T, pn_Call_T_result);
-
- if (is_type_scalar(return_type)) {
- ir_mode *mode = get_ir_mode_storage(return_type);
- result = new_d_Proj(dbgi, resproj, mode, 0);
+ if (!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
+ assert(is_type_scalar(return_type));
+ ir_mode *mode = get_ir_mode_storage(return_type);
+ result = new_Proj(node, mode, pn_Builtin_1_result);
ir_mode *mode_arith = get_ir_mode_arithmetic(return_type);
result = create_conv(NULL, result, mode_arith);
- } else {
- ir_mode *mode = mode_P_data;
- result = new_d_Proj(dbgi, resproj, mode, 0);
+ }
+ } else {
+ node = new_d_Call(dbgi, store, callee, n_parameters, in, ir_method_type);
+ if (! (function_type->modifiers & DM_CONST)) {
+ ir_node *mem = new_Proj(node, mode_M, pn_Call_M);
+ set_store(mem);
+ }
+
+ if (!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
+ ir_node *resproj = new_Proj(node, mode_T, pn_Call_T_result);
+
+ if (is_type_scalar(return_type)) {
+ ir_mode *mode = get_ir_mode_storage(return_type);
+ result = new_Proj(resproj, mode, 0);
+ ir_mode *mode_arith = get_ir_mode_arithmetic(return_type);
+ result = create_conv(NULL, result, mode_arith);
+ } else {
+ ir_mode *mode = mode_P_data;
+ result = new_Proj(resproj, mode, 0);
+ }
}
}
return false;
reference_expression_t *ref = &function->reference;
if (ref->entity->kind != ENTITY_FUNCTION ||
- ref->entity->function.btk != bk_gnu_builtin_expect)
+ ref->entity->function.btk != BUILTIN_EXPECT)
return false;
return true;
continue;
if (entity->kind == ENTITY_FUNCTION) {
- if (entity->function.btk != bk_none) {
+ if (entity->function.btk != BUILTIN_NONE) {
/* builtins have no representation */
continue;
}
continue;
if (entity->kind == ENTITY_FUNCTION) {
- if (entity->function.btk != bk_none) {
+ if (entity->function.btk != BUILTIN_NONE) {
/* builtins have no representation */
continue;
}
#include "types.h"
#include "entity_t.h"
#include "ast_t.h"
+#include "symbol_t.h"
#include "parser.h"
#include "builtins.h"
#include "lang_features.h"
-static entity_t *create_builtin_function(builtin_kind_t kind, const char *name,
+static entity_t *create_builtin_function(builtin_kind_t kind, symbol_t *symbol,
type_t *function_type)
{
- symbol_t *const symbol = symbol_table_insert(name);
entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol);
entity->declaration.storage_class = STORAGE_CLASS_EXTERN;
entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
return entity;
}
-void create_gnu_builtins(void)
+static symbol_t *finalize_symbol_string(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(ffsl, make_function_1_type(type_int, type_unsigned_long));
- GNU_BUILTIN(ffsll, make_function_1_type(type_int, type_unsigned_long_long));
- GNU_BUILTIN(clz, make_function_1_type(type_int, type_unsigned_int));
- GNU_BUILTIN(clzl, make_function_1_type(type_int, type_unsigned_long));
- GNU_BUILTIN(clzll, make_function_1_type(type_int, type_unsigned_long_long));
- GNU_BUILTIN(ctz, make_function_1_type(type_int, type_unsigned_int));
- GNU_BUILTIN(ctzl, make_function_1_type(type_int, type_unsigned_long));
- GNU_BUILTIN(ctzll, make_function_1_type(type_int, type_unsigned_long_long));
- GNU_BUILTIN(popcount, make_function_1_type(type_int, type_unsigned_int));
- GNU_BUILTIN(popcountl, make_function_1_type(type_int, type_unsigned_long));
- GNU_BUILTIN(popcountll, make_function_1_type(type_int, type_unsigned_long_long));
- 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_type(type_void, 0, NULL, DM_NORETURN));
- GNU_BUILTIN(object_size, make_function_2_type(type_size_t, type_void_ptr, type_int));
- GNU_BUILTIN(abort, make_function_type(type_void, 0, NULL, DM_NORETURN));
- GNU_BUILTIN(abs, make_function_type(type_int, 1, (type_t *[]) { type_int }, DM_CONST));
- GNU_BUILTIN(labs, make_function_type(type_long, 1, (type_t *[]) { type_long }, DM_CONST));
- GNU_BUILTIN(llabs, make_function_type(type_long_long, 1, (type_t *[]) { type_long_long }, DM_CONST));
- GNU_BUILTIN(memcpy, make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t }, DM_NONE));
- GNU_BUILTIN(__memcpy_chk, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t, type_size_t}, DM_NONE));
- GNU_BUILTIN(memcmp, make_function_type(type_int, 3, (type_t *[]) { type_const_void_ptr, type_const_void_ptr, type_size_t }, DM_PURE));
- GNU_BUILTIN(memset, make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr, type_int, type_size_t }, DM_NONE));
- GNU_BUILTIN(__memset_chk, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr, type_int, type_size_t, type_size_t }, DM_NONE));
- GNU_BUILTIN(memmove, make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t }, DM_NONE));
- GNU_BUILTIN(__memmove_chk, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t, type_size_t }, DM_NONE));
- GNU_BUILTIN(strcat, make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
- GNU_BUILTIN(__strcat_chk, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
- GNU_BUILTIN(strncat, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
- GNU_BUILTIN(__strncat_chk, make_function_type(type_char_ptr, 4, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t, type_size_t }, DM_NONE));
- GNU_BUILTIN(strlen, make_function_type(type_size_t, 1, (type_t *[]) { type_const_char_ptr }, DM_PURE));
- GNU_BUILTIN(strcmp, make_function_type(type_int, 2, (type_t *[]) { type_const_char_ptr, type_const_char_ptr }, DM_PURE));
- GNU_BUILTIN(strcpy, make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
- GNU_BUILTIN(__strcpy_chk, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
- GNU_BUILTIN(stpcpy, make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
- GNU_BUILTIN(__stpcpy_chk, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
- GNU_BUILTIN(strncpy, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
- GNU_BUILTIN(__strncpy_chk, make_function_type(type_char_ptr, 4, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t, type_size_t }, DM_NONE));
- GNU_BUILTIN(exit, make_function_type(type_void, 1, (type_t *[]) { type_int }, DM_NORETURN));
- GNU_BUILTIN(malloc, make_function_type(type_void_ptr, 1, (type_t *[]) { type_size_t }, DM_MALLOC));
+ obstack_1grow(&symbol_obstack, '\0');
+ char *string = obstack_finish(&symbol_obstack);
+ symbol_t *symbol = symbol_table_insert(string);
+ if (symbol->string != string)
+ obstack_free(&symbol_obstack, string);
+ return symbol;
+}
- /* TODO: gcc has a LONG list of builtin functions (nearly everything from
- * C89-C99 and others. Complete this */
+static entity_t *create_gnu_builtin(builtin_kind_t kind, const char *name,
+ type_t *type)
+{
+ obstack_printf(&symbol_obstack, "__builtin_%s", name);
+ symbol_t *symbol = finalize_symbol_string();
+ entity_t *entity = create_builtin_function(kind, symbol, type);
+ return entity;
+}
-#undef GNU_BUILTIN
+static entity_t *create_gnu_builtin_firm(ir_builtin_kind kind, const char *name,
+ type_t *type)
+{
+ obstack_printf(&symbol_obstack, "__builtin_%s", name);
+ symbol_t *symbol = finalize_symbol_string();
+ entity_t *entity = create_builtin_function(BUILTIN_FIRM, symbol, type);
+ entity->function.b.firm_builtin_kind = kind;
+ return entity;
}
-static const char *get_builtin_replacement_name(builtin_kind_t kind)
+static entity_t *create_gnu_builtin_libc(const char *name, type_t *type)
{
- switch (kind) {
- case bk_gnu_builtin___memcpy_chk: return "memcpy";
- case bk_gnu_builtin___memmove_chk: return "memmove";
- case bk_gnu_builtin___memset_chk: return "memset";
- case bk_gnu_builtin___snprintf_chk: return "snprintf";
- case bk_gnu_builtin___sprintf_chk: return "sprintf";
- case bk_gnu_builtin___stpcpy_chk: return "stpcpy";
- case bk_gnu_builtin___strcat_chk: return "strcat";
- case bk_gnu_builtin___strcpy_chk: return "strcpy";
- case bk_gnu_builtin___strncat_chk: return "strncat";
- case bk_gnu_builtin___strncpy_chk: return "strncpy";
- case bk_gnu_builtin___vsnprintf_chk: return "vsnprintf";
- case bk_gnu_builtin___vsprintf_chk: return "vsprintf";
- case bk_gnu_builtin_abort: return "abort";
- case bk_gnu_builtin_abs: return "abs";
- case bk_gnu_builtin_exit: return "exit";
- case bk_gnu_builtin_labs: return "labs";
- case bk_gnu_builtin_llabs: return "llabs";
- case bk_gnu_builtin_malloc: return "malloc";
- case bk_gnu_builtin_memcmp: return "memcmp";
- case bk_gnu_builtin_memcpy: return "memcpy";
- case bk_gnu_builtin_memmove: return "memmove";
- case bk_gnu_builtin_memset: return "memset";
- case bk_gnu_builtin_snprintf: return "snprintf";
- case bk_gnu_builtin_sprintf: return "sprintf";
- case bk_gnu_builtin_stpcpy: return "stpcpy";
- case bk_gnu_builtin_strcat: return "strcat";
- case bk_gnu_builtin_strcmp: return "strcmp";
- case bk_gnu_builtin_strcpy: return "strcpy";
- case bk_gnu_builtin_strlen: return "strlen";
- case bk_gnu_builtin_strncat: return "strncat";
- case bk_gnu_builtin_strncpy: return "strncpy";
- case bk_gnu_builtin_vsnprintf: return "vsnprintf";
- case bk_gnu_builtin_vsprintf: return "vsprintf";
-
- default:
- break;
- }
- return NULL;
+ obstack_printf(&symbol_obstack, "__builtin_%s", name);
+ symbol_t *symbol = finalize_symbol_string();
+ entity_t *entity = create_builtin_function(BUILTIN_LIBC, symbol, type);
+ entity->function.actual_name = symbol_table_insert(name);
+ return entity;
}
-int get_builtin_chk_arg_pos(builtin_kind_t kind)
+static entity_t *create_gnu_builtin_chk(const char *name, unsigned chk_arg_pos,
+ type_t *type)
{
- switch (kind) {
- case bk_gnu_builtin___sprintf_chk:
- case bk_gnu_builtin___strcat_chk:
- case bk_gnu_builtin___strcpy_chk:
- case bk_gnu_builtin___vsprintf_chk:
- return 2;
- case bk_gnu_builtin___memcpy_chk:
- case bk_gnu_builtin___memmove_chk:
- case bk_gnu_builtin___memset_chk:
- case bk_gnu_builtin___snprintf_chk:
- case bk_gnu_builtin___strncat_chk:
- case bk_gnu_builtin___strncpy_chk:
- case bk_gnu_builtin___vsnprintf_chk:
- return 3;
- default:
- break;
- }
- return -1;
+ obstack_printf(&symbol_obstack, "__builtin___%s_chk", name);
+ symbol_t *symbol = finalize_symbol_string();
+ entity_t *entity = create_builtin_function(BUILTIN_LIBC_CHECK, symbol, type);
+ entity->function.actual_name = symbol_table_insert(name);
+ entity->function.b.chk_arg_pos = chk_arg_pos;
+ return entity;
}
-entity_t *get_builtin_replacement(const entity_t *builtin_entity)
+void create_gnu_builtins(void)
{
- builtin_kind_t kind = builtin_entity->function.btk;
- const char *replacement = get_builtin_replacement_name(kind);
- if (replacement == NULL)
- return NULL;
+ entity_t *(*b)(builtin_kind_t,const char*,type_t*) = create_gnu_builtin;
+ b(BUILTIN_ALLOCA, "alloca", make_function_1_type(type_void_ptr, type_size_t, DM_NONE));
+ b(BUILTIN_INF, "huge_val", make_function_0_type(type_double, DM_CONST));
+ b(BUILTIN_INF, "huge_valf", make_function_0_type(type_float, DM_CONST));
+ b(BUILTIN_INF, "huge_vall", make_function_0_type(type_long_double, DM_CONST));
+ b(BUILTIN_INF, "inf", make_function_0_type(type_double, DM_CONST));
+ b(BUILTIN_INF, "inff", make_function_0_type(type_float, DM_CONST));
+ b(BUILTIN_INF, "infl", make_function_0_type(type_long_double, DM_CONST));
+ b(BUILTIN_NAN, "nan", make_function_1_type(type_double, type_char_ptr, DM_CONST));
+ b(BUILTIN_NAN, "nanf", make_function_1_type(type_float, type_char_ptr, DM_CONST));
+ b(BUILTIN_NAN, "nanl", make_function_1_type(type_long_double, type_char_ptr, DM_CONST));
+ b(BUILTIN_VA_END, "va_end", make_function_1_type(type_void, type_valist, DM_NONE));
+ b(BUILTIN_EXPECT, "expect", make_function_2_type(type_long, type_long, type_long, DM_CONST));
+ b(BUILTIN_OBJECT_SIZE, "object_size", make_function_2_type(type_size_t, type_void_ptr, type_int, DM_CONST));
+
+ entity_t *(*f)(ir_builtin_kind,const char*,type_t*)
+ = create_gnu_builtin_firm;
+ f(ir_bk_return_address, "return_address", make_function_1_type(type_void_ptr, type_unsigned_int, DM_NONE));
+ f(ir_bk_frame_address, "frame_address", make_function_1_type(type_void_ptr, type_unsigned_int, DM_NONE));
+ f(ir_bk_ffs, "ffs", make_function_1_type(type_int, type_unsigned_int, DM_CONST));
+ f(ir_bk_ffs, "ffsl", make_function_1_type(type_int, type_unsigned_long, DM_CONST));
+ f(ir_bk_ffs, "ffsll", make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
+ f(ir_bk_clz, "clz", make_function_1_type(type_int, type_unsigned_int, DM_CONST));
+ f(ir_bk_clz, "clzl", make_function_1_type(type_int, type_unsigned_long, DM_CONST));
+ f(ir_bk_clz, "clzll", make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
+ f(ir_bk_ctz, "ctz", make_function_1_type(type_int, type_unsigned_int, DM_CONST));
+ f(ir_bk_ctz, "ctzl", make_function_1_type(type_int, type_unsigned_long, DM_CONST));
+ f(ir_bk_ctz, "ctzll", make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
+ f(ir_bk_popcount, "popcount", make_function_1_type(type_int, type_unsigned_int, DM_CONST));
+ f(ir_bk_popcount, "popcountl", make_function_1_type(type_int, type_unsigned_long, DM_CONST));
+ f(ir_bk_popcount, "popcountll", make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
+ f(ir_bk_parity, "parity", make_function_1_type(type_int, type_unsigned_int, DM_CONST));
+ f(ir_bk_parity, "parityl", make_function_1_type(type_int, type_unsigned_long, DM_CONST));
+ f(ir_bk_parity, "parityll", make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
+ f(ir_bk_prefetch, "prefetch", make_function_1_type_variadic(type_float, type_void_ptr, DM_NONE));
+ f(ir_bk_trap, "trap", make_function_type(type_void, 0, NULL, DM_NORETURN));
+
+ entity_t *(*l)(const char*,type_t*) = create_gnu_builtin_libc;
+ l("abort", make_function_type(type_void, 0, NULL, DM_NORETURN));
+ l("abs", make_function_type(type_int, 1, (type_t *[]) { type_int }, DM_CONST));
+ l("labs", make_function_type(type_long, 1, (type_t *[]) { type_long }, DM_CONST));
+ l("llabs", make_function_type(type_long_long, 1, (type_t *[]) { type_long_long }, DM_CONST));
+ l("memcpy", make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t }, DM_NONE));
+ l("memcmp", make_function_type(type_int, 3, (type_t *[]) { type_const_void_ptr, type_const_void_ptr, type_size_t }, DM_PURE));
+ l("memset", make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr, type_int, type_size_t }, DM_NONE));
+ l("memmove", make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t }, DM_NONE));
+ l("strcat", make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
+ l("strncat", make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
+ l("strlen", make_function_type(type_size_t, 1, (type_t *[]) { type_const_char_ptr }, DM_PURE));
+ l("strcmp", make_function_type(type_int, 2, (type_t *[]) { type_const_char_ptr, type_const_char_ptr }, DM_PURE));
+ l("strcpy", make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
+ l("stpcpy", make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
+ l("strncpy", make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
+ l("exit", make_function_type(type_void, 1, (type_t *[]) { type_int }, DM_NORETURN));
+ l("malloc", make_function_type(type_void_ptr, 1, (type_t *[]) { type_size_t }, DM_MALLOC));
+
+ entity_t *(*c)(const char*,unsigned,type_t*) = create_gnu_builtin_chk;
+ c("memcpy", 3, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t, type_size_t}, DM_NONE));
+ c("memset", 3, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr, type_int, type_size_t, type_size_t }, DM_NONE));
+ c("memmove", 3, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t, type_size_t }, DM_NONE));
+ c("strcat", 2, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
+ c("strncat", 3, make_function_type(type_char_ptr, 4, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t, type_size_t }, DM_NONE));
+ c("strcpy", 2, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
+ c("stpcpy", 2, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
+ c("strncpy", 3, make_function_type(type_char_ptr, 4, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t, type_size_t }, DM_NONE));
- symbol_t *const symbol = symbol_table_insert(replacement);
- entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol);
- entity->base.source_position = builtin_source_position;
- entity->declaration.storage_class = STORAGE_CLASS_EXTERN;
- entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
- entity->declaration.type = builtin_entity->declaration.type;
- entity->declaration.implicit = true;
- entity->declaration.modifiers = builtin_entity->declaration.modifiers;
+ /* TODO: gcc has a LONG list of builtin functions (nearly everything from
+ * C89-C99 and others. Complete this */
+}
+static entity_t *create_intrinsic_firm(ir_builtin_kind kind, const char *name,
+ type_t *type)
+{
+ symbol_t *symbol = symbol_table_insert(name);
+ entity_t *entity = create_builtin_function(BUILTIN_FIRM, symbol, type);
+ entity->function.b.firm_builtin_kind = kind;
return entity;
}
-void create_microsoft_intrinsics(void)
+static entity_t *create_intrinsic(builtin_kind_t kind, const char *name,
+ type_t *type)
{
-#define MS_BUILTIN(a, b) create_builtin_function(bk_ms##a, #a, b)
+ symbol_t *symbol = symbol_table_insert(name);
+ entity_t *entity = create_builtin_function(kind, symbol, type);
+ return entity;
+}
+void create_microsoft_intrinsics(void)
+{
+ entity_t *(*i)(builtin_kind_t,const char*,type_t*) = create_intrinsic;
+ entity_t *(*f)(ir_builtin_kind,const char*,type_t*) = create_intrinsic_firm;
/* 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));
+ i(BUILTIN_ROTL, "_rotl", make_function_2_type(type_unsigned_int, type_unsigned_int, type_int, DM_CONST));
+ i(BUILTIN_ROTL, "_rotl64", make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int, DM_CONST));
+ i(BUILTIN_ROTR, "_rotr", make_function_2_type(type_unsigned_int, type_unsigned_int, type_int, DM_CONST));
+ i(BUILTIN_ROTR, "_rotr64", make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int, DM_CONST));
+
+ f(ir_bk_bswap, "_byteswap_ushort", make_function_1_type(type_unsigned_short, type_unsigned_short, DM_CONST));
+ f(ir_bk_bswap, "_byteswap_ulong", make_function_1_type(type_unsigned_long, type_unsigned_long, DM_CONST));
+ f(ir_bk_bswap, "_byteswap_uint64", make_function_1_type(type_unsigned_int64, type_unsigned_int64, DM_CONST));
+
+ f(ir_bk_debugbreak, "__debugbreak", make_function_0_type(type_void, DM_NONE));
+ f(ir_bk_return_address, "_ReturnAddress", make_function_0_type(type_void_ptr, DM_NONE));
+ f(ir_bk_popcount, "__popcount", make_function_1_type(type_unsigned_int, type_unsigned_int, DM_CONST));
/* 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_type(type_void, 0, NULL, DM_NORETURN));
- 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));
-#undef MS_BUILTIN
+ f(ir_bk_inport, "__inbyte", make_function_1_type(type_unsigned_char, type_unsigned_short, DM_NONE));
+ f(ir_bk_inport, "__inword", make_function_1_type(type_unsigned_short, type_unsigned_short, DM_NONE));
+ f(ir_bk_inport, "__indword", make_function_1_type(type_unsigned_long, type_unsigned_short, DM_NONE));
+ f(ir_bk_outport, "__outbyte", make_function_2_type(type_void, type_unsigned_short, type_unsigned_char, DM_NONE));
+ f(ir_bk_outport, "__outword", make_function_2_type(type_void, type_unsigned_short, type_unsigned_short, DM_NONE));
+ f(ir_bk_outport, "__outdword", make_function_2_type(type_void, type_unsigned_short, type_unsigned_long, DM_NONE));
+ f(ir_bk_trap, "__ud2", make_function_type(type_void, 0, NULL, DM_NORETURN));
}