Skip to content
This repository has been archived by the owner on Jun 20, 2019. It is now read-only.

Commit

Permalink
Remove cgraph workarounds for nested functions that have a custom sta…
Browse files Browse the repository at this point in the history
…tic chain.
  • Loading branch information
ibuclaw committed Jun 12, 2014
1 parent 54d27cc commit 8b77c00
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 119 deletions.
15 changes: 15 additions & 0 deletions gcc/d/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
2014-06-12 Iain Buclaw <ibuclaw@gdcproject.org>

* d-codegen.cc(d_decl_context): Always return parent context for
functions nested in functions.
(is_degenerate_closure): Remove function.
(needs_static_chain): Remove function.
* d-decls.cc(FuncDeclaration::toSymbol): Remove workaround for cgraph
nesting structure, saving the original context decl.
* d-lang.h(D_DECL_STATIC_CHAIN): Remove macro.
* d-objfile.cc(Symbol::Symbol): Remove ScontextDecl field.
(FuncDeclaration::toObjFile): Remove workaround for cgraph nesting
structure, restoring the original context decl. Delay building the
cgraph node until...
(d_finish_function): ... here, where the function is unnested.

2014-06-11 Iain Buclaw <ibuclaw@gdcproject.org>

* d-objfile.cc(d_finish_function): Update the callgraph to reflect
Expand Down
101 changes: 10 additions & 91 deletions gcc/d/d-codegen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,16 @@ tree
d_decl_context (Dsymbol *dsym)
{
Dsymbol *parent = dsym;
AggregateDeclaration *ad;

while ((parent = parent->toParent2()))
{
// Nested functions.
if (parent->isFuncDeclaration())
{
FuncDeclaration *fd = dsym->isFuncDeclaration();
if (fd && !needs_static_chain (fd))
return NULL_TREE;
return parent->toSymbol()->Stree;

return parent->toSymbol()->Stree;
}
else if ((ad = parent->isAggregateDeclaration()))
// Methods of classes or structs.
AggregateDeclaration *ad = parent->isAggregateDeclaration();
if (ad != NULL)
{
tree context = ad->type->toCtype();
// Want the underlying RECORD_TYPE.
Expand All @@ -58,11 +55,12 @@ d_decl_context (Dsymbol *dsym)

return context;
}
else if (parent->isModule())

// We've reached the top-level module namespace.
// Set DECL_CONTEXT as the NAMESPACE_DECL of the enclosing module,
// but only for extern(D) symbols.
if (parent->isModule())
{
// We've reached the top-level module namespace.
// Set DECL_CONTEXT as the NAMESPACE_DECL of the enclosing
// module, but only for extern(D) symbols.
Declaration *decl = dsym->isDeclaration();
if (decl != NULL && decl->linkage != LINKd)
return NULL_TREE;
Expand Down Expand Up @@ -3450,85 +3448,6 @@ get_framedecl (FuncDeclaration *inner, FuncDeclaration *outer)
}
}

// Special case: If a function returns a nested class with functions
// but there are no "closure variables" the frontend (needsClosure)
// returns false even though the nested class _is_ returned from the
// function. (See case 4 in needsClosure)
// A closure is strictly speaking not necessary, but we also can not
// use a static function chain for functions in the nested class as
// they can be called from outside. GCC's nested functions can't deal
// with those kind of functions. We have to detect them manually here
// and make sure we neither construct a static chain nor a closure.

static bool
is_degenerate_closure (FuncDeclaration *f)
{
if (!f->needsClosure() && f->closureVars.dim == 0)
{
Type *tret = ((TypeFunction *) f->type)->next;
gcc_assert(tret);
tret = tret->toBasetype();
if (tret->ty == Tclass || tret->ty == Tstruct)
{
Dsymbol *st = tret->toDsymbol(NULL);
for (Dsymbol *s = st->parent; s; s = s->parent)
{
if (s == f)
return true;
}
}
}
return false;
}

// Return true if function F needs to have the static chain passed to it.
// This only applies to nested function handling provided by the GDC
// front end (not D closures).

bool
needs_static_chain (FuncDeclaration *f)
{
Dsymbol *s;
FuncDeclaration *pf = NULL;
TemplateInstance *ti = NULL;

if (f->isNested())
{
s = f->toParent();
ti = s->isTemplateInstance();
if (ti && ti->enclosing == NULL && ti->parent->isModule())
return false;

pf = f->toParent2()->isFuncDeclaration();
if (pf && !get_frameinfo (pf)->is_closure)
return true;
}

if (f->isStatic())
return false;

s = f->toParent2();

while (s)
{
AggregateDeclaration *ad = s->isAggregateDeclaration();
if (!ad || !ad->isNested())
break;

if (!s->isTemplateInstance())
break;

s = s->toParent2();
if ((pf = s->isFuncDeclaration())
&& !get_frameinfo (pf)->is_closure
&& !is_degenerate_closure (pf))
return true;
}

return false;
}


// Construct a WrappedExp, whose components are an EXP_NODE, which contains
// a list of instructions in GCC to be passed through.

Expand Down
2 changes: 0 additions & 2 deletions gcc/d/d-codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,6 @@ extern tree build_vthis (Dsymbol *decl, FuncDeclaration *fd, Expression *e);
// Static chain for nested functions
extern tree get_frame_for_symbol (FuncDeclaration *func, Dsymbol *sym);

extern bool needs_static_chain (FuncDeclaration *f);

// Local variables
extern void build_local_var (VarDeclaration *vd, FuncDeclaration *fd);
extern tree build_local_temp (tree type);
Expand Down
8 changes: 0 additions & 8 deletions gcc/d/d-decls.cc
Original file line number Diff line number Diff line change
Expand Up @@ -328,14 +328,6 @@ FuncDeclaration::toSymbol (void)

csym->Stree = fndecl;

if (needs_static_chain (this))
{
D_DECL_STATIC_CHAIN (fndecl) = 1;
// Save context and set decl_function_context for cgraph.
csym->ScontextDecl = DECL_CONTEXT (fndecl);
DECL_CONTEXT (fndecl) = decl_function_context (fndecl);
}

TREE_TYPE (fndecl) = ftype->toCtype();
DECL_LANG_SPECIFIC (fndecl) = build_d_decl_lang_specific (this);
d_keep (fndecl);
Expand Down
3 changes: 0 additions & 3 deletions gcc/d/d-lang.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,6 @@ extern GTY(()) tree d_eh_personality_decl;
is not affected by -femit-templates. */
#define D_DECL_IS_TEMPLATE(NODE) (DECL_LANG_FLAG_1 (NODE))

/* True if a custom static chain has been set-up for function. */
#define D_DECL_STATIC_CHAIN(NODE) (DECL_LANG_FLAG_3 (FUNCTION_DECL_CHECK (NODE)))

/* The D front-end does not use the 'binding level' system for a symbol table,
It is only needed to get debugging information for local variables and
otherwise support the backend. */
Expand Down
14 changes: 2 additions & 12 deletions gcc/d/d-objfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ Symbol::Symbol (void)
this->Sreadonly = false;

this->Stree = NULL_TREE;
this->ScontextDecl = NULL_TREE;
this->SframeField = NULL_TREE;
this->SnamedResult = NULL_TREE;

Expand Down Expand Up @@ -1298,16 +1297,6 @@ FuncDeclaration::toObjFile (int)

if (!errorcount && !global.errors)
{
// Build cgraph for function.
cgraph_get_create_node (fndecl);

// Set original decl context back to true context
if (D_DECL_STATIC_CHAIN (fndecl))
{
Declaration *decl = lang_ddecl (fndecl);
DECL_CONTEXT (fndecl) = decl->toSymbol()->ScontextDecl;
}

// Dump the D-specific tree IR.
int local_dump_flags;
FILE *dump_file = dump_begin (TDI_original, &local_dump_flags);
Expand Down Expand Up @@ -1901,7 +1890,8 @@ d_finish_function (FuncDeclaration *fd)
static_dtor_list.safe_push (fd);
}

struct cgraph_node *node = cgraph_get_node (decl);
// Build cgraph for function.
struct cgraph_node *node = cgraph_get_create_node (decl);

// For nested functions update the cgraph to reflect unnesting,
// which is handled by the front-end.
Expand Down
3 changes: 0 additions & 3 deletions gcc/d/d-objfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ struct Symbol
// Our GNU backend tree for the symbol.
tree Stree;

// The real DECL_CONTEXT of the symbol, if the context of Stree differs.
tree ScontextDecl;

// FIELD_DECL in frame struct that this variable is allocated in.
tree SframeField;

Expand Down

1 comment on commit 8b77c00

@ibuclaw
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jpf91 - This commit depends on 16be749 - should have put that in the commit message.

Please sign in to comment.