Skip to content

Commit 81eaffc

Browse files
authored
Global types comdat (#179)
1 parent a2c6841 commit 81eaffc

16 files changed

+181
-126
lines changed

lib/passes/instrumentation/TypeIDProvider.cpp

Lines changed: 72 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -76,33 +76,6 @@ inline std::string create_prefixed_name(Args&&... args) {
7676

7777
namespace typedb {
7878

79-
struct GlobalTypeData {
80-
struct TypeData {
81-
llvm::Constant* type_struct;
82-
llvm::GlobalVariable* type;
83-
llvm::Constant* name;
84-
llvm::Constant* offset;
85-
llvm::Constant* count;
86-
};
87-
llvm::StringMap<TypeData> global_type_data;
88-
89-
inline bool has_type_name(llvm::StringRef name) const {
90-
#if LLVM_VERSION_MAJOR > 17
91-
return global_type_data.contains(name);
92-
#else
93-
return global_type_data.find(name) != global_type_data.end();
94-
#endif
95-
}
96-
97-
inline const TypeData& get_type(llvm::StringRef name) const {
98-
#if LLVM_VERSION_MAJOR > 17
99-
return global_type_data.at(name);
100-
#else
101-
return global_type_data.find(name)->second;
102-
#endif
103-
}
104-
};
105-
10679
struct GlobalTypeCallback {
10780
llvm::Module* module_;
10881
const TAFunctionQuery* f_query_;
@@ -245,7 +218,6 @@ struct GlobalTypeRegistrar {
245218
llvm::IRBuilder<> ir_build;
246219
GlobalTypeCallback type_callback;
247220
llvm::StructType* struct_layout_type_;
248-
GlobalTypeData global_types_;
249221
TypeHelper types_helper;
250222
const bool builtin_emit_name{false};
251223

@@ -267,119 +239,108 @@ struct GlobalTypeRegistrar {
267239

268240
llvm::GlobalVariable* create_global(
269241
llvm::StringRef name, llvm::Type* type, llvm::Constant* init = nullptr,
270-
llvm::GlobalVariable::LinkageTypes link_type = llvm::GlobalValue::WeakODRLinkage) const {
271-
// TODO: https://llvm.org/docs/LangRef.html#linkage w.r.t. forward declared types
242+
llvm::GlobalVariable::LinkageTypes link_type = llvm::GlobalValue::PrivateLinkage) const {
272243
auto* global_struct =
273244
new llvm::GlobalVariable(*module_, type, true, link_type, init, helper::create_prefixed_name(name));
274245
return global_struct;
275246
}
276247

277-
llvm::Constant* make_gep(llvm::Type* type, llvm::GlobalVariable* global) {
278-
auto* i32_zero_const = llvm::ConstantInt::get(ir_build.getInt32Ty(), 0);
279-
return llvm::ConstantExpr::getInBoundsGetElementPtr(
280-
type, global, llvm::ArrayRef<llvm::Constant*>{i32_zero_const, i32_zero_const});
281-
}
282-
283-
llvm::Constant* create_global_constant_string(llvm::StringRef name) {
284-
// TODO think about linkage
285-
// auto* name_str = ir_build.CreateGlobalStringPtr(name, helper::create_prefixed_name("typename_", name), 0,
286-
// module_);
248+
llvm::Constant* create_global_constant_string(llvm::StringRef name, llvm::StringRef payload) {
287249
auto* global_string =
288-
ir_build.CreateGlobalString(name, helper::create_prefixed_name("typename_", name), 0, module_);
250+
ir_build.CreateGlobalString(payload, helper::create_prefixed_name("typename_", name), 0, module_);
289251
global_string->setConstant(true);
290-
global_string->setLinkage(llvm::GlobalValue::WeakODRLinkage);
291-
return make_gep(global_string->getValueType(), global_string);
252+
global_string->setLinkage(llvm::GlobalValue::PrivateLinkage);
253+
return global_string;
292254
}
293255

294-
llvm::Constant* create_global_array_ptr(const llvm::StringRef name, llvm::ArrayRef<uint64_t> values) {
295-
if (values.empty()) {
296-
LOG_DEBUG("No values for global array, returning nullptr")
256+
template <typename InputRange, typename ConversionFunc>
257+
llvm::Constant* create_global_array_from_range(llvm::StringRef global_name, const InputRange& inputs,
258+
llvm::Type* element_type, ConversionFunc&& convert_element) {
259+
if (inputs.empty()) {
260+
LOG_DEBUG("No values for global array, returning nullptr");
297261
return types_helper.get_constant_nullptr();
298262
}
299263

300264
std::vector<llvm::Constant*> constants;
301-
constants.reserve(values.size());
302-
for (uint64_t val : values) {
303-
constants.push_back(types_helper.get_constant_for(IGlobalType::member_offsets, val));
265+
constants.reserve(inputs.size());
266+
267+
for (const auto& val : inputs) {
268+
constants.push_back(convert_element(val));
304269
}
305270

306-
auto* array_ty = llvm::ArrayType::get(types_helper.get_type_for(IGlobalType::member_offsets, true), values.size());
271+
auto* array_ty = llvm::ArrayType::get(element_type, inputs.size());
307272
auto* constant_array = llvm::ConstantArray::get(array_ty, constants);
308-
auto* gv = create_global(name, array_ty, constant_array);
309-
return make_gep(array_ty, gv);
310-
}
311-
312-
llvm::GlobalVariable* registerGlobalStruct(const std::string& name, int type_id, uint64_t type_size,
313-
uint64_t member_count, llvm::Constant* offset_ptr,
314-
llvm::Constant* members_data_ptr, llvm::Constant* count_ptr,
315-
StructTypeFlag flag = StructTypeFlag::USER_DEFINED) {
316-
const auto name_struct = flag == StructTypeFlag::FWD_DECL ? helper::concat(name, "_fwd") : name;
317273

318-
llvm::GlobalVariable* global_struct = create_global(name_struct, struct_layout_type_);
319-
global_struct->setConstant(false);
320-
321-
// In the current scheme, built-ins do not need to produce a name string (Built)
322-
const bool is_builtin = flag == StructTypeFlag::BUILTIN;
323-
const bool emit_builtin_typename = is_builtin && builtin_emit_name;
324-
llvm::Constant* name_str = (emit_builtin_typename || !is_builtin) ? create_global_constant_string(name)
325-
: types_helper.get_constant_nullptr();
326-
327-
std::vector<llvm::Constant*> members = {
328-
types_helper.get_constant_for(IGlobalType::type_id, type_id),
329-
types_helper.get_constant_for(IGlobalType::extent, type_size),
330-
types_helper.get_constant_for(IGlobalType::member_count, member_count),
331-
types_helper.get_constant_for(IGlobalType::type_flag,
332-
static_cast<int>(flag)), // TODO: use real type
333-
name_str, //
334-
offset_ptr, //
335-
count_ptr, //
336-
members_data_ptr};
337-
llvm::Constant* init = llvm::ConstantStruct::get(struct_layout_type_, members);
338-
global_struct->setInitializer(init);
274+
return create_global(global_name, array_ty, constant_array);
275+
}
339276

340-
global_types_.global_type_data.try_emplace(
341-
name, GlobalTypeData::TypeData{init, global_struct, name_str, offset_ptr, count_ptr});
277+
llvm::Constant* create_global_array_ptr(const llvm::StringRef name, llvm::ArrayRef<uint64_t> values,
278+
IGlobalType type = IGlobalType::member_offsets) {
279+
return create_global_array_from_range(name, values, types_helper.get_type_for(IGlobalType::member_offsets, true),
280+
[&](uint64_t val) { return types_helper.get_constant_for(type, val); });
281+
}
342282

343-
return global_struct;
283+
llvm::Constant* create_global_member_array_ptr(const llvm::StringRef name, llvm::ArrayRef<int> member_types) {
284+
return create_global_array_from_range(name, member_types, types_helper.get_type_for(IGlobalType::member_types),
285+
[&](int member_id) { return getOrRegister(member_id); });
344286
}
345287

346288
llvm::GlobalVariable* registerTypeStruct(const StructTypeInfo* type_struct) {
347-
const auto name = type_struct->name;
348-
const auto type_size = type_struct->extent;
289+
const auto base_name = type_struct->name;
290+
const bool is_fwd = type_struct->flag == StructTypeFlag::FWD_DECL;
291+
const auto link_name = is_fwd ? helper::concat(base_name, "_fwd") : base_name;
349292

350-
if (type_struct->flag == StructTypeFlag::FWD_DECL) {
351-
LOG_DEBUG("Type is forward decl " << name)
352-
// return registerGlobalStructDecl(name);
293+
if (is_fwd) {
294+
LOG_DEBUG("Type is forward decl " << base_name)
353295
}
354296

355-
llvm::Constant* offset_ptr = create_global_array_ptr(helper::concat("offsets_", name), type_struct->offsets);
356-
llvm::Constant* count_ptr = create_global_array_ptr(helper::concat("counts_", name), type_struct->array_sizes);
297+
llvm::Constant* offsets_ptr = create_global_array_ptr(helper::concat("offsets_", link_name), type_struct->offsets);
298+
llvm::Constant* counts_ptr = create_global_array_ptr(helper::concat("counts_", link_name), type_struct->array_sizes,
299+
IGlobalType::member_count);
300+
llvm::Constant* members_ptr =
301+
create_global_member_array_ptr(helper::concat("member_types_", link_name), type_struct->member_types);
357302

358-
llvm::Constant* members_array;
359-
llvm::Type* ptr_type{nullptr}; // TODO: make this unqual?
360-
std::vector<llvm::Constant*> member_types{};
303+
const bool is_builtin = type_struct->flag == StructTypeFlag::BUILTIN;
304+
const bool emit_name = !is_builtin || builtin_emit_name;
361305

362-
for (auto member_type_id : type_struct->member_types) {
363-
llvm::Constant* member = getOrRegister(member_type_id);
364-
if (ptr_type == nullptr) {
365-
ptr_type = member->getType();
366-
}
367-
member_types.emplace_back(member);
368-
}
306+
llvm::Constant* name_str_ptr =
307+
emit_name ? create_global_constant_string(link_name, base_name) : types_helper.get_constant_nullptr();
369308

370-
const auto member_count = type_struct->member_types.size();
371-
if (ptr_type != nullptr) {
372-
assert(member_count == type_struct->num_members);
373-
llvm::ArrayType* member_array_ty = llvm::ArrayType::get(ptr_type, member_count);
374-
llvm::Constant* init = llvm::ConstantArray::get(member_array_ty, member_types);
375-
members_array = create_global(helper::concat("member_types_", name), member_array_ty, init);
376-
} else {
377-
llvm::Constant* null_member = types_helper.get_constant_nullptr();
378-
members_array = null_member;
309+
llvm::GlobalVariable* global_struct =
310+
create_global(link_name, struct_layout_type_, nullptr, llvm::GlobalValue::LinkOnceODRLinkage);
311+
global_struct->setConstant(false);
312+
313+
std::vector<llvm::Constant*> init_fields = {
314+
types_helper.get_constant_for(IGlobalType::type_id, type_struct->type_id),
315+
types_helper.get_constant_for(IGlobalType::extent, type_struct->extent),
316+
types_helper.get_constant_for(IGlobalType::member_count, type_struct->member_types.size()),
317+
types_helper.get_constant_for(IGlobalType::type_flag, static_cast<int>(type_struct->flag)),
318+
name_str_ptr,
319+
offsets_ptr,
320+
counts_ptr,
321+
members_ptr};
322+
323+
llvm::Constant* init = llvm::ConstantStruct::get(struct_layout_type_, init_fields);
324+
global_struct->setInitializer(init);
325+
326+
{
327+
llvm::Comdat* comdat = this->module_->getOrInsertComdat(helper::create_prefixed_name(link_name));
328+
comdat->setSelectionKind(llvm::Comdat::Any);
329+
global_struct->setComdat(comdat);
330+
331+
auto add_to_comdat = [&](llvm::Constant* ptr) {
332+
if (auto* global = llvm::dyn_cast_or_null<llvm::GlobalObject>(ptr)) {
333+
global->setComdat(comdat);
334+
}
335+
};
336+
337+
add_to_comdat(offsets_ptr);
338+
add_to_comdat(counts_ptr);
339+
add_to_comdat(members_ptr);
340+
add_to_comdat(name_str_ptr);
379341
}
380342

381-
return registerGlobalStruct(name, type_struct->type_id, type_size, member_count, offset_ptr, members_array,
382-
count_ptr, type_struct->flag);
343+
return global_struct;
383344
}
384345

385346
llvm::GlobalVariable* registerBuiltin(int type_id) {

lib/runtime/GlobalTypeDefCallbacks.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ class GlobalTypeTranslator::Impl {
8585
}
8686

8787
const bool fwd_decl = type_descriptor.flag == StructTypeFlag::FWD_DECL;
88+
{
89+
LOG_DEBUG("StructTypeInfo Dump " << (fwd_decl ? "FWD" : "") << type_descriptor.name);
90+
LOG_DEBUG(" Type_id: " << type_descriptor.type_id);
91+
LOG_DEBUG(" Extent: " << type_descriptor.extent);
92+
LOG_DEBUG(" Num Members: " << type_descriptor.num_members);
93+
LOG_DEBUG(" Flag: " << static_cast<int>(type_descriptor.flag));
94+
for (uint32_t i = 0; i < type->num_members; ++i) {
95+
LOG_DEBUG(" Member[" << i << "]: "
96+
<< "ID=" << type_db_.getTypeName(type_descriptor.member_types[i]) << ", Offset="
97+
<< type_descriptor.offsets[i] << ", ArraySize=" << type_descriptor.array_sizes[i]);
98+
}
99+
}
88100
type_db_.registerStruct(type_descriptor, not fwd_decl);
89101
translator_map_.try_emplace(type, type_descriptor.type_id);
90102

test/pass/inline_types/02_calloc_realloc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S 2>&1 | %filecheck %s --check-prefix=REALLOC
33
// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S 2>&1 | %filecheck %s
44

5-
// REQUIRES: llvm-18 || llvm-19
5+
// REQUIRES: !llvm-14
66
// clang-format on
77
#include <stdlib.h>
88

test/pass/inline_types/03_simple_malloc_struct.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=file -S 2>&1 | %filecheck %s --check-prefix FILE
77

8-
// REQUIRES: llvm-18 || llvm-19
8+
// REQUIRES: !llvm-14
99
// clang-format on
1010
#include <stdlib.h>
1111
typedef struct ms {

test/pass/inline_types/04_fwd_decl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %cpp-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S | %filecheck %s
22

3-
// CHECK: @_typeart__ZTS6Domain_fwd = weak_odr global %struct._typeart_struct_layout_t { i32 256,
3+
// CHECK: @_typeart__ZTS6Domain_fwd = linkonce_odr global %struct._typeart_struct_layout_t { i32 256,
44

5-
// REQUIRES: llvm-18 || llvm-19
5+
// REQUIRES: !llvm-14
66

77
class Domain {
88
public:
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %c-to-llvm %s | %apply-typeart -typeart-type-serialization=inline -S | %filecheck --match-full-lines %s
2+
3+
// REQUIRES: !llvm-14
4+
5+
#include <stdlib.h>
6+
7+
struct DataNested {
8+
struct DataNested* nested_pointer;
9+
};
10+
11+
struct DataHolder {
12+
double a;
13+
float b;
14+
int c;
15+
struct DataNested nested;
16+
};
17+
18+
int main(void) {
19+
struct DataHolder* p = (struct DataHolder*)malloc(2 * sizeof(struct DataHolder));
20+
free(p);
21+
return 0;
22+
}
23+
24+
// clang-format off
25+
// CHECK-DAG: @_typeart_member_types_DataNested = private constant [1 x ptr] [ptr @_typeart_ptr], comdat($_typeart_DataNested)
26+
// CHECK-DAG: @_typeart_DataHolder = linkonce_odr global %struct._typeart_struct_layout_t { i32 256, i32 24, i16 4, i16 1, ptr @_typeart_typename_DataHolder, ptr @_typeart_offsets_DataHolder, ptr @_typeart_counts_DataHolder, ptr @_typeart_member_types_DataHolder }, comdat
27+
// CHECK-DAG: @_typeart_member_types_DataHolder = private constant [4 x ptr] [ptr @_typeart_double, ptr @_typeart_float, ptr @_typeart_int, ptr @_typeart_DataNested], comdat($_typeart_DataHolder)
28+
// CHECK-DAG: @_typeart_typename_DataHolder = private unnamed_addr constant [11 x i8] c"DataHolder\00", comdat($_typeart_DataHolder), align 1

test/runtime_inlined_types/01_simple_malloc_int.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %wrapper-cc -O1 %s -o %s.exe
44
// RUN: %s.exe 2>&1 | %filecheck %s
55

6-
// REQUIRES: llvm-18 || llvm-19
6+
// REQUIRES: !llvm-14
77
// clang-format on
88

99
#include <stdlib.h>
@@ -14,4 +14,4 @@ int main(void) {
1414
}
1515

1616
// CHECK: Allocation type detail (heap, stack, global)
17-
// CHECK-NEXT: 13 : 1 , 0 , 0 , int
17+
// CHECK-NEXT: 13 : 1 , 0 , 0 , int

test/runtime_inlined_types/02_simple_malloc_int_multi_tu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// RUN: %wrapper-cc -O1 %s.o %s_1.o -o %s.exe
1010
// RUN: %s.exe 2>&1 | %filecheck %s
1111

12-
// REQUIRES: llvm-18 || llvm-19
12+
// REQUIRES: !llvm-14
1313
// clang-format on
1414

1515
#include <stdlib.h>
@@ -29,4 +29,4 @@ int main(void) {
2929
#endif
3030

3131
// CHECK: Allocation type detail (heap, stack, global)
32-
// CHECK-NEXT: 13 : 2 , 0 , 0 , int
32+
// CHECK-NEXT: 13 : 2 , 0 , 0 , int

test/runtime_inlined_types/03_simple_malloc_struct.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %wrapper-cc -O1 %s -o %s.exe
44
// RUN: %s.exe 2>&1 | %filecheck %s
55

6-
// REQUIRES: llvm-18 || llvm-19
6+
// REQUIRES: !llvm-14
77
// clang-format on
88

99
#include <stdlib.h>

test/runtime_inlined_types/04_malloc_struct.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %wrapper-cc -O1 %s -o %s.exe
44
// RUN: %s.exe 2>&1 | %filecheck %s
55

6-
// REQUIRES: llvm-18 || llvm-19
6+
// REQUIRES: !llvm-14
77
// clang-format on
88

99
#include <stdlib.h>

0 commit comments

Comments
 (0)