Skip to content

Conversation

@kkjeer
Copy link
Contributor

@kkjeer kkjeer commented Apr 22, 2021

Fixes #1032

This PR refactors PreorderAST to move Coalesce, Sort, ConstantFold, Compare, Cleanup, and PrettyPrint behavior into Node subclass methods.

@kkjeer kkjeer requested review from mgrang and sulekhark April 22, 2021 19:05

// Cleanup the memory consumed by this node.
// @param[in] this is the current node of the AST.
virtual void Cleanup() {
Copy link

Choose a reason for hiding this comment

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

The Node class must have a virtual destructor otherwise when you invoke delete on the derived class object the base class destructor won't be called. I also see a compile-time warning for this:

PreorderAST.cpp:410:14: warning: deleting object of polymorphic class type ‘clang::Node’ which has non-virtual destructor might cause undefined behavior [-Wdelete-non-virtual-dtor] 410 | delete(*I);

// @param[in] Changed indicates whether a node was coalesced. We need this
// to control when to stop recursive coalescing.
// @param[in] Error indicates whether an error occurred during coalescing.
virtual void Coalesce(bool &Changed, bool &Error) { }
Copy link

@mgrang mgrang Apr 22, 2021

Choose a reason for hiding this comment

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

Ideally we should make any function which does not have an implementation in the base class a pure virtual function meaning that its implementation is present only in the derived class. For example:
virtual void Coalesce(bool &Changed, bool &Error) = 0;

But that also means we would not be able to instantiate the Node class which is not something we want.

kakje added 2 commits April 22, 2021 15:13
…ex-based for loop

This fixes a crash that would happen on Linux for certain binary operators.
// Since Children is modified within the loop, we need to evaluate
// the loop end on each iteration.
for (size_t I = 0; I != Children.size(); ++I) {
auto *Child = Children[I];
Copy link
Contributor

Choose a reason for hiding this comment

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

There is still an incorrectness here - Consider this scenario:
In the third iteration of the loop, I = 2. Child will be Children[2]. Let the coalesce function called on Child (which is now the same as Children[2]) erase Child. Because of this erasure, Children[2] will now contain what was previously Children[3]. Then the control comes out of the Coalesce function and I gets incremented to 3. In the next iteration of the loop, Children[3] will be processed while Children[2] never got processed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed offline. Summary:

Not every child of a BinaryOperatorNode B will be processed in a call to B->Coalesce(). Any children of B that were not processed during a call to B->Coalesce() will be processed during future calls to B->Coalesce() in the PreorderAST::Normalize method, which calls Root->Coalesce(), Root->Sort(), and Root->ConstantFold() in a while loop while a Changed flag is true.

In the future, we may want to rewrite the for (size_t I = 0; I != Children.size(); ++I) loop on line 259 so that all children of B are processed in a single call to B->Coalesce(). This would be done in separate PR(s).

// Remove the current node from the list of children of its parent.
// Since BParent is modified within the loop, we need to evaluate
// the loop end on each iteration.
for (auto I = BParent->Children.begin(); I != BParent->Children.end(); ++I) {
Copy link

Choose a reason for hiding this comment

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

Actually, as soon as the loop is modified we break out of the loop. So we don't really need to evaluate BParent->Children.end() on each iteration. This can be changed to:
for (auto I = BParent->Children.begin(), E != BParent->Children.end(); I != E; ++I)

@kkjeer kkjeer marked this pull request as ready for review April 24, 2021 04:50
Copy link
Contributor

@sulekhark sulekhark left a comment

Choose a reason for hiding this comment

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

LGTM!

Copy link

@mgrang mgrang left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove switch statements in PreorderAST methods

4 participants