125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Function return value location for IA64 ABI. 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Copyright (C) 2006-2010 Red Hat, Inc. 325b3c049e70834cf33790a28643ab058b507b35cBen Cheng This file is part of Red Hat elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 625b3c049e70834cf33790a28643ab058b507b35cBen Cheng it under the terms of the GNU General Public License as published by the 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Free Software Foundation; version 2 of the License. 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng You should have received a copy of the GNU General Public License along 1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is an included package of the Open Invention Network. 1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng An included package of the Open Invention Network is a package for which 2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Open Invention Network licensees cross-license their patents. No patent 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng license is granted, either expressly or impliedly, by designation as an 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng included package. Should you wish to participate in the Open Invention 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Network licensing program, please visit www.openinventionnetwork.com 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng <http://www.openinventionnetwork.com>. */ 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H 2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h> 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h> 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <dwarf.h> 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define BACKEND ia64_ 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libebl_CPU.h" 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* r8, or pair r8, r9, or aggregate up to r8-r11. */ 3825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const Dwarf_Op loc_intreg[] = 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_reg8 }, { .atom = DW_OP_piece, .number = 8 }, 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_reg9 }, { .atom = DW_OP_piece, .number = 8 }, 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_reg10 }, { .atom = DW_OP_piece, .number = 8 }, 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_reg11 }, { .atom = DW_OP_piece, .number = 8 }, 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define nloc_intreg 1 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define nloc_intregs(n) (2 * (n)) 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* f8, or aggregate up to f8-f15. */ 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define DEFINE_FPREG(size) \ 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng static const Dwarf_Op loc_fpreg_##size[] = \ 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { \ 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_regx, .number = 128 + 8 }, \ 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_piece, .number = size }, \ 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_regx, .number = 128 + 9 }, \ 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_piece, .number = size }, \ 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_regx, .number = 128 + 10 }, \ 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_piece, .number = size }, \ 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_regx, .number = 128 + 11 }, \ 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_piece, .number = size }, \ 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_regx, .number = 128 + 12 }, \ 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_piece, .number = size }, \ 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_regx, .number = 128 + 13 }, \ 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_piece, .number = size }, \ 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_regx, .number = 128 + 14 }, \ 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_piece, .number = size }, \ 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_regx, .number = 128 + 15 }, \ 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_piece, .number = size }, \ 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define nloc_fpreg 1 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define nloc_fpregs(n) (2 * (n)) 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7225b3c049e70834cf33790a28643ab058b507b35cBen ChengDEFINE_FPREG (4); 7325b3c049e70834cf33790a28643ab058b507b35cBen ChengDEFINE_FPREG (8); 7425b3c049e70834cf33790a28643ab058b507b35cBen ChengDEFINE_FPREG (10); 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef DEFINE_FPREG 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* The return value is a structure and is actually stored in stack space 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng passed in a hidden argument by the caller. But, the compiler 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng helpfully returns the address of that space in r8. */ 8225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const Dwarf_Op loc_aggregate[] = 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { .atom = DW_OP_breg8, .number = 0 } 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define nloc_aggregate 1 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* If this type is an HFA small enough to be returned in FP registers, 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return the number of registers to use. Otherwise 9, or -1 for errors. */ 9125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 9225b3c049e70834cf33790a28643ab058b507b35cBen Chenghfa_type (Dwarf_Die *typedie, Dwarf_Word size, 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Dwarf_Op **locp, int fpregs_used) 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Descend the type structure, counting elements and finding their types. 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng If we find a datum that's not an FP type (and not quad FP), punt. 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng If we find a datum that's not the same FP type as the first datum, punt. 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng If we count more than eight total homogeneous FP data, punt. */ 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline int hfa (const Dwarf_Op *loc, int nregs) 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fpregs_used == 0) 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc; 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (*locp != loc) 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 9; 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fpregs_used + nregs; 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int tag = dwarf_tag (typedie); 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (tag) 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Attribute attr_mem; 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case -1: 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_base_type:; 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Word encoding; 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng &attr_mem), &encoding) != 0) 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (encoding) 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_ATE_float: 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (size) 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 4: /* float */ 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return hfa (loc_fpreg_4, 1); 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 8: /* double */ 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return hfa (loc_fpreg_8, 1); 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 10: /* x86-style long double, not really used */ 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return hfa (loc_fpreg_10, 1); 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_ATE_complex_float: 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (size) 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 4 * 2: /* complex float */ 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return hfa (loc_fpreg_4, 2); 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 8 * 2: /* complex double */ 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return hfa (loc_fpreg_8, 2); 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 10 * 2: /* complex long double (x86-style) */ 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return hfa (loc_fpreg_10, 2); 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_structure_type: 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_class_type: 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_union_type:; 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Die child_mem; 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (dwarf_child (typedie, &child_mem)) 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 1: /* No children: empty struct. */ 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 0:; /* Look at each element. */ 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng int max_used = fpregs_used; 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (dwarf_tag (&child_mem)) 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case -1: 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_member:; 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Die child_type_mem; 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Die *child_typedie 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng = dwarf_formref_die (dwarf_attr_integrate (&child_mem, 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng DW_AT_type, 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng &attr_mem), 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng &child_type_mem); 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Word child_size; 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dwarf_aggregate_size (child_typedie, &child_size) != 0) 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (tag == DW_TAG_union_type) 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int used = hfa_type (child_typedie, child_size, 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng locp, fpregs_used); 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (used < 0 || used > 8) 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return used; 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (used > max_used) 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng max_used = used; 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng fpregs_used = hfa_type (child_typedie, child_size, 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng locp, fpregs_used); 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fpregs_used < 0 || fpregs_used > 8) 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fpregs_used; 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (dwarf_siblingof (&child_mem, &child_mem) == 0); 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (tag == DW_TAG_union_type) 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng fpregs_used = max_used; 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_array_type: 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (size == 0) 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Die base_type_mem; 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Die *base_typedie 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng = dwarf_formref_die (dwarf_attr_integrate (typedie, DW_AT_type, 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng &attr_mem), 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng &base_type_mem); 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Word base_size; 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dwarf_aggregate_size (base_typedie, &base_size) != 0) 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int used = hfa_type (base_typedie, base_size, locp, 0); 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (used < 0 || used > 8) 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return used; 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (size % (*locp)[1].number != 0) 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng fpregs_used += used * (size / (*locp)[1].number); 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 9; 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fpregs_used; 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23325b3c049e70834cf33790a28643ab058b507b35cBen Chengint 23425b3c049e70834cf33790a28643ab058b507b35cBen Chengia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Start with the function's type, and get the DW_AT_type attribute, 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng which is the type of the return value. */ 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Attribute attr_mem; 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng &attr_mem); 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (attr == NULL) 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The function has no return value, like a `void' function in C. */ 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Die die_mem; 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem); 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int tag = dwarf_tag (typedie); 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Follow typedefs and qualifiers to get to the actual type. */ 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (tag == DW_TAG_typedef 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type) 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng attr = dwarf_attr (typedie, DW_AT_type, &attr_mem); 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng typedie = dwarf_formref_die (attr, &die_mem); 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng tag = dwarf_tag (typedie); 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Word size; 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (tag) 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case -1: 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_subrange_type: 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size)) 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng typedie = dwarf_formref_die (attr, &die_mem); 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng tag = dwarf_tag (typedie); 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Fall through. */ 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_base_type: 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_enumeration_type: 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_pointer_type: 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_ptr_to_member_type: 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng &attr_mem), &size) != 0) 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type) 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size = 8; 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (tag == DW_TAG_base_type) 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Word encoding; 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng &attr_mem), 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng &encoding) != 0) 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (encoding) 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_ATE_float: 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (size) 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 4: /* float */ 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_fpreg_4; 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_fpreg; 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 8: /* double */ 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_fpreg_8; 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_fpreg; 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 10: /* x86-style long double, not really used */ 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_fpreg_10; 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_fpreg; 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 16: /* long double, IEEE quad format */ 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_intreg; 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_intregs (2); 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -2; 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_ATE_complex_float: 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (size) 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 4 * 2: /* complex float */ 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_fpreg_4; 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_fpregs (2); 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 8 * 2: /* complex double */ 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_fpreg_8; 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_fpregs (2); 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 10 * 2: /* complex long double (x86-style) */ 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_fpreg_10; 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_fpregs (2); 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 16 * 2: /* complex long double (IEEE quad) */ 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_intreg; 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_intregs (4); 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -2; 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng intreg: 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_intreg; 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (size <= 8) 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_intreg; 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (size <= 32) 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_intregs ((size + 7) / 8); 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng large: 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *locp = loc_aggregate; 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nloc_aggregate; 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_structure_type: 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_class_type: 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_union_type: 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case DW_TAG_array_type: 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dwarf_aggregate_size (typedie, &size) != 0) 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If this qualifies as an homogeneous floating-point aggregate 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (HFA), then it should be returned in FP regs. */ 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int nfpreg = hfa_type (typedie, size, locp, 0); 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nfpreg < 0) 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nfpreg; 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (nfpreg > 0 && nfpreg <= 8) 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nfpreg == 1 ? nloc_fpreg : nloc_fpregs (nfpreg); 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (size > 32) 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto large; 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto intreg; 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* XXX We don't have a good way to return specific errors from ebl calls. 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng This value means we do not understand the type, but it is well-formed 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng DWARF and might be valid. */ 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -2; 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 372