diff --git a/spicy/toolchain/bin/spicy-dump/printer-json.cc b/spicy/toolchain/bin/spicy-dump/printer-json.cc index f9c9f31b8..b848d3f8a 100644 --- a/spicy/toolchain/bin/spicy-dump/printer-json.cc +++ b/spicy/toolchain/bin/spicy-dump/printer-json.cc @@ -99,6 +99,14 @@ nlohmann::json JSONPrinter::convert(const hilti::rt::type_info::Value& v) { // Field not set. continue; + if ( f.type->tag == TypeInfo::Bitfield && f.isAnonymous() ) { + // Special case anonymous bitfield: map field to into current array. + for ( const auto& [b, val] : f.type->bitfield->iterate(y) ) + j[b.name] = convert(val); + + continue; + } + j[f.name] = convert(y); } @@ -106,6 +114,7 @@ nlohmann::json JSONPrinter::convert(const hilti::rt::type_info::Value& v) { const auto& __offsets = spicy::rt::get_offsets_for_unit(*struct_, v); if ( _options.include_offsets && __offsets ) { auto fields = struct_->fields(); + for ( const auto&& [index, offset] : enumerate(*__offsets) ) { auto o = json::object(); @@ -116,8 +125,15 @@ nlohmann::json JSONPrinter::convert(const hilti::rt::type_info::Value& v) { } const auto& field = fields[index].get(); - offsets[field.name] = std::move(o); + if ( field.type->tag == TypeInfo::Bitfield && field.isAnonymous() ) { + // Special case anonymous bitfield: add offsets for all its items + for ( const auto& b : field.type->bitfield->bits() ) + offsets[b.name] = o; + } + else + offsets[field.name] = std::move(o); } + j["__offsets"] = offsets; } diff --git a/spicy/toolchain/bin/spicy-dump/printer-text.cc b/spicy/toolchain/bin/spicy-dump/printer-text.cc index 876bc6a78..248329e03 100644 --- a/spicy/toolchain/bin/spicy-dump/printer-text.cc +++ b/spicy/toolchain/bin/spicy-dump/printer-text.cc @@ -133,35 +133,32 @@ void TextPrinter::print(const type_info::Value& v) { const auto* x = type.struct_; - const auto& offsets = spicy::rt::get_offsets_for_unit(*x, v); - bool empty = true; uint64_t index = 0; indent([&]() { for ( const auto& [f, y] : x->iterate(v) ) { if ( y ) { - out() << '\n'; - outputIndent(); - - if ( ! f.isAnonymous() ) - out() << f.name; - - out() << ": "; - print(y); - - const auto& offset = offsets && offsets->size() > index ? offsets->at(index) : std::nullopt; - - if ( _options.include_offsets && offset ) { - const auto& start = std::get<0>(*offset); - const auto& end = std::get<1>(*offset); + if ( f.type->tag == TypeInfo::Bitfield && f.isAnonymous() ) { + // Special case anonymous bitfield: print at top level. + for ( const auto& [b, val] : f.type->bitfield->iterate(y) ) { + out() << '\n'; + outputIndent(); + + out() << b.name << ": "; + print(val); + printOffsets(*x, v, index); + } + } + else { + out() << '\n'; + outputIndent(); - out() << " [" << start << ", "; + if ( ! f.isAnonymous() ) + out() << f.name; - if ( end ) - out() << *end; - else - out() << "-"; - out() << "]"; + out() << ": "; + print(y); + printOffsets(*x, v, index); } empty = false; @@ -251,3 +248,21 @@ void TextPrinter::print(const type_info::Value& v) { } } } + +void TextPrinter::printOffsets(const type_info::Struct& ti, const type_info::Value& v, uint64_t index) { + const auto& offsets = spicy::rt::get_offsets_for_unit(ti, v); + const auto& offset = offsets && offsets->size() > index ? offsets->at(index) : std::nullopt; + + if ( _options.include_offsets && offset ) { + const auto& start = std::get<0>(*offset); + const auto& end = std::get<1>(*offset); + + out() << " [" << start << ", "; + + if ( end ) + out() << *end; + else + out() << "-"; + out() << "]"; + } +} diff --git a/spicy/toolchain/bin/spicy-dump/printer-text.h b/spicy/toolchain/bin/spicy-dump/printer-text.h index 98f851958..066c25cb6 100644 --- a/spicy/toolchain/bin/spicy-dump/printer-text.h +++ b/spicy/toolchain/bin/spicy-dump/printer-text.h @@ -33,6 +33,9 @@ class TextPrinter { // Return output stream. std::ostream& out() { return _output; } + // Append rendering of offsets to current output line. + void printOffsets(const hilti::rt::type_info::Struct& ti, const hilti::rt::type_info::Value& v, uint64_t index); + // Insert current indentation into output stream. void outputIndent() { out() << std::string(static_cast::size_type>(_level) * 2, ' '); } diff --git a/tests/Baseline/spicy.tools.spicy-dump-bitfields/output-json b/tests/Baseline/spicy.tools.spicy-dump-bitfields/output-json new file mode 100644 index 000000000..9d04176be --- /dev/null +++ b/tests/Baseline/spicy.tools.spicy-dump-bitfields/output-json @@ -0,0 +1,2 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +{"__offsets":{"a1":{"end":2,"start":1},"a2":{"end":2,"start":1},"b":{"end":3,"start":2},"x":{"end":1,"start":0}},"a1":2,"a2":2,"b":{"b1":3,"b2":3},"x":1} diff --git a/tests/Baseline/spicy.tools.spicy-dump-bitfields/output-text b/tests/Baseline/spicy.tools.spicy-dump-bitfields/output-text new file mode 100644 index 000000000..12a841c2e --- /dev/null +++ b/tests/Baseline/spicy.tools.spicy-dump-bitfields/output-text @@ -0,0 +1,10 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +Test::X { + x: 1 [0, 1] + a1: 2 [1, 2] + a2: 2 [1, 2] + b: { + b1: 3 + b2: 3 + } [2, 3] +} diff --git a/tests/Baseline/spicy.types.bitfield.anonymous-field/output b/tests/Baseline/spicy.types.bitfield.anonymous-field/output index dc200f22c..2636cf834 100644 --- a/tests/Baseline/spicy.types.bitfield.anonymous-field/output +++ b/tests/Baseline/spicy.types.bitfield.anonymous-field/output @@ -1,5 +1,6 @@ ### 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) + x: 15 + y: 15 } diff --git a/tests/Baseline/spicy.types.bitfield.typedef/output b/tests/Baseline/spicy.types.bitfield.typedef/output index 864026029..bc3f17a9a 100644 --- a/tests/Baseline/spicy.types.bitfield.typedef/output +++ b/tests/Baseline/spicy.types.bitfield.typedef/output @@ -1,4 +1,6 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. foo::Y { - x: (a: 31) + x: { + a: 31 + } } diff --git a/tests/spicy/tools/spicy-dump-bitfields.spicy b/tests/spicy/tools/spicy-dump-bitfields.spicy new file mode 100644 index 000000000..091b2a032 --- /dev/null +++ b/tests/spicy/tools/spicy-dump-bitfields.spicy @@ -0,0 +1,13 @@ +# @TEST-EXEC: spicyc -j -Q -o test.hlto %INPUT +# @TEST-EXEC: printf '\001\002\003' | spicy-dump -Q test.hlto >output-text +# @TEST-EXEC: btest-diff output-text +# @TEST-EXEC: printf '\001\002\003' | spicy-dump -J -Q test.hlto >output-json +# @TEST-EXEC: btest-diff output-json + +module Test; + +public type X = unit { + x: uint8; + : bitfield(8) { a1: 0..7; a2: 0..7; }; + b: bitfield(8) { b1: 0..7; b2: 0..7; }; +};