X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Flower%2Flower_intrinsics.h;h=77a6dbee55544deb0583217f4b18400f1903fd1d;hb=e7228c94cf04aec3a231acf138e9e4cac5b24447;hp=f800cad1c39901ef9c80134019f2f83a943ed8a4;hpb=7dc955dcd058f1d0b67bfc17db4a818e98fa2a01;p=libfirm diff --git a/ir/lower/lower_intrinsics.h b/ir/lower/lower_intrinsics.h index f800cad1c..77a6dbee5 100644 --- a/ir/lower/lower_intrinsics.h +++ b/ir/lower/lower_intrinsics.h @@ -24,36 +24,62 @@ /** * An intrinsic mapper function. * - * @param call the Call node + * @param node the IR-node that will be mapped * @param ctx a context * * @return non-zero if the call was mapped */ -typedef int (*i_mapper_func)(ir_node *call, void *ctx); +typedef int (*i_mapper_func)(ir_node *node, void *ctx); + +enum ikind { + INTRINSIC_CALL = 0, /**< the record represents an intrinsic call */ + INTRINSIC_INSTR /**< the record represents an intrinsic instruction */ +}; /** * An intrinsic record. */ -typedef struct _i_record { - entity *i_ent; /**< the entity representing an intrinsic */ +typedef struct _i_call_record { + enum ikind kind; /**< must be INTRINSIC_CALL */ + entity *i_ent; /**< the entity representing an intrinsic call */ + i_mapper_func i_mapper; /**< the mapper function to call */ + void *ctx; /**< mapper context */ + void *link; /**< used in the construction algorithm, must be NULL */ +} i_call_record; + +/** + * An intrinsic instruction record. + */ +typedef struct _i_instr_record { + enum ikind kind; /**< must be INTRINSIC_INSTR */ + ir_op *op; /**< the opcode that must be mapped. */ i_mapper_func i_mapper; /**< the mapper function to call */ void *ctx; /**< mapper context */ + void *link; /**< used in the construction algorithm, must be NULL */ +} i_instr_record; + +/** + * An intrinsic record. + */ +typedef union _i_record { + i_call_record i_call; + i_instr_record i_instr; } i_record; /** - * Go through all graphs and map calls to intrinsic functions. + * Go through all graphs and map calls to intrinsic functions and instructions. * - * Every call is reported to its mapper function, which is responsible for - * rebuilding the graph. + * Every call or instruction is reported to its mapper function, + * which is responsible for rebuilding the graph. * * current_ir_graph is always set. * * @param list an array of intrinsic map records * @param length the length of the array * - * @return number of found intrinsic calls + * @return number of found intrinsics. */ -unsigned lower_intrinsic_calls(const i_record *list, int length); +unsigned lower_intrinsics(i_record *list, int length); /** * A mapper for the integer absolute value: inttype abs(inttype v). @@ -71,4 +97,73 @@ int i_mapper_Abs(ir_node *call, void *ctx); */ int i_mapper_Alloca(ir_node *call, void *ctx); +/** + * A runtime routine description. + */ +typedef struct _runtime_rt { + entity *ent; /**< The entity representing the runtime routine. */ + ir_mode *mode; /**< The operation mode of the mapped instruction. */ + long mem_proj_nr; /**< if >= 0, create a memory ProjM() */ + long exc_proj_nr; /**< if >= 0, create a exception ProjX() */ + long exc_mem_proj_nr; /**< if >= 0, create a exception memory ProjM() */ + long res_proj_nr; /**< if >= 0, first result projection number */ +} runtime_rt; + +/** + * A mapper for mapping unsupported instructions to runtime calls. + * Maps a op(arg_0, ..., arg_n) into a call to a runtime function + * rt(arg_0, ..., arg_n). + * + * The mapping is only done, if the modes of all arguments matches the + * modes of rt's argument. + * Further, if op has a memory input, the generated Call uses it, else + * it gets a NoMem. + * The pinned state of the Call will be set to the pinned state of op. + * + * Note that i_mapper_RuntimeCall() must be used with a i_instr_record. + * + * @return 1 if an op was mapped, 0 else + * + * Some examples: + * + * - Maps Div nodes to calls to rt_Div(): + @code + runtime_rt rt_Div = { + ent("int rt_Div(int, int)"), + mode_T, + pn_Div_M, + pn_Div_X_except, + pn_Div_M, + pn_Div_res + }; + i_instr_record map_Div = { + INTRINSIC_INSTR, + op_Div, + i_mapper_RuntimeCall, + &rt_Div, + NULL + }; + @endcode + * + * - Maps ConvD(F) to calls to rt_Float2Div(): + @code + runtime_rt rt_Float2Double = { + ent("double rt_Float2Div(float)"), + get_type_mode("double"), + -1, + -1, + -1, + -1 + }; + i_instr_record map_Float2Double = { + INTRINSIC_INSTR, + op_Conv, + i_mapper_RuntimeCall, + &rt_Float2Double, + NULL + }; + @endcode + */ +int i_mapper_RuntimeCall(ir_node *node, runtime_rt *rt); + #endif /* _LOWER_INTRINSICS_H_ */