Skip to content

Commit

Permalink
[spicy-dump] Level up anonymous bitfields.
Browse files Browse the repository at this point in the history
Spicy-dump now renders items of anonymous bitfields at the parent
level. Offsets are added accordingly as well if requested.
  • Loading branch information
rsmmr committed Aug 22, 2023
1 parent a7c99a6 commit 33f5855
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 25 deletions.
18 changes: 17 additions & 1 deletion spicy/toolchain/bin/spicy-dump/printer-json.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,22 @@ 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);
}

auto offsets = json::object();
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();

Expand All @@ -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;
}

Expand Down
59 changes: 37 additions & 22 deletions spicy/toolchain/bin/spicy-dump/printer-text.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() << "]";
}
}
3 changes: 3 additions & 0 deletions spicy/toolchain/bin/spicy-dump/printer-text.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::basic_string<char>::size_type>(_level) * 2, ' '); }

Expand Down
2 changes: 2 additions & 0 deletions tests/Baseline/spicy.tools.spicy-dump-bitfields/output-json
Original file line number Diff line number Diff line change
@@ -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}
10 changes: 10 additions & 0 deletions tests/Baseline/spicy.tools.spicy-dump-bitfields/output-text
Original file line number Diff line number Diff line change
@@ -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]
}
3 changes: 2 additions & 1 deletion tests/Baseline/spicy.types.bitfield.anonymous-field/output
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 3 additions & 1 deletion tests/Baseline/spicy.types.bitfield.typedef/output
Original file line number Diff line number Diff line change
@@ -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
}
}
13 changes: 13 additions & 0 deletions tests/spicy/tools/spicy-dump-bitfields.spicy
Original file line number Diff line number Diff line change
@@ -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; };
};

0 comments on commit 33f5855

Please sign in to comment.