extensive rewrite of generation & execution of run-time initialization

This commit is contained in:
Vern Paxson 2021-11-07 17:00:19 -08:00
parent bc3bf4ea6c
commit e1a760e674
26 changed files with 3459 additions and 1580 deletions

View file

@ -4,55 +4,26 @@
#include "zeek/RE.h"
#include "zeek/script_opt/CPP/Compile.h"
using namespace std;
namespace zeek::detail
{
using namespace std;
string CPPCompile::BuildConstant(const Obj* parent, const ValPtr& vp)
shared_ptr<CPP_InitInfo> CPPCompile::RegisterConstant(const ValPtr& vp, int& consts_offset)
{
if ( ! vp )
return "nullptr";
// Make sure the value pointer, which might be transient
// in construction, sticks around so we can track its
// value.
cv_indices.push_back(vp);
if ( AddConstant(vp) )
{
auto v = vp.get();
AddInit(parent);
NoteInitDependency(parent, v);
// Make sure the value pointer, which might be transient
// in construction, sticks around so we can track its
// value.
cv_indices.push_back(vp);
return const_vals[v];
}
else
return NativeToGT(GenVal(vp), vp->GetType(), GEN_VAL_PTR);
}
void CPPCompile::AddConstant(const ConstExpr* c)
{
auto v = c->ValuePtr();
if ( AddConstant(v) )
{
AddInit(c);
NoteInitDependency(c, v.get());
}
}
bool CPPCompile::AddConstant(const ValPtr& vp)
{
auto v = vp.get();
if ( IsNativeType(v->GetType()) )
// These we instantiate directly.
return false;
if ( const_vals.count(v) > 0 )
{
// Already did this one.
return true;
consts_offset = const_offsets[v];
return const_vals[v];
}
// Formulate a key that's unique per distinct constant.
@ -82,213 +53,100 @@ bool CPPCompile::AddConstant(const ValPtr& vp)
if ( constants.count(c_desc) > 0 )
{
const_vals[v] = constants[c_desc];
auto orig_v = constants_to_vals[c_desc];
ASSERT(v != orig_v);
AddInit(v);
NoteInitDependency(v, orig_v);
return true;
consts_offset = const_offsets[v] = constants_offsets[c_desc];
return const_vals[v];
}
// Need a C++ global for this constant.
auto const_name = string("CPP__const__") + Fmt(int(constants.size()));
const_vals[v] = constants[c_desc] = const_name;
constants_to_vals[c_desc] = v;
auto tag = t->Tag();
auto const_name = const_info[tag]->NextName();
shared_ptr<CPP_InitInfo> gi;
switch ( tag )
{
case TYPE_STRING:
AddStringConstant(vp, const_name);
case TYPE_BOOL:
gi = make_shared<BasicConstInfo>(vp->AsBool() ? "true" : "false");
break;
case TYPE_PATTERN:
AddPatternConstant(vp, const_name);
case TYPE_INT:
gi = make_shared<BasicConstInfo>(to_string(vp->AsInt()));
break;
case TYPE_LIST:
AddListConstant(vp, const_name);
case TYPE_COUNT:
gi = make_shared<BasicConstInfo>(to_string(vp->AsCount()) + "ULL");
break;
case TYPE_RECORD:
AddRecordConstant(vp, const_name);
case TYPE_DOUBLE:
gi = make_shared<BasicConstInfo>(to_string(vp->AsDouble()));
break;
case TYPE_TABLE:
AddTableConstant(vp, const_name);
case TYPE_TIME:
gi = make_shared<BasicConstInfo>(to_string(vp->AsDouble()));
break;
case TYPE_VECTOR:
AddVectorConstant(vp, const_name);
case TYPE_INTERVAL:
gi = make_shared<BasicConstInfo>(to_string(vp->AsDouble()));
break;
case TYPE_ADDR:
case TYPE_SUBNET:
{
auto prefix = (tag == TYPE_ADDR) ? "Addr" : "SubNet";
Emit("%sValPtr %s;", prefix, const_name);
ODesc d;
v->Describe(&d);
AddInit(v, const_name,
string("make_intrusive<") + prefix + "Val>(\"" + d.Description() + "\")");
}
gi = make_shared<DescConstInfo>(this, vp);
break;
case TYPE_FUNC:
Emit("FuncValPtr %s;", const_name);
case TYPE_SUBNET:
gi = make_shared<DescConstInfo>(this, vp);
break;
// We can't generate the initialization now because it
// depends on first having compiled the associated body,
// so we know its hash. So for now we just note it
// to deal with later.
func_vars[v->AsFuncVal()] = const_name;
case TYPE_ENUM:
gi = make_shared<EnumConstInfo>(this, vp);
break;
case TYPE_STRING:
gi = make_shared<StringConstInfo>(this, vp);
break;
case TYPE_PATTERN:
gi = make_shared<PatternConstInfo>(this, vp);
break;
case TYPE_PORT:
gi = make_shared<PortConstInfo>(vp);
break;
case TYPE_LIST:
gi = make_shared<ListConstInfo>(this, vp);
break;
case TYPE_VECTOR:
gi = make_shared<VectorConstInfo>(this, vp);
break;
case TYPE_RECORD:
gi = make_shared<RecordConstInfo>(this, vp);
break;
case TYPE_TABLE:
gi = make_shared<TableConstInfo>(this, vp);
break;
case TYPE_FILE:
{
Emit("FileValPtr %s;", const_name);
gi = make_shared<FileConstInfo>(this, vp);
break;
auto f = cast_intrusive<FileVal>(vp)->Get();
AddInit(v, const_name,
string("make_intrusive<FileVal>(") + "make_intrusive<File>(\"" + f->Name() +
"\", \"w\"))");
}
case TYPE_FUNC:
gi = make_shared<FuncConstInfo>(this, vp);
break;
default:
reporter->InternalError("bad constant type in CPPCompile::AddConstant");
break;
}
return true;
}
const_info[tag]->AddInstance(gi);
const_vals[v] = constants[c_desc] = gi;
void CPPCompile::AddStringConstant(const ValPtr& v, string& const_name)
{
Emit("StringValPtr %s;", const_name);
consts_offset = const_offsets[v] = constants_offsets[c_desc] = consts.size();
consts.emplace_back(pair(tag, gi->Offset()));
auto s = v->AsString();
const char* b = (const char*)(s->Bytes());
auto len = s->Len();
AddInit(v, const_name, GenString(b, len));
}
void CPPCompile::AddPatternConstant(const ValPtr& v, string& const_name)
{
Emit("PatternValPtr %s;", const_name);
auto re = v->AsPatternVal()->Get();
AddInit(v, string("{ auto re = new RE_Matcher(") + CPPEscape(re->OrigText()) + ");");
if ( re->IsCaseInsensitive() )
AddInit(v, "re->MakeCaseInsensitive();");
AddInit(v, "re->Compile();");
AddInit(v, const_name, "make_intrusive<PatternVal>(re)");
AddInit(v, "}");
}
void CPPCompile::AddListConstant(const ValPtr& v, string& const_name)
{
Emit("ListValPtr %s;", const_name);
// No initialization dependency on the main type since we don't
// use the underlying TypeList. However, we *do* use the types of
// the elements.
AddInit(v, const_name, string("make_intrusive<ListVal>(TYPE_ANY)"));
auto lv = cast_intrusive<ListVal>(v);
auto n = lv->Length();
for ( auto i = 0; i < n; ++i )
{
const auto& l_i = lv->Idx(i);
auto l_i_c = BuildConstant(v, l_i);
AddInit(v, const_name + "->Append(" + l_i_c + ");");
NoteInitDependency(v, TypeRep(l_i->GetType()));
}
}
void CPPCompile::AddRecordConstant(const ValPtr& v, string& const_name)
{
const auto& t = v->GetType();
Emit("RecordValPtr %s;", const_name);
NoteInitDependency(v, TypeRep(t));
AddInit(v, const_name,
string("make_intrusive<RecordVal>(") + "cast_intrusive<RecordType>(" + GenTypeName(t) +
"))");
auto r = cast_intrusive<RecordVal>(v);
auto n = r->NumFields();
for ( auto i = 0u; i < n; ++i )
{
const auto& r_i = r->GetField(i);
if ( r_i )
{
auto r_i_c = BuildConstant(v, r_i);
AddInit(v, const_name + "->Assign(" + Fmt(static_cast<int>(i)) + ", " + r_i_c + ");");
}
}
}
void CPPCompile::AddTableConstant(const ValPtr& v, string& const_name)
{
const auto& t = v->GetType();
Emit("TableValPtr %s;", const_name);
NoteInitDependency(v, TypeRep(t));
AddInit(v, const_name,
string("make_intrusive<TableVal>(") + "cast_intrusive<TableType>(" + GenTypeName(t) +
"))");
auto tv = cast_intrusive<TableVal>(v);
auto tv_map = tv->ToMap();
for ( auto& tv_i : tv_map )
{
auto ind = BuildConstant(v, tv_i.first);
auto val = BuildConstant(v, tv_i.second);
AddInit(v, const_name + "->Assign(" + ind + ", " + val + ");");
}
}
void CPPCompile::AddVectorConstant(const ValPtr& v, string& const_name)
{
const auto& t = v->GetType();
Emit("VectorValPtr %s;", const_name);
NoteInitDependency(v, TypeRep(t));
AddInit(v, const_name,
string("make_intrusive<VectorVal>(") + "cast_intrusive<VectorType>(" + GenTypeName(t) +
"))");
auto vv = cast_intrusive<VectorVal>(v);
auto n = vv->Size();
for ( auto i = 0u; i < n; ++i )
{
const auto& v_i = vv->ValAt(i);
auto v_i_c = BuildConstant(v, v_i);
AddInit(v, const_name + "->Append(" + v_i_c + ");");
}
return gi;
}
} // zeek::detail