diff --git a/src/script_opt/CPP/Compile.h b/src/script_opt/CPP/Compile.h index 9a99db499c..6b110a00de 100644 --- a/src/script_opt/CPP/Compile.h +++ b/src/script_opt/CPP/Compile.h @@ -820,7 +820,8 @@ private: std::string GenIndexAssign(const ExprPtr& lhs, const ExprPtr& rhs, const std::string& rhs_val_ptr, GenType gt, bool top_level); std::string GenFieldAssign(const ExprPtr& lhs, const ExprPtr& rhs, - const std::string& rhs_val_ptr, GenType gt, bool top_level); + const std::string& rhs_native, const std::string& rhs_val_ptr, + GenType gt, bool top_level); std::string GenListAssign(const ExprPtr& lhs, const ExprPtr& rhs); // Support for element-by-element vector operations. diff --git a/src/script_opt/CPP/Exprs.cc b/src/script_opt/CPP/Exprs.cc index 6dd82356a5..b0ec6cd8e4 100644 --- a/src/script_opt/CPP/Exprs.cc +++ b/src/script_opt/CPP/Exprs.cc @@ -396,13 +396,35 @@ string CPPCompile::GenInExpr(const Expr* e, GenType gt) string CPPCompile::GenFieldExpr(const FieldExpr* fe, GenType gt) { + auto& t = fe->GetType(); auto r = fe->GetOp1(); auto f = fe->Field(); auto f_s = GenField(r, f); - auto gen = string("field_access__CPP(") + GenExpr(r, GEN_VAL_PTR) + ", " + f_s + ")"; + string gen; - return GenericValPtrToGT(gen, fe->GetType(), gt); + if ( IsNativeType(t) ) + { + auto nt = TypeName(t); + gen = string("field_access_") + nt + "__CPP(" + GenExpr(r, GEN_VAL_PTR) + ", " + f_s + ")"; + return NativeToGT(gen, t, gt); + } + + switch ( t->Tag() ) + { + case TYPE_FILE: + case TYPE_FUNC: + case TYPE_VOID: + gen = string("field_access__CPP(") + GenExpr(r, GEN_VAL_PTR) + ", " + f_s + ")"; + return GenericValPtrToGT(gen, t, gt); + + default: + { + auto nt = TypeName(t); + return string("field_access_") + nt + "__CPP(" + GenExpr(r, GEN_VAL_PTR) + ", " + f_s + + ")"; + } + } } string CPPCompile::GenHasFieldExpr(const HasFieldExpr* hfe, GenType gt) @@ -411,8 +433,7 @@ string CPPCompile::GenHasFieldExpr(const HasFieldExpr* hfe, GenType gt) auto f = hfe->Field(); auto f_s = GenField(r, f); - // Need to use accessors for native types. - auto gen = string("(") + GenExpr(r, GEN_DONT_CARE) + "->GetField(" + f_s + ") != nullptr)"; + auto gen = GenExpr(r, GEN_DONT_CARE) + "->HasField(" + f_s + ")"; return NativeToGT(gen, hfe->GetType(), gt); } @@ -1090,7 +1111,7 @@ string CPPCompile::GenAssign(const ExprPtr& lhs, const ExprPtr& rhs, const strin return GenIndexAssign(lhs, rhs, rhs_val_ptr, gt, top_level); case EXPR_FIELD: - return GenFieldAssign(lhs, rhs, rhs_val_ptr, gt, top_level); + return GenFieldAssign(lhs, rhs, rhs_native, rhs_val_ptr, gt, top_level); case EXPR_LIST: return GenListAssign(lhs, rhs); @@ -1159,20 +1180,24 @@ string CPPCompile::GenIndexAssign(const ExprPtr& lhs, const ExprPtr& rhs, const return gen; } -string CPPCompile::GenFieldAssign(const ExprPtr& lhs, const ExprPtr& rhs, const string& rhs_val_ptr, - GenType gt, bool top_level) +string CPPCompile::GenFieldAssign(const ExprPtr& lhs, const ExprPtr& rhs, const string& rhs_native, + const string& rhs_val_ptr, GenType gt, bool top_level) { auto rec = lhs->GetOp1(); auto rec_gen = GenExpr(rec, GEN_VAL_PTR); auto field = GenField(rec, lhs->AsFieldExpr()->Field()); - if ( top_level ) - return rec_gen + "->Assign(" + field + ", " + rhs_val_ptr + ")"; - else + if ( ! top_level ) { auto gen = string("assign_field__CPP(") + rec_gen + ", " + field + ", " + rhs_val_ptr + ")"; return GenericValPtrToGT(gen, rhs->GetType(), gt); } + + auto rt = rhs ? rhs->GetType() : nullptr; + if ( rt && (IsNativeType(rt) || rt->Tag() == TYPE_STRING) ) + return rec_gen + "->Assign(" + field + ", " + rhs_native + ")"; + else + return rec_gen + "->Assign(" + field + ", " + rhs_val_ptr + ")"; } string CPPCompile::GenListAssign(const ExprPtr& lhs, const ExprPtr& rhs) diff --git a/src/script_opt/CPP/RuntimeOps.h b/src/script_opt/CPP/RuntimeOps.h index 85cc61eeca..4318e7c7ff 100644 --- a/src/script_opt/CPP/RuntimeOps.h +++ b/src/script_opt/CPP/RuntimeOps.h @@ -5,7 +5,7 @@ #pragma once #include "zeek/Frame.h" -#include "zeek/Val.h" +#include "zeek/OpaqueVal.h" #include "zeek/script_opt/CPP/Func.h" namespace zeek @@ -16,6 +16,12 @@ using SubNetValPtr = IntrusivePtr; namespace detail { +class CPPRuntime + { +public: + static auto RawOptField(const RecordValPtr& rv, int field) { return rv->RawOptField(field); } + }; + // Returns the concatenation of the given strings. extern StringValPtr str_concat__CPP(const String* s1, const String* s2); @@ -109,6 +115,42 @@ inline ValPtr field_access__CPP(const RecordValPtr& rec, int field) return v; } +#define NATIVE_FIELD_ACCESS(type, zaccessor, vaccessor) \ + inline type field_access_##type##__CPP(const RecordValPtr& r, int field) \ + { \ + auto rv = CPPRuntime::RawOptField(r, field); \ + if ( rv ) \ + return (*rv).zaccessor(); \ + return field_access__CPP(r, field)->vaccessor(); \ + } + +NATIVE_FIELD_ACCESS(bool, AsInt, AsBool) +NATIVE_FIELD_ACCESS(int, AsInt, AsInt) +NATIVE_FIELD_ACCESS(zeek_int_t, AsInt, AsInt) +NATIVE_FIELD_ACCESS(zeek_uint_t, AsCount, AsCount) +NATIVE_FIELD_ACCESS(double, AsDouble, AsDouble) + +#define VP_FIELD_ACCESS(type, zaccessor) \ + inline type##Ptr field_access_##type##__CPP(const RecordValPtr& r, int field) \ + { \ + auto rv = CPPRuntime::RawOptField(r, field); \ + if ( rv ) \ + return {NewRef{}, rv->zaccessor()}; \ + return cast_intrusive(field_access__CPP(r, field)); \ + } + +VP_FIELD_ACCESS(StringVal, AsString) +VP_FIELD_ACCESS(AddrVal, AsAddr) +VP_FIELD_ACCESS(SubNetVal, AsSubNet) +VP_FIELD_ACCESS(ListVal, AsList) +VP_FIELD_ACCESS(OpaqueVal, AsOpaque) +VP_FIELD_ACCESS(PatternVal, AsPattern) +VP_FIELD_ACCESS(TableVal, AsTable) +VP_FIELD_ACCESS(RecordVal, AsRecord) +VP_FIELD_ACCESS(VectorVal, AsVector) +VP_FIELD_ACCESS(TypeVal, AsType) +VP_FIELD_ACCESS(Val, AsAny) + // Each of the following executes the assignment "v1[v2] = v3" for // tables/vectors/strings. extern ValPtr assign_to_index__CPP(TableValPtr v1, ValPtr v2, ValPtr v3);