fixes for order-of-initialization in scripts compiled to C++

annotations of such initializations to tie them to the original Zeek script
This commit is contained in:
Vern Paxson 2023-02-14 15:19:49 -08:00
parent ce7e253dfd
commit 3d0faa8cea
2 changed files with 61 additions and 25 deletions

View file

@ -18,14 +18,14 @@ string CPP_InitsInfo::Name(int index) const
void CPP_InitsInfo::AddInstance(shared_ptr<CPP_InitInfo> g) void CPP_InitsInfo::AddInstance(shared_ptr<CPP_InitInfo> g)
{ {
auto init_cohort = g->InitCohort(); auto final_init_cohort = g->FinalInitCohort();
if ( static_cast<int>(instances.size()) <= init_cohort ) if ( static_cast<int>(instances.size()) <= final_init_cohort )
instances.resize(init_cohort + 1); instances.resize(final_init_cohort + 1);
g->SetOffset(this, size++); g->SetOffset(this, size++);
instances[init_cohort].push_back(move(g)); instances[final_init_cohort].push_back(move(g));
} }
string CPP_InitsInfo::Declare() const string CPP_InitsInfo::Declare() const
@ -47,9 +47,14 @@ void CPP_InitsInfo::GenerateInitializers(CPPCompile* c)
c->IndentUp(); c->IndentUp();
c->Emit("{"); c->Emit("{");
int n = 0;
// Add each cohort as a vector element. // Add each cohort as a vector element.
for ( auto& cohort : instances ) for ( auto& cohort : instances )
{ {
if ( ++n > 1 )
c->Emit("");
c->Emit("{"); c->Emit("{");
BuildCohort(c, cohort); BuildCohort(c, cohort);
c->Emit("},"); c->Emit("},");
@ -83,11 +88,17 @@ void CPP_InitsInfo::BuildOffsetSet(CPPCompile* c)
void CPP_InitsInfo::BuildCohort(CPPCompile* c, std::vector<std::shared_ptr<CPP_InitInfo>>& cohort) void CPP_InitsInfo::BuildCohort(CPPCompile* c, std::vector<std::shared_ptr<CPP_InitInfo>>& cohort)
{ {
int n = 0;
for ( auto& co : cohort ) for ( auto& co : cohort )
{ {
vector<string> ivs; vector<string> ivs;
auto o = co->InitObj();
if ( o )
c->Emit("/* #%s: Initializing %s: */", Fmt(co->Offset()), obj_desc(o));
co->InitializerVals(ivs); co->InitializerVals(ivs);
BuildCohortElement(c, co->InitializerType(), ivs); BuildCohortElement(c, co->InitializerType(), ivs);
++n;
} }
} }
@ -137,7 +148,7 @@ string CPP_InitInfo::ValElem(CPPCompile* c, ValPtr v)
return Fmt(-1); return Fmt(-1);
} }
DescConstInfo::DescConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo() DescConstInfo::DescConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo(v)
{ {
ODesc d; ODesc d;
v->Describe(&d); v->Describe(&d);
@ -145,7 +156,7 @@ DescConstInfo::DescConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo()
init = Fmt(s); init = Fmt(s);
} }
EnumConstInfo::EnumConstInfo(CPPCompile* c, ValPtr v) EnumConstInfo::EnumConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo(v)
{ {
auto ev = v->AsEnumVal(); auto ev = v->AsEnumVal();
auto& ev_t = ev->GetType(); auto& ev_t = ev->GetType();
@ -154,7 +165,7 @@ EnumConstInfo::EnumConstInfo(CPPCompile* c, ValPtr v)
e_val = v->AsEnum(); e_val = v->AsEnum();
} }
StringConstInfo::StringConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo() StringConstInfo::StringConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo(v)
{ {
auto s = v->AsString(); auto s = v->AsString();
const char* b = (const char*)(s->Bytes()); const char* b = (const char*)(s->Bytes());
@ -163,7 +174,7 @@ StringConstInfo::StringConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo()
chars = c->TrackString(CPPEscape(b, len)); chars = c->TrackString(CPPEscape(b, len));
} }
PatternConstInfo::PatternConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo() PatternConstInfo::PatternConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo(v)
{ {
auto re = v->AsPatternVal()->Get(); auto re = v->AsPatternVal()->Get();
pattern = c->TrackString(CPPEscape(re->OrigText())); pattern = c->TrackString(CPPEscape(re->OrigText()));
@ -171,7 +182,7 @@ PatternConstInfo::PatternConstInfo(CPPCompile* c, ValPtr v) : CPP_InitInfo()
is_single_line = re->IsSingleLine(); is_single_line = re->IsSingleLine();
} }
CompoundItemInfo::CompoundItemInfo(CPPCompile* _c, ValPtr v) : CPP_InitInfo(), c(_c) CompoundItemInfo::CompoundItemInfo(CPPCompile* _c, ValPtr v) : CPP_InitInfo(v), c(_c)
{ {
auto& t = v->GetType(); auto& t = v->GetType();
type = c->TypeOffset(t); type = c->TypeOffset(t);
@ -330,7 +341,7 @@ AttrsInfo::AttrsInfo(CPPCompile* _c, const AttributesPtr& _attrs) : CompoundItem
} }
GlobalInitInfo::GlobalInitInfo(CPPCompile* c, const ID* g, string _CPP_name) GlobalInitInfo::GlobalInitInfo(CPPCompile* c, const ID* g, string _CPP_name)
: CPP_InitInfo(), CPP_name(move(_CPP_name)) : CPP_InitInfo(g), CPP_name(move(_CPP_name))
{ {
Zeek_name = g->Name(); Zeek_name = g->Name();
@ -369,7 +380,7 @@ void GlobalInitInfo::InitializerVals(std::vector<std::string>& ivs) const
} }
CallExprInitInfo::CallExprInitInfo(CPPCompile* c, ExprPtr _e, string _e_name, string _wrapper_class) CallExprInitInfo::CallExprInitInfo(CPPCompile* c, ExprPtr _e, string _e_name, string _wrapper_class)
: e(move(_e)), e_name(move(_e_name)), wrapper_class(move(_wrapper_class)) : CPP_InitInfo(_e), e(move(_e)), e_name(move(_e_name)), wrapper_class(move(_wrapper_class))
{ {
auto gi = c->RegisterType(e->GetType()); auto gi = c->RegisterType(e->GetType());
init_cohort = max(init_cohort, gi->InitCohort() + 1); init_cohort = max(init_cohort, gi->InitCohort() + 1);
@ -378,7 +389,8 @@ CallExprInitInfo::CallExprInitInfo(CPPCompile* c, ExprPtr _e, string _e_name, st
LambdaRegistrationInfo::LambdaRegistrationInfo(CPPCompile* c, string _name, FuncTypePtr ft, LambdaRegistrationInfo::LambdaRegistrationInfo(CPPCompile* c, string _name, FuncTypePtr ft,
string _wrapper_class, p_hash_type _h, string _wrapper_class, p_hash_type _h,
bool _has_captures) bool _has_captures)
: name(move(_name)), wrapper_class(move(_wrapper_class)), h(_h), has_captures(_has_captures) : CPP_InitInfo(ft), name(move(_name)), wrapper_class(move(_wrapper_class)), h(_h),
has_captures(_has_captures)
{ {
auto gi = c->RegisterType(ft); auto gi = c->RegisterType(ft);
init_cohort = max(init_cohort, gi->InitCohort() + 1); init_cohort = max(init_cohort, gi->InitCohort() + 1);
@ -440,22 +452,27 @@ void VectorTypeInfo::AddInitializerVals(std::vector<std::string>& ivs) const
ListTypeInfo::ListTypeInfo(CPPCompile* _c, TypePtr _t) ListTypeInfo::ListTypeInfo(CPPCompile* _c, TypePtr _t)
: AbstractTypeInfo(_c, move(_t)), types(t->AsTypeList()->GetTypes()) : AbstractTypeInfo(_c, move(_t)), types(t->AsTypeList()->GetTypes())
{ {
// Note, we leave init_cohort at 0 because the skeleton of this type
// is built in the first cohort.
for ( auto& tl_i : types ) for ( auto& tl_i : types )
{ {
auto gi = c->RegisterType(tl_i); auto gi = c->RegisterType(tl_i);
if ( gi ) if ( gi )
init_cohort = max(init_cohort, gi->InitCohort()); final_init_cohort = max(final_init_cohort, gi->InitCohort());
} }
if ( ! types.empty() ) if ( ! types.empty() )
++init_cohort; ++final_init_cohort;
} }
void ListTypeInfo::AddInitializerVals(std::vector<std::string>& ivs) const void ListTypeInfo::AddInitializerVals(std::vector<std::string>& ivs) const
{ {
string type_list; string type_list;
for ( auto& t : types ) for ( auto& t : types )
ivs.emplace_back(Fmt(c->TypeOffset(t))); {
auto iv = Fmt(c->TypeOffset(t));
ivs.emplace_back(iv);
}
} }
TableTypeInfo::TableTypeInfo(CPPCompile* _c, TypePtr _t) : AbstractTypeInfo(_c, move(_t)) TableTypeInfo::TableTypeInfo(CPPCompile* _c, TypePtr _t) : AbstractTypeInfo(_c, move(_t))
@ -512,6 +529,8 @@ void FuncTypeInfo::AddInitializerVals(std::vector<std::string>& ivs) const
RecordTypeInfo::RecordTypeInfo(CPPCompile* _c, TypePtr _t) : AbstractTypeInfo(_c, move(_t)) RecordTypeInfo::RecordTypeInfo(CPPCompile* _c, TypePtr _t) : AbstractTypeInfo(_c, move(_t))
{ {
// Note, we leave init_cohort at 0 because the skeleton of this type
// is built in the first cohort.
auto r = t->AsRecordType()->Types(); auto r = t->AsRecordType()->Types();
if ( ! r ) if ( ! r )
@ -523,7 +542,7 @@ RecordTypeInfo::RecordTypeInfo(CPPCompile* _c, TypePtr _t) : AbstractTypeInfo(_c
auto gi = c->RegisterType(r_i->type); auto gi = c->RegisterType(r_i->type);
if ( gi ) if ( gi )
init_cohort = max(init_cohort, gi->InitCohort()); final_init_cohort = max(final_init_cohort, gi->InitCohort());
// else it's a recursive type, no need to adjust cohort here // else it's a recursive type, no need to adjust cohort here
field_types.push_back(r_i->type); field_types.push_back(r_i->type);
@ -531,7 +550,7 @@ RecordTypeInfo::RecordTypeInfo(CPPCompile* _c, TypePtr _t) : AbstractTypeInfo(_c
if ( r_i->attrs ) if ( r_i->attrs )
{ {
gi = c->RegisterAttributes(r_i->attrs); gi = c->RegisterAttributes(r_i->attrs);
init_cohort = max(init_cohort, gi->InitCohort() + 1); final_init_cohort = max(final_init_cohort, gi->InitCohort() + 1);
field_attrs.push_back(gi->Offset()); field_attrs.push_back(gi->Offset());
} }
else else

View file

@ -116,7 +116,7 @@ public:
// The largest initialization cohort of any item in this collection. // The largest initialization cohort of any item in this collection.
int MaxCohort() const { return static_cast<int>(instances.size()) - 1; } int MaxCohort() const { return static_cast<int>(instances.size()) - 1; }
// Returns the number of initializations in this collection that below // Returns the number of initializations in this collection that belong
// to the given cohort c. // to the given cohort c.
int CohortSize(int c) const { return c > MaxCohort() ? 0 : instances[c].size(); } int CohortSize(int c) const { return c > MaxCohort() ? 0 : instances[c].size(); }
@ -258,9 +258,8 @@ public:
class CPP_InitInfo class CPP_InitInfo
{ {
public: public:
// No constructor - basic initialization happens when the object is CPP_InitInfo(const IntrusivePtr<Obj>& _o) : o(_o.get()) { }
// added via AddInstance() to a CPP_InitsInfo object, which in turn CPP_InitInfo(const Obj* _o) : o(_o) { }
// will lead to invocation of this object's SetOffset() method.
virtual ~CPP_InitInfo() { } virtual ~CPP_InitInfo() { }
@ -282,6 +281,10 @@ public:
// Returns this item's initialization cohort. // Returns this item's initialization cohort.
int InitCohort() const { return init_cohort; } int InitCohort() const { return init_cohort; }
// Returns this item's "final" initialization cohort. See
// discussion below.
int FinalInitCohort() const { return final_init_cohort ? final_init_cohort : init_cohort; }
// Returns the type used for this initializer. // Returns the type used for this initializer.
virtual std::string InitializerType() const { return "<shouldn't-be-used>"; } virtual std::string InitializerType() const { return "<shouldn't-be-used>"; }
@ -289,6 +292,8 @@ public:
// constructor parameter. // constructor parameter.
virtual void InitializerVals(std::vector<std::string>& ivs) const = 0; virtual void InitializerVals(std::vector<std::string>& ivs) const = 0;
const Obj* InitObj() const { return o; }
protected: protected:
// Returns an offset (into the run-time vector holding all Zeek // Returns an offset (into the run-time vector holding all Zeek
// constant values) corresponding to the given value. Registers // constant values) corresponding to the given value. Registers
@ -300,18 +305,27 @@ protected:
// value in their constructors. // value in their constructors.
int init_cohort = 0; int init_cohort = 0;
// Some initializers (record and list types, in particular) become
// available for other initializers to use them after the first
// cohort is initialized; however, the final initialization comes
// later. If non-zero, this variable tracks the latter.
int final_init_cohort = 0;
// Tracks the collection to which this item belongs. // Tracks the collection to which this item belongs.
const CPP_InitsInfo* inits_collection = nullptr; const CPP_InitsInfo* inits_collection = nullptr;
// Offset of this item in the collection, or -1 if no association. // Offset of this item in the collection, or -1 if no association.
int offset = -1; int offset = -1;
// Associated object. Used for annotating output.
const Obj* o;
}; };
// Information associated with initializing a basic (non-compound) constant. // Information associated with initializing a basic (non-compound) constant.
class BasicConstInfo : public CPP_InitInfo class BasicConstInfo : public CPP_InitInfo
{ {
public: public:
BasicConstInfo(std::string _val) : val(std::move(_val)) { } BasicConstInfo(std::string _val) : CPP_InitInfo(nullptr), val(std::move(_val)) { }
void InitializerVals(std::vector<std::string>& ivs) const override { ivs.emplace_back(val); } void InitializerVals(std::vector<std::string>& ivs) const override { ivs.emplace_back(val); }
@ -386,7 +400,10 @@ private:
class PortConstInfo : public CPP_InitInfo class PortConstInfo : public CPP_InitInfo
{ {
public: public:
PortConstInfo(ValPtr v) : p(static_cast<UnsignedValImplementation*>(v->AsPortVal())->Get()) { } PortConstInfo(ValPtr v)
: CPP_InitInfo(v), p(static_cast<UnsignedValImplementation*>(v->AsPortVal())->Get())
{
}
void InitializerVals(std::vector<std::string>& ivs) const override void InitializerVals(std::vector<std::string>& ivs) const override
{ {
@ -404,7 +421,7 @@ public:
// The first of these is used for items with custom Zeek types, // The first of these is used for items with custom Zeek types,
// the second when the type is generic/inapplicable. // the second when the type is generic/inapplicable.
CompoundItemInfo(CPPCompile* c, ValPtr v); CompoundItemInfo(CPPCompile* c, ValPtr v);
CompoundItemInfo(CPPCompile* _c) : c(_c) { type = -1; } CompoundItemInfo(CPPCompile* _c) : CPP_InitInfo(nullptr), c(_c) { type = -1; }
void InitializerVals(std::vector<std::string>& ivs) const override void InitializerVals(std::vector<std::string>& ivs) const override
{ {
@ -545,7 +562,7 @@ protected:
class AbstractTypeInfo : public CPP_InitInfo class AbstractTypeInfo : public CPP_InitInfo
{ {
public: public:
AbstractTypeInfo(CPPCompile* _c, TypePtr _t) : c(_c), t(std::move(_t)) { } AbstractTypeInfo(CPPCompile* _c, TypePtr _t) : CPP_InitInfo(_t), c(_c), t(std::move(_t)) { }
void InitializerVals(std::vector<std::string>& ivs) const override void InitializerVals(std::vector<std::string>& ivs) const override
{ {