Page MenuHomePhabricator

Add postorder support to RecursiveASTVisitor
ClosedPublic

Authored by teemperor on May 18 2016, 1:41 PM.

Details

Summary

This patch adds postorder traversal support to the RecursiveASTVisitor.

This feature needs to be explicitly enabled by overriding shouldTraversePostOrder()
as it has performance drawbacks for the iterative Stmt-traversal.

Diff Detail

Event Timeline

teemperor updated this revision to Diff 57660.May 18 2016, 1:41 PM
teemperor retitled this revision from to Add postorder support to RecursiveASTVisitor.
teemperor updated this object.
teemperor added a subscriber: cfe-commits.

The motivation for this patch is a hashing algorithm for all AST nodes
which reuses child hash values to be O(n) and therefore needs postorder support
(think Java's Object.hashCode() but on AST nodes as an example).

The full code that currently uses this feature can be seen here:
https://github.com/Teemperor/clang/commit/9fdb10a8a910968a795cdd48e1271fe2140fcd2f

Generally makes sense; adding d0k for additional thoughts.

bkramer edited edge metadata.May 31 2016, 2:03 AM

Having postorder traversal makes sense to me. The thing I'm worried about is how much this will bloat object code. RecursiveASTVisitor is already a major contributor to the size of clang's binary and we've hit issues with it in the past (hitting .obj size limits on Windows for example) can you show numbers of the size of clang before and after this change? Ideally in Release and Debug configurations.

If it grows it too much we'll have to find another way of enabling/disabling it.

This comment was removed by teemperor.
teemperor added a comment.EditedJun 3 2016, 12:59 PM

The previous stats were wrong (only applied this patch, not the patch using the code):

Release:
63311672 Byte -> 77212960 Byte (+22% or +13.8 MB)
Debug:
1240292520 Byte -> 1264866776 Byte (+2% or +24.6 MB)

IMO a 20% release binary size increase is not acceptable. Is there a way to compile in support only if it's actually used? Maybe some constexpr or template magic?

teemperor updated this revision to Diff 60176.Jun 9 2016, 8:00 AM
teemperor edited edge metadata.

Reduced executable size bloat. Made postorder and preorder mutually exclusive and postorder also uses the normal Visit* methods for callbacks.

teemperor added a comment.EditedJun 9 2016, 8:02 AM

Agreed. The new patch is now reusing the Visit methods so that the executable size stays the same.
The downside is that you can no longer create a single Visitor class that is both post- and preorder traversing,
but I don't think there is any major use case for that.

v.g.vassilev edited edge metadata.Jun 27 2016, 8:09 AM

@bkramer are those modifications enough to accept this patch? It is holding back quite a lot of ongoing development from @teemperor as part of his GSoC project.

bkramer accepted this revision.Jun 27 2016, 8:27 AM
bkramer edited edge metadata.

If there's no more executable size bloat this seems fine to me.

This revision is now accepted and ready to land.Jun 27 2016, 8:27 AM
rsmith added inline comments.Jun 27 2016, 12:18 PM
include/clang/AST/RecursiveASTVisitor.h
630–635

Does this really give a postorder traversal rather than some kind of postorder / reverse preorder hybrid (based on whether we use data recursion or regular recursion for different parts of the graph)?

I would expect the right way to handle this would be to call PostVisitStmt from the if (Visited) branch above, where we call dataTraverseStmtPost.

teemperor updated this revision to Diff 62015.EditedJun 27 2016, 1:50 PM
teemperor edited edge metadata.
  • Stmt traversal is now always postorder, even if child statements don't support iterative traversal (thanks Richard). The test also tests this behavior now.
rsmith accepted this revision.Jun 30 2016, 2:31 PM
rsmith edited edge metadata.
v.g.vassilev closed this revision.Jul 1 2016, 6:40 AM

Landed in r274348 and r274349.