summaryrefslogtreecommitdiffstats
path: root/loc2c.c
diff options
context:
space:
mode:
authorroland <roland>2005-10-14 11:30:45 +0000
committerroland <roland>2005-10-14 11:30:45 +0000
commitce48dbc707c6d0c9b67f9b22f84f0d8d00df332d (patch)
tree25f3f359eb4179106529176bc41d325bfbd8887d /loc2c.c
parent068ddd4357ea29d4cfb611d2ac01dc0e0507d1cf (diff)
downloadsystemtap-steved-ce48dbc707c6d0c9b67f9b22f84f0d8d00df332d.tar.gz
systemtap-steved-ce48dbc707c6d0c9b67f9b22f84f0d8d00df332d.tar.xz
systemtap-steved-ce48dbc707c6d0c9b67f9b22f84f0d8d00df332d.zip
2005-10-14 Roland McGrath <roland@redhat.com>
PR 1271. * loc2c.c (translate): Set LOC->byte_size in loc_noncontiguous result. (struct location.address): New member `declare'. (new_synthetic_loc, translate): Initialize it. (struct location.type): Add loc_fragment, loc_decl to enum. (c_emit_location): Emit unadorned code for loc_fragment. (discontiguify): New function. (c_translate_fetch, c_translate_store): Call it. (get_bitfield): New function, broken out of .... (emit_bitfield): ... here. Function removed. (declare_noncontig_union): New function. (max_fetch_size): New function. (translate_base_fetch): New function, broken out of ... (c_translate_fetch): ... here. Call it. Use get_bitfield here, not emit_bitfield. (c_translate_store): Likewise. (c_emit_location): Emit declarations first. * loc2c.c (dwarf_diename_integrate): Function removed. Change all callers to use dwarf_diename. 2005-10-13 Roland McGrath <roland@redhat.com> * loc2c.c (c_emit_location): Use final location's used_deref flag too. * loc2c.c (translate): Pass LOC to alloc_location, not INPUT.
Diffstat (limited to 'loc2c.c')
-rw-r--r--loc2c.c528
1 files changed, 395 insertions, 133 deletions
diff --git a/loc2c.c b/loc2c.c
index 70d3cca8..fee66d04 100644
--- a/loc2c.c
+++ b/loc2c.c
@@ -33,14 +33,19 @@ struct location
Dwarf_Word byte_size;
- enum { loc_address, loc_register, loc_noncontiguous, loc_final } type;
+ enum
+ {
+ loc_address, loc_register, loc_noncontiguous,
+ loc_decl, loc_fragment, loc_final
+ } type;
union
{
- struct /* loc_address or loc_final */
+ struct /* loc_address, loc_fragment, loc_final */
{
+ struct location *frame_base;
+ const char *declare; /* Temporary that needs declared. */
char *program; /* C fragment, leaves address in s0. */
unsigned int stack_depth; /* Temporaries "s0..<N>" used by it. */
- struct location *frame_base;
bool used_deref; /* Program uses "deref" macro. */
} address;
unsigned int regno; /* loc_register */
@@ -55,6 +60,7 @@ alloc_location (struct obstack *pool, struct location *origin)
loc->fail = origin->fail;
loc->fail_arg = origin->fail_arg;
loc->emit_address = origin->emit_address;
+ loc->byte_size = 0;
return loc;
}
@@ -68,13 +74,6 @@ default_emit_address (void *fail_arg __attribute__ ((unused)),
obstack_printf (pool, AFORMAT, address);
}
-static const char *
-dwarf_diename_integrate (Dwarf_Die *die)
-{
- Dwarf_Attribute attr_mem;
- return dwarf_formstring (dwarf_attr_integrate (die, DW_AT_name, &attr_mem));
-}
-
/* Synthesize a new loc_address using the program on the obstack. */
static struct location *
new_synthetic_loc (struct obstack *pool, struct location *origin, bool deref)
@@ -88,6 +87,7 @@ new_synthetic_loc (struct obstack *pool, struct location *origin, bool deref)
loc->type = loc_address;
loc->address.program = program;
loc->address.stack_depth = 0;
+ loc->address.declare = NULL;
loc->address.frame_base = NULL;
loc->address.used_deref = deref;
@@ -201,6 +201,7 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias,
obstack_1grow (pool, '\0');
char *program = obstack_finish (pool);
piece->type = loc_address;
+ piece->address.declare = NULL;
piece->address.program = program;
piece->address.stack_depth = max_stack;
piece->address.frame_base = NULL;
@@ -219,6 +220,7 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias,
struct location *pieces = NULL, **tailpiece = &pieces;
size_t piece_expr_start = 0;
+ Dwarf_Word piece_total_bytes = 0;
for (i = 0; i < len; ++i)
{
unsigned int reg;
@@ -469,7 +471,7 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias,
DIE ("DW_OP_piece left multiple values on stack");
else
{
- struct location *piece = alloc_location (pool, input);
+ struct location *piece = alloc_location (pool, loc);
const char *failure = finish (piece);
if (failure != NULL)
return failure;
@@ -478,7 +480,7 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias,
piece->nops = i - piece_expr_start;
piece_expr_start = i + 1;
- piece->byte_size = expr[i].number;
+ piece_total_bytes += piece->byte_size = expr[i].number;
*tailpiece = piece;
tailpiece = &piece->next;
@@ -504,6 +506,7 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias,
loc->type = loc_noncontiguous;
loc->pieces = pieces;
+ loc->byte_size = piece_total_bytes;
return NULL;
@@ -534,6 +537,7 @@ location_from_address (struct obstack *pool,
loc->fail = *input == NULL ? fail : (*input)->fail;
loc->fail_arg = *input == NULL ? fail_arg : (*input)->fail_arg;
loc->emit_address = *input == NULL ? emit_address : (*input)->emit_address;
+ loc->byte_size = 0;
bool need_fb = false;
size_t loser;
@@ -950,7 +954,7 @@ location_relative (struct obstack *pool,
If DW_OP_fbreg is used, it may have a subfragment computing from
the FB_ATTR location expression.
- On errors, exit and never return (XXX ?). On success, return the
+ On errors, call FAIL and never return. On success, return the
first fragment created, which is also chained onto (*INPUT)->next.
*INPUT is then updated with the new tail of that chain. */
@@ -1006,7 +1010,6 @@ c_translate_location (struct obstack *pool,
return location_relative (pool, indent, dwbias, expr, len, address,
input, fb_attr);
- case loc_final: /* Bogus caller. */
default:
abort ();
break;
@@ -1015,7 +1018,6 @@ c_translate_location (struct obstack *pool,
return NULL;
}
-
/* Emit "uintNN_t TARGET = ...;". */
static bool
emit_base_fetch (struct obstack *pool, Dwarf_Word byte_size,
@@ -1028,10 +1030,10 @@ emit_base_fetch (struct obstack *pool, Dwarf_Word byte_size,
{
case loc_address:
if (byte_size != 0 && byte_size != (Dwarf_Word) -1)
- obstack_printf (pool, "%s = deref (%" PRIu64 ", addr); ",
+ obstack_printf (pool, "%s = deref (%" PRIu64 ", addr);",
target, byte_size);
else
- obstack_printf (pool, "%s = deref (sizeof %s, addr); ",
+ obstack_printf (pool, "%s = deref (sizeof %s, addr);",
target, target);
return true;
@@ -1040,8 +1042,7 @@ emit_base_fetch (struct obstack *pool, Dwarf_Word byte_size,
break;
case loc_noncontiguous:
- /* Could be handled if it ever happened. */
- FAIL (loc, N_("noncontiguous locations not supported"));
+ FAIL (loc, N_("noncontiguous location for base fetch"));
break;
default:
@@ -1073,8 +1074,7 @@ emit_base_store (struct obstack *pool, Dwarf_Word byte_size,
break;
case loc_noncontiguous:
- /* Could be handled if it ever happened. */
- FAIL (loc, N_("noncontiguous locations not supported"));
+ FAIL (loc, N_("noncontiguous location for base store"));
break;
default:
@@ -1085,42 +1085,130 @@ emit_base_store (struct obstack *pool, Dwarf_Word byte_size,
return false;
}
-/* Translate a fragment to dereference the given pointer type,
- where *INPUT is the location of the pointer with that type.
- We chain on a loc_address program that yields this pointer value
- (i.e. the location of what it points to). */
+/* Slice up an object into pieces no larger than MAX_PIECE_BYTES,
+ yielding a loc_noncontiguous location unless LOC is small enough. */
+static struct location *
+discontiguify (struct obstack *pool, int indent, struct location *loc,
+ Dwarf_Word total_bytes, Dwarf_Word max_piece_bytes)
+{
+ inline bool pieces_small_enough (void)
+ {
+ if (loc->type != loc_noncontiguous)
+ return (loc->byte_size ?: total_bytes) <= max_piece_bytes;
+ for (struct location *p = loc->pieces; p != NULL; p = p->next)
+ if (p->byte_size > max_piece_bytes)
+ return false;
+ return true;
+ }
-void
-c_translate_pointer (struct obstack *pool, int indent,
- Dwarf_Addr dwbias __attribute__ ((unused)),
- Dwarf_Die *typedie, struct location **input)
+ if (pieces_small_enough ())
+ return loc;
+
+ struct location *noncontig = alloc_location (pool, loc);
+ noncontig->next = NULL;
+ noncontig->type = loc_noncontiguous;
+ noncontig->byte_size = total_bytes;
+ noncontig->pieces = NULL;
+ struct location **tailpiece = &noncontig->pieces;
+ inline void add (struct location *piece)
+ {
+ *tailpiece = piece;
+ tailpiece = &piece->next;
+ }
+
+ switch (loc->type)
+ {
+ case loc_address:
+ {
+ /* Synthesize a piece that sets "container_addr" to the computed
+ address of the whole object. Each piece will refer to this. */
+ obstack_printf (pool, "%*scontainer_addr = addr;\n",
+ indent++ * 2, "");
+ loc->next = new_synthetic_loc (pool, loc, false);
+ loc->next->byte_size = loc->byte_size;
+ loc->next->type = loc_fragment;
+ loc->next->address.declare = "container_addr";
+ loc = loc->next;
+
+ /* Synthesize pieces that just compute "container_addr + N". */
+ Dwarf_Word offset = 0;
+ while (total_bytes - offset > 0)
+ {
+ Dwarf_Word size = total_bytes - offset;
+ if (size > max_piece_bytes)
+ size = max_piece_bytes;
+
+ obstack_printf (pool, "%*saddr = container_addr + " UFORMAT "\n",
+ indent * 2, "", offset);
+ struct location *piece = new_synthetic_loc (pool, loc, false);
+ piece->byte_size = size;
+ add (piece);
+
+ offset += size;
+ }
+
+ --indent;
+ break;
+ }
+
+ case loc_register:
+ FAIL (loc, N_("single register too big for fetch/store ???"));
+ break;
+
+ case loc_noncontiguous:
+ /* Could be handled if it ever happened. */
+ FAIL (loc, N_("discontiguify of noncontiguous location not supported"));
+ break;
+
+ default:
+ abort ();
+ break;
+ }
+
+ loc->next = noncontig;
+ return noncontig;
+}
+
+/* Make a fragment that declares a union such as:
+ union {
+ char bytes[8];
+ struct {
+ uint32_t p0;
+ uint32_t p4;
+ } pieces __attribute__ ((packed));
+ uint64_t whole;
+ } u;
+*/
+static void
+declare_noncontig_union (struct obstack *pool, int indent,
+ struct location **input, struct location *loc)
{
- assert (dwarf_tag (typedie) == DW_TAG_pointer_type);
+ obstack_printf (pool, "%*sunion {\n", indent++ * 2, "");
- ++indent;
+ obstack_printf (pool, "%*schar bytes[%" PRIu64 "];\n",
+ indent * 2, "", loc->byte_size);
- obstack_printf (pool, "%*s{ ", (indent + 2) * 2, "");
+ obstack_printf (pool, "%*sstruct {\n", indent++ * 2, "");
- bool deref = false;
- Dwarf_Attribute attr_mem;
- Dwarf_Word byte_size;
- if (dwarf_attr_integrate (typedie, DW_AT_byte_size, &attr_mem) == NULL)
+ Dwarf_Word offset = 0;
+ for (struct location *p = loc->pieces; p != NULL; p = p->next)
{
- obstack_printf (pool, "uintptr_t ");
- deref = emit_base_fetch (pool, 0, "tmp", false, *input);
+ obstack_printf (pool, "%*suint%" PRIu64 "_t p%" PRIu64 ";\n",
+ indent * 2, "", p->byte_size * 8, offset);
+ offset += p->byte_size;
}
- else if (dwarf_formudata (&attr_mem, &byte_size) != 0)
- FAIL (*input,
- N_("cannot get byte_size attribute for type %s: %s"),
- dwarf_diename_integrate (typedie) ?: "<anonymous>",
- dwarf_errmsg (-1));
- else
- deref = emit_base_fetch (pool, byte_size, "tmp", true, *input);
- obstack_printf (pool, " addr = tmp; }\n");
+ obstack_printf (pool, "%*s} pieces __attribute__ ((packed));\n",
+ --indent * 2, "");
- struct location *loc = new_synthetic_loc (pool, *input, deref);
+ obstack_printf (pool, "%*suint%" PRIu64 "_t whole;\n",
+ indent * 2, "", loc->byte_size * 8);
+
+ obstack_printf (pool, "%*s} u;\n", --indent * 2, "");
+
+ loc = new_synthetic_loc (pool, *input, false);
+ loc->type = loc_decl;
(*input)->next = loc;
*input = loc;
}
@@ -1140,80 +1228,62 @@ base_byte_size (Dwarf_Die *typedie, struct location *origin)
FAIL (origin,
N_("cannot get byte_size attribute for type %s: %s"),
- dwarf_diename_integrate (typedie) ?: "<anonymous>",
+ dwarf_diename (typedie) ?: "<anonymous>",
dwarf_errmsg (-1));
return -1;
}
-/* Emit a code fragment like:
- { uintNN_t tmp = ...; fetch_bitfield (TARGET, tmp, B0, Bn); }
- or
- { uintNN_t tmp = ...; store_bitfield (tmp, TARGET, B0, Bn);
- ... = tmp; }
-*/
-static bool
-emit_bitfield (struct obstack *pool, int indent,
- Dwarf_Die *die, Dwarf_Word byte_size, struct location *loc,
- const char *target, bool store)
+/* Fetch the bitfield parameters. */
+static void
+get_bitfield (struct location *loc,
+ Dwarf_Die *die, Dwarf_Word *bit_offset, Dwarf_Word *bit_size)
{
- Dwarf_Word bit_offset, bit_size;
Dwarf_Attribute attr_mem;
if (dwarf_attr_integrate (die, DW_AT_bit_offset, &attr_mem) == NULL
- || dwarf_formudata (&attr_mem, &bit_offset) != 0
+ || dwarf_formudata (&attr_mem, bit_offset) != 0
|| dwarf_attr_integrate (die, DW_AT_bit_size, &attr_mem) == NULL
- || dwarf_formudata (&attr_mem, &bit_size) != 0)
+ || dwarf_formudata (&attr_mem, bit_size) != 0)
FAIL (loc, N_("cannot get bit field parameters: %s"), dwarf_errmsg (-1));
-
- /* Emit "{ uintNN_t tmp = ...;" to fetch the base type. */
-
- obstack_printf (pool, "%*s{ ", indent * 2, "");
- bool deref = emit_base_fetch (pool, byte_size, "tmp", true, loc);
-
- if (store)
- {
- obstack_printf (pool,
- "\n%*s"
- "store_bitfield (tmp, %s, %" PRIu64 ", %" PRIu64 ");\n"
- "\n%*s",
- indent * 2, "",
- target, bit_offset, bit_size,
- (indent + 1) * 2, "");
- deref = emit_base_store (pool, byte_size, "tmp", loc) || deref;
- obstack_printf (pool, "}\n");
- }
- else
- obstack_printf (pool,
- "fetch_bitfield (%s, tmp, %" PRIu64 ", %" PRIu64 "); }\n",
- target, bit_offset, bit_size);
-
- return deref;
}
-/* Translate a fragment to fetch the value of variable or member DIE
+/* Translate a fragment to fetch the base-type value of BYTE_SIZE bytes
at the *INPUT location and store it in lvalue TARGET. */
-
-void
-c_translate_fetch (struct obstack *pool, int indent,
- Dwarf_Addr dwbias __attribute__ ((unused)),
- Dwarf_Die *die, Dwarf_Die *typedie,
- struct location **input, const char *target)
+static void
+translate_base_fetch (struct obstack *pool, int indent, Dwarf_Word byte_size,
+ struct location **input, const char *target)
{
- ++indent;
+ bool deref = false;
- Dwarf_Attribute size_attr;
- Dwarf_Word byte_size;
- if (dwarf_attr_integrate (die, DW_AT_byte_size, &size_attr) == NULL
- || dwarf_formudata (&size_attr, &byte_size) != 0)
- byte_size = base_byte_size (typedie, *input);
+ if ((*input)->type == loc_noncontiguous)
+ {
+ struct location *p = (*input)->pieces;
- bool deref = false;
- if (dwarf_hasattr_integrate (die, DW_AT_bit_offset))
- /* This is a bit field. */
- deref = emit_bitfield (pool, indent, die, byte_size, *input,
- target, false);
+ declare_noncontig_union (pool, indent, input, *input);
+
+ Dwarf_Word offset = 0;
+ char piece[sizeof "u.pieces.p" + 20] = "u.pieces.p";
+ while (p != NULL)
+ {
+ struct location *newp = obstack_alloc (pool, sizeof *newp);
+ *newp = *p;
+ newp->next = NULL;
+ (*input)->next = newp;
+ *input = newp;
+
+ snprintf (&piece[sizeof "u.pieces.p" - 1], 20, "%" PRIu64, offset);
+ translate_base_fetch (pool, indent, p->byte_size, input, piece);
+ (*input)->type = loc_fragment;
+
+ offset += p->byte_size;
+ p = p->next;
+ }
+
+ obstack_printf (pool, "%*s%s = u.whole;\n", indent * 2, "", target);
+ }
else
switch (byte_size)
{
+ case 0: /* Special case, means address size. */
case 1:
case 2:
case 4:
@@ -1230,11 +1300,136 @@ c_translate_fetch (struct obstack *pool, int indent,
}
struct location *loc = new_synthetic_loc (pool, *input, deref);
+ loc->byte_size = byte_size;
loc->type = loc_final;
(*input)->next = loc;
*input = loc;
}
+/* Determine the maximum size of a base type, from some DIE in the CU. */
+static Dwarf_Word
+max_fetch_size (struct location *loc, Dwarf_Die *die)
+{
+ Dwarf_Die cu_mem;
+ uint8_t address_size;
+#define dwarf_diecu(d,m,a,n) (*m = *d, *a = 4, m) /* XXX */
+ Dwarf_Die *cu = dwarf_diecu (die, &cu_mem, &address_size, NULL);
+ if (cu == NULL)
+ FAIL (loc, N_("cannot determine CU address size from %s: %s"),
+ dwarf_diename (die), dwarf_errmsg (-1));
+
+ return address_size;
+}
+
+/* Translate a fragment to fetch the value of variable or member DIE
+ at the *INPUT location and store it in lvalue TARGET. */
+void
+c_translate_fetch (struct obstack *pool, int indent,
+ Dwarf_Addr dwbias __attribute__ ((unused)),
+ Dwarf_Die *die, Dwarf_Die *typedie,
+ struct location **input, const char *target)
+{
+ ++indent;
+
+ Dwarf_Attribute size_attr;
+ Dwarf_Word byte_size;
+ if (dwarf_attr_integrate (die, DW_AT_byte_size, &size_attr) == NULL
+ || dwarf_formudata (&size_attr, &byte_size) != 0)
+ byte_size = base_byte_size (typedie, *input);
+
+ *input = discontiguify (pool, indent, *input, byte_size,
+ max_fetch_size (*input, die));
+
+ if (dwarf_hasattr_integrate (die, DW_AT_bit_offset))
+ {
+ /* This is a bit field. Fetch the containing base type into a
+ temporary variable. */
+
+ translate_base_fetch (pool, indent, byte_size, input, "tmp");
+ (*input)->type = loc_fragment;
+ (*input)->address.declare = "tmp";
+
+ Dwarf_Word bit_offset, bit_size;
+ get_bitfield (*input, die, &bit_offset, &bit_size);
+
+ obstack_printf (pool, "%*s"
+ "fetch_bitfield (%s, tmp, %" PRIu64 ", %" PRIu64 ");\n",
+ indent *2, "", target, bit_offset, bit_size);
+
+ struct location *loc = new_synthetic_loc (pool, *input, false);
+ loc->type = loc_final;
+ (*input)->next = loc;
+ *input = loc;
+ }
+ else
+ translate_base_fetch (pool, indent, byte_size, input, target);
+}
+
+/* Translate a fragment to store RVALUE into the base-type value of
+ BYTE_SIZE bytes at the *INPUT location. */
+static void
+translate_base_store (struct obstack *pool, int indent, Dwarf_Word byte_size,
+ struct location **input, struct location *store_loc,
+ const char *rvalue)
+{
+ bool deref = false;
+
+ if (store_loc->type == loc_noncontiguous)
+ {
+ declare_noncontig_union (pool, indent, input, store_loc);
+
+ obstack_printf (pool, "%*su.whole = %s;\n", indent * 2, "", rvalue);
+ struct location *loc = new_synthetic_loc (pool, *input, deref);
+ loc->type = loc_fragment;
+ (*input)->next = loc;
+ *input = loc;
+
+ Dwarf_Word offset = 0;
+ char piece[sizeof "u.pieces.p" + 20] = "u.pieces.p";
+ for (struct location *p = store_loc->pieces; p != NULL; p = p->next)
+ {
+ struct location *newp = obstack_alloc (pool, sizeof *newp);
+ *newp = *p;
+ newp->next = NULL;
+ (*input)->next = newp;
+ *input = newp;
+
+ snprintf (&piece[sizeof "u.pieces.p" - 1], 20, "%" PRIu64, offset);
+ translate_base_store (pool, indent,
+ p->byte_size, input, *input, piece);
+ (*input)->type = loc_fragment;
+
+ offset += p->byte_size;
+ }
+
+ (*input)->type = loc_final;
+ }
+ else
+ {
+ switch (byte_size)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ obstack_printf (pool, "%*s", indent * 2, "");
+ deref = emit_base_store (pool, byte_size, rvalue, store_loc);
+ obstack_printf (pool, "\n");
+ break;
+
+ default:
+ /* Could handle this generating call to memcpy equivalent. */
+ FAIL (*input, N_("store is larger than base integer types"));
+ break;
+ }
+
+ struct location *loc = new_synthetic_loc (pool, *input, deref);
+ loc->type = loc_final;
+ (*input)->next = loc;
+ *input = loc;
+ }
+}
+
/* Translate a fragment to fetch the value of variable or member DIE
at the *INPUT location and store it in rvalue RVALUE. */
@@ -1252,32 +1447,65 @@ c_translate_store (struct obstack *pool, int indent,
|| dwarf_formudata (&size_attr, &byte_size) != 0)
byte_size = base_byte_size (typedie, *input);
- bool deref = false;
+ *input = discontiguify (pool, indent, *input, byte_size,
+ max_fetch_size (*input, die));
+
+ struct location *store_loc = *input;
+
if (dwarf_hasattr_integrate (die, DW_AT_bit_offset))
- /* This is a bit field. */
- deref = emit_bitfield (pool, indent, die, byte_size, *input, rvalue, true);
- else
- switch (byte_size)
- {
- case 1:
- case 2:
- case 4:
- case 8:
- obstack_printf (pool, "%*s", indent * 2, "");
- deref = emit_base_store (pool, byte_size, rvalue, *input);
- obstack_printf (pool, "\n");
- break;
+ {
+ /* This is a bit field. Fetch the containing base type into a
+ temporary variable. */
- default:
- /* Could handle this generating call to memcpy equivalent. */
- FAIL (*input, N_("fetch is larger than base integer types"));
- break;
- }
+ translate_base_fetch (pool, indent, byte_size, input, "tmp");
+ (*input)->type = loc_fragment;
+ (*input)->address.declare = "tmp";
- struct location *loc = new_synthetic_loc (pool, *input, deref);
- loc->type = loc_final;
- (*input)->next = loc;
- *input = loc;
+ Dwarf_Word bit_offset, bit_size;
+ get_bitfield (*input, die, &bit_offset, &bit_size);
+
+ obstack_printf (pool, "%*s"
+ "store_bitfield (tmp, %s, %" PRIu64 ", %" PRIu64 ");\n",
+ indent * 2, "", rvalue, bit_offset, bit_size);
+
+ struct location *loc = new_synthetic_loc (pool, *input, false);
+ loc->type = loc_fragment;
+ (*input)->next = loc;
+ *input = loc;
+
+ /* We have mixed RVALUE into the bits in "tmp".
+ Now we'll store "tmp" back whence we fetched it. */
+ rvalue = "tmp";
+ }
+
+ translate_base_store (pool, indent, byte_size, input, store_loc, rvalue);
+}
+
+/* Translate a fragment to dereference the given pointer type,
+ where *INPUT is the location of the pointer with that type.
+
+ We chain on a loc_address program that yields this pointer value
+ (i.e. the location of what it points to). */
+
+void
+c_translate_pointer (struct obstack *pool, int indent,
+ Dwarf_Addr dwbias __attribute__ ((unused)),
+ Dwarf_Die *typedie, struct location **input)
+{
+ assert (dwarf_tag (typedie) == DW_TAG_pointer_type);
+
+ Dwarf_Attribute attr_mem;
+ Dwarf_Word byte_size;
+ if (dwarf_attr_integrate (typedie, DW_AT_byte_size, &attr_mem) == NULL)
+ byte_size = 0;
+ else if (dwarf_formudata (&attr_mem, &byte_size) != 0)
+ FAIL (*input,
+ N_("cannot get byte_size attribute for type %s: %s"),
+ dwarf_diename (typedie) ?: "<anonymous>",
+ dwarf_errmsg (-1));
+
+ translate_base_fetch (pool, indent + 1, byte_size, input, "addr");
+ (*input)->type = loc_address;
}
@@ -1326,7 +1554,7 @@ array_stride (Dwarf_Die *typedie, struct location *origin)
if (dwarf_formudata (&attr_mem, &stride) == 0)
return stride;
FAIL (origin, N_("cannot get stride_size attribute array type %s: %s"),
- dwarf_diename_integrate (typedie) ?: "<anonymous>",
+ dwarf_diename (typedie) ?: "<anonymous>",
dwarf_errmsg (-1));
}
@@ -1334,7 +1562,7 @@ array_stride (Dwarf_Die *typedie, struct location *origin)
if (dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem) == NULL
|| dwarf_formref_die (&attr_mem, &die_mem) == NULL)
FAIL (origin, N_("cannot get element type of array type %s: %s"),
- dwarf_diename_integrate (typedie) ?: "<anonymous>",
+ dwarf_diename (typedie) ?: "<anonymous>",
dwarf_errmsg (-1));
if (dwarf_attr_integrate (&die_mem, DW_AT_byte_size, &attr_mem) != NULL)
@@ -1344,7 +1572,7 @@ array_stride (Dwarf_Die *typedie, struct location *origin)
return stride;
FAIL (origin,
N_("cannot get byte_size attribute for array element type %s: %s"),
- dwarf_diename_integrate (&die_mem) ?: "<anonymous>",
+ dwarf_diename (&die_mem) ?: "<anonymous>",
dwarf_errmsg (-1));
}
@@ -1516,17 +1744,51 @@ c_emit_location (FILE *out, struct location *loc, int indent)
{
emit ("%*s{\n", indent * 2, "");
+ bool declared_addr = false;
+ for (struct location *l = loc; l != NULL; l = l->next)
+ switch (l->type)
+ {
+ case loc_decl:
+ emit ("%s", l->address.program);
+ break;
+
+ case loc_address:
+ if (declared_addr)
+ break;
+ declared_addr = true;
+ l->address.declare = "addr";
+ case loc_fragment:
+ case loc_final:
+ if (l->address.declare != NULL)
+ {
+ if (l->byte_size == 0 || l->byte_size == (Dwarf_Word) -1)
+ emit ("%*s%s %s;\n", (indent + 1) * 2, "",
+ STACK_TYPE, l->address.declare);
+ else
+ emit ("%*suint%" PRIu64 "_t %s;\n", (indent + 1) * 2, "",
+ l->byte_size * 8, l->address.declare);
+ }
+
+ default:
+ break;
+ }
+
bool deref = false;
- for (bool declare_addr = true; loc->next != NULL; loc = loc->next)
+ for (; loc->next != NULL; loc = loc->next)
switch (loc->type)
{
case loc_address:
/* Emit the program fragment to calculate the address. */
- emit_loc_value (out, loc, indent + 1, "addr", declare_addr);
- declare_addr = false;
+ emit_loc_value (out, loc, indent + 1, "addr", false);
+ deref = deref || loc->address.used_deref;
+ break;
+
+ case loc_fragment:
+ emit ("%s", loc->address.program);
deref = deref || loc->address.used_deref;
break;
+ case loc_decl:
case loc_register:
case loc_noncontiguous:
/* These don't produce any code directly.
@@ -1544,7 +1806,7 @@ c_emit_location (FILE *out, struct location *loc, int indent)
emit ("%s%*s}\n", loc->address.program, indent * 2, "");
- return deref;
+ return deref || loc->address.used_deref;
}
#undef emit