static int MPIDU_Segment_contig_unpack_external32_to_buf(DLOOP_Offset *blocks_p, DLOOP_Type el_type, DLOOP_Offset rel_off, void *bufp, void *v_paramp) { int src_el_size, dest_el_size; struct MPIDU_Segment_piece_params *paramp = v_paramp; MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_SEGMENT_CONTIG_UNPACK_EXTERNAL32_TO_BUF); MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_SEGMENT_CONTIG_UNPACK_EXTERNAL32_TO_BUF); src_el_size = MPIDU_Datatype_get_basic_size(el_type); dest_el_size = MPIDI_Datatype_get_basic_size_external32(el_type); MPIR_Assert(dest_el_size); /* * h = handle value * do = datatype buffer offset * dp = datatype buffer pointer * up = unpack buffer pointer (current location, incremented as we go) * sz = size of datatype (guess we could get this from handle value if * we wanted...) */ #ifdef MPID_SP_VERBOSE dbg_printf("\t[contig unpack [external32]: do=%d, dp=%x, up=%x, " "src_el_sz=%d, dest_el_sz=%d, blksz=%d]\n", rel_off, (unsigned) bufp, (unsigned) paramp->u.unpack.unpack_buffer, src_el_size, dest_el_size, (int) *blocks_p); #endif /* TODO: DEAL WITH CASE WHERE ALL DATA DOESN'T FIT! */ if ((src_el_size == dest_el_size) && (src_el_size == 1)) { MPIR_Memcpy(((char *)bufp) + rel_off, paramp->u.unpack.unpack_buffer, *blocks_p); } else if (is_float_type(el_type)) { external32_float_convert(((char *) bufp) + rel_off, paramp->u.unpack.unpack_buffer, dest_el_size, src_el_size, *blocks_p); } else { external32_basic_convert(((char *) bufp) + rel_off, paramp->u.unpack.unpack_buffer, dest_el_size, src_el_size, *blocks_p); } paramp->u.unpack.unpack_buffer += (dest_el_size * (*blocks_p)); MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_SEGMENT_CONTIG_UNPACK_EXTERNAL32_TO_BUF); return 0; }
bool Grammar::is_object_type(const std::string& str) { return is_boolean_type(str) || is_character_type(str) || is_integer_type(str) || is_float_type(str) || is_string_type(str); }
static MonoInst* emit_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args, const MagicTypeInfo *info) { int i = 0; const char *name = cmethod->name; MonoInst *ins; int type_index, stack_type; if (info->op_index == 2 && cfg->r4fp && SIZEOF_VOID_P == 4) { type_index = 3; stack_type = STACK_R4; } else { type_index = info->op_index; stack_type = info->stack_type; } if (!strcmp ("op_Implicit", name) || !strcmp ("op_Explicit", name)) { int source_size = type_size (cfg, fsig->params [0]); int dest_size = type_size (cfg, fsig->ret); switch (info->big_stack_type) { case STACK_I8: if (!is_int_type (fsig->params [0]) || !is_int_type (fsig->ret)) return NULL; break; case STACK_R8: if (!is_float_type (fsig->params [0]) || !is_float_type (fsig->ret)) return NULL; break; default: g_assert_not_reached (); } //4 -> 4 or 8 -> 8 if (source_size == dest_size) return args [0]; //4 -> 8 if (source_size < dest_size) return emit_widen (cfg, info, args [0]->dreg); //8 -> 4 return emit_narrow (cfg, info, args [0]->dreg); } if (!strcmp (".ctor", name)) { gboolean is_ldaddr = args [0]->opcode == OP_LDADDR; int arg0 = args [1]->dreg; int arg_size = type_size (cfg, fsig->params [0]); if (arg_size > SIZEOF_VOID_P) //8 -> 4 arg0 = emit_narrow (cfg, info, arg0)->dreg; else if (arg_size < SIZEOF_VOID_P) //4 -> 8 arg0 = emit_widen (cfg, info, arg0)->dreg; if (is_ldaddr) { /*Eliminate LDADDR if it's initing a local var*/ int dreg = ((MonoInst*)args [0]->inst_p0)->dreg; NULLIFY_INS (args [0]); EMIT_NEW_UNALU (cfg, ins, info->move, dreg, arg0); cfg->has_indirection = TRUE; } else { EMIT_NEW_STORE_MEMBASE (cfg, ins, info->store_op, args [0]->dreg, 0, arg0); } return ins; } if (!strcmp ("op_Increment", name) || !strcmp ("op_Decrement", name)) { gboolean inc = !strcmp ("op_Increment", name); /* FIXME float inc is too complex to bother with*/ //this is broken with ints too // if (!info->inc_op) return NULL; /* We have IR for inc/dec */ MONO_INST_NEW (cfg, ins, inc ? info->inc_op : info->dec_op); ins->dreg = alloc_dreg (cfg, info->stack_type); ins->sreg1 = args [0]->dreg; ins->inst_imm = 1; ins->type = info->stack_type; MONO_ADD_INS (cfg->cbb, ins); return ins; } for (i = 0; i < sizeof (int_binop) / sizeof (IntIntrisic); ++i) { if (!strcmp (int_binop [i].op_name, name)) { if (!int_binop [i].op_table [info->op_index]) return NULL; g_assert (int_binop [i].op_table [type_index]); MONO_INST_NEW (cfg, ins, int_binop [i].op_table [type_index]); ins->dreg = alloc_dreg (cfg, stack_type); ins->sreg1 = args [0]->dreg; ins->sreg2 = args [1]->dreg; ins->type = stack_type; MONO_ADD_INS (cfg->cbb, ins); return mono_decompose_opcode (cfg, ins); } } for (i = 0; i < sizeof (int_unnop) / sizeof (IntIntrisic); ++i) { if (!strcmp (int_unnop [i].op_name, name)) { g_assert (int_unnop [i].op_table [type_index]); MONO_INST_NEW (cfg, ins, int_unnop [i].op_table [type_index]); ins->dreg = alloc_dreg (cfg, stack_type); ins->sreg1 = args [0]->dreg; ins->type = stack_type; MONO_ADD_INS (cfg->cbb, ins); return ins; } } for (i = 0; i < sizeof (int_cmpop) / sizeof (IntIntrisic); ++i) { if (!strcmp (int_cmpop [i].op_name, name)) { short op_cmp = int_cmpop [i].op_table [type_index]; g_assert (op_cmp); if (info->compare_op) { MONO_INST_NEW (cfg, ins, info->compare_op); ins->dreg = -1; ins->sreg1 = args [0]->dreg; ins->sreg2 = args [1]->dreg; MONO_ADD_INS (cfg->cbb, ins); MONO_INST_NEW (cfg, ins, op_cmp); ins->dreg = alloc_preg (cfg); ins->type = STACK_I4; MONO_ADD_INS (cfg->cbb, ins); } else { MONO_INST_NEW (cfg, ins, op_cmp); guint32 fcmp_dreg = ins->dreg = alloc_ireg (cfg); ins->sreg1 = args [0]->dreg; ins->sreg2 = args [1]->dreg; MONO_ADD_INS (cfg->cbb, ins); if (op_cmp == OP_FCLT_UN || op_cmp == OP_FCGT_UN || op_cmp == OP_RCLT_UN || op_cmp == OP_RCGT_UN) { /* we have to negate the result of this comparison: * - op_GreaterThanOrEqual maps to NOT x OP_FCLT_UN / OP_RCLT_UN * - op_LessThanOrEqual maps to NOT x OP_FCGT_UN / OP_RCGT_UN * * this matches generated bytecode by C# when doing the * same operations on float/double. the `_UN` suffix says * that if an operand is NaN, the result is true. If * OP_FCGE/OP_FCLE is used, it is mapped to instructions * on some architectures that don't detect NaN. For * example, on arm64 the condition `eq` doesn't respect * NaN results of a `fcmp` instruction. */ MONO_INST_NEW (cfg, ins, OP_ICOMPARE_IMM); ins->dreg = -1; ins->sreg1 = fcmp_dreg; ins->inst_imm = 0; MONO_ADD_INS (cfg->cbb, ins); MONO_INST_NEW (cfg, ins, OP_CEQ); ins->dreg = alloc_preg (cfg); ins->type = STACK_I4; MONO_ADD_INS (cfg->cbb, ins); } } return ins; } } return NULL; }
bool Type::is_float() const { return is_float_type(_type_info); }
static MonoInst* emit_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args, const MagicTypeInfo *info) { int i = 0; const char *name = cmethod->name; MonoInst *ins; int type_index, stack_type; if (info->op_index == 2 && cfg->r4fp && SIZEOF_VOID_P == 4) { type_index = 3; stack_type = STACK_R4; } else { type_index = info->op_index; stack_type = info->stack_type; } if (!strcmp ("op_Implicit", name) || !strcmp ("op_Explicit", name)) { int source_size = type_size (cfg, fsig->params [0]); int dest_size = type_size (cfg, fsig->ret); switch (info->big_stack_type) { case STACK_I8: if (!is_int_type (fsig->params [0]) || !is_int_type (fsig->ret)) return NULL; break; case STACK_R8: if (!is_float_type (fsig->params [0]) || !is_float_type (fsig->ret)) return NULL; break; default: g_assert_not_reached (); } //4 -> 4 or 8 -> 8 if (source_size == dest_size) return args [0]; //4 -> 8 if (source_size < dest_size) return emit_widen (cfg, info, args [0]->dreg); //8 -> 4 return emit_narrow (cfg, info, args [0]->dreg); } if (!strcmp (".ctor", name)) { gboolean is_ldaddr = args [0]->opcode == OP_LDADDR; int arg0 = args [1]->dreg; int arg_size = type_size (cfg, fsig->params [0]); if (arg_size > SIZEOF_VOID_P) //8 -> 4 arg0 = emit_narrow (cfg, info, arg0)->dreg; else if (arg_size < SIZEOF_VOID_P) //4 -> 8 arg0 = emit_widen (cfg, info, arg0)->dreg; if (is_ldaddr) { /*Eliminate LDADDR if it's initing a local var*/ int dreg = ((MonoInst*)args [0]->inst_p0)->dreg; NULLIFY_INS (args [0]); EMIT_NEW_UNALU (cfg, ins, info->move, dreg, arg0); cfg->has_indirection = TRUE; } else { EMIT_NEW_STORE_MEMBASE (cfg, ins, info->store_op, args [0]->dreg, 0, arg0); } return ins; } if (!strcmp ("op_Increment", name) || !strcmp ("op_Decrement", name)) { gboolean inc = !strcmp ("op_Increment", name); /* FIXME float inc is too complex to bother with*/ //this is broken with ints too // if (!info->inc_op) return NULL; /* We have IR for inc/dec */ MONO_INST_NEW (cfg, ins, inc ? info->inc_op : info->dec_op); ins->dreg = alloc_dreg (cfg, info->stack_type); ins->sreg1 = args [0]->dreg; ins->inst_imm = 1; ins->type = info->stack_type; MONO_ADD_INS (cfg->cbb, ins); return ins; } for (i = 0; i < sizeof (int_binop) / sizeof (IntIntrisic); ++i) { if (!strcmp (int_binop [i].op_name, name)) { if (!int_binop [i].op_table [info->op_index]) return NULL; g_assert (int_binop [i].op_table [type_index]); MONO_INST_NEW (cfg, ins, int_binop [i].op_table [type_index]); ins->dreg = alloc_dreg (cfg, stack_type); ins->sreg1 = args [0]->dreg; ins->sreg2 = args [1]->dreg; ins->type = stack_type; MONO_ADD_INS (cfg->cbb, ins); return mono_decompose_opcode (cfg, ins); } } for (i = 0; i < sizeof (int_unnop) / sizeof (IntIntrisic); ++i) { if (!strcmp (int_unnop [i].op_name, name)) { g_assert (int_unnop [i].op_table [type_index]); MONO_INST_NEW (cfg, ins, int_unnop [i].op_table [type_index]); ins->dreg = alloc_dreg (cfg, stack_type); ins->sreg1 = args [0]->dreg; ins->type = stack_type; MONO_ADD_INS (cfg->cbb, ins); return ins; } } for (i = 0; i < sizeof (int_cmpop) / sizeof (IntIntrisic); ++i) { if (!strcmp (int_cmpop [i].op_name, name)) { g_assert (int_cmpop [i].op_table [type_index]); if (info->compare_op) { MONO_INST_NEW (cfg, ins, info->compare_op); ins->dreg = -1; ins->sreg1 = args [0]->dreg; ins->sreg2 = args [1]->dreg; MONO_ADD_INS (cfg->cbb, ins); MONO_INST_NEW (cfg, ins, int_cmpop [i].op_table [type_index]); ins->dreg = alloc_preg (cfg); ins->type = STACK_I4; MONO_ADD_INS (cfg->cbb, ins); } else { MONO_INST_NEW (cfg, ins, int_cmpop [i].op_table [type_index]); ins->dreg = alloc_ireg (cfg); ins->sreg1 = args [0]->dreg; ins->sreg2 = args [1]->dreg; MONO_ADD_INS (cfg->cbb, ins); } return ins; } } return NULL; }
void gen_condition(Node node, Symbol destination, int branch_cond) /*;gen_condition*/ { /* IMPORTANT WARNING: destination is where to go when expression is * equal to branch_cond */ /* These maps are realized in procedures immediately following. * const * jump_false_code = { * ['=', I_JUMP_IF_FALSE], * ['!=', I_JUMP_IF_TRUE], * ['<', I_JUMP_IF_GREATER_OR_EQUAL], * ['>', I_JUMP_IF_LESS_OR_EQUAL], * ['<=', I_JUMP_IF_GREATER], * ['>=', I_JUMP_IF_LESS] }, * * jump_true_code = { * ['=', I_JUMP_IF_TRUE], * ['<', I_JUMP_IF_LESS], * ['>', I_JUMP_IF_GREATER], * ['<=', I_JUMP_IF_LESS_OR_EQUAL], * ['>=', I_JUMP_IF_GREATER_OR_EQUAL] }; */ Tuple tup; Node opnode, args, op1, op2; Symbol opcode, optype; #ifdef TRACE if (debug_flag) gen_trace_node("GEN_CONDITION", node); #endif if (N_KIND(node) == as_op) { opnode = N_AST1(node); args = N_AST2(node); opcode = N_UNQ(opnode); if (opcode == symbol_eq || opcode == symbol_ne || opcode == symbol_lt || opcode == symbol_gt || opcode == symbol_le || opcode == symbol_ge){ tup = N_LIST(args); op1 = (Node) tup[1]; op2 = (Node) tup[2]; gen_value(op1); gen_value(op2); optype = get_type(op1); if (is_simple_type(optype)) { if (is_float_type(optype)) gen_k(I_FLOAT_COMPARE, kind_of(optype)); else gen_k(I_COMPARE, kind_of(optype)); } else { if (is_record_type(optype)) { gen_s(I_PUSH_EFFECTIVE_ADDRESS, optype); } if (is_array_type(optype) && (opcode != symbol_eq) && (opcode != symbol_ne)) { gen(I_COMPARE_ARRAYS); } else { gen(I_COMPARE_STRUC); } } } else { gen_value(node); opcode = symbol_eq; } } else { gen_value(node); opcode = symbol_eq; } if (branch_cond) gen_s(jump_true_code(opcode), destination); else gen_s(jump_false_code(opcode), destination); }