{"id":48112712,"url":"https://github.com/ahueck/llvm-dimeta","last_synced_at":"2026-04-04T16:10:08.029Z","repository":{"id":268774212,"uuid":"454069059","full_name":"ahueck/llvm-dimeta","owner":"ahueck","description":"A library for identifying types of stack, global, and heap allocations in LLVM IR using only LLVM's debug information and metadata.","archived":false,"fork":false,"pushed_at":"2026-03-19T16:04:50.000Z","size":310,"stargazers_count":14,"open_issues_count":2,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-20T08:13:26.587Z","etag":null,"topics":["llvm","llvm-ir","metadata"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ahueck.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-01-31T15:51:50.000Z","updated_at":"2025-11-22T16:57:31.000Z","dependencies_parsed_at":"2024-12-18T21:20:13.058Z","dependency_job_id":"15d4066c-a9f9-4773-9825-d13914a8092a","html_url":"https://github.com/ahueck/llvm-dimeta","commit_stats":null,"previous_names":["ahueck/llvm-dimeta"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/ahueck/llvm-dimeta","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ahueck%2Fllvm-dimeta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ahueck%2Fllvm-dimeta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ahueck%2Fllvm-dimeta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ahueck%2Fllvm-dimeta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ahueck","download_url":"https://codeload.github.com/ahueck/llvm-dimeta/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ahueck%2Fllvm-dimeta/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31405641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["llvm","llvm-ir","metadata"],"created_at":"2026-04-04T16:10:07.304Z","updated_at":"2026-04-04T16:10:07.938Z","avatar_url":"https://github.com/ahueck.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# llvm-dimeta  \u0026middot; [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Coverage Status](https://coveralls.io/repos/github/ahueck/llvm-dimeta/badge.svg?branch=main)](https://coveralls.io/github/ahueck/llvm-dimeta)\n\nllvm-dimeta \\[[DI25](#ref-llvm-dimeta-2025)\\] is library to determine the type of stack (`AllocaInst`), globals (`GlobalVariables`) and heap allocations in LLVM IR based only on the LLVM debug information and metadata.\n\nTo that end, [Dimeta.h](lib/type/Dimeta.h) defines an API to\n(a) query the LLVM debug metadata entry (`DIType`) for an allocation, or (b) query source location-specific type information with a custom type serialization as defined in [DimetaData.h](lib/type/DimetaData.h).\nThis representation can be transformed to a `yaml` format with [DimetaIO.h](lib/type/DimetaIO.h).\n\n*Note*: For llvm-dimeta to work, LLVM debug information is required (additionally compile with the `-g` flag).\n\n\n## 1. Usage\n\n### 1.1 Code\nExample function of some LLVM plugin using llvm-dimeta to query the type layout of heap-like allocations, and printing it to console as yaml.\n\n```cpp\n#include \"Dimeta.h\"\n#include \"DimetaIO.h\"\n...\nvoid runOnFunction(llvm::Function\u0026 func) {\n  for (const auto\u0026 inst : llvm::instructions(func)) {\n    if (const auto* call_inst = llvm::dyn_cast\u003cCallBase\u003e(\u0026inst)) {\n      // not empty only if malloc- or new-like call:\n      auto ditype = get_located_type(call_inst);\n      if (ditype) {\n        std::string yaml_string;\n        llvm::raw_string_ostream yaml_oss(yaml_string);\n        io::emit(yaml_oss, ditype.value());\n        llvm::outs() \u003c\u003c \"Final heap type: \\n\" \u003c\u003c yaml_oss.str() \u003c\u003c \"\\n\";\n      }\n    }\n  }\n}\n```\n\n### 1.2 Consuming llvm-dimeta\nExample using CMake [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) for consuming the llvm-dimeta library.\nSee [2. Building llvm-dimeta](#2-building-llvm-dimeta) for software requirements.\n\n```cmake\nFetchContent_Declare(\n  llvm-dimeta\n  GIT_REPOSITORY https://github.com/ahueck/llvm-dimeta\n  GIT_TAG main\n  GIT_SHALLOW 1\n)\nFetchContent_MakeAvailable(llvm-dimeta)\n\ntarget_link_libraries(my_project_target PRIVATE dimeta::Types)\n```\n\n\n### 1.3 Algorithmic approach\n\nConsider the simplified LLVM IR code of the [C file](test/pass/c/heap_struct_member.c) generated with Clang 19:\n\n```llvm\n%struct.A = type { ptr }\n\ndefine dso_local void @foo() !dbg !10 {\nentry:\n  %a_struct = alloca %struct.A, align 8\n    #dbg_declare(ptr %a_struct, !15, !DIExpression(), !21)\n  %call = call noalias ptr @malloc(i64 noundef 4) #2, !dbg !22\n  %a = getelementptr inbounds nuw %struct.A, ptr %a_struct, i32 0, i32 0, !dbg !23\n  store ptr %call, ptr %a, align 8, !dbg !24\n  ret void, !dbg !25\n}\n\n...\n!15 = !DILocalVariable(name: \"a_struct\", scope: !10, file: !11, line: 8, type: !16)\n!16 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: \"A\", file: !11, line: 3, size: 64, elements: !17)\n!17 = !{!18}\n!18 = !DIDerivedType(tag: DW_TAG_member, name: \"a\", scope: !16, file: !11, line: 4, baseType: !19, size: 64)\n!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)\n!20 = !DIBasicType(name: \"int\", size: 32, encoding: DW_ATE_signed)\n!21 = !DILocation(line: 10, column: 12, scope: !10)\n!22 = !DILocation(line: 12, column: 16, scope: !10)\n...\n```\n\n1. Calling `located_type_for` on the `llvm::AllocaInst` `%a_struct` results in: \n\n    ```yaml\n    SourceLoc:\n        File:            'path/to/heap_struct_member.c'\n        Function:        foo\n        Line:            10\n    Builtin:         false\n    Type:\n        Compound:\n            Name:            A\n            Type:            struct\n            Extent:          8\n            Sizes:           [ 8 ]\n            Offsets:         [ 0 ]\n            Members:\n            - Name:            a\n                Builtin:         true\n                Type:\n                Fundamental:     { Name: int, Extent: 4, Encoding: signed_int }\n                Qualifiers:      [ ptr ]\n    ```\n\n    The library searches the function `@foo` for the `#dbg_declare` debug record of the `alloca` and parses the layout of `!15`.\n\n2. Calling `located_type_for` on the `llvm::CallBase` for `@malloc` results in:\n\n    ```yaml\n    SourceLoc:\n        File:            'path/to/heap_struct_member.c'\n        Function:        foo\n        Line:            12\n    Builtin:         true\n    Type:\n        Fundamental:     { Name: int, Extent: 4, Encoding: signed_int }\n        Qualifiers:      [ ptr ]\n    ```\n   \n   Since there is no debug type metadata mapping for the call, we use dataflow analysis starting from the `malloc` call to resolve the type:\n   The process starts with a forward data flow search from the `malloc` call, finding the store instruction. A subsequent backward search of the store target identifies the alloca `%a_struct` as the root node. The type of the root is identified as `struct A` through the debug record (`!16`). \n   Using the root type, we analyze the rest of the instruction to refine the `DIType`: The `getelementptr` instruction determines the LHS of the assignment. By using the access indices `0 0`, we trace through the debug metadata of the root node (`!16`) and identify that it points to the member pointer `!18`, which has the base type `int` (`!19`).\n\n\n## 2. Building llvm-dimeta\n\nllvm-dimeta is tested with LLVM version 13-15 and 18-22, and CMake version \u003e= 3.20. Use CMake presets `develop` or `release` to build.\n\n### 2.1 Build example\n\nRelease build recipe, installs to default prefix\n`${dimeta_SOURCE_DIR}/install/dimeta`\n\n```sh\n$\u003e cd llvm-dimeta\n$\u003e cmake --preset release\n$\u003e cmake --build build --target install --parallel\n```\n\n### 2.2 Main build flags\n\n| Option                     | Default | Description                                                              |\n|----------------------------|:-------:|--------------------------------------------------------------------------|\n| `DIMETA_USE_HEAPALLOCSITE` |  `ON`   | Use `!heapallocsite` metadata to type the allocation                     |\n| `DIMETA_USE_TBAA`          |  `OFF`  | Use C/C++ type-based alias analysis data to type the allocation          |\n| `DIMETA_TEST_CONFIG`       |  `OFF`  | Enable test config, see Section [2.3](#23-testing) (sets log level etc.) |\n| `DIMETA_LOG_LEVEL`         |   `1`   | Granularity of pass logger. 3 is most verbose, 0 is least                |\n| `DIMETA_ENABLE_COVERAGE`   |  `OFF`  | Enable collecting (test) coverage information                            |\n| `DIMETA_ENABLE_FLANG`      |  `OFF`  | Enable Fortran type extraction support                                   |\n\n### 2.3 Testing\nFor testing we require `lit` and `FileCheck`.\nTo execute the lit test suite:\n\n```sh\n$\u003e cmake --build build --target check-dimeta\n```\n\n## References\n\n\u003ctable style=\"border:0px\"\u003e\n\u003ctr\u003e\n    \u003ctd valign=\"top\"\u003e\u003ca name=\"ref-llvm-dimeta-2025\"\u003e\u003c/a\u003e[DI25]\u003c/td\u003e\n    \u003ctd\u003eHück, Alexander and Kreutzer, Sebastian and Bischof, Christian.\n    \u003cb\u003ellvm-dimeta: A library for extracting source-level type information in LLVM IR using debug metadata\u003c/b\u003e.\n    In \u003ci\u003e2025 IEEE International Conference on Source Code Analysis \u0026 Manipulation (SCAM)\u003c/i\u003e,\n    pages 116-121. IEEE, 2025. DOI: \u003ca href=\"https://doi.org/10.1109/SCAM67354.2025.00019\"\u003e10.1109/SCAM67354.2025.00019\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fahueck%2Fllvm-dimeta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fahueck%2Fllvm-dimeta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fahueck%2Fllvm-dimeta/lists"}