/* generate function prolog of type 't' */ void gfunc_prolog(int t) { int addr, u, func_call; Sym *sym; char buf[1024]; init_outfile(); /* XXX: pass function name to gfunc_prolog */ il_type_to_str(buf, sizeof(buf), t, funcname); fprintf(il_outfile, ".method static %s il managed\n", buf); fprintf(il_outfile, "{\n"); /* XXX: cannot do better now */ fprintf(il_outfile, " .maxstack %d\n", NB_REGS); fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n"); if (!strcmp(funcname, "main")) fprintf(il_outfile, " .entrypoint\n"); sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT); func_call = sym->r; addr = ARG_BASE; /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->t; func_var = (sym->c == FUNC_ELLIPSIS); if ((func_vt & VT_BTYPE) == VT_STRUCT) { func_vc = addr; addr++; } /* define parameters */ while ((sym = sym->next) != NULL) { u = sym->t; sym_push(sym->v & ~SYM_FIELD, u, VT_LOCAL | lvalue_type(sym->type.t), addr); addr++; } }
tree convert_to_reference (tree reftype, tree expr, int convtype, int flags, tree decl) { tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); tree intype; tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; bool can_convert_intype_to_type; if (TREE_CODE (type) == FUNCTION_TYPE && TREE_TYPE (expr) == unknown_type_node) expr = instantiate_type (type, expr, (flags & LOOKUP_COMPLAIN) ? tf_warning_or_error : tf_none); if (expr == error_mark_node) return error_mark_node; intype = TREE_TYPE (expr); gcc_assert (TREE_CODE (intype) != REFERENCE_TYPE); gcc_assert (TREE_CODE (reftype) == REFERENCE_TYPE); intype = TYPE_MAIN_VARIANT (intype); can_convert_intype_to_type = can_convert (type, intype); if (!can_convert_intype_to_type && (convtype & CONV_IMPLICIT) && MAYBE_CLASS_TYPE_P (intype) && ! (flags & LOOKUP_NO_CONVERSION)) { /* Look for a user-defined conversion to lvalue that we can use. */ rval_as_conversion = build_type_conversion (reftype, expr); if (rval_as_conversion && rval_as_conversion != error_mark_node && real_lvalue_p (rval_as_conversion)) { expr = rval_as_conversion; rval_as_conversion = NULL_TREE; intype = type; can_convert_intype_to_type = 1; } } if (((convtype & CONV_STATIC) && can_convert (intype, type)) || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type)) { if (flags & LOOKUP_COMPLAIN) { tree ttl = TREE_TYPE (reftype); tree ttr = lvalue_type (expr); if (! real_lvalue_p (expr)) warn_ref_binding (reftype, intype, decl); if (! (convtype & CONV_CONST) && !at_least_as_qualified_p (ttl, ttr)) permerror (input_location, "conversion from %qT to %qT discards qualifiers", ttr, reftype); } return build_up_reference (reftype, expr, flags, decl); } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { /* When casting an lvalue to a reference type, just convert into a pointer to the new type and deference it. This is allowed by San Diego WP section 5.2.9 paragraph 12, though perhaps it should be done directly (jason). (int &)ri ---> *(int*)&ri */ /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ if (TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_DERIVED))) warning (0, "casting %qT to %qT does not dereference pointer", intype, reftype); rval = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error); if (rval != error_mark_node) rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval, 0); if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } else { rval = convert_for_initialization (NULL_TREE, type, expr, flags, "converting", 0, 0, tf_warning_or_error); if (rval == NULL_TREE || rval == error_mark_node) return rval; warn_ref_binding (reftype, intype, decl); rval = build_up_reference (reftype, rval, flags, decl); } if (rval) { /* If we found a way to convert earlier, then use it. */ return rval; } if (flags & LOOKUP_COMPLAIN) error ("cannot convert type %qT to type %qT", intype, reftype); return error_mark_node; }
/* generate function prolog of type 't' */ void gfunc_prolog(CType *func_type) { int addr, align, size, func_call, fastcall_nb_regs; int param_index, param_addr; uint8_t *fastcall_regs_ptr; Sym *sym; CType *type; sym = func_type->ref; func_call = FUNC_CALL(sym->r); addr = 8; loc = 0; if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) { fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1; fastcall_regs_ptr = fastcall_regs; } else if (func_call == FUNC_FASTCALLW) { fastcall_nb_regs = 2; fastcall_regs_ptr = fastcallw_regs; } else { fastcall_nb_regs = 0; fastcall_regs_ptr = NULL; } param_index = 0; ind += FUNC_PROLOG_SIZE; func_sub_sp_offset = ind; /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->type; if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { /* XXX: fastcall case ? */ func_vc = addr; addr += 4; param_index++; } /* define parameters */ while ((sym = sym->next) != NULL) { type = &sym->type; size = type_size(type, &align); size = (size + 3) & ~3; #ifdef FUNC_STRUCT_PARAM_AS_PTR /* structs are passed as pointer */ if ((type->t & VT_BTYPE) == VT_STRUCT) { size = 4; } #endif if (param_index < fastcall_nb_regs) { /* save FASTCALL register */ loc -= 4; o(0x89); /* movl */ gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc); param_addr = loc; } else { param_addr = addr; addr += size; } sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), param_addr); param_index++; } func_ret_sub = 0; /* pascal type call ? */ if (func_call == FUNC_STDCALL) func_ret_sub = addr - 8; /* leave some room for bound checking code */ if (tcc_state->do_bounds_check) { oad(0xb8, 0); /* lbound section pointer */ oad(0xb8, 0); /* call to function */ func_bound_offset = lbounds_section->data_offset; } }