Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}