mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Reformat Zeek in Spicy style
This largely copies over Spicy's `.clang-format` configuration file. The one place where we deviate is header include order since Zeek depends on headers being included in a certain order.
This commit is contained in:
parent
7b8e7ed72c
commit
f5a76c1aed
786 changed files with 131714 additions and 153609 deletions
|
@ -7,272 +7,254 @@
|
|||
#include "zeek/script_opt/ScriptOpt.h"
|
||||
#include "zeek/script_opt/StmtOptInfo.h"
|
||||
|
||||
namespace zeek::detail
|
||||
{
|
||||
namespace zeek::detail {
|
||||
|
||||
constexpr int MAX_INLINE_SIZE = 1000;
|
||||
|
||||
void Inliner::Analyze()
|
||||
{
|
||||
// Locate self- and indirectly recursive functions.
|
||||
void Inliner::Analyze() {
|
||||
// Locate self- and indirectly recursive functions.
|
||||
|
||||
// Maps each function to any functions that it calls, either
|
||||
// directly or (ultimately) indirectly.
|
||||
std::unordered_map<const Func*, std::unordered_set<const Func*>> call_set;
|
||||
// Maps each function to any functions that it calls, either
|
||||
// directly or (ultimately) indirectly.
|
||||
std::unordered_map<const Func*, std::unordered_set<const Func*>> call_set;
|
||||
|
||||
// Prime the call set for each function with the functions it
|
||||
// directly calls.
|
||||
for ( auto& f : funcs )
|
||||
{
|
||||
std::unordered_set<const Func*> cs;
|
||||
// Prime the call set for each function with the functions it
|
||||
// directly calls.
|
||||
for ( auto& f : funcs ) {
|
||||
std::unordered_set<const Func*> cs;
|
||||
|
||||
// Aspirational ....
|
||||
non_recursive_funcs.insert(f.Func());
|
||||
// Aspirational ....
|
||||
non_recursive_funcs.insert(f.Func());
|
||||
|
||||
for ( auto& func : f.Profile()->ScriptCalls() )
|
||||
{
|
||||
cs.insert(func);
|
||||
for ( auto& func : f.Profile()->ScriptCalls() ) {
|
||||
cs.insert(func);
|
||||
|
||||
if ( func == f.Func() )
|
||||
{
|
||||
if ( report_recursive )
|
||||
printf("%s is directly recursive\n", func->Name());
|
||||
if ( func == f.Func() ) {
|
||||
if ( report_recursive )
|
||||
printf("%s is directly recursive\n", func->Name());
|
||||
|
||||
non_recursive_funcs.erase(func);
|
||||
}
|
||||
}
|
||||
non_recursive_funcs.erase(func);
|
||||
}
|
||||
}
|
||||
|
||||
call_set[f.Func()] = cs;
|
||||
}
|
||||
call_set[f.Func()] = cs;
|
||||
}
|
||||
|
||||
// Transitive closure. If we had any self-respect, we'd implement
|
||||
// Warshall's algorithm. What we do here is feasible though since
|
||||
// Zeek call graphs tend not to be super-deep. (We could also save
|
||||
// cycles by only analyzing non-[direct-or-indirect] leaves, as
|
||||
// was computed by the previous version of this code. But in
|
||||
// practice, the execution time for this is completely dwarfed
|
||||
// by the expense of compiling inlined functions, so we keep it
|
||||
// simple.)
|
||||
// Transitive closure. If we had any self-respect, we'd implement
|
||||
// Warshall's algorithm. What we do here is feasible though since
|
||||
// Zeek call graphs tend not to be super-deep. (We could also save
|
||||
// cycles by only analyzing non-[direct-or-indirect] leaves, as
|
||||
// was computed by the previous version of this code. But in
|
||||
// practice, the execution time for this is completely dwarfed
|
||||
// by the expense of compiling inlined functions, so we keep it
|
||||
// simple.)
|
||||
|
||||
// Whether a change has occurred.
|
||||
bool did_addition = true;
|
||||
while ( did_addition )
|
||||
{
|
||||
did_addition = false;
|
||||
// Whether a change has occurred.
|
||||
bool did_addition = true;
|
||||
while ( did_addition ) {
|
||||
did_addition = false;
|
||||
|
||||
// Loop over all the functions of interest.
|
||||
for ( auto& c : call_set )
|
||||
{
|
||||
// For each of them, loop over the set of functions
|
||||
// they call.
|
||||
// Loop over all the functions of interest.
|
||||
for ( auto& c : call_set ) {
|
||||
// For each of them, loop over the set of functions
|
||||
// they call.
|
||||
|
||||
std::unordered_set<const Func*> addls;
|
||||
std::unordered_set<const Func*> addls;
|
||||
|
||||
for ( auto& cc : c.second )
|
||||
{
|
||||
if ( cc == c.first )
|
||||
// Don't loop over ourselves.
|
||||
continue;
|
||||
for ( auto& cc : c.second ) {
|
||||
if ( cc == c.first )
|
||||
// Don't loop over ourselves.
|
||||
continue;
|
||||
|
||||
// For each called function, pull up *its*
|
||||
// set of called functions.
|
||||
for ( auto& ccc : call_set[cc] )
|
||||
{
|
||||
// For each of those, if we don't
|
||||
// already have it, add it.
|
||||
if ( c.second.count(ccc) > 0 )
|
||||
// We already have it.
|
||||
continue;
|
||||
// For each called function, pull up *its*
|
||||
// set of called functions.
|
||||
for ( auto& ccc : call_set[cc] ) {
|
||||
// For each of those, if we don't
|
||||
// already have it, add it.
|
||||
if ( c.second.count(ccc) > 0 )
|
||||
// We already have it.
|
||||
continue;
|
||||
|
||||
addls.insert(ccc);
|
||||
addls.insert(ccc);
|
||||
|
||||
if ( ccc != c.first )
|
||||
// Non-recursive.
|
||||
continue;
|
||||
if ( ccc != c.first )
|
||||
// Non-recursive.
|
||||
continue;
|
||||
|
||||
if ( report_recursive )
|
||||
printf("%s is indirectly recursive, called by %s\n", c.first->Name(),
|
||||
cc->Name());
|
||||
if ( report_recursive )
|
||||
printf("%s is indirectly recursive, called by %s\n", c.first->Name(), cc->Name());
|
||||
|
||||
non_recursive_funcs.erase(c.first);
|
||||
non_recursive_funcs.erase(cc);
|
||||
}
|
||||
}
|
||||
non_recursive_funcs.erase(c.first);
|
||||
non_recursive_funcs.erase(cc);
|
||||
}
|
||||
}
|
||||
|
||||
if ( addls.size() > 0 )
|
||||
{
|
||||
did_addition = true;
|
||||
if ( addls.size() > 0 ) {
|
||||
did_addition = true;
|
||||
|
||||
for ( auto& a : addls )
|
||||
c.second.insert(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
for ( auto& a : addls )
|
||||
c.second.insert(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto& f : funcs )
|
||||
{
|
||||
const auto& func_ptr = f.FuncPtr();
|
||||
const auto& func = func_ptr.get();
|
||||
const auto& body = f.Body();
|
||||
for ( auto& f : funcs ) {
|
||||
const auto& func_ptr = f.FuncPtr();
|
||||
const auto& func = func_ptr.get();
|
||||
const auto& body = f.Body();
|
||||
|
||||
if ( ! should_analyze(func_ptr, body) )
|
||||
continue;
|
||||
if ( ! should_analyze(func_ptr, body) )
|
||||
continue;
|
||||
|
||||
// Candidates are non-event, non-hook, non-recursive,
|
||||
// non-compiled functions ...
|
||||
if ( func->Flavor() != FUNC_FLAVOR_FUNCTION )
|
||||
continue;
|
||||
// Candidates are non-event, non-hook, non-recursive,
|
||||
// non-compiled functions ...
|
||||
if ( func->Flavor() != FUNC_FLAVOR_FUNCTION )
|
||||
continue;
|
||||
|
||||
if ( non_recursive_funcs.count(func) == 0 )
|
||||
continue;
|
||||
if ( non_recursive_funcs.count(func) == 0 )
|
||||
continue;
|
||||
|
||||
if ( body->Tag() == STMT_CPP )
|
||||
continue;
|
||||
if ( body->Tag() == STMT_CPP )
|
||||
continue;
|
||||
|
||||
inline_ables.insert(func);
|
||||
}
|
||||
inline_ables.insert(func);
|
||||
}
|
||||
|
||||
for ( auto& f : funcs )
|
||||
if ( should_analyze(f.FuncPtr(), f.Body()) )
|
||||
InlineFunction(&f);
|
||||
}
|
||||
for ( auto& f : funcs )
|
||||
if ( should_analyze(f.FuncPtr(), f.Body()) )
|
||||
InlineFunction(&f);
|
||||
}
|
||||
|
||||
void Inliner::InlineFunction(FuncInfo* f)
|
||||
{
|
||||
max_inlined_frame_size = 0;
|
||||
void Inliner::InlineFunction(FuncInfo* f) {
|
||||
max_inlined_frame_size = 0;
|
||||
|
||||
// It's important that we take the current frame size from the
|
||||
// *scope* and not f->Func(). The latter tracks the maximum required
|
||||
// across all bodies, but we want to track the size for this
|
||||
// particular body.
|
||||
curr_frame_size = f->Scope()->Length();
|
||||
// It's important that we take the current frame size from the
|
||||
// *scope* and not f->Func(). The latter tracks the maximum required
|
||||
// across all bodies, but we want to track the size for this
|
||||
// particular body.
|
||||
curr_frame_size = f->Scope()->Length();
|
||||
|
||||
auto oi = f->Body()->GetOptInfo();
|
||||
num_stmts = oi->num_stmts;
|
||||
num_exprs = oi->num_exprs;
|
||||
auto oi = f->Body()->GetOptInfo();
|
||||
num_stmts = oi->num_stmts;
|
||||
num_exprs = oi->num_exprs;
|
||||
|
||||
f->Body()->Inline(this);
|
||||
f->Body()->Inline(this);
|
||||
|
||||
oi->num_stmts = num_stmts;
|
||||
oi->num_exprs = num_exprs;
|
||||
oi->num_stmts = num_stmts;
|
||||
oi->num_exprs = num_exprs;
|
||||
|
||||
int new_frame_size = curr_frame_size + max_inlined_frame_size;
|
||||
int new_frame_size = curr_frame_size + max_inlined_frame_size;
|
||||
|
||||
if ( new_frame_size > f->Func()->FrameSize() )
|
||||
f->Func()->SetFrameSize(new_frame_size);
|
||||
}
|
||||
if ( new_frame_size > f->Func()->FrameSize() )
|
||||
f->Func()->SetFrameSize(new_frame_size);
|
||||
}
|
||||
|
||||
ExprPtr Inliner::CheckForInlining(CallExprPtr c)
|
||||
{
|
||||
auto f = c->Func();
|
||||
ExprPtr Inliner::CheckForInlining(CallExprPtr c) {
|
||||
auto f = c->Func();
|
||||
|
||||
if ( f->Tag() != EXPR_NAME )
|
||||
// We don't inline indirect calls.
|
||||
return c;
|
||||
if ( f->Tag() != EXPR_NAME )
|
||||
// We don't inline indirect calls.
|
||||
return c;
|
||||
|
||||
auto n = f->AsNameExpr();
|
||||
auto func = n->Id();
|
||||
auto n = f->AsNameExpr();
|
||||
auto func = n->Id();
|
||||
|
||||
if ( ! func->IsGlobal() )
|
||||
return c;
|
||||
if ( ! func->IsGlobal() )
|
||||
return c;
|
||||
|
||||
const auto& func_v = func->GetVal();
|
||||
if ( ! func_v )
|
||||
return c;
|
||||
const auto& func_v = func->GetVal();
|
||||
if ( ! func_v )
|
||||
return c;
|
||||
|
||||
auto function = func_v->AsFunc();
|
||||
auto function = func_v->AsFunc();
|
||||
|
||||
if ( function->GetKind() != Func::SCRIPT_FUNC )
|
||||
return c;
|
||||
if ( function->GetKind() != Func::SCRIPT_FUNC )
|
||||
return c;
|
||||
|
||||
auto func_vf = static_cast<ScriptFunc*>(function);
|
||||
auto func_vf = static_cast<ScriptFunc*>(function);
|
||||
|
||||
if ( inline_ables.count(func_vf) == 0 )
|
||||
return c;
|
||||
if ( inline_ables.count(func_vf) == 0 )
|
||||
return c;
|
||||
|
||||
if ( c->IsInWhen() )
|
||||
{
|
||||
// Don't inline these, as doing so requires propagating
|
||||
// the in-when attribute to the inlined function body.
|
||||
skipped_inlining.insert(func_vf);
|
||||
return c;
|
||||
}
|
||||
if ( c->IsInWhen() ) {
|
||||
// Don't inline these, as doing so requires propagating
|
||||
// the in-when attribute to the inlined function body.
|
||||
skipped_inlining.insert(func_vf);
|
||||
return c;
|
||||
}
|
||||
|
||||
// Check for mismatches in argument count due to single-arg-of-type-any
|
||||
// loophole used for variadic BiFs. (The issue isn't calls to the
|
||||
// BiFs, which won't happen here, but instead to script functions that
|
||||
// are misusing/abusing the loophole.)
|
||||
if ( function->GetType()->Params()->NumFields() == 1 && c->Args()->Exprs().size() != 1 )
|
||||
{
|
||||
skipped_inlining.insert(func_vf);
|
||||
return c;
|
||||
}
|
||||
// Check for mismatches in argument count due to single-arg-of-type-any
|
||||
// loophole used for variadic BiFs. (The issue isn't calls to the
|
||||
// BiFs, which won't happen here, but instead to script functions that
|
||||
// are misusing/abusing the loophole.)
|
||||
if ( function->GetType()->Params()->NumFields() == 1 && c->Args()->Exprs().size() != 1 ) {
|
||||
skipped_inlining.insert(func_vf);
|
||||
return c;
|
||||
}
|
||||
|
||||
// We're going to inline the body, unless it's too large.
|
||||
auto body = func_vf->GetBodies()[0].stmts; // there's only 1 body
|
||||
auto oi = body->GetOptInfo();
|
||||
// We're going to inline the body, unless it's too large.
|
||||
auto body = func_vf->GetBodies()[0].stmts; // there's only 1 body
|
||||
auto oi = body->GetOptInfo();
|
||||
|
||||
if ( num_stmts + oi->num_stmts + num_exprs + oi->num_exprs > MAX_INLINE_SIZE )
|
||||
{
|
||||
skipped_inlining.insert(func_vf);
|
||||
return nullptr; // signals "stop inlining"
|
||||
}
|
||||
if ( num_stmts + oi->num_stmts + num_exprs + oi->num_exprs > MAX_INLINE_SIZE ) {
|
||||
skipped_inlining.insert(func_vf);
|
||||
return nullptr; // signals "stop inlining"
|
||||
}
|
||||
|
||||
did_inline.insert(func_vf);
|
||||
did_inline.insert(func_vf);
|
||||
|
||||
num_stmts += oi->num_stmts;
|
||||
num_exprs += oi->num_exprs;
|
||||
num_stmts += oi->num_stmts;
|
||||
num_exprs += oi->num_exprs;
|
||||
|
||||
auto body_dup = body->Duplicate();
|
||||
body_dup->GetOptInfo()->num_stmts = oi->num_stmts;
|
||||
body_dup->GetOptInfo()->num_exprs = oi->num_exprs;
|
||||
auto body_dup = body->Duplicate();
|
||||
body_dup->GetOptInfo()->num_stmts = oi->num_stmts;
|
||||
body_dup->GetOptInfo()->num_exprs = oi->num_exprs;
|
||||
|
||||
// Getting the names of the parameters is tricky. It's tempting
|
||||
// to take them from the function's type declaration, but alas
|
||||
// Zeek allows forward-declaring a function with one set of parameter
|
||||
// names and then defining a later instance of it with different
|
||||
// names, as long as the types match. So we have to glue together
|
||||
// the type declaration, which gives us the number of parameters,
|
||||
// with the scope, which gives us all the variables declared in
|
||||
// the function, *using the knowledge that the parameters are
|
||||
// declared first*.
|
||||
auto scope = func_vf->GetScope();
|
||||
auto& vars = scope->OrderedVars();
|
||||
int nparam = func_vf->GetType()->Params()->NumFields();
|
||||
// Getting the names of the parameters is tricky. It's tempting
|
||||
// to take them from the function's type declaration, but alas
|
||||
// Zeek allows forward-declaring a function with one set of parameter
|
||||
// names and then defining a later instance of it with different
|
||||
// names, as long as the types match. So we have to glue together
|
||||
// the type declaration, which gives us the number of parameters,
|
||||
// with the scope, which gives us all the variables declared in
|
||||
// the function, *using the knowledge that the parameters are
|
||||
// declared first*.
|
||||
auto scope = func_vf->GetScope();
|
||||
auto& vars = scope->OrderedVars();
|
||||
int nparam = func_vf->GetType()->Params()->NumFields();
|
||||
|
||||
std::vector<IDPtr> params;
|
||||
params.reserve(nparam);
|
||||
std::vector<IDPtr> params;
|
||||
params.reserve(nparam);
|
||||
|
||||
for ( int i = 0; i < nparam; ++i )
|
||||
params.emplace_back(vars[i]);
|
||||
for ( int i = 0; i < nparam; ++i )
|
||||
params.emplace_back(vars[i]);
|
||||
|
||||
// Recursively inline the body. This is safe to do because we've
|
||||
// ensured there are no recursive loops ... but we have to be
|
||||
// careful in accounting for the frame sizes.
|
||||
int frame_size = func_vf->FrameSize();
|
||||
// Recursively inline the body. This is safe to do because we've
|
||||
// ensured there are no recursive loops ... but we have to be
|
||||
// careful in accounting for the frame sizes.
|
||||
int frame_size = func_vf->FrameSize();
|
||||
|
||||
int hold_curr_frame_size = curr_frame_size;
|
||||
curr_frame_size = frame_size;
|
||||
int hold_curr_frame_size = curr_frame_size;
|
||||
curr_frame_size = frame_size;
|
||||
|
||||
int hold_max_inlined_frame_size = max_inlined_frame_size;
|
||||
max_inlined_frame_size = 0;
|
||||
int hold_max_inlined_frame_size = max_inlined_frame_size;
|
||||
max_inlined_frame_size = 0;
|
||||
|
||||
body_dup->Inline(this);
|
||||
body_dup->Inline(this);
|
||||
|
||||
curr_frame_size = hold_curr_frame_size;
|
||||
curr_frame_size = hold_curr_frame_size;
|
||||
|
||||
int new_frame_size = frame_size + max_inlined_frame_size;
|
||||
if ( new_frame_size > hold_max_inlined_frame_size )
|
||||
max_inlined_frame_size = new_frame_size;
|
||||
else
|
||||
max_inlined_frame_size = hold_max_inlined_frame_size;
|
||||
int new_frame_size = frame_size + max_inlined_frame_size;
|
||||
if ( new_frame_size > hold_max_inlined_frame_size )
|
||||
max_inlined_frame_size = new_frame_size;
|
||||
else
|
||||
max_inlined_frame_size = hold_max_inlined_frame_size;
|
||||
|
||||
auto t = c->GetType();
|
||||
auto ie = make_intrusive<InlineExpr>(c->ArgsPtr(), std::move(params), body_dup, curr_frame_size,
|
||||
t);
|
||||
ie->SetOriginal(c);
|
||||
auto t = c->GetType();
|
||||
auto ie = make_intrusive<InlineExpr>(c->ArgsPtr(), std::move(params), body_dup, curr_frame_size, t);
|
||||
ie->SetOriginal(c);
|
||||
|
||||
return ie;
|
||||
}
|
||||
return ie;
|
||||
}
|
||||
|
||||
} // namespace zeek::detail
|
||||
} // namespace zeek::detail
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue