Skip to content

Commit c8a44e7

Browse files
authored
Generate hashed names for anon structs (#161)
1 parent 176a45a commit c8a44e7

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

lib/passes/typegen/dimeta/DimetaTypeGen.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include "typelib/TypeDatabase.h"
1919
#include "typelib/TypeInterface.h"
2020

21+
#include "llvm/ADT/StringExtras.h"
22+
#include "llvm/Support/MD5.h"
23+
2124
#include <cassert>
2225
#include <cstddef>
2326
#include <cstdint>
@@ -136,6 +139,34 @@ dimeta::ArraySize vector_num_elements(const Type& type) {
136139
});
137140
}
138141

142+
std::string get_anon_struct_identifier(const dimeta::QualifiedCompound& compound) {
143+
llvm::MD5 compound_hash;
144+
if (compound.type.members.empty()) {
145+
LOG_WARNING("Anonymous struct has no members")
146+
}
147+
for (const auto& [member, offset, size] :
148+
llvm::zip(compound.type.members, compound.type.offsets, compound.type.sizes)) {
149+
compound_hash.update(member->name);
150+
compound_hash.update(offset);
151+
compound_hash.update(size);
152+
compound_hash.update(std::visit(overload{[&](const dimeta::QualifiedFundamental& member_fundamental) {
153+
return std::to_string(
154+
static_cast<int>(member_fundamental.type.encoding)) +
155+
std::to_string(static_cast<int>(member_fundamental.type.extent));
156+
},
157+
[&](const dimeta::QualifiedCompound& member_compound) {
158+
return get_anon_struct_identifier(member_compound);
159+
}},
160+
member->member));
161+
compound_hash.update("\0");
162+
}
163+
compound_hash.update(compound.type.extent);
164+
compound_hash.update("\0");
165+
llvm::MD5::MD5Result hash_result;
166+
compound_hash.final(hash_result);
167+
return "anonymous_compound_" + std::string(hash_result.digest().str());
168+
}
169+
139170
template <typename Type>
140171
dimeta::ArraySize array_size(const Type& type) {
141172
return detail::apply_function(type, [](const auto& t) -> dimeta::Extent {
@@ -158,6 +189,10 @@ std::string name_or_typedef_of(const Type& type) {
158189
const bool no_name = qual_type.type.name.empty();
159190
if constexpr (std::is_same_v<Type, typename dimeta::QualifiedCompound>) {
160191
const bool no_identifier = qual_type.type.identifier.empty();
192+
const bool no_typedef = qual_type.typedef_name.empty();
193+
if (no_identifier && no_name && no_typedef) {
194+
return get_anon_struct_identifier(qual_type);
195+
}
161196
if (no_identifier && no_name) {
162197
return qual_type.typedef_name;
163198
}

test/typemapping/06_anon_struct.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %c-to-llvm %s | %apply-typeart --typeart-stack=true
2+
// RUN: cat %tu_yaml | %filecheck %s
3+
4+
// REQUIRES: dimeta
5+
6+
struct {
7+
int dir;
8+
int length;
9+
float coeff;
10+
float forwback;
11+
} q_paths;
12+
13+
struct {
14+
int dir;
15+
float length;
16+
float coeff;
17+
float forwback;
18+
} q_paths_2;
19+
20+
struct {
21+
float dir;
22+
float length;
23+
float coeff;
24+
float forwback;
25+
} q_paths_3;
26+
27+
struct {
28+
struct {
29+
float dir;
30+
float length;
31+
float coeff;
32+
float forwback;
33+
} inner;
34+
} q_paths_4;
35+
36+
// CHECK-COUNT-4: name: anonymous_compound_{{[0-9a-z]+}}

0 commit comments

Comments
 (0)