From dfc0c627491b01bda341aa40d10e085bcc410de0 Mon Sep 17 00:00:00 2001 From: Alastair Robertson Date: Wed, 19 Jul 2023 07:49:27 -0700 Subject: [PATCH] AlignmentCalc: Tests for bitfields Extend TypeGraphParser to understand bitfields --- test/TypeGraphParser.cpp | 45 +++++++++++++++++++----------------- test/test_alignment_calc.cpp | 17 ++++++++++++++ 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/test/TypeGraphParser.cpp b/test/TypeGraphParser.cpp index c9a78b1..a743763 100644 --- a/test/TypeGraphParser.cpp +++ b/test/TypeGraphParser.cpp @@ -102,28 +102,28 @@ void removePrefix(std::string_view& line, std::string_view prefix) { std::string{line} + "'."}; } -std::optional tryParseIntAttribute(std::string_view line, - std::string_view marker) { +std::optional tryParseNumericAttribute(std::string_view line, + std::string_view marker) { auto attrStartPos = line.find(marker); if (attrStartPos == line.npos) return {}; auto valStartPos = attrStartPos + marker.size(); - auto valEndPos = line.find_first_not_of("0123456789", valStartPos); + auto valEndPos = line.find_first_not_of("0123456789.", valStartPos); auto valStr = line.substr(valStartPos, valEndPos); - uint64_t val = std::stoi(std::string{valStr}); // Makes a string copy :'( + double val = std::stod(std::string{valStr}); // Makes a string copy :'( return val; } -uint64_t parseIntAttribute(std::string_view line, - std::string_view type, - std::string_view marker) { - auto val = tryParseIntAttribute(line, marker); +double parseNumericAttribute(std::string_view line, + std::string_view type, + std::string_view marker) { + auto val = tryParseNumericAttribute(line, marker); if (!val) throw TypeGraphParserError{ - std::string{type} + " must have an attribute: '" + std::string{marker} + - "'. Got: '" + std::string{line} + "'"}; + std::string{type} + " must have a numeric attribute: '" + + std::string{marker} + "'. Got: '" + std::string{line} + "'"}; return *val; } @@ -219,12 +219,12 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) { auto nameEndPos = line.find('(', nameStartPos + 1); auto name = line.substr(nameStartPos, nameEndPos - nameStartPos - 1); - auto size = parseIntAttribute(line, nodeTypeName, "size: "); - auto align = tryParseIntAttribute(line, "align: "); + auto size = parseNumericAttribute(line, nodeTypeName, "size: "); + auto align = tryParseNumericAttribute(line, "align: "); Class& c = typeGraph_.makeType(id, kind, std::string{name}, size); if (align) - c.setAlign(*align); + c.setAlign(static_cast(*align)); nodesById_.insert({id, c}); parseParams(c, input, indent + 2); @@ -244,7 +244,7 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) { auto& info = getContainerInfo(name); - auto size = parseIntAttribute(line, nodeTypeName, "size: "); + auto size = parseNumericAttribute(line, nodeTypeName, "size: "); Container& c = typeGraph_.makeType(id, info, size); nodesById_.insert({id, c}); @@ -262,11 +262,11 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) { removePrefix(line, "Enum: "); auto nameEndPos = line.find(' '); auto name = line.substr(0, nameEndPos); - auto size = parseIntAttribute(line, nodeTypeName, "size: "); + auto size = parseNumericAttribute(line, nodeTypeName, "size: "); type = &typeGraph_.makeType(std::string{name}, size); } else if (nodeTypeName == "Array") { // Format: "Array: (length: 5) - auto len = parseIntAttribute(line, nodeTypeName, "length: "); + auto len = parseNumericAttribute(line, nodeTypeName, "length: "); auto& elementType = parseType(input, indent + 2); type = &typeGraph_.makeType(id, elementType, len); } else if (nodeTypeName == "Typedef") { @@ -337,7 +337,7 @@ void TypeGraphParser::parseParents(Class& c, if (!tryRemovePrefix(line, "Parent ")) break; - auto offset = parseIntAttribute(line, "Parent", "offset: "); + auto offset = parseNumericAttribute(line, "Parent", "offset: "); Type& type = parseType(input, rootIndent + 2); c.parents.emplace_back(type, offset * 8); @@ -361,13 +361,16 @@ void TypeGraphParser::parseMembers(Class& c, auto nameEndPos = line.find(' '); auto name = line.substr(0, nameEndPos); - auto offset = parseIntAttribute(line, "Member", "offset: "); - auto align = tryParseIntAttribute(line, "align: "); + auto offset = parseNumericAttribute(line, "Member", "offset: "); + auto align = tryParseNumericAttribute(line, "align: "); + auto bitsize = tryParseNumericAttribute(line, "bitsize: "); Type& type = parseType(input, rootIndent + 2); - Member member{type, std::string{name}, offset * 8}; + Member member{type, std::string{name}, static_cast(offset * 8)}; if (align) - member.align = *align; + member.align = static_cast(*align); + if (bitsize) + member.bitsize = static_cast(*bitsize); c.members.push_back(member); } diff --git a/test/test_alignment_calc.cpp b/test/test_alignment_calc.cpp index 22cdfa3..e49ccf0 100644 --- a/test/test_alignment_calc.cpp +++ b/test/test_alignment_calc.cpp @@ -165,3 +165,20 @@ TEST(AlignmentCalcTest, RecurseClassChild) { Primitive: int64_t )"); } + +TEST(AlignmentCalcTest, Bitfields) { + test(AlignmentCalc::createPass(), R"( +[0] Class: MyClass (size: 8) + Member: a (offset: 0, bitsize: 2) + Primitive: int8_t + Member: b (offset: 0.25, bitsize: 30) + Primitive: int64_t +)", + R"( +[0] Class: MyClass (size: 8, align: 8) + Member: a (offset: 0, align: 1, bitsize: 2) + Primitive: int8_t + Member: b (offset: 0.25, align: 8, bitsize: 30) + Primitive: int64_t +)"); +}