gollvm: cleanup of Bnode tree deletion/removal utilities
Move the Bnode::destroy method into BnodeBuilder, and incorporate
support for deleting arbitrary Bnode trees (with a mix of Bstatements
and Bexpressions) instead of just expression trees. Other small
cleanups.
Change-Id: I7b4f623a6543f62720d3f734df5f8fdd28a2159d
Reviewed-on: https://go-review.googlesource.com/47910
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/llvm-gofrontend/go-llvm-bnode.cpp b/llvm-gofrontend/go-llvm-bnode.cpp
index 82ff9d8..c49bc16 100644
--- a/llvm-gofrontend/go-llvm-bnode.cpp
+++ b/llvm-gofrontend/go-llvm-bnode.cpp
@@ -1,4 +1,4 @@
-//===-- bnode.cpp - implementation of 'Bnode' class ---=======================//
+//===-- go-llvm-bnode.cpp - implementation of 'Bnode' class ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -267,8 +267,19 @@
kid->osdump(os, ilevel + 2, linemap, terse);
}
-void Bnode::destroy(Bnode *node, WhichDel which)
+void BnodeBuilder::destroy(Bnode *node, WhichDel which)
{
+ std::set<Bnode *> visited;
+ destroyRec(node, which, visited);
+}
+
+void BnodeBuilder::destroyRec(Bnode *node,
+ WhichDel which,
+ std::set<Bnode *> &visited)
+{
+ if (visited.find(node) != visited.end())
+ return;
+ visited.insert(node);
if (which != DelWrappers) {
Bexpression *expr = node->castToBexpression();
if (expr) {
@@ -279,9 +290,9 @@
}
}
for (auto &kid : node->kids_)
- destroy(kid, which);
+ destroyRec(kid, which, visited);
if (which != DelInstructions)
- delete node;
+ freeNode(node);
}
SwitchDescriptor *Bnode::getSwitchCases()
@@ -291,12 +302,6 @@
return u.swcases;
}
-// only for unit testing, not for general use.
-void Bnode::removeAllChildren()
-{
- kids_.clear();
-}
-
Blabel *Bnode::label() const
{
assert(flavor() == N_LabelStmt || flavor() == N_GotoStmt ||
@@ -369,13 +374,22 @@
swcases_.clear();
}
-void BnodeBuilder::freeExpr(Bexpression *expr)
+void BnodeBuilder::freeNode(Bnode *node)
{
- assert(expr);
- earchive_[expr->id()] = nullptr;
- if (expr->id() == earchive_.size()-1)
- earchive_.pop_back();
- delete expr;
+ assert(node);
+ Bexpression *expr = node->castToBexpression();
+ if (expr) {
+ earchive_[expr->id()] = nullptr;
+ if (expr->id() == earchive_.size()-1)
+ earchive_.pop_back();
+ delete expr;
+ } else {
+ Bstatement *stmt = node->castToBstatement();
+ sarchive_[stmt->id()] = nullptr;
+ if (stmt->id() == sarchive_.size()-1)
+ sarchive_.pop_back();
+ delete stmt;
+ }
}
void BnodeBuilder::checkTreeInteg(Bnode *node)
@@ -672,9 +686,9 @@
std::vector<Bnode *> kids = { st, expr };
Bexpression *rval =
new Bexpression(N_Compound, kids, expr->value(), expr->btype(), loc);
+ rval->setTag(expr->tag());
if (expr->varExprPending())
rval->setVarExprPending(expr->varContext());
- rval->setTag(expr->tag());
return archive(rval);
}
@@ -937,7 +951,7 @@
integrityVisitor_->deletePending(node);
Bexpression *expr = node->castToBexpression();
assert(expr); // statements not yet supported, could be if needed
- freeExpr(expr);
+ freeNode(expr);
return orphans;
}
diff --git a/llvm-gofrontend/go-llvm-bnode.h b/llvm-gofrontend/go-llvm-bnode.h
index 833d7e2..9c8ce2e 100644
--- a/llvm-gofrontend/go-llvm-bnode.h
+++ b/llvm-gofrontend/go-llvm-bnode.h
@@ -149,12 +149,6 @@
void osdump(llvm::raw_ostream &os, unsigned ilevel = 0,
Llvm_linemap *linemap = nullptr, bool terse = false);
- // Delete some or all or this Bnode and its component
- // pieces. Deallocates just the Bnode, its contained instructions,
- // or both (depending on setting of 'which'). This is used mainly in
- // unit testing.
- static void destroy(Bnode *node, WhichDel which = DelWrappers);
-
// Cast to Bexpression. Returns NULL if not correct flavor.
Bexpression *castToBexpression() const;
@@ -198,10 +192,6 @@
Bnode(const Bnode &src);
SwitchDescriptor *getSwitchCases();
- // mainly for unit testing, not for general use.
- void removeAllChildren();
-
-
private:
void replaceChild(unsigned idx, Bnode *newchild);
@@ -347,8 +337,15 @@
// var is not an unadopted temp, then NULL is returned.
Bvariable *adoptTemporaryVariable(llvm::AllocaInst *alloca);
- // Free up this expr (it is garbage). Does not free up children.
- void freeExpr(Bexpression *expr);
+ // Free up this expr or stmt (it is garbage). Does not free up children.
+ void freeNode(Bnode *node);
+
+ // Delete some or all or this Bnode and its children/contents.
+ // Here 'which' can be set to DelInstructions (deletes only the
+ // LLVM instructions found in the subtree), DelWrappers (deletes
+ // Bnodes but not instructions), or DelBoth (gets rid of nodes and
+ // instructions).
+ void destroy(Bnode *node, WhichDel which = DelWrappers);
// Clone an expression subtree.
Bexpression *cloneSubtree(Bexpression *expr);
@@ -381,6 +378,7 @@
Bexpression *cloneSub(Bexpression *expr,
std::map<llvm::Value *, llvm::Value *> &vm);
void checkTreeInteg(Bnode *node);
+ void destroyRec(Bnode *node, WhichDel which, std::set<Bnode *> &visited);
private:
std::unique_ptr<Bstatement> errorStatement_;
diff --git a/llvm-gofrontend/go-llvm-bstatement.cpp b/llvm-gofrontend/go-llvm-bstatement.cpp
index dc23b25..64180ba 100644
--- a/llvm-gofrontend/go-llvm-bstatement.cpp
+++ b/llvm-gofrontend/go-llvm-bstatement.cpp
@@ -187,8 +187,3 @@
{
vars_.push_back(var);
}
-
-void Bblock::clearStatements()
-{
- removeAllChildren();
-}
diff --git a/llvm-gofrontend/go-llvm-bstatement.h b/llvm-gofrontend/go-llvm-bstatement.h
index ecdac15..536ba0a 100644
--- a/llvm-gofrontend/go-llvm-bstatement.h
+++ b/llvm-gofrontend/go-llvm-bstatement.h
@@ -159,9 +159,6 @@
// the backend temporary_variable() method-- allow for this here.
void addTemporaryVariable(Bvariable *var);
- // Exposed for unit testing the tree integrity checker. Not for general use.
- void clearStatements();
-
private:
friend class BnodeBuilder;
Bblock(Bfunction *func,
diff --git a/llvm-gofrontend/go-llvm.cpp b/llvm-gofrontend/go-llvm.cpp
index dac46a3..0ff4173 100644
--- a/llvm-gofrontend/go-llvm.cpp
+++ b/llvm-gofrontend/go-llvm.cpp
@@ -450,7 +450,7 @@
valbtype vbt(std::make_pair(val, btype));
auto it = valueExprmap_.find(vbt);
if (it != valueExprmap_.end()) {
- nbuilder_.freeExpr(expr);
+ nbuilder_.freeNode(expr);
return it->second;
}
valueExprmap_[vbt] = expr;
@@ -2494,7 +2494,7 @@
// Steal this return.
cachedReturn_ = rst;
} else {
- Bnode::destroy(re, DelInstructions);
+ be_->nodeBuilder().destroy(re, DelInstructions);
}
llvm::BranchInst::Create(finallyBlock_, curblock);
} else {
diff --git a/unittests/BackendCore/BackendTreeIntegrity.cpp b/unittests/BackendCore/BackendTreeIntegrity.cpp
index 000d630..c0fa2dc 100644
--- a/unittests/BackendCore/BackendTreeIntegrity.cpp
+++ b/unittests/BackendCore/BackendTreeIntegrity.cpp
@@ -72,9 +72,10 @@
Bfunction *func = mkFunci32o64(be.get(), "foo");
Btype *bi64t = be->integer_type(false, 64);
Bvariable *loc1 = be->local_variable(func, "loc1", bi64t, true, loc);
+ Bvariable *loc2 = be->local_variable(func, "loc2", bi64t, true, loc);
// Create "loc1" varexpr, then supply to more than one statement
- Bexpression *ve = be->var_expression(loc1, VE_lvalue, loc);
+ Bexpression *ve = be->var_expression(loc1, VE_rvalue, loc);
Bstatement *es1 = be->expression_statement(func, ve);
Bblock *block = mkBlockFromStmt(be.get(), func, es1);
Bstatement *es2 = be->expression_statement(func, ve);
@@ -86,7 +87,9 @@
EXPECT_FALSE(result.first);
EXPECT_TRUE(containstokens(result.second, "expr has multiple parents"));
- Bexpression *ve3= be->var_expression(loc1, VE_lvalue, loc);
+ be->nodeBuilder().destroy(block, DelBoth);
+
+ Bexpression *ve3 = be->var_expression(loc2, VE_rvalue, loc);
Bstatement *es3 = be->expression_statement(func, ve3);
Bblock *block2 = mkBlockFromStmt(be.get(), func, es3);