Skip to content

Commit

Permalink
Include a flag into a unit field's type information indicating if it'…
Browse files Browse the repository at this point in the history
…s anonymous.

This preservers the information if a field had a name even though
internally we do carry a generated dummy name around in that case. For
now, we just adapt `spicy-dump` to not print the dummy name in that
case in its text output. Later, Zeek will leverage this when
auto-generating record types.
  • Loading branch information
rsmmr committed Aug 9, 2023
1 parent cae3e87 commit de71633
Show file tree
Hide file tree
Showing 12 changed files with 51 additions and 18 deletions.
6 changes: 4 additions & 2 deletions hilti/runtime/include/type-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -900,9 +900,9 @@ struct Field {
* @param offset offset of the field in number bytes inside the struct
* @param accessor function returning a pointer to a fields value
*/
Field(const char* name, const TypeInfo* type, std::ptrdiff_t offset, bool internal,
Field(const char* name, const TypeInfo* type, std::ptrdiff_t offset, bool internal, bool anonymous,
Accessor accessor = accessor_default)
: name(name), type(type), offset(offset), accessor(accessor), internal(internal) {}
: name(name), type(type), offset(offset), accessor(accessor), internal(internal), anonymous(anonymous) {}

/** Default accessor function suitable for non-optional fields. */
static const void* accessor_default(const Value& v) { return v.pointer(); }
Expand All @@ -921,6 +921,7 @@ struct Field {
};
}

bool isAnonymous() const { return anonymous; }
bool isInternal() const { return internal; }

const std::string name; /**< ID of the field */
Expand All @@ -935,6 +936,7 @@ struct Field {
const std::ptrdiff_t offset;
const Accessor accessor;
const bool internal;
const bool anonymous;
};

}; // namespace struct_
Expand Down
35 changes: 27 additions & 8 deletions hilti/runtime/src/tests/type-info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ namespace {
const hilti::rt::TypeInfo __ti_Test_X =
{"Test::X", "Test::X",
new hilti::rt::type_info::Struct(std::vector<hilti::rt::type_info::struct_::Field>(
{hilti::rt::type_info::struct_::Field{"i", &hilti::rt::type_info::int32, offsetof(Test::X, i), false},
hilti::rt::type_info::struct_::Field{"s", &hilti::rt::type_info::string, offsetof(Test::X, s), false},
hilti::rt::type_info::struct_::Field{"y", &type_info::__ti_Test_Y, offsetof(Test::X, y), false}}))};
{hilti::rt::type_info::struct_::Field{"i", &hilti::rt::type_info::int32, offsetof(Test::X, i), false, false},
hilti::rt::type_info::struct_::Field{"s", &hilti::rt::type_info::string, offsetof(Test::X, s), false, false},
hilti::rt::type_info::struct_::Field{"y", &type_info::__ti_Test_Y, offsetof(Test::X, y), false, false}}))};
const hilti::rt::TypeInfo __ti_Test_Y =
{"Test::Y", "Test::Y",
new hilti::rt::type_info::Struct(std::vector<hilti::rt::type_info::struct_::Field>(
{hilti::rt::type_info::struct_::Field{"b", &hilti::rt::type_info::bool_, offsetof(Test::Y, b), false},
hilti::rt::type_info::struct_::Field{"r", &hilti::rt::type_info::real, offsetof(Test::Y, r), false}}))};
{hilti::rt::type_info::struct_::Field{"b", &hilti::rt::type_info::bool_, offsetof(Test::Y, b), false, false},
hilti::rt::type_info::struct_::Field{"r", &hilti::rt::type_info::real, offsetof(Test::Y, r), false, false}}))};
} // namespace
} // namespace __hlt::type_info

Expand Down Expand Up @@ -126,10 +126,10 @@ TEST_CASE("internal fields") {

const TypeInfo ti = {"A", "A",
new type_info::Struct(
{type_info::struct_::Field{"f1", &type_info::int32, offsetof(A, f1), false},
type_info::struct_::Field{"f2", &type_info::string, offsetof(A, f2), false},
{type_info::struct_::Field{"f1", &type_info::int32, offsetof(A, f1), false, false},
type_info::struct_::Field{"f2", &type_info::string, offsetof(A, f2), false, false},
type_info::struct_::Field{"__internal", &type_info::bool_, offsetof(A, __internal),
true}})};
true, false}})};

auto sx = StrongReference<A>({42, "foo", true});
auto p = type_info::value::Parent(sx);
Expand All @@ -146,4 +146,23 @@ TEST_CASE("internal fields") {
CHECK_EQ(s->iterate(v, true).size(), 3U);
}

TEST_CASE("anonymous fields") {
struct A {
std::string f1;
};

const TypeInfo ti = {"A", "A",
new type_info::Struct(
{type_info::struct_::Field{"f1", &type_info::int32, offsetof(A, f1), false, true}})};

auto sx = StrongReference<A>({"foo"});
auto p = type_info::value::Parent(sx);
auto v = type_info::Value(&*sx, &ti, p);

const auto s = type_info::value::auxType<type_info::Struct>(v);

CHECK_EQ(s->fields().size(), 1U);
CHECK(s->fields()[0].get().isAnonymous());
}

TEST_SUITE_END();
1 change: 1 addition & 0 deletions hilti/toolchain/include/ast/declarations/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Field : public DeclarationBase {
return {};
}

auto isAnonymous() const { return AttributeSet::find(attributes(), "&anonymous").has_value(); }
auto isInternal() const { return AttributeSet::find(attributes(), "&internal").has_value(); }
auto isOptional() const { return AttributeSet::find(attributes(), "&optional").has_value(); }
auto isStatic() const { return AttributeSet::find(attributes(), "&static").has_value(); }
Expand Down
4 changes: 2 additions & 2 deletions hilti/toolchain/src/compiler/codegen/types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -901,8 +901,8 @@ struct VisitorTypeInfoDynamic : hilti::visitor::PreOrder<cxx::Expression, Visito
if ( auto x = cxxID(p.node) )
cxx_type_id = *x;

fields.push_back(fmt("::hilti::rt::type_info::struct_::Field{ \"%s\", %s, offsetof(%s, %s), %s%s }",
cxx::ID(f.id()), cg->typeInfo(f.type()), cxx_type_id, cxx::ID(f.id()), f.isInternal(),
fields.push_back(fmt("::hilti::rt::type_info::struct_::Field{ \"%s\", %s, offsetof(%s, %s), %s, %s%s }",
cxx::ID(f.id()), cg->typeInfo(f.type()), cxx_type_id, cxx::ID(f.id()), f.isInternal(), f.isAnonymous(),
accessor));
}

Expand Down
6 changes: 5 additions & 1 deletion spicy/toolchain/bin/spicy-dump/printer-text.cc
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,11 @@ void TextPrinter::print(const type_info::Value& v) {
if ( y ) {
out() << '\n';
outputIndent();
out() << f.name << ": ";

if ( ! f.isAnonymous() )
out() << f.name;

out() << ": ";
print(y);

const auto& offset = offsets && offsets->size() > index ? offsets->at(index) : std::nullopt;
Expand Down
3 changes: 3 additions & 0 deletions spicy/toolchain/src/compiler/codegen/unit-builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ struct FieldBuilder : public hilti::visitor::PreOrder<void, FieldBuilder> {
if ( auto x = AttributeSet::find(f.attributes(), "&default") )
attrs = AttributeSet::add(attrs, *x);

if ( f.isAnonymous() )
attrs = AttributeSet::add(attrs, Attribute("&anonymous"));

if ( (f.isAnonymous() || f.isSkip() || f.parseType().isA<type::Void>()) &&
! f.itemType().isA<type::Bitfield>() )
// This field will never make it into the C++ struct. We still
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ type C = struct {
method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __parse_foo_C_stage2(inout value_ref<stream> __data, copy view<stream> __cur, copy bool __trim, copy int<64> __lah, copy iterator<stream> __lahe, copy optional<hilti::RecoverableFailure> __error);
} &on-heap;
public type D = struct {
value_ref<C> anon &optional &no-emit;
value_ref<C> anon &optional &anonymous &no-emit;
optional<iterator<stream>> __begin &internal &needed-by-feature="uses_random_access";
optional<iterator<stream>> __position &internal &needed-by-feature="uses_random_access";
optional<iterator<stream>> __position_update &internal &needed-by-feature="uses_random_access";
Expand Down
2 changes: 1 addition & 1 deletion tests/Baseline/spicy.optimization.unused-functions/opt.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type C = struct {
method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __parse_foo_C_stage2(inout value_ref<stream> __data, copy view<stream> __cur, copy bool __trim, copy int<64> __lah, copy iterator<stream> __lahe, copy optional<hilti::RecoverableFailure> __error);
} &on-heap;
public type D = struct {
value_ref<C> anon &optional &no-emit;
value_ref<C> anon &optional &anonymous &no-emit;
spicy_rt::Parser __parser &static &internal &needed-by-feature="supports_filters" &always-emit;
optional<hilti::RecoverableFailure> __error &always-emit &internal;
method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __parse_stage1(inout value_ref<stream> __data, copy view<stream> __cur, copy bool __trim, copy int<64> __lah, copy iterator<stream> __lahe, copy optional<hilti::RecoverableFailure> __error);
Expand Down
4 changes: 2 additions & 2 deletions tests/Baseline/spicy.optimization.unused-types/noopt.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ type Priv3 = struct {
method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __parse_foo_Priv3_stage2(inout value_ref<stream> __data, copy view<stream> __cur, copy bool __trim, copy int<64> __lah, copy iterator<stream> __lahe, copy optional<hilti::RecoverableFailure> __error);
} &on-heap;
type Priv4 = struct {
value_ref<Priv2> anon &optional &no-emit;
value_ref<Priv2> anon &optional &anonymous &no-emit;
value_ref<Priv3> x &optional;
optional<iterator<stream>> __begin &internal &needed-by-feature="uses_random_access";
optional<iterator<stream>> __position &internal &needed-by-feature="uses_random_access";
Expand Down Expand Up @@ -190,7 +190,7 @@ type Priv6 = struct {
method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __parse_foo_Priv6_stage2(inout value_ref<stream> __data, copy view<stream> __cur, copy bool __trim, copy int<64> __lah, copy iterator<stream> __lahe, copy optional<hilti::RecoverableFailure> __error);
} &on-heap;
public type Pub3 = struct {
value_ref<Priv5> anon_2 &optional &no-emit;
value_ref<Priv5> anon_2 &optional &anonymous &no-emit;
value_ref<Priv6> x &optional;
optional<iterator<stream>> __begin &internal &needed-by-feature="uses_random_access";
optional<iterator<stream>> __position &internal &needed-by-feature="uses_random_access";
Expand Down
2 changes: 1 addition & 1 deletion tests/Baseline/spicy.optimization.unused-types/opt.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type Priv6 = struct {
method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __parse_foo_Priv6_stage2(inout value_ref<stream> __data, copy view<stream> __cur, copy bool __trim, copy int<64> __lah, copy iterator<stream> __lahe, copy optional<hilti::RecoverableFailure> __error);
} &on-heap;
public type Pub3 = struct {
value_ref<Priv5> anon_2 &optional &no-emit;
value_ref<Priv5> anon_2 &optional &anonymous &no-emit;
value_ref<Priv6> x &optional;
spicy_rt::Parser __parser &static &internal &needed-by-feature="supports_filters" &always-emit;
optional<hilti::RecoverableFailure> __error &always-emit &internal;
Expand Down
3 changes: 3 additions & 0 deletions tests/Baseline/spicy.types.bitfield.anonymous-field/output
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
15, 15
Test::Foo {
: (x: 15, y: 15)
}
1 change: 1 addition & 0 deletions tests/spicy/types/bitfield/anonymous-field.spicy
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# @TEST-EXEC: printf '\377' | spicy-driver %INPUT >output
# @TEST-EXEC: printf '\377' | spicy-dump %INPUT >>output
# @TEST-EXEC: btest-diff output

module Test;
Expand Down

0 comments on commit de71633

Please sign in to comment.