Commit c433f42a authored by Michael Beck's avatar Michael Beck
Browse files

- implemented Builtin node to represent builtins ...

[r24785]
parent dca5f038
......@@ -210,11 +210,18 @@ typedef enum {
heap_alloc /**< Alloc allocates the object on the heap. */
} ir_where_alloc;
/** A input/output constraint attribute */
/** A input/output constraint attribute. */
typedef struct {
unsigned pos; /**< The inputs/output position for this constraint. */
ident *constraint; /**< The constraint for this input/output. */
ir_mode *mode; /**< The mode of the constraint. */
} ir_asm_constraint;
/** Supported libFirm builtins. */
typedef enum {
ir_bk_return_address, /**< GCC __builtin_return_address() */
ir_bk_frame_addess, /**< GCC __builtin_frame_address() */
ir_bk_prefetch, /**< GCC __builtin_prefetch() */
} ir_builtin_kind;
#endif
......@@ -271,7 +271,9 @@
* ir_node *new_Sel (ir_node *store, ir_node *objptr, int arity,
* ir_node **in, ir_entity *ent);
* ir_node *new_Call (ir_node *store, ir_node *callee, int arity,
* ir_node **in, type_method *type);
* ir_node **in, type_method *type);
* ir_node *new_Builtin(ir_node *store, ir_builtin_kind kind, int arity,
* ir_node **in, type_method *type);
* ir_node *new_Add (ir_node *op1, ir_node *op2, ir_mode *mode);
* ir_node *new_Sub (ir_node *op1, ir_node *op2, ir_mode *mode);
* ir_node *new_Minus (ir_node *op, ir_mode *mode);
......@@ -658,8 +660,30 @@
* A tuple containing the eventually changed store and the procedure
* results.
* Attributes:
* attr.call Contains the type information for the procedure.
* attr.call Contains the attributes for the procedure.
*
* ir_node *new_Builtin(ir_node *store, ir_builtin_kind kind, int arity, ir_node **in,
* -----------------------------------------------------------------------------------
* type_method *type)
* ------------------
*
* Creates a builtin call.
*
* Parameters
* *store The actual store.
* kind Describes the called builtin.
* arity The number of procedure parameters.
* **in An array with the pointers to the parameters.
* The constructor copies this array.
* *type Type information of the procedure called.
*
* Inputs:
* The store, the kind and the parameters.
* Output:
* A tuple containing the eventually changed store and the procedure
* results.
* Attributes:
* attr.builtin Contains the attributes for the called builtin.
*
* ir_node *new_Add (ir_node *op1, ir_node *op2, ir_mode *mode)
* ------------------------------------------------------------
......@@ -1422,7 +1446,7 @@ ir_node *new_rd_Sel (dbg_info *db, ir_graph *irg, ir_node *block, ir_node *st
/** Constructor for a Call node.
*
* Represents all kinds of method and function calls.
* Represents all kinds of method and function calls.
*
* @param *db A pointer for debug information.
* @param *irg The IR graph the node belongs to.
......@@ -1436,6 +1460,22 @@ ir_node *new_rd_Sel (dbg_info *db, ir_graph *irg, ir_node *block, ir_node *st
ir_node *new_rd_Call (dbg_info *db, ir_graph *irg, ir_node *block, ir_node *store,
ir_node *callee, int arity, ir_node *in[], ir_type *tp);
/** Constructor for a ´Builtin node.
*
* Represents a call of a backend-specific builtin..
*
* @param *db A pointer for debug information.
* @param *irg The IR graph the node belongs to.
* @param *block The IR block the node belongs to.
* @param *store The current memory state.
* @param kind The kind of the called builtin.
* @param arity The number of procedure parameters.
* @param *in[] An array with the procedure parameters. The constructor copies this array.
* @param *tp Type information of the procedure called.
*/
ir_node *new_rd_Builtin(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *store,
ir_builtin_kind kind, int arity, ir_node *in[], ir_type *tp);
/** Constructor for a Add node.
*
* @param *db A pointer for debug information.
......@@ -2250,7 +2290,7 @@ ir_node *new_r_Sel (ir_graph *irg, ir_node *block, ir_node *store,
/** Constructor for a Call node.
*
* Represents all kinds of method and function calls.
* Represents all kinds of method and function calls.
*
* @param *irg The IR graph the node belongs to.
* @param *block The IR block the node belongs to.
......@@ -2261,8 +2301,22 @@ ir_node *new_r_Sel (ir_graph *irg, ir_node *block, ir_node *store,
* @param *tp Type information of the procedure called.
*/
ir_node *new_r_Call (ir_graph *irg, ir_node *block, ir_node *store,
ir_node *callee, int arity, ir_node *in[],
ir_type *tp);
ir_node *callee, int arity, ir_node *in[], ir_type *tp);
/** Constructor for a Builtin node.
*
* Represents a call of a backend-specific builtin..
*
* @param *irg The IR graph the node belongs to.
* @param *block The IR block the node belongs to.
* @param *store The actual store.
* @param kind The kind of the called builtin.
* @param arity The number of procedure parameters.
* @param *in[] An array with the pointers to the parameters. The constructor copies this array.
* @param *tp Type information of the procedure called.
*/
ir_node *new_r_Builtin(ir_graph *irg, ir_node *block, ir_node *store,
ir_builtin_kind kind, int arity, ir_node *in[], ir_type *tp);
/** Constructor for a Add node.
*
......@@ -3073,8 +3127,8 @@ ir_node *new_d_Sel (dbg_info *db, ir_node *store, ir_node *objptr, int arity,
/** Constructor for a Call node.
*
* Represents all kinds of method and function calls.
* Adds the node to the block in current_ir_block.
* Represents all kinds of method and function calls.
* Adds the node to the block in current_ir_block.
*
* @param *db A pointer for debug information.
* @param *store The actual store.
......@@ -3084,7 +3138,22 @@ ir_node *new_d_Sel (dbg_info *db, ir_node *store, ir_node *objptr, int arity,
* @param *tp Type information of the procedure called.
*/
ir_node *new_d_Call (dbg_info *db, ir_node *store, ir_node *callee, int arity, ir_node *in[],
ir_type *tp);
ir_type *tp);
/** Constructor for a Builtin node.
*
* Represents a call of a backend-specific builtin..
* Adds the node to the block in current_ir_block.
*
* @param *db A pointer for debug information.
* @param *store The actual store.
* @param kind The kind of the called builtin.
* @param arity The number of procedure parameters.
* @param *in[] An array with the pointers to the parameters. The constructor copies this array.
* @param *tp Type information of the procedure called.
*/
ir_node *new_d_Builtin(dbg_info *db, ir_node *store, ir_builtin_kind kind, int arity, ir_node *in[],
ir_type *tp);
/** Constructor for a Add node.
*
......@@ -3884,8 +3953,8 @@ ir_node *new_Sel (ir_node *store, ir_node *objptr, int arity, ir_node *in[],
/** Constructor for a Call node.
*
* Adds the node to the block in current_ir_block.
* Represents all kinds of method and function calls.
* Adds the node to the block in current_ir_block.
* Represents all kinds of method and function calls.
*
* @param *store The actual store.
* @param *callee A pointer to the called procedure.
......@@ -3896,6 +3965,20 @@ ir_node *new_Sel (ir_node *store, ir_node *objptr, int arity, ir_node *in[],
ir_node *new_Call (ir_node *store, ir_node *callee, int arity, ir_node *in[],
ir_type *tp);
/** Constructor for a Builtin node.
*
* Represents a call of a backend-specific builtin..
* Represents all kinds of method and function calls.
*
* @param *store The actual store.
* @param kind The kind of the called builtin.
* @param arity The number of procedure parameters.
* @param *in[] An array with the pointers to the parameters. The constructor copies this array.
* @param *tp Type information of the procedure called.
*/
ir_node *new_Builtin(ir_node *store, ir_builtin_kind kind, int arity, ir_node *in[],
ir_type *tp);
/** Constructor for a CallBegin node.
*
* CallBegin represents control flow depending of the pointer value
......
......@@ -620,8 +620,6 @@ void set_Call_param(ir_node *node, int pos, ir_node *param);
ir_type *get_Call_type(ir_node *node);
/** Sets the type of a call. */
void set_Call_type(ir_node *node, ir_type *tp);
/** Gets the arity of a call. Identical to get_Call_n_params(). */
int get_Call_arity(const ir_node *node);
/**
* Returns non-zero if a Call is surely a self-recursive Call.
......@@ -656,6 +654,33 @@ ir_entity *get_Call_callee(const ir_node *node, int pos);
void set_Call_callee_arr(ir_node *node, const int n, ir_entity **arr);
void remove_Call_callee_arr(ir_node *node);
/**
* Projection numbers for result of Builtin node: use for Proj nodes!
*/
typedef enum {
pn_Builtin_M = pn_Generic_M_regular, /**< The memory result. */
pn_Builtin_T_result = pn_Generic_other, /**< The tuple containing all (0, 1, 2, ...) results. */
pn_Builtin_max /**< number of projections from a Builtin */
} pn_Builtin; /* Projection numbers for Builtin. */
ir_node *get_Builtin_mem(const ir_node *node);
void set_Builtin_mem(ir_node *node, ir_node *mem);
ir_builtin_kind get_Builtin_kind(const ir_node *node);
void set_Builtin_kind(ir_node *node, ir_builtin_kind kind);
ir_node **get_Builtin_param_arr(ir_node *node);
/** Gets the number of parameters of a Builtin. */
int get_Builtin_n_params(const ir_node *node);
/** Gets the Builtin parameter at position pos. */
ir_node *get_Builtin_param(const ir_node *node, int pos);
/** Sets the Builtin parameter at position pos. */
void set_Builtin_param(ir_node *node, int pos, ir_node *param);
/** Gets the type of a builtin. */
ir_type *get_Builtin_type(ir_node *node);
/** Sets the type of a Builtin. */
void set_Builtin_type(ir_node *node, ir_type *tp);
/** Returns a human readable string for the ir_builtin_kind. */
const char *get_builtin_kind_name(ir_builtin_kind kind);
ir_node *get_CallBegin_ptr(const ir_node *node);
void set_CallBegin_ptr(ir_node *node, ir_node *ptr);
ir_node *get_CallBegin_call(const ir_node *node);
......@@ -1237,6 +1262,8 @@ int is_Unknown(const ir_node *node);
int is_Return(const ir_node *node);
/** Returns true if node is a Call node. */
int is_Call(const ir_node *node);
/** Returns true if node is a Builtin node. */
int is_Builtin(const ir_node *node);
/** Returns true if node is a CallBegin node. */
int is_CallBegin(const ir_node *node);
/** Returns true if node is a Sel node. */
......
......@@ -95,7 +95,7 @@ typedef enum {
iro_NoMem, iro_Mux, iro_Min, iro_Max, iro_CopyB,
iro_InstOf, iro_Raise, iro_Bound,
iro_Pin,
iro_ASM,
iro_ASM, iro_Builtin,
iro_Anchor,
/* first not middleend node number */
iro_Last = iro_Anchor,
......@@ -197,6 +197,7 @@ extern ir_op *op_Bound; ir_op *get_op_Bound (void);
extern ir_op *op_Pin; ir_op *get_op_Pin (void);
extern ir_op *op_ASM; ir_op *get_op_ASM (void);
extern ir_op *op_Builtin; ir_op *get_op_Builtin (void);
extern ir_op *op_Anchor; ir_op *get_op_Anchor (void);
......
......@@ -1601,8 +1601,6 @@ static inline void set_transformer(ir_op *op, be_transform_func arm_transform_fu
* Enters all transform functions into the generic pointer
*/
static void arm_register_transformers(void) {
ir_op *op_Max, *op_Min, *op_Mulh;
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
......@@ -1612,6 +1610,7 @@ static void arm_register_transformers(void) {
GEN(Add);
GEN(Sub);
GEN(Mul);
BAD(Mulh); /* unsupported yet */
GEN(And);
GEN(Or);
GEN(Eor);
......@@ -1661,6 +1660,9 @@ static void arm_register_transformers(void) {
BAD(EndReg);
BAD(EndExcept);
/* handle builtins */
BAD(Builtin);
/* handle generic backend nodes */
GEN(be_FrameAddr);
//GEN(be_Call);
......@@ -1672,16 +1674,6 @@ static void arm_register_transformers(void) {
/* set the register for all Unknown nodes */
GEN(Unknown);
op_Max = get_op_Max();
if (op_Max)
BAD(Max); /* unsupported yet */
op_Min = get_op_Min();
if (op_Min)
BAD(Min); /* unsupported yet */
op_Mulh = get_op_Mulh();
if (op_Mulh)
BAD(Mulh); /* unsupported yet */
#undef GEN
#undef BAD
}
......
......@@ -4790,8 +4790,6 @@ static ir_node *gen_Proj(ir_node *node)
*/
static void register_transformers(void)
{
ir_op *op_Mulh;
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
......@@ -4801,6 +4799,7 @@ static void register_transformers(void)
GEN(Add);
GEN(Sub);
GEN(Mul);
GEN(Mulh);
GEN(And);
GEN(Or);
GEN(Eor);
......@@ -4868,6 +4867,9 @@ static void register_transformers(void)
BAD(EndReg);
BAD(EndExcept);
/* handle builtins */
BAD(Builtin);
/* handle generic backend nodes */
GEN(be_FrameAddr);
GEN(be_Call);
......@@ -4877,10 +4879,6 @@ static void register_transformers(void)
GEN(be_SubSP);
GEN(be_Copy);
op_Mulh = get_op_Mulh();
if (op_Mulh)
GEN(Mulh);
#undef GEN
#undef BAD
}
......
......@@ -1245,8 +1245,6 @@ static ir_node *bad_transform(ppc32_transform_env_t *env) {
* Enters all transform functions into the generic pointer
*/
void ppc32_register_transformers(void) {
ir_op *op_Max, *op_Min, *op_Mulh;
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
......@@ -1256,6 +1254,7 @@ void ppc32_register_transformers(void) {
FIRM_OP(Add);
FIRM_OP(Mul);
FIRM_OP(Mulh);
FIRM_OP(And);
FIRM_OP(Or);
FIRM_OP(Eor);
......@@ -1315,16 +1314,11 @@ void ppc32_register_transformers(void) {
BAD(EndReg);
BAD(EndExcept);
/* handle builtins */
BAD(Builtin);
/* handle generic backend nodes */
FIRM_OP(be_FrameAddr);
op_Mulh = get_op_Mulh();
if (op_Mulh)
FIRM_OP(Mulh);
op_Max = get_op_Max();
if (op_Max)
BAD(Max);
op_Min = get_op_Min();
if (op_Min)
BAD(Min);
}
typedef ir_node *(transform_func)(ppc32_transform_env_t *env);
......
......@@ -479,7 +479,7 @@ new_bd_Call(dbg_info *db, ir_node *block, ir_node *store,
int r_arity;
ir_graph *irg = current_ir_graph;
r_arity = arity+2;
r_arity = arity + 2;
NEW_ARR_A(ir_node *, r_in, r_arity);
r_in[0] = store;
r_in[1] = callee;
......@@ -496,6 +496,30 @@ new_bd_Call(dbg_info *db, ir_node *block, ir_node *store,
return res;
} /* new_bd_Call */
static ir_node *
new_bd_Builtin(dbg_info *db, ir_node *block, ir_node *store,
ir_builtin_kind kind, int arity, ir_node **in, ir_type *tp) {
ir_node **r_in;
ir_node *res;
int r_arity;
ir_graph *irg = current_ir_graph;
r_arity = arity + 1;
NEW_ARR_A(ir_node *, r_in, r_arity);
r_in[0] = store;
memcpy(&r_in[1], in, sizeof(ir_node *) * arity);
res = new_ir_node(db, irg, block, op_Builtin, mode_T, r_arity, r_in);
assert((get_unknown_type() == tp) || is_Method_type(tp));
res->attr.builtin.exc.pin_state = op_pin_state_pinned;
res->attr.builtin.kind = kind;
res->attr.builtin.builtin_tp = tp;
res = optimize_node(res);
IRN_VRFY_IRG(res, irg);
return res;
} /* new_bd_Buildin */
static ir_node *
new_bd_Return(dbg_info *db, ir_node *block,
ir_node *store, int arity, ir_node **in) {
......@@ -1125,6 +1149,19 @@ new_rd_Call(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *store,
return res;
} /* new_rd_Call */
ir_node *
new_rd_Builtin(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *store,
ir_builtin_kind kind, int arity, ir_node **in, ir_type *tp) {
ir_node *res;
ir_graph *rem = current_ir_graph;
current_ir_graph = irg;
res = new_bd_Builtin(db, block, store, kind, arity, in, tp);
current_ir_graph = rem;
return res;
} /* new_rd_Builtin */
ir_node *
new_rd_Return(dbg_info *db, ir_graph *irg, ir_node *block,
ir_node *store, int arity, ir_node **in) {
......@@ -1509,6 +1546,11 @@ ir_node *new_r_Call(ir_graph *irg, ir_node *block, ir_node *store,
ir_type *tp) {
return new_rd_Call(NULL, irg, block, store, callee, arity, in, tp);
}
ir_node *new_r_Builtin(ir_graph *irg, ir_node *block, ir_node *store,
ir_builtin_kind kind, int arity, ir_node **in,
ir_type *tp) {
return new_rd_Builtin(NULL, irg, block, store, kind, arity, in, tp);
}
#ifdef USE_ORIGINAL
ir_node *new_r_Add(ir_graph *irg, ir_node *block,
ir_node *op1, ir_node *op2, ir_mode *mode) {
......@@ -2497,6 +2539,12 @@ new_d_Call(dbg_info *db, ir_node *store, ir_node *callee, int arity, ir_node **i
return res;
} /* new_d_Call */
ir_node *
new_d_Builtin(dbg_info *db, ir_node *store, ir_builtin_kind kind, int arity, ir_node **in,
ir_type *tp) {
return new_bd_Builtin(db, current_ir_graph->current_block, store, kind, arity, in, tp);
} /* new_d_Builtin */
ir_node *
new_d_Return(dbg_info *db, ir_node* store, int arity, ir_node **in) {
return new_bd_Return(db, current_ir_graph->current_block,
......@@ -2943,6 +2991,10 @@ ir_node *new_Call(ir_node *store, ir_node *callee, int arity, ir_node **in,
ir_type *tp) {
return new_d_Call(NULL, store, callee, arity, in, tp);
}
ir_node *new_Builtin(ir_node *store, ir_builtin_kind kind, int arity, ir_node **in,
ir_type *tp) {
return new_d_Builtin(NULL, store, kind, arity, in, tp);
}
#ifdef USE_ORIGINAL
ir_node *new_Add(ir_node *op1, ir_node *op2, ir_mode *mode) {
return new_d_Add(NULL, op1, op2, mode);
......
......@@ -828,6 +828,9 @@ int dump_node_opcode(FILE *F, ir_node *n)
case iro_DivMod:
fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_DivMod_resmode(n), &bad));
break;
case iro_Builtin:
fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
break;
default:
default_case:
......
......@@ -48,7 +48,7 @@
/* some constants fixing the positions of nodes predecessors
in the in array */
#define CALL_PARAM_OFFSET 2
#define FUNCCALL_PARAM_OFFSET 1
#define BUILDIN_PARAM_OFFSET 1
#define SEL_INDEX_OFFSET 2
#define RETURN_RESULT_OFFSET 1 /* mem is not a result */
#define END_KEEPALIVE_OFFSET 0
......@@ -1343,18 +1343,6 @@ get_Call_n_params(const ir_node *node) {
return (get_irn_arity(node) - CALL_PARAM_OFFSET);
}
int
get_Call_arity(const ir_node *node) {
assert(is_Call(node));
return get_Call_n_params(node);
}
/* void
set_Call_arity(ir_node *node, ir_node *arity) {
assert(is_Call(node));
}
*/
ir_node *
get_Call_param(const ir_node *node, int pos) {
assert(is_Call(node));
......@@ -1380,6 +1368,80 @@ set_Call_type(ir_node *node, ir_type *tp) {
node->attr.call.cld_tp = tp;
}
ir_node *
get_Builtin_mem(const ir_node *node) {
assert(is_Builtin(node));
return get_irn_n(node, 0);
}
void
set_Builin_mem(ir_node *node, ir_node *mem) {
assert(is_Builtin(node));
set_irn_n(node, 0, mem);
}
ir_builtin_kind
get_Builtin_kind(const ir_node *node) {
assert(is_Builtin(node));
return node->attr.builtin.kind;
}
void
set_Builtin_kind(ir_node *node, ir_builtin_kind kind) {
assert(is_Builtin(node));
node->attr.builtin.kind = kind;
}
ir_node **
get_Builtin_param_arr(ir_node *node) {
assert(is_Builtin(node));
return &get_irn_in(node)[BUILDIN_PARAM_OFFSET + 1];
}
int
get_Builtin_n_params(const ir_node *node) {
assert(is_Builtin(node));
return (get_irn_arity(node) - BUILDIN_PARAM_OFFSET);
}
ir_node *
get_Builtin_param(const ir_node *node, int pos) {
assert(is_Builtin(node));
return get_irn_n(node, pos + BUILDIN_PARAM_OFFSET);
}
void
set_Builtin_param(ir_node *node, int pos, ir_node *param) {
assert(is_Builtin(node));
set_irn_n(node, pos + BUILDIN_PARAM_OFFSET, param);
}
ir_type *
get_Builtin_type(ir_node *node) {
assert(is_Builtin(node));
return node->attr.builtin.builtin_tp = skip_tid(node->attr.builtin.builtin_tp);
}
void
set_Builtin_type(ir_node *node, ir_type *tp) {
assert(is_Builtin(node));
assert((get_unknown_type() == tp) || is_Method_type(tp));
node->attr.builtin.builtin_tp = tp;
}
/* Returns a human readable string for the ir_builtin_kind. */
const char *get_builtin_kind_name(ir_builtin_kind kind) {
#define X(a) case a: return #a + 6;
switch (kind) {
X(ir_bk_return_address);
X(ir_bk_frame_addess);
X(ir_bk_prefetch);
}
return "<unknown>";
#undef X
}
int Call_has_callees(const ir_node *node) {
assert(is_Call(node));
return ((get_irg_callee_info_state(get_irn_irg(node)) != irg_callee_info_none) &&
......@@ -2771,6 +2833,12 @@ int
return _is_Call(node);
}
/* returns true if node is a Builtin node. */
int
(is_Builtin)(const ir_node *node) {
return _is_Builtin(node);
}
/* returns true if node is a CallBegin node. */
int
(is_CallBegin)(const ir_node *node) {
......
......@@ -627,6 +627,12 @@ _is_Call(const ir_node *node) {
return (_get_irn_op(node) == op_Call);
}
static inline int
_is_Builtin(const ir_node *node) {
assert(node);
return (_get_irn_op(node) == op_Builtin);
}
static inline int
_is_CallBegin(const ir_node *node) {
assert(node);
......@@ -1037,6 +1043,7 @@ _is_arg_Proj(const ir_node *node) {
#define is_Unknown(node) _is_Unknown(node)
#define is_Return(node) _is_Return(node)
#define is_Call(node) _is_Call(node)
#define is_Builtin(node) _is_Builtin(node)
#define is_CallBegin(node) _is_CallBegin(node)