88#include " support/ConfigurationBase.h"
99#include " support/Logger.h"
1010
11+ #include < cstdint>
1112#include < llvm/ADT/ArrayRef.h>
1213#include < llvm/ADT/StringMap.h>
1314#include < llvm/ADT/StringRef.h>
2930#include < optional>
3031#include < string>
3132#include < utility>
33+ #include < vector>
3234
3335namespace typeart {
3436
@@ -72,6 +74,40 @@ inline std::string create_prefixed_name(Args&&... args) {
7274 return name;
7375}
7476
77+ namespace detail {
78+ template <typename T, typename SourceT>
79+ T safe_cast (SourceT val) {
80+ // Check if value exceeds the maximum limit of the target type T
81+ // We cast max() to size_t to ensure we are comparing compatible types safely
82+ assert (static_cast <size_t >(val) <= static_cast <size_t >(std::numeric_limits<T>::max ()) &&
83+ " Data loss detected: Value exceeds target type limits!" );
84+ return static_cast <T>(val);
85+ }
86+ } // namespace detail
87+
88+ template <typename T>
89+ std::vector<T> get_serialized_members_for (const StructTypeInfo& info) {
90+ using namespace detail ;
91+ std::vector<T> dest;
92+ const size_t required_space = info.offsets .size () + info.array_sizes .size () + 2 ;
93+ dest.reserve (required_space);
94+
95+ // Layout : [ num_member, flag, offsets...[num_member], array_sizes...[num_member] ]
96+
97+ dest.push_back (safe_cast<T>(info.num_members ));
98+ dest.push_back (safe_cast<T>(static_cast <std::underlying_type_t <StructTypeFlag>>(info.flag )));
99+
100+ for (size_t offset : info.offsets ) {
101+ dest.push_back (safe_cast<T>(offset));
102+ }
103+
104+ for (size_t size : info.array_sizes ) {
105+ dest.push_back (safe_cast<T>(size));
106+ }
107+
108+ return dest;
109+ }
110+
75111} // namespace helper
76112
77113namespace typedb {
@@ -151,7 +187,8 @@ enum class IGlobalType : short {
151187 member_types,
152188 member_count,
153189 type_flag,
154- ptr
190+ ptr,
191+ info_holder
155192};
156193
157194struct TypeHelper {
@@ -181,13 +218,14 @@ struct TypeHelper {
181218 }
182219 case IGlobalType::name:
183220 case IGlobalType::ptr:
221+ case IGlobalType::info_holder:
184222#if LLVM_VERSION_MAJOR < 15
185223 return ir_build_.getInt8PtrTy ();
186224#else
187225 return ir_build_.getPtrTy ();
188226#endif
189227 }
190- llvm_unreachable (" Should not be reached disk " );
228+ llvm_unreachable (" Should not be reached" );
191229 }
192230
193231 llvm::Constant* get_constant_for (IGlobalType type, size_t value) {
@@ -218,22 +256,23 @@ struct GlobalTypeRegistrar {
218256 llvm::IRBuilder<> ir_build;
219257 GlobalTypeCallback type_callback;
220258 llvm::StructType* struct_layout_type_;
259+ llvm::StructType* struct_layout_type_cold_;
221260 TypeHelper types_helper;
222261 const bool builtin_emit_name{false };
223262
224263 void declare_layout () {
225264 auto & context = module_->getContext ();
226265 struct_layout_type_ = llvm::StructType::create (context, " struct._typeart_struct_layout_t" );
227266 struct_layout_type_->setBody ({
228- types_helper.get_type_for (IGlobalType::type_id), // int type_id
229- types_helper.get_type_for (IGlobalType::extent), // uint32 extent
230- types_helper.get_type_for (IGlobalType::num_members), // uint16 num_members
231- types_helper.get_type_for (IGlobalType::type_flag), // uint16 type_flag
267+ types_helper.get_type_for (IGlobalType::type_id), // uint32 type_id
268+ types_helper.get_type_for (IGlobalType::extent), // uint32 extent
269+ types_helper.get_type_for (IGlobalType::info_holder),
270+ });
271+ struct_layout_type_cold_ = llvm::StructType::create (context, " struct._typeart_struct_layout_info_t" );
272+ struct_layout_type_cold_->setBody ({
232273 types_helper.get_type_for (IGlobalType::name), // const char* name
233274 types_helper.get_type_for (IGlobalType::member_offsets), // const uint16* offsets
234- types_helper.get_type_for (IGlobalType::member_count), // const uint16* count
235275 types_helper.get_type_for (IGlobalType::member_types), // const typeart_struct_layout_t** member_types
236-
237276 });
238277 }
239278
@@ -274,10 +313,11 @@ struct GlobalTypeRegistrar {
274313 return create_global (global_name, array_ty, constant_array);
275314 }
276315
277- llvm::Constant* create_global_array_ptr (const llvm::StringRef name, llvm::ArrayRef<uint64_t > values,
316+ template <typename T>
317+ llvm::Constant* create_global_array_ptr (const llvm::StringRef name, llvm::ArrayRef<T> values,
278318 IGlobalType type = IGlobalType::member_offsets) {
279319 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); });
320+ [&](const T& val) { return types_helper.get_constant_for (type, val); });
281321 }
282322
283323 llvm::Constant* create_global_member_array_ptr (const llvm::StringRef name, llvm::ArrayRef<int > member_types) {
@@ -294,51 +334,55 @@ struct GlobalTypeRegistrar {
294334 LOG_DEBUG (" Type is forward decl " << base_name)
295335 }
296336
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 );
302-
303337 const bool is_builtin = type_struct->flag == StructTypeFlag::BUILTIN;
304338 const bool emit_name = !is_builtin || builtin_emit_name;
305339
306- llvm::Constant* name_str_ptr =
307- emit_name ? create_global_constant_string (link_name, base_name) : types_helper.get_constant_nullptr ();
308-
309340 llvm::GlobalVariable* global_struct =
310341 create_global (link_name, struct_layout_type_, nullptr , llvm::GlobalValue::LinkOnceODRLinkage);
311342 global_struct->setConstant (false );
312343
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);
344+ llvm::Comdat* comdat = this ->module_ ->getOrInsertComdat (helper::create_prefixed_name (link_name));
345+ comdat->setSelectionKind (llvm::Comdat::Any);
346+ global_struct->setComdat (comdat);
325347
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);
348+ auto add_to_comdat = [&](llvm::Constant* ptr) {
349+ if (auto * global = llvm::dyn_cast_or_null<llvm::GlobalObject>(ptr)) {
350+ global->setComdat (comdat);
351+ }
352+ };
330353
331- auto add_to_comdat = [&](llvm::Constant* ptr) {
332- if (auto * global = llvm::dyn_cast_or_null<llvm::GlobalObject>(ptr)) {
333- global->setComdat (comdat);
354+ const auto get_info_object = [&]() -> llvm::Constant* {
355+ if (emit_name) {
356+ llvm::Constant* name_str_ptr = create_global_constant_string (link_name, base_name);
357+ const auto info_data = helper::get_serialized_members_for<uint16_t >(*type_struct);
358+ llvm::Constant* data_ptr =
359+ create_global_array_ptr<uint16_t >(helper::concat (" info_data_" , link_name), info_data);
360+ llvm::Constant* members_ptr =
361+ create_global_member_array_ptr (helper::concat (" member_types_" , link_name), type_struct->member_types );
362+
363+ llvm::GlobalVariable* global_struct_info =
364+ create_global (helper::concat (link_name, " _info" ), struct_layout_type_cold_, nullptr );
365+
366+ std::vector<llvm::Constant*> init_fields_cold = {name_str_ptr, data_ptr, members_ptr};
367+ global_struct_info->setInitializer (llvm::ConstantStruct::get (struct_layout_type_cold_, init_fields_cold));
368+
369+ {
370+ add_to_comdat (global_struct_info);
371+ add_to_comdat (data_ptr);
372+ add_to_comdat (members_ptr);
373+ add_to_comdat (name_str_ptr);
334374 }
335- };
336375
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);
341- }
376+ return global_struct_info;
377+ }
378+ return types_helper.get_constant_nullptr ();
379+ };
380+
381+ std::vector<llvm::Constant*> init_fields = {
382+ types_helper.get_constant_for (IGlobalType::type_id, type_struct->type_id ),
383+ types_helper.get_constant_for (IGlobalType::extent, type_struct->extent ), get_info_object ()};
384+ llvm::Constant* init = llvm::ConstantStruct::get (struct_layout_type_, init_fields);
385+ global_struct->setInitializer (init);
342386
343387 return global_struct;
344388 }
0 commit comments