Skip to content

Commit

Permalink
Fix Issue 10311 - GDB prints wrong value for variable updated from cl…
Browse files Browse the repository at this point in the history
…osure
  • Loading branch information
tramker committed Nov 8, 2014
1 parent 15b6899 commit 7298c30
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 2 deletions.
30 changes: 30 additions & 0 deletions src/backend/dwarf.c
Expand Up @@ -1256,6 +1256,36 @@ void dwarf_func_term(Symbol *sfunc)
{ // BUG: register pairs not supported in Dwarf?
infobuf->writeByte(DW_OP_reg0 + sa->Sreglsw);
}
else if (sa->Sscope && vcode == autocode)
{
assert(sa->Sscope->Stype->Tnext && sa->Sscope->Stype->Tnext->Tty == TYstruct);

/* find member offset in closure */
targ_size_t memb_off = 0;
struct_t *st = sa->Sscope->Stype->Tnext->Ttag->Sstruct; // Sscope is __closptr
for (symlist_t sl = st->Sfldlst; sl; sl = list_next(sl))
{
symbol *sf = list_symbol(sl);
if (sf->Sclass == SCmember)
{
if(strcmp(sa->Sident, sf->Sident) == 0)
{
memb_off = sf->Smemoff;
goto L2;
}
}
}
L2:
targ_size_t closptr_off = sa->Sscope->Soffset; // __closptr offset
//printf("dwarf closure: sym: %s, closptr: %s, ptr_off: %lli, memb_off: %lli\n",
// sa->Sident, sa->Sscope->Sident, closptr_off, memb_off);

infobuf->writeByte(DW_OP_fbreg);
infobuf->writesLEB128(Auto.size + BPoff - Para.size + closptr_off); // closure pointer offset from frame base
infobuf->writeByte(DW_OP_deref);
infobuf->writeByte(DW_OP_plus_uconst);
infobuf->writeuLEB128(memb_off); // closure variable offset
}
else
{
infobuf->writeByte(DW_OP_fbreg);
Expand Down
2 changes: 1 addition & 1 deletion src/backend/symbol.c
Expand Up @@ -133,7 +133,7 @@ void symbol_print(symbol *s)
#endif
dbg_printf(" Sl = %p",s->Sl);
dbg_printf(" Sr = %p\n",s->Sr);
#if SCPP
#if SCPP || MARS
if (s->Sscope)
dbg_printf(" Sscope = '%s'\n",s->Sscope->Sident);
#endif
Expand Down
24 changes: 23 additions & 1 deletion src/toir.c
Expand Up @@ -669,8 +669,20 @@ void buildClosure(FuncDeclaration *fd, IRState *irs)
* }
*/
//printf("FuncDeclaration::buildClosure() %s\n", toChars());

/* Generate type name for closure struct */
const char *name1 = "CLOSURE.";
const char *name2 = fd->toPrettyChars();
size_t namesize = strlen(name1)+strlen(name2)+1;
char *closname = (char *) calloc(namesize, sizeof(char));
strcat(strcat(closname, name1), name2);

/* Build type for closure */
type *Closstru = type_struct_class(closname, Target::ptrsize, 0, NULL, NULL, false, false, true);
symbol_struct_addField(Closstru->Ttag, "__chain", Type_toCtype(Type::tvoidptr), 0);

Symbol *sclosure;
sclosure = symbol_name("__closptr", SCauto, Type_toCtype(Type::tvoidptr));
sclosure = symbol_name("__closptr", SCauto, type_pointer(Closstru));
sclosure->Sflags |= SFLtrue | SFLfree;
symbol_add(sclosure);
irs->sclosure = sclosure;
Expand Down Expand Up @@ -734,6 +746,15 @@ void buildClosure(FuncDeclaration *fd, IRState *irs)
v->offset = offset;
offset += memsize;

/* Set Sscope to closure */
Symbol *vsym = toSymbol(v);
assert(vsym->Sscope == NULL);
vsym->Sscope = sclosure;

/* Add variable as closure type member */
symbol_struct_addField(Closstru->Ttag, vsym->Sident, vsym->Stype, v->offset);
//printf("closure field %s: memalignsize: %i, offset: %i\n", vsym->Sident, memalignsize, v->offset);

/* Can't do nrvo if the variable is put in a closure, since
* what the shidden points to may no longer exist.
*/
Expand All @@ -743,6 +764,7 @@ void buildClosure(FuncDeclaration *fd, IRState *irs)
}
}
// offset is now the size of the closure
Closstru->Ttag->Sstruct->Sstructsize = offset;

// Allocate memory for the closure
elem *e = el_long(TYsize_t, offset);
Expand Down

0 comments on commit 7298c30

Please sign in to comment.