mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-09 21:24:14 +00:00
AlignmentCalc: Tests for bitfields
Extend TypeGraphParser to understand bitfields
This commit is contained in:
parent
14d193df64
commit
dfc0c62749
@ -102,28 +102,28 @@ void removePrefix(std::string_view& line, std::string_view prefix) {
|
|||||||
std::string{line} + "'."};
|
std::string{line} + "'."};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<uint64_t> tryParseIntAttribute(std::string_view line,
|
std::optional<double> tryParseNumericAttribute(std::string_view line,
|
||||||
std::string_view marker) {
|
std::string_view marker) {
|
||||||
auto attrStartPos = line.find(marker);
|
auto attrStartPos = line.find(marker);
|
||||||
if (attrStartPos == line.npos)
|
if (attrStartPos == line.npos)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto valStartPos = attrStartPos + marker.size();
|
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);
|
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;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t parseIntAttribute(std::string_view line,
|
double parseNumericAttribute(std::string_view line,
|
||||||
std::string_view type,
|
std::string_view type,
|
||||||
std::string_view marker) {
|
std::string_view marker) {
|
||||||
auto val = tryParseIntAttribute(line, marker);
|
auto val = tryParseNumericAttribute(line, marker);
|
||||||
if (!val)
|
if (!val)
|
||||||
throw TypeGraphParserError{
|
throw TypeGraphParserError{
|
||||||
std::string{type} + " must have an attribute: '" + std::string{marker} +
|
std::string{type} + " must have a numeric attribute: '" +
|
||||||
"'. Got: '" + std::string{line} + "'"};
|
std::string{marker} + "'. Got: '" + std::string{line} + "'"};
|
||||||
return *val;
|
return *val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,12 +219,12 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) {
|
|||||||
auto nameEndPos = line.find('(', nameStartPos + 1);
|
auto nameEndPos = line.find('(', nameStartPos + 1);
|
||||||
auto name = line.substr(nameStartPos, nameEndPos - nameStartPos - 1);
|
auto name = line.substr(nameStartPos, nameEndPos - nameStartPos - 1);
|
||||||
|
|
||||||
auto size = parseIntAttribute(line, nodeTypeName, "size: ");
|
auto size = parseNumericAttribute(line, nodeTypeName, "size: ");
|
||||||
auto align = tryParseIntAttribute(line, "align: ");
|
auto align = tryParseNumericAttribute(line, "align: ");
|
||||||
|
|
||||||
Class& c = typeGraph_.makeType<Class>(id, kind, std::string{name}, size);
|
Class& c = typeGraph_.makeType<Class>(id, kind, std::string{name}, size);
|
||||||
if (align)
|
if (align)
|
||||||
c.setAlign(*align);
|
c.setAlign(static_cast<uint64_t>(*align));
|
||||||
nodesById_.insert({id, c});
|
nodesById_.insert({id, c});
|
||||||
|
|
||||||
parseParams(c, input, indent + 2);
|
parseParams(c, input, indent + 2);
|
||||||
@ -244,7 +244,7 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) {
|
|||||||
|
|
||||||
auto& info = getContainerInfo(name);
|
auto& info = getContainerInfo(name);
|
||||||
|
|
||||||
auto size = parseIntAttribute(line, nodeTypeName, "size: ");
|
auto size = parseNumericAttribute(line, nodeTypeName, "size: ");
|
||||||
|
|
||||||
Container& c = typeGraph_.makeType<Container>(id, info, size);
|
Container& c = typeGraph_.makeType<Container>(id, info, size);
|
||||||
nodesById_.insert({id, c});
|
nodesById_.insert({id, c});
|
||||||
@ -262,11 +262,11 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) {
|
|||||||
removePrefix(line, "Enum: ");
|
removePrefix(line, "Enum: ");
|
||||||
auto nameEndPos = line.find(' ');
|
auto nameEndPos = line.find(' ');
|
||||||
auto name = line.substr(0, nameEndPos);
|
auto name = line.substr(0, nameEndPos);
|
||||||
auto size = parseIntAttribute(line, nodeTypeName, "size: ");
|
auto size = parseNumericAttribute(line, nodeTypeName, "size: ");
|
||||||
type = &typeGraph_.makeType<Enum>(std::string{name}, size);
|
type = &typeGraph_.makeType<Enum>(std::string{name}, size);
|
||||||
} else if (nodeTypeName == "Array") {
|
} else if (nodeTypeName == "Array") {
|
||||||
// Format: "Array: (length: 5)
|
// Format: "Array: (length: 5)
|
||||||
auto len = parseIntAttribute(line, nodeTypeName, "length: ");
|
auto len = parseNumericAttribute(line, nodeTypeName, "length: ");
|
||||||
auto& elementType = parseType(input, indent + 2);
|
auto& elementType = parseType(input, indent + 2);
|
||||||
type = &typeGraph_.makeType<Array>(id, elementType, len);
|
type = &typeGraph_.makeType<Array>(id, elementType, len);
|
||||||
} else if (nodeTypeName == "Typedef") {
|
} else if (nodeTypeName == "Typedef") {
|
||||||
@ -337,7 +337,7 @@ void TypeGraphParser::parseParents(Class& c,
|
|||||||
if (!tryRemovePrefix(line, "Parent "))
|
if (!tryRemovePrefix(line, "Parent "))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
auto offset = parseIntAttribute(line, "Parent", "offset: ");
|
auto offset = parseNumericAttribute(line, "Parent", "offset: ");
|
||||||
Type& type = parseType(input, rootIndent + 2);
|
Type& type = parseType(input, rootIndent + 2);
|
||||||
|
|
||||||
c.parents.emplace_back(type, offset * 8);
|
c.parents.emplace_back(type, offset * 8);
|
||||||
@ -361,13 +361,16 @@ void TypeGraphParser::parseMembers(Class& c,
|
|||||||
|
|
||||||
auto nameEndPos = line.find(' ');
|
auto nameEndPos = line.find(' ');
|
||||||
auto name = line.substr(0, nameEndPos);
|
auto name = line.substr(0, nameEndPos);
|
||||||
auto offset = parseIntAttribute(line, "Member", "offset: ");
|
auto offset = parseNumericAttribute(line, "Member", "offset: ");
|
||||||
auto align = tryParseIntAttribute(line, "align: ");
|
auto align = tryParseNumericAttribute(line, "align: ");
|
||||||
|
auto bitsize = tryParseNumericAttribute(line, "bitsize: ");
|
||||||
Type& type = parseType(input, rootIndent + 2);
|
Type& type = parseType(input, rootIndent + 2);
|
||||||
|
|
||||||
Member member{type, std::string{name}, offset * 8};
|
Member member{type, std::string{name}, static_cast<uint64_t>(offset * 8)};
|
||||||
if (align)
|
if (align)
|
||||||
member.align = *align;
|
member.align = static_cast<uint64_t>(*align);
|
||||||
|
if (bitsize)
|
||||||
|
member.bitsize = static_cast<uint64_t>(*bitsize);
|
||||||
|
|
||||||
c.members.push_back(member);
|
c.members.push_back(member);
|
||||||
}
|
}
|
||||||
|
@ -165,3 +165,20 @@ TEST(AlignmentCalcTest, RecurseClassChild) {
|
|||||||
Primitive: int64_t
|
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
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user