From de5ce90fa70c8ae4b859b50704dd0ffacbeedb1e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 May 2024 15:28:09 +0100 Subject: [PATCH] Add metadata to packed structs field accesses to state it is packed --- src/llvm_backend.hpp | 6 +++++- src/llvm_backend_general.cpp | 6 ++++++ src/llvm_backend_utility.cpp | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 7dc5f6b63..975aa17c5 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -581,6 +581,10 @@ gb_internal LLVMTypeRef llvm_array_type(LLVMTypeRef ElementType, uint64_t Elemen #endif } + +gb_internal void lb_set_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name, u64 value); +gb_internal u64 lb_get_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name); + #define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime" #define LB_CLEANUP_RUNTIME_PROC_NAME "__$cleanup_runtime" #define LB_TYPE_INFO_DATA_NAME "__$type_info_data" @@ -719,4 +723,4 @@ gb_global char const *llvm_linkage_strings[] = { "linker private weak linkage" }; -#define ODIN_METADATA_REQUIRE "odin-metadata-require", 21 +#define ODIN_METADATA_IS_PACKED str_lit("odin-is-packed") \ No newline at end of file diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 15cbb7c71..22ffbd89c 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1107,6 +1107,12 @@ gb_internal lbValue lb_emit_load(lbProcedure *p, lbValue value) { GB_ASSERT(is_type_pointer(value.type)); Type *t = type_deref(value.type); LLVMValueRef v = LLVMBuildLoad2(p->builder, lb_type(p->module, t), value.value, ""); + + u64 is_packed = lb_get_metadata_custom_u64(p->module, v, ODIN_METADATA_IS_PACKED); + if (is_packed != 0) { + LLVMSetAlignment(v, 1); + } + return lbValue{v, t}; } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index db99ebc99..8b046c784 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -57,6 +57,29 @@ gb_internal lbValue lb_correct_endianness(lbProcedure *p, lbValue value) { return value; } + +gb_internal void lb_set_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name, u64 value) { + unsigned md_id = LLVMGetMDKindIDInContext(m->ctx, cast(char const *)name.text, cast(unsigned)name.len); + LLVMMetadataRef md = LLVMValueAsMetadata(LLVMConstInt(lb_type(m, t_u64), value, false)); + LLVMValueRef node = LLVMMetadataAsValue(m->ctx, LLVMMDNodeInContext2(m->ctx, &md, 1)); + LLVMSetMetadata(v_ref, md_id, node); +} +gb_internal u64 lb_get_metadata_custom_u64(lbModule *m, LLVMValueRef v_ref, String name) { + unsigned md_id = LLVMGetMDKindIDInContext(m->ctx, cast(char const *)name.text, cast(unsigned)name.len); + LLVMValueRef v_md = LLVMGetMetadata(v_ref, md_id); + if (v_md == nullptr) { + return 0; + } + unsigned node_count = LLVMGetMDNodeNumOperands(v_md); + if (node_count == 0) { + return 0; + } + GB_ASSERT(node_count == 1); + LLVMValueRef value = nullptr; + LLVMGetMDNodeOperands(v_md, &value); + return LLVMConstIntGetZExtValue(value); +} + gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile) { return lb_mem_zero_ptr_internal(p, ptr, LLVMConstInt(lb_type(p->module, t_uint), len, false), alignment, is_volatile); } @@ -1148,7 +1171,15 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { GB_ASSERT_MSG(result_type != nullptr, "%s %d", type_to_string(t), index); - return lb_emit_struct_ep_internal(p, s, index, result_type); + lbValue gep = lb_emit_struct_ep_internal(p, s, index, result_type); + + Type *bt = base_type(t); + if (bt->kind == Type_Struct && bt->Struct.is_packed) { + lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1); + GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1); + } + + return gep; } gb_internal lbValue lb_emit_tuple_ev(lbProcedure *p, lbValue value, i32 index) {