mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +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::Location* GetLocationInfo() const { return &loc; }
|
||||
|
||||
void DescribeReST(ODesc* d, bool roles_only = false) const;
|
||||
|
||||
TypePtr type;
|
||||
detail::AttributesPtr attrs;
|
||||
const char* id = nullptr;
|
||||
|
||||
private:
|
||||
detail::Location loc = detail::GetCurrentLocation();
|
||||
};
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
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
|
||||
// is built in the first cohort.
|
||||
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 {
|
||||
ivs.emplace_back(Fmt(c->TrackString(t->GetName())));
|
||||
ivs.emplace_back(Fmt(addl_fields));
|
||||
|
||||
auto n = field_names.size();
|
||||
|
||||
|
|
|
@ -644,11 +644,15 @@ private:
|
|||
|
||||
class RecordTypeInfo : public AbstractTypeInfo {
|
||||
public:
|
||||
RecordTypeInfo(CPPCompile* c, TypePtr _t);
|
||||
RecordTypeInfo(CPPCompile* c, TypePtr _t, int _addl_fields);
|
||||
|
||||
void AddInitializerVals(std::vector<std::string>& ivs) const override;
|
||||
|
||||
private:
|
||||
// If non-zero, where additional fields begin. Only used for standalone
|
||||
// compilation.
|
||||
int addl_fields;
|
||||
|
||||
std::vector<std::string> field_names;
|
||||
std::vector<TypePtr> field_types;
|
||||
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]);
|
||||
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;
|
||||
|
||||
auto n = init_vals.size();
|
||||
auto i = 2U;
|
||||
auto i = 3U + addl_fields * 3;
|
||||
|
||||
while ( i < n ) {
|
||||
auto s = im->Strings(init_vals[i++]);
|
||||
|
|
|
@ -189,9 +189,43 @@ shared_ptr<CPP_InitInfo> CPPCompile::RegisterType(const TypePtr& tp) {
|
|||
|
||||
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;
|
||||
|
||||
if ( (standalone && obj_matches_opt_files(tp)) || t->GetName().empty() ) {
|
||||
if ( type_init_needed || t->GetName().empty() ) {
|
||||
switch ( t->Tag() ) {
|
||||
case TYPE_ADDR:
|
||||
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_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;
|
||||
|
||||
|
|
|
@ -125,13 +125,13 @@ bool should_analyze(const ScriptFuncPtr& f, const StmtPtr& body) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool obj_matches_opt_files(const Obj* obj) {
|
||||
bool filename_matches_opt_files(const char* filename) {
|
||||
auto& ofiles = analysis_options.only_files;
|
||||
|
||||
if ( ofiles.empty() )
|
||||
return false;
|
||||
|
||||
auto fin = util::detail::normalize_path(obj->GetLocationInfo()->filename);
|
||||
auto fin = util::detail::normalize_path(filename);
|
||||
|
||||
for ( auto& o : ofiles )
|
||||
if ( std::regex_match(fin, o) )
|
||||
|
@ -140,6 +140,8 @@ bool obj_matches_opt_files(const Obj* obj) {
|
|||
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,
|
||||
ScopePtr scope, StmtPtr& body) {
|
||||
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.
|
||||
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=...
|
||||
extern bool filename_matches_opt_files(const char* filename);
|
||||
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()); }
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue