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
* 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);
* 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)
* ------------------------------------------------------------
/** 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.
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.
/** 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.
* @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.
*
/** 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.
* @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.
*
/** 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.
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
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.
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);
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. */
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,
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);
* 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();
GEN(Add);
GEN(Sub);
GEN(Mul);
+ BAD(Mulh); /* unsupported yet */
GEN(And);
GEN(Or);
GEN(Eor);
BAD(EndReg);
BAD(EndExcept);
+ /* handle builtins */
+ BAD(Builtin);
+
/* handle generic backend nodes */
GEN(be_FrameAddr);
//GEN(be_Call);
/* 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
}
*/
static void register_transformers(void)
{
- ir_op *op_Mulh;
-
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
GEN(Add);
GEN(Sub);
GEN(Mul);
+ GEN(Mulh);
GEN(And);
GEN(Or);
GEN(Eor);
BAD(EndReg);
BAD(EndExcept);
+ /* handle builtins */
+ BAD(Builtin);
+
/* handle generic backend nodes */
GEN(be_FrameAddr);
GEN(be_Call);
GEN(be_SubSP);
GEN(be_Copy);
- op_Mulh = get_op_Mulh();
- if (op_Mulh)
- GEN(Mulh);
-
#undef GEN
#undef BAD
}
* 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();
FIRM_OP(Add);
FIRM_OP(Mul);
+ FIRM_OP(Mulh);
FIRM_OP(And);
FIRM_OP(Or);
FIRM_OP(Eor);
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);
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;
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) {
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) {
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) {
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,
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);
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:
/* 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
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));
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) &&
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) {
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);
#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)
#define is_Sel(node) _is_Sel(node)
#define is_Mul(node) _is_Mul(node)
ir_op *op_SymConst; ir_op *get_op_SymConst (void) { return op_SymConst; }
ir_op *op_Call; ir_op *get_op_Call (void) { return op_Call; }
+ir_op *op_Builtin; ir_op *get_op_Builtin (void) { return op_Builtin; }
ir_op *op_Add; ir_op *get_op_Add (void) { return op_Add; }
ir_op *op_Sub; ir_op *get_op_Sub (void) { return op_Sub; }
ir_op *op_Minus; ir_op *get_op_Minus (void) { return op_Minus; }
op_Pin = new_ir_op(iro_Pin, "Pin", op_pin_state_pinned, H, oparity_unary, -1, 0, NULL);
op_ASM = new_ir_op(iro_ASM, "ASM", op_pin_state_mem_pinned, K|M, oparity_variable, -1, sizeof(asm_attr), NULL);
+ op_Builtin = new_ir_op(iro_Builtin, "Builtin", op_pin_state_mem_pinned, M, oparity_variable, -1, sizeof(builtin_attr), NULL);
op_Anchor = new_ir_op(iro_Anchor, "Anchor", op_pin_state_pinned, N|NB, oparity_variable, -1, 0, NULL);
ir_entity ** callee_arr; /**< result of callee analysis */
} call_attr;
+/** Builtin attributes. */
+typedef struct {
+ except_attr exc; /**< the exception attribute. MUST be the first one. */
+ ir_builtin_kind kind; /**< kind of the called builtin procedure */
+ ir_type *builtin_tp; /**< type of called builtin procedure */
+} builtin_attr;
+
/** Alloc attributes. */
typedef struct {
except_attr exc; /**< the exception attribute. MUST be the first one. */
const_attr con; /**< For Const: contains the value of the constant and a type */
symconst_attr symc; /**< For SymConst. */
sel_attr sel; /**< For Sel. */
- call_attr call; /**< For Call: pointer to the type of the method to call */
+ call_attr call; /**< For Call. */
+ builtin_attr builtin; /**< For Builtin. */
callbegin_attr callbegin; /**< For CallBegin. */
alloc_attr alloc; /**< For Alloc. */
free_attr free; /**< For Free. */