mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
support for record extensions when using -O gen-standalone-C++
This commit is contained in:
parent
300b3788e2
commit
960931ba5c
7 changed files with 64 additions and 9 deletions
|
@ -618,11 +618,16 @@ public:
|
||||||
|
|
||||||
const detail::AttrPtr& GetAttr(detail::AttrTag a) const { return attrs ? attrs->Find(a) : detail::Attr::nil; }
|
const detail::AttrPtr& GetAttr(detail::AttrTag a) const { return attrs ? attrs->Find(a) : detail::Attr::nil; }
|
||||||
|
|
||||||
|
const detail::Location* GetLocationInfo() const { return &loc; }
|
||||||
|
|
||||||
void DescribeReST(ODesc* d, bool roles_only = false) const;
|
void DescribeReST(ODesc* d, bool roles_only = false) const;
|
||||||
|
|
||||||
TypePtr type;
|
TypePtr type;
|
||||||
detail::AttributesPtr attrs;
|
detail::AttributesPtr attrs;
|
||||||
const char* id = nullptr;
|
const char* id = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
detail::Location loc = detail::GetCurrentLocation();
|
||||||
};
|
};
|
||||||
|
|
||||||
using type_decl_list = PList<TypeDecl>;
|
using type_decl_list = PList<TypeDecl>;
|
||||||
|
|
|
@ -544,7 +544,8 @@ void FuncTypeInfo::AddInitializerVals(std::vector<std::string>& ivs) const {
|
||||||
ivs.emplace_back(Fmt(static_cast<int>(expressionless_return_okay)));
|
ivs.emplace_back(Fmt(static_cast<int>(expressionless_return_okay)));
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordTypeInfo::RecordTypeInfo(CPPCompile* _c, TypePtr _t) : AbstractTypeInfo(_c, std::move(_t)) {
|
RecordTypeInfo::RecordTypeInfo(CPPCompile* _c, TypePtr _t, int _addl_fields)
|
||||||
|
: AbstractTypeInfo(_c, std::move(_t)), addl_fields(_addl_fields) {
|
||||||
// Note, we leave init_cohort at 0 because the skeleton of this type
|
// Note, we leave init_cohort at 0 because the skeleton of this type
|
||||||
// is built in the first cohort.
|
// is built in the first cohort.
|
||||||
auto r = t->AsRecordType()->Types();
|
auto r = t->AsRecordType()->Types();
|
||||||
|
@ -574,6 +575,7 @@ RecordTypeInfo::RecordTypeInfo(CPPCompile* _c, TypePtr _t) : AbstractTypeInfo(_c
|
||||||
|
|
||||||
void RecordTypeInfo::AddInitializerVals(std::vector<std::string>& ivs) const {
|
void RecordTypeInfo::AddInitializerVals(std::vector<std::string>& ivs) const {
|
||||||
ivs.emplace_back(Fmt(c->TrackString(t->GetName())));
|
ivs.emplace_back(Fmt(c->TrackString(t->GetName())));
|
||||||
|
ivs.emplace_back(Fmt(addl_fields));
|
||||||
|
|
||||||
auto n = field_names.size();
|
auto n = field_names.size();
|
||||||
|
|
||||||
|
|
|
@ -644,11 +644,15 @@ private:
|
||||||
|
|
||||||
class RecordTypeInfo : public AbstractTypeInfo {
|
class RecordTypeInfo : public AbstractTypeInfo {
|
||||||
public:
|
public:
|
||||||
RecordTypeInfo(CPPCompile* c, TypePtr _t);
|
RecordTypeInfo(CPPCompile* c, TypePtr _t, int _addl_fields);
|
||||||
|
|
||||||
void AddInitializerVals(std::vector<std::string>& ivs) const override;
|
void AddInitializerVals(std::vector<std::string>& ivs) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// If non-zero, where additional fields begin. Only used for standalone
|
||||||
|
// compilation.
|
||||||
|
int addl_fields;
|
||||||
|
|
||||||
std::vector<std::string> field_names;
|
std::vector<std::string> field_names;
|
||||||
std::vector<TypePtr> field_types;
|
std::vector<TypePtr> field_types;
|
||||||
std::vector<int> field_attrs;
|
std::vector<int> field_attrs;
|
||||||
|
|
|
@ -383,11 +383,18 @@ TypePtr CPP_TypeInits::BuildRecordType(InitsManager* im, ValElemVec& init_vals,
|
||||||
auto r = cast_intrusive<RecordType>(inits_vec[offset]);
|
auto r = cast_intrusive<RecordType>(inits_vec[offset]);
|
||||||
ASSERT(r);
|
ASSERT(r);
|
||||||
|
|
||||||
if ( r->NumFields() == 0 ) {
|
auto addl_fields = init_vals[2];
|
||||||
|
|
||||||
|
if ( addl_fields > 0 || r->NumFields() == 0 ) {
|
||||||
|
// We shouldn't be adding fields if the record doesn't have any
|
||||||
|
// existing fields - that would reflect an initialization botch.
|
||||||
|
if ( addl_fields > 0 && r->NumFields() == 0 )
|
||||||
|
reporter->InternalError("record unexpectedly empty when adding fields");
|
||||||
|
|
||||||
type_decl_list tl;
|
type_decl_list tl;
|
||||||
|
|
||||||
auto n = init_vals.size();
|
auto n = init_vals.size();
|
||||||
auto i = 2U;
|
auto i = 3U + addl_fields * 3;
|
||||||
|
|
||||||
while ( i < n ) {
|
while ( i < n ) {
|
||||||
auto s = im->Strings(init_vals[i++]);
|
auto s = im->Strings(init_vals[i++]);
|
||||||
|
|
|
@ -189,9 +189,43 @@ shared_ptr<CPP_InitInfo> CPPCompile::RegisterType(const TypePtr& tp) {
|
||||||
|
|
||||||
processed_types[t] = nullptr;
|
processed_types[t] = nullptr;
|
||||||
|
|
||||||
|
// When doing standalone compilation, if the type is a record *and*
|
||||||
|
// (1) it's not one that we're fully generating (i.e., it's not solely
|
||||||
|
// defined in the scripts that we're compiling-to-standalone), and (2) the
|
||||||
|
// scripts we're compiling extend the record using "redef += record ...",
|
||||||
|
// then we need to track the offset where those record extensions start,
|
||||||
|
// so that when initializing the standalone code, we can add in those
|
||||||
|
// record fields.
|
||||||
|
//
|
||||||
|
// If any of those conditions don't hold, then this variable will remain 0.
|
||||||
|
int addl_fields = 0;
|
||||||
|
|
||||||
|
bool type_init_needed = standalone && obj_matches_opt_files(tp);
|
||||||
|
|
||||||
|
if ( standalone && ! type_init_needed ) {
|
||||||
|
if ( tp->Tag() == TYPE_RECORD ) {
|
||||||
|
auto tr = tp->AsRecordType();
|
||||||
|
for ( auto i = tr->NumOrigFields(); i < tr->NumFields(); ++i ) {
|
||||||
|
auto fd = tr->FieldDecl(i);
|
||||||
|
if ( filename_matches_opt_files(fd->GetLocationInfo()->filename) ) {
|
||||||
|
if ( addl_fields == 0 )
|
||||||
|
addl_fields = i;
|
||||||
|
}
|
||||||
|
else if ( addl_fields > 0 )
|
||||||
|
reporter->FatalError(
|
||||||
|
"can't compile standalone-C++ with field \"%s\" in record \"%s\" added after those introduced "
|
||||||
|
"by compiled script",
|
||||||
|
fd->id, t->GetName().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( addl_fields > 0 )
|
||||||
|
type_init_needed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shared_ptr<CPP_InitInfo> gi;
|
shared_ptr<CPP_InitInfo> gi;
|
||||||
|
|
||||||
if ( (standalone && obj_matches_opt_files(tp)) || t->GetName().empty() ) {
|
if ( type_init_needed || t->GetName().empty() ) {
|
||||||
switch ( t->Tag() ) {
|
switch ( t->Tag() ) {
|
||||||
case TYPE_ADDR:
|
case TYPE_ADDR:
|
||||||
case TYPE_ANY:
|
case TYPE_ANY:
|
||||||
|
@ -221,7 +255,7 @@ shared_ptr<CPP_InitInfo> CPPCompile::RegisterType(const TypePtr& tp) {
|
||||||
|
|
||||||
case TYPE_TABLE: gi = make_shared<TableTypeInfo>(this, tp); break;
|
case TYPE_TABLE: gi = make_shared<TableTypeInfo>(this, tp); break;
|
||||||
|
|
||||||
case TYPE_RECORD: gi = make_shared<RecordTypeInfo>(this, tp); break;
|
case TYPE_RECORD: gi = make_shared<RecordTypeInfo>(this, tp, addl_fields); break;
|
||||||
|
|
||||||
case TYPE_FUNC: gi = make_shared<FuncTypeInfo>(this, tp); break;
|
case TYPE_FUNC: gi = make_shared<FuncTypeInfo>(this, tp); break;
|
||||||
|
|
||||||
|
|
|
@ -125,13 +125,13 @@ bool should_analyze(const ScriptFuncPtr& f, const StmtPtr& body) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool obj_matches_opt_files(const Obj* obj) {
|
bool filename_matches_opt_files(const char* filename) {
|
||||||
auto& ofiles = analysis_options.only_files;
|
auto& ofiles = analysis_options.only_files;
|
||||||
|
|
||||||
if ( ofiles.empty() )
|
if ( ofiles.empty() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto fin = util::detail::normalize_path(obj->GetLocationInfo()->filename);
|
auto fin = util::detail::normalize_path(filename);
|
||||||
|
|
||||||
for ( auto& o : ofiles )
|
for ( auto& o : ofiles )
|
||||||
if ( std::regex_match(fin, o) )
|
if ( std::regex_match(fin, o) )
|
||||||
|
@ -140,6 +140,8 @@ bool obj_matches_opt_files(const Obj* obj) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool obj_matches_opt_files(const Obj* obj) { return filename_matches_opt_files(obj->GetLocationInfo()->filename); }
|
||||||
|
|
||||||
static bool optimize_AST(ScriptFuncPtr f, std::shared_ptr<ProfileFunc>& pf, std::shared_ptr<Reducer>& rc,
|
static bool optimize_AST(ScriptFuncPtr f, std::shared_ptr<ProfileFunc>& pf, std::shared_ptr<Reducer>& rc,
|
||||||
ScopePtr scope, StmtPtr& body) {
|
ScopePtr scope, StmtPtr& body) {
|
||||||
pf = std::make_shared<ProfileFunc>(f.get(), body, true);
|
pf = std::make_shared<ProfileFunc>(f.get(), body, true);
|
||||||
|
|
|
@ -254,8 +254,9 @@ extern void add_file_analysis_pattern(AnalyOpt& opts, const char* pat);
|
||||||
// it should be skipped.
|
// it should be skipped.
|
||||||
extern bool should_analyze(const ScriptFuncPtr& f, const StmtPtr& body);
|
extern bool should_analyze(const ScriptFuncPtr& f, const StmtPtr& body);
|
||||||
|
|
||||||
// True if the given object's location matches one specified by
|
// True if the given filename or object location matches one specified by
|
||||||
// --optimize-files=...
|
// --optimize-files=...
|
||||||
|
extern bool filename_matches_opt_files(const char* filename);
|
||||||
extern bool obj_matches_opt_files(const Obj* obj);
|
extern bool obj_matches_opt_files(const Obj* obj);
|
||||||
inline bool obj_matches_opt_files(const ObjPtr& obj) { return obj_matches_opt_files(obj.get()); }
|
inline bool obj_matches_opt_files(const ObjPtr& obj) { return obj_matches_opt_files(obj.get()); }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue