mirror of
https://github.com/zeek/zeek.git
synced 2025-10-12 03:28:19 +00:00
broader tracking of aggregate modifications
This commit is contained in:
parent
f0eccda180
commit
8a18d5f8a2
3 changed files with 66 additions and 45 deletions
|
@ -162,8 +162,7 @@ TraversalCode ProfileFunc::PreStmt(const Stmt* s) {
|
||||||
auto ad_stmt = static_cast<const AddDelStmt*>(s);
|
auto ad_stmt = static_cast<const AddDelStmt*>(s);
|
||||||
auto ad_e = ad_stmt->StmtExpr();
|
auto ad_e = ad_stmt->StmtExpr();
|
||||||
auto& lhs_t = ad_e->GetOp1()->GetType();
|
auto& lhs_t = ad_e->GetOp1()->GetType();
|
||||||
if ( lhs_t->Tag() == TYPE_TABLE )
|
aggr_mods.insert(lhs_t.get());
|
||||||
tbl_mods.insert(lhs_t.get());
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
|
@ -262,7 +261,10 @@ TraversalCode ProfileFunc::PreExpr(const Expr* e) {
|
||||||
// use of "=" such as in a table constructor.
|
// use of "=" such as in a table constructor.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ( lhs->Tag() == EXPR_NAME ) {
|
auto lhs_t = lhs->GetType();
|
||||||
|
|
||||||
|
switch ( lhs->Tag() ) {
|
||||||
|
case EXPR_NAME: {
|
||||||
auto id = lhs->AsNameExpr()->Id();
|
auto id = lhs->AsNameExpr()->Id();
|
||||||
TrackAssignment(id);
|
TrackAssignment(id);
|
||||||
|
|
||||||
|
@ -274,22 +276,24 @@ TraversalCode ProfileFunc::PreExpr(const Expr* e) {
|
||||||
// inside a when clause.
|
// inside a when clause.
|
||||||
when_locals.insert(id);
|
when_locals.insert(id);
|
||||||
}
|
}
|
||||||
else if ( lhs->GetType()->Tag() == TYPE_TABLE )
|
else if ( IsAggr(lhs_t->Tag()) )
|
||||||
tbl_mods.insert(lhs->GetType().get());
|
aggr_mods.insert(lhs_t.get());
|
||||||
}
|
} break;
|
||||||
else if ( lhs->Tag() == EXPR_INDEX ) {
|
|
||||||
|
case EXPR_INDEX: {
|
||||||
auto lhs_aggr = lhs->GetOp1();
|
auto lhs_aggr = lhs->GetOp1();
|
||||||
auto lhs_aggr_t = lhs_aggr->GetType();
|
auto lhs_aggr_t = lhs_aggr->GetType();
|
||||||
if ( lhs_aggr_t->Tag() == TYPE_TABLE ) {
|
|
||||||
// Determine which aggregate is being modified. For an
|
// Determine which aggregate is being modified. For an
|
||||||
// assignment "a[b] = aggr", it's not a[b]'s type but
|
// assignment "a[b] = aggr", it's not a[b]'s type but
|
||||||
// rather a's type. However, for any of the others,
|
// rather a's type. However, for any of the others,
|
||||||
// e.g. "a[b] -= aggr" it is a[b]'s type.
|
// e.g. "a[b] -= aggr" it is a[b]'s type.
|
||||||
if ( e->Tag() == EXPR_ASSIGN )
|
if ( e->Tag() == EXPR_ASSIGN )
|
||||||
tbl_mods.insert(lhs_aggr_t.get());
|
aggr_mods.insert(lhs_aggr_t.get());
|
||||||
else
|
else
|
||||||
tbl_mods.insert(lhs->GetType().get());
|
aggr_mods.insert(lhs_t.get());
|
||||||
|
|
||||||
|
if ( lhs_aggr_t->Tag() == TYPE_TABLE ) {
|
||||||
// We don't want the default recursion into the expression's
|
// We don't want the default recursion into the expression's
|
||||||
// LHS because it will treat this table modification as
|
// LHS because it will treat this table modification as
|
||||||
// a reference instead. So do it manually. Given that,
|
// a reference instead. So do it manually. Given that,
|
||||||
|
@ -303,6 +307,19 @@ TraversalCode ProfileFunc::PreExpr(const Expr* e) {
|
||||||
|
|
||||||
return TC_ABORTSTMT;
|
return TC_ABORTSTMT;
|
||||||
}
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EXPR_FIELD: aggr_mods.insert(lhs_t.get()); break;
|
||||||
|
|
||||||
|
case EXPR_LIST: {
|
||||||
|
for ( auto id : lhs->AsListExpr()->Exprs() ) {
|
||||||
|
auto id_t = id->GetType();
|
||||||
|
if ( IsAggr(id_t->Tag()) )
|
||||||
|
aggr_mods.insert(id_t.get());
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: reporter->InternalError("bad expression in ProfileFunc: %s", obj_desc(e).c_str());
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -971,6 +988,8 @@ void ProfileFuncs::ComputeSideEffects() {
|
||||||
// Weed out very-common-and-completely-safe expressions.
|
// Weed out very-common-and-completely-safe expressions.
|
||||||
if ( ! DefinitelyHasNoSideEffects(a->GetExpr()) )
|
if ( ! DefinitelyHasNoSideEffects(a->GetExpr()) )
|
||||||
candidates.insert(a);
|
candidates.insert(a);
|
||||||
|
else
|
||||||
|
printf("attribute %s definitely has no side effects\n", obj_desc(a).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1001,7 +1020,7 @@ void ProfileFuncs::ComputeSideEffects() {
|
||||||
std::unordered_set<const Type*> aggrs;
|
std::unordered_set<const Type*> aggrs;
|
||||||
bool is_unknown = true;
|
bool is_unknown = true;
|
||||||
for ( auto c : candidates ) {
|
for ( auto c : candidates ) {
|
||||||
// printf("jackpot for %s\n", obj_desc(c).c_str());
|
printf("jackpot for %s\n", obj_desc(c).c_str());
|
||||||
SetSideEffects(c, non_local_ids, aggrs, is_unknown);
|
SetSideEffects(c, non_local_ids, aggrs, is_unknown);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1026,12 +1045,12 @@ void ProfileFuncs::SetSideEffects(const Attr* a, IDSet& non_local_ids, std::unor
|
||||||
at = SideEffectsOp::READ;
|
at = SideEffectsOp::READ;
|
||||||
|
|
||||||
if ( non_local_ids.empty() && aggrs.empty() && ! is_unknown ) {
|
if ( non_local_ids.empty() && aggrs.empty() && ! is_unknown ) {
|
||||||
// printf("%s has no side effects\n", obj_desc(a).c_str());
|
printf("%s has no side effects\n", obj_desc(a).c_str());
|
||||||
// Definitely no side effects.
|
// Definitely no side effects.
|
||||||
seo_vec.push_back(std::make_shared<SideEffectsOp>());
|
seo_vec.push_back(std::make_shared<SideEffectsOp>());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// printf("%s has side effects\n", obj_desc(a).c_str());
|
printf("%s has side effects\n", obj_desc(a).c_str());
|
||||||
|
|
||||||
for ( auto ea_t : expr_attrs[a] ) {
|
for ( auto ea_t : expr_attrs[a] ) {
|
||||||
auto seo = std::make_shared<SideEffectsOp>(at, ea_t);
|
auto seo = std::make_shared<SideEffectsOp>(at, ea_t);
|
||||||
|
@ -1063,7 +1082,7 @@ bool ProfileFuncs::DefinitelyHasNoSideEffects(const ExprPtr& e) const {
|
||||||
|
|
||||||
const auto& pf = ep->second;
|
const auto& pf = ep->second;
|
||||||
|
|
||||||
if ( ! pf->NonLocalAssignees().empty() || ! pf->TableRefs().empty() || ! pf->TableMods().empty() ||
|
if ( ! pf->NonLocalAssignees().empty() || ! pf->TableRefs().empty() || ! pf->AggrMods().empty() ||
|
||||||
! pf->ScriptCalls().empty() )
|
! pf->ScriptCalls().empty() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1160,8 +1179,8 @@ bool ProfileFuncs::AssessSideEffects(const ProfileFunc* pf, IDSet& non_local_ids
|
||||||
if ( ! AssessAggrEffects(SideEffectsOp::READ, tr, nla, mod_aggrs, is_unknown) )
|
if ( ! AssessAggrEffects(SideEffectsOp::READ, tr, nla, mod_aggrs, is_unknown) )
|
||||||
return is_unknown;
|
return is_unknown;
|
||||||
|
|
||||||
for ( auto& tm : pf->TableMods() ) {
|
for ( auto& tm : pf->AggrMods() ) {
|
||||||
if ( ! AssessAggrEffects(SideEffectsOp::WRITE, tm, nla, mod_aggrs, is_unknown) )
|
if ( tm->Tag() == TYPE_TABLE && ! AssessAggrEffects(SideEffectsOp::WRITE, tm, nla, mod_aggrs, is_unknown) )
|
||||||
return is_unknown;
|
return is_unknown;
|
||||||
|
|
||||||
mod_aggrs.insert(tm);
|
mod_aggrs.insert(tm);
|
||||||
|
|
|
@ -96,7 +96,7 @@ public:
|
||||||
const std::unordered_map<const ID*, int>& Assignees() const { return assignees; }
|
const std::unordered_map<const ID*, int>& Assignees() const { return assignees; }
|
||||||
const std::unordered_set<const ID*>& NonLocalAssignees() const { return non_local_assignees; }
|
const std::unordered_set<const ID*>& NonLocalAssignees() const { return non_local_assignees; }
|
||||||
const auto& TableRefs() const { return tbl_refs; }
|
const auto& TableRefs() const { return tbl_refs; }
|
||||||
const auto& TableMods() const { return tbl_mods; }
|
const auto& AggrMods() const { return aggr_mods; }
|
||||||
const IDSet& Inits() const { return inits; }
|
const IDSet& Inits() const { return inits; }
|
||||||
const std::vector<const Stmt*>& Stmts() const { return stmts; }
|
const std::vector<const Stmt*>& Stmts() const { return stmts; }
|
||||||
const std::vector<const Expr*>& Exprs() const { return exprs; }
|
const std::vector<const Expr*>& Exprs() const { return exprs; }
|
||||||
|
@ -190,7 +190,7 @@ protected:
|
||||||
std::unordered_set<const ID*> non_local_assignees;
|
std::unordered_set<const ID*> non_local_assignees;
|
||||||
|
|
||||||
std::unordered_set<const Type*> tbl_refs;
|
std::unordered_set<const Type*> tbl_refs;
|
||||||
std::unordered_set<const Type*> tbl_mods;
|
std::unordered_set<const Type*> aggr_mods;
|
||||||
|
|
||||||
// Same for locals seen in initializations, so we can find,
|
// Same for locals seen in initializations, so we can find,
|
||||||
// for example, unused aggregates.
|
// for example, unused aggregates.
|
||||||
|
|
|
@ -1008,9 +1008,11 @@ bool CSE_ValidityChecker::CheckID(const ID* id, bool ignore_orig) const {
|
||||||
return true; // reassignment
|
return true; // reassignment
|
||||||
|
|
||||||
if ( id_t && same_type(id_t, i->GetType()) ) {
|
if ( id_t && same_type(id_t, i->GetType()) ) {
|
||||||
// printf("identifier %s (%d), start %s, end %s\n", id->Name(), ignore_orig, obj_desc(start_e).c_str(),
|
// Same-type aggregate.
|
||||||
// obj_desc(end_e).c_str()); Same-type aggregate.
|
if ( ! ignore_orig )
|
||||||
// if ( ignore_orig )
|
printf("identifier %s (%d), start %s, end %s\n", id->Name(), ignore_orig, obj_desc(start_e).c_str(),
|
||||||
|
obj_desc(end_e).c_str());
|
||||||
|
if ( ignore_orig )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue