struct value * value_subscripted_rvalue (struct value *array, LONGEST index, int lowerbound) { struct type *array_type = check_typedef (value_type (array)); struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type)); unsigned int elt_size = TYPE_LENGTH (elt_type); unsigned int elt_offs = elt_size * longest_to_int (index - lowerbound); struct value *v; if (index < lowerbound || (!TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (array_type) && elt_offs >= TYPE_LENGTH (array_type))) error (_("no such vector element")); if (VALUE_LVAL (array) == lval_memory && value_lazy (array)) v = allocate_value_lazy (elt_type); else { v = allocate_value (elt_type); value_contents_copy (v, value_embedded_offset (v), array, value_embedded_offset (array) + elt_offs, elt_size); } set_value_component_location (v, array); VALUE_REGNUM (v) = VALUE_REGNUM (array); VALUE_FRAME_ID (v) = VALUE_FRAME_ID (array); set_value_offset (v, value_offset (array) + elt_offs); return v; }
static void ppc_push_argument (struct ppc_stack_abi *abi, struct ppc_stack_context *c, struct value *arg, int argno, int do_copy, int floatonly) { struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); struct type *type = check_typedef (value_type (arg)); int len = TYPE_LENGTH (type); gdb_byte buf[16]; c->argoffset = ROUND_UP (c->argoffset, 4); switch (TYPE_CODE (type)) { case TYPE_CODE_FLT: { if (c->freg <= abi->last_freg) { struct value *rval; struct type *rtype; int rlen; /* APPLE LOCAL: If the thing is already a long double type, don't cast it to a builtin type double, since there are two long double types, and we will pass an 16 byte long double wrong if we assume it is an 8 byte double. */ if (strcmp (TYPE_NAME (type), "long double") != 0) { rval = value_cast (builtin_type_double, arg); rtype = check_typedef (value_type (rval)); rlen = TYPE_LENGTH (rtype); } else { rval = arg; rtype = type; rlen = len; } /* APPLE LOCAL: GCC 4.0 has 16 byte long doubles */ if ((len != 4) && (len != 8) && (len != 16)) error ("floating point parameter had unexpected size"); if (rlen != 8 && rlen != 16) error ("floating point parameter had unexpected size"); if (do_copy) regcache_raw_write (current_regcache, FP0_REGNUM + c->freg, value_contents (rval)); if (do_copy && ! floatonly && abi->fregs_shadow_gregs) ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, len, value_contents (arg)); if (do_copy && ! floatonly && abi->regs_shadow_stack) write_memory (c->sp + c->argoffset, value_contents (arg), len); c->freg++; /* APPLE LOCAL: We took up two registers... */ if (rlen == 16) c->freg++; if (! floatonly && (abi->fregs_shadow_gregs) && (c->greg <= abi->last_greg)) c->greg += len / 4; if (! floatonly && abi->regs_shadow_stack) c->argoffset += len; } else if (! floatonly) { if ((len != 4) && (len != 8) && (len != 16)) error ("floating point parameter had unexpected size"); c->argoffset = ROUND_UP (c->argoffset, len); if (do_copy) write_memory (c->sp + c->argoffset, value_contents (arg), len); c->argoffset += len; } break; } case TYPE_CODE_INT: case TYPE_CODE_ENUM: case TYPE_CODE_PTR: case TYPE_CODE_REF: { int nregs; gdb_byte *val_contents; if (floatonly) break; /* APPLE LOCAL: Huge Hack... The problem is that if we are a 32 bit app on Mac OS X, the registers are really 64 bits, but we don't want to pass all 64 bits. So if we get passed a value that came from a register, and it's length is > the wordsize, cast it to the wordsize first before passing it in. */ if (VALUE_REGNUM (arg) != -1 && len == 8 && tdep->wordsize == 4) { len = 4; val_contents = value_contents (arg) + 4; } else val_contents = value_contents (arg); /* END APPLE LOCAL */ nregs = (len <= 4) ? 1 : 2; if ((len != 1) && (len != 2) && (len != 4) && (len != 8)) error ("integer parameter had unexpected size"); if (c->greg <= abi->last_greg) { /* If the parameter fits in the remaining argument registers, write it to the registers, and to the stack if the abi requires it. */ if (do_copy) { /* Split the argument between registers & the stack if it doesn't fit in the remaining registers. */ int regs_avaliable = abi->last_greg - c->greg + 1; if (regs_avaliable >= nregs) regs_avaliable = nregs; ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, regs_avaliable * 4, val_contents); } if (do_copy && abi->regs_shadow_stack) write_memory (c->sp + c->argoffset, val_contents, len); c->greg += nregs; if (abi->regs_shadow_stack) c->argoffset += (nregs * 4); } else { /* If we've filled up the registers, then just write it on the stack. */ if (do_copy) write_memory (c->sp + c->argoffset, val_contents, len); c->argoffset += (nregs * 4); } break; } case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: { if (! abi->structs_with_args) { if (floatonly) break; if (len > 4) { /* Rounding to the nearest multiple of 8 may not be necessary, but it is safe. Particularly since we don't know the field types of the structure */ c->structoffset = ROUND_UP (c->structoffset, 8); if (do_copy) { write_memory (c->sp + c->structoffset, value_contents (arg), len); store_unsigned_integer (buf, 4, c->sp + c->structoffset); } c->structoffset += ROUND_UP (len, 8); } else if (do_copy) { memset (buf, 0, 4); memcpy (buf, value_contents (arg), len); } if (c->greg <= abi->last_greg) { if (do_copy) ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, 4, buf); c->greg++; } else { if (do_copy) write_memory (c->sp + c->argoffset, buf, 4); c->argoffset += 4; } break; } else { int i; int regspace = (abi->last_greg - c->greg + 1) * 4; int stackspace = (len <= regspace) ? 0 : (len - regspace); int writereg = (regspace > len) ? len : regspace; int writestack = abi->regs_shadow_stack ? len : stackspace; for (i = 0; i < TYPE_NFIELDS (type); i++) { struct value *subarg = value_field (arg, i); ppc_push_argument (abi, c, subarg, argno, do_copy, 1); } if (floatonly) break; if (do_copy) { gdb_byte *ptr = value_contents (arg); if (len < 4) { memset (buf, 0, 4); if ((len == 1) || (len == 2)) memcpy (buf + 4 - len, ptr, len); else memcpy (buf, ptr, len); ptr = buf; } ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, (writereg < 4) ? 4 : writereg, ptr); write_memory (c->sp + c->argoffset, ptr, (writestack < 4) ? 4 : writestack); } c->greg += ROUND_UP (writereg, 4) / 4; c->argoffset += writestack; } break; } case TYPE_CODE_ARRAY: { if (floatonly) break; if (! TYPE_VECTOR (type)) error ("non-vector array type"); if (len != 16) error ("unexpected vector length"); if (c->vreg <= abi->last_vreg) { if (do_copy) regcache_raw_write (current_regcache, tdep->ppc_vr0_regnum + c->vreg, value_contents (arg)); c->vreg++; } else { /* Vector arguments must be aligned to 16 bytes on the stack. */ c->argoffset = ROUND_UP (c->argoffset, 16); if (do_copy) write_memory (c->sp + c->argoffset, value_contents (arg), len); c->argoffset += len; } break; } default: error ("argument %d has unknown type code 0x%x (%s)", argno, TYPE_CODE (type), type_code_name (TYPE_CODE (type))); } return; }