{"id":51645621,"url":"https://github.com/yucl80/llvm-parser","last_synced_at":"2026-07-13T22:03:19.214Z","repository":{"id":360422624,"uuid":"1249922754","full_name":"yucl80/llvm-parser","owner":"yucl80","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-26T09:55:37.000Z","size":322,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-26T11:32:52.819Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yucl80.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2026-05-26T06:37:51.000Z","updated_at":"2026-05-26T09:55:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yucl80/llvm-parser","commit_stats":null,"previous_names":["yucl80/llvm-parser"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/yucl80/llvm-parser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yucl80%2Fllvm-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yucl80%2Fllvm-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yucl80%2Fllvm-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yucl80%2Fllvm-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yucl80","download_url":"https://codeload.github.com/yucl80/llvm-parser/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yucl80%2Fllvm-parser/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35437768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-13T02:00:06.543Z","response_time":119,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2026-07-13T22:03:18.485Z","updated_at":"2026-07-13T22:03:19.209Z","avatar_url":"https://github.com/yucl80.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# llvm-parser\n\nSVF-based call graph analysis tool that performs Andersen-style pointer analysis on LLVM bitcode and outputs a topological call graph tree.\n\n## Components\n\n### Analyzer\n\n- **`svf-api-demo/test.cpp`** / **`svf-api-demo/a.cpp`** — Loads LLVM bitcode, builds SVFIR (Program Assignment Graph), runs AndersenWaveDiff pointer analysis, and prints the resolved call graph as a tree topology with `├──`/`└──` branch connectors.\n- **`svf-api-demo/test_svf`** — Compiled analyzer binary.\n\n### Test Programs\n\n| File | Description |\n|------|-------------|\n| `svf-api-demo/test_prog.c` | Simple C program with direct function calls (`foo`, `bar`, `zoo`) |\n| `svf-api-demo/test_complex.cpp` | Comprehensive C++ test covering all indirect call patterns |\n\n## Test Scenarios (test_complex.cpp)\n\nThe complex test covers the following call patterns that SVF's pointer analysis must resolve:\n\n### Direct Calls\n- `directCall()` → `printf` — trivial direct call\n\n### Function Pointers\n- **Basic function pointer**: `FuncPtr fp = calleeViaPtr; fp();`\n- **Function pointer array**: `FuncPtr table[3] = {fa, fb, fc}; table[i]();`\n- **Callback parameter**: `sortWithCallback(arr, n, cmp)` where `cmp` is a function pointer parameter, called with `compareAsc` / `compareDesc`\n- **Pointer to function pointer** (double/triple indirection): `FuncPtr* fpp = \u0026fp; FuncPtr** fppp = \u0026fpp;`\n- **Struct member function pointer**: `Handler` struct with `HandlerFunc onEvent` member, including runtime swap between instances\n- **Function returning function pointer**: `chooseHandler(kind)` returns `fa` or `fb`; caller invokes the returned pointer\n- **Array of pointers to function pointers**: `FuncPtr* fptrs[2] = {\u0026fns[0], \u0026fns[1]}; (*fptrs[i])();`\n- **Nested callback**: `middleWare()` receives both a `Comparator` and a `void (*report)(int)` function pointer, demonstrating multi-layer indirect call chains\n\n### Function Overloading\n- `overloaded(int)` and `overloaded(double)` — resolved via LLVM mangling\n\n### Virtual Dispatch\n- Single virtual inheritance: `Base* b = new Derived(); b-\u003evirtualMethod();`\n- Polymorphic array: `Animal* animals[3]` holding `Animal`, `Dog`, `Cat` instances, iterated in a loop\n- **Multiple inheritance**: `MultiDerived` inherits from both `MixinA` and `MixinB`, each with virtual methods; calls dispatch through each base pointer with this-pointer adjustment\n- **Diamond virtual inheritance**: `DiamondTip` inherits from `MidLeft` and `MidRight`, both virtually derived from `DiamondBase`; virtual base pointer resolution\n- **Abstract base class dispatch**: `AbstractBase` with pure virtual `doit()`/`report()`, dispatched through array of `ConcreteA`/`ConcreteB` pointers\n- **Multi-level virtual chain**: `VBase → VMid → VDerived` three-level override hierarchy dispatched through base pointer array\n- **Virtual calls in constructor/destructor**: `TraceDerived` calls virtual `log()` during construction and destruction (dynamic type changes during these contexts)\n- **Pure virtual call in base destructor**: `AbstractBase::~AbstractBase()` dispatches via `llvm.trap` (undefined behavior guard)\n\n### Lambdas\n- Stateless lambda: `[](){}`\n- Capture-by-value lambda with return: `[x](int y) -\u003e int`\n- Capture-by-reference lambda calling another function\n- **Generic lambda (C++14)**: `[](auto a, auto b){}` — templated call operator instantiated with `int` and `double`\n- **Capture by move (C++14)**: `[p = ptr](){}` — lambda captures a dynamically allocated pointer via move\n- **Nested lambda**: Lambda `makeAdder()` returns a capturing lambda; closure-in-closure call chain\n- **Lambda wrapped in std::function**: Stateless lambda assigned to `std::function\u003cvoid()\u003e`, invoked through the type-erased wrapper\n\n### Modern C++ Callable Wrappers\n- **std::function**: Wraps free functions (`stdFuncTarget1`, `stdFuncTarget2`), a lambda, and supports reassignment between targets\n- **std::bind**: Binds arguments to `bindTarget(a,b,c)` using `std::placeholders`, creating callable objects with fewer parameters\n- **std::function + bind**: A `std::function\u003cvoid()\u003e` wrapping a `std::bind` expression\n- **std::invoke (C++17)**: Unified call syntax invoking a free function, a member function (`Calculator::add` via pointer-to-member), and a lambda\n\n### Member Pointers \u0026 Functors\n- **Pointer to member function**: `int (Calculator::*MathOp)(int,int)` called via `.*` and `-\u003e*` syntax on instances of `Calculator`, selecting `add`, `sub`, `mul` at runtime\n- **Functor (function object)**: `Greeter` class with `operator()(const char*)` — different instances hold different state; calling `hello(\"World\")` vs `goodbye(\"World\")` dispatches to the same operator with different internal data\n\n### Function Pointer Advanced Patterns\n- **Ternary/conditional dispatch**: `FuncPtr f = flag ? condTrue : condFalse;` — runtime condition selects between two function pointers\n- **State machine with function pointer table**: `StateHandler states[3] = {stateIdle, stateRunning, stateStopped};` dispatched in a loop\n- **Function pointer reassignment in loop**: `FuncPtr fp` reassigned each iteration through a loop over `fns[]` array\n- **Struct dispatch table**: `DispatchEntry` struct array with `name` string and `handler` function pointer; iterated and invoked\n- **Function pointer on struct with operator()**: `CallableOps` struct wrapping a function pointer, called via `operator()()` overload\n\n### Recursion\n- **Direct recursion**: `factorial(n)` calls itself with `n-1`\n- **Mutual recursion**: `mutualA()` and `mutualB()` call each other alternately with decreasing counter\n\n### Template \u0026 Generic Patterns\n- **Function templates**: `maxOf\u003cint\u003e(3,7)` and `maxOf\u003cdouble\u003e(3.14,2.72)` — different template instantiations produce distinct call targets\n- **Variadic function template**: `varargSink(1,2,3,4,5)` — recursive template instantiation over parameter pack\n- **CRTP (Curiously Recurring Template Pattern)**: `ShapeBase\u003cDerived\u003e::draw()` calls `static_cast\u003cDerived*\u003e(this)-\u003edrawImpl()`, resolved at compile time to `Circle::drawImpl()` or `Square::drawImpl()`\n\n### Other C++ Features\n- **Default arguments**: `defaultArgsFunc(1)`, `defaultArgsFunc(2,20)`, `defaultArgsFunc(3,30,\"explicit\")` — calls with different argument counts expand differently at IR level\n- **Operator overloading**: Built-in `operator+` called on `int` operands to verify operator call edges\n\n### C++17 Callable \u0026 Dispatch Patterns (New)\n- **std::mem_fn**: `std::mem_fn(\u0026Calculator::add)` wraps a member function pointer into a callable, invoked via `_Mem_fn::operator()` with `__invoke_memfun_ref` / `__invoke_memfun_deref` paths\n- **std::bind with member function**: `std::bind(\u0026Calculator::add, \u0026calc, _1, _2)` — binds a member function pointer with an instance pointer and placeholders, creating a complex nested call chain through `_Bind::__call` → `__invoke_memfun_deref`\n- **Delegate pattern**: `Button` class stores `std::function\u003cvoid()\u003e` / `std::function\u003cvoid(int)\u003e` as members. Callbacks (`delegateClickA/B`, `delegateKeyHandler`) are dynamically registered with `setOnClick`/`setOnKey` and dispatched through `operator()` — includes runtime reassignment\n- **std::map dispatch table**: `std::map\u003cint, FuncPtr\u003e` storing `mapCmdStart`/`mapCmdStop`/`mapCmdStatus`, looked up via `find()` and invoked through `it-\u003esecond()`\n- **if constexpr dispatch (C++17)**: `algoDispatch\u003ctrue\u003e()` vs `algoDispatch\u003cfalse\u003e()` — compile-time branch elimination via `if constexpr`, only the selected path survives in IR\n- **Fold expression call (C++17)**: `(foldTarget(args), ...)` expands a parameter pack over the comma operator into sequential calls; `(fns(), ...)` calls a pack of function pointers\n- **std::apply (C++17)**: `std::apply(applyTarget, tuple)` unpacks a tuple into function arguments; also tested with a lambda\n- **Overloaded lambda pattern (C++17)**: `Overloaded{[](int){}, [](const char*){}}` uses variadic `using Ts::operator()...` and CTAD deduction guide to create a multi-overload callable; dispatched through the synthesized `operator()`\n- **std::variant + std::visit**: `VariantType = std::variant\u003cint, double, const char*\u003e` visited in a loop with an `Overloaded` visitor, dispatching to `variantIntHandler` / `variantDoubleHandler` / `variantStrHandler` per alternative\n- **Recursive lambda via std::function**: Lambda that captures itself by reference (`[\u0026fib]`) in a `std::function\u003cint(int)\u003e` and calls `fib(n-1) + fib(n-2)` recursively to compute Fibonacci, relying on type-erased self-reference\n\n## Build \u0026 Usage\n\n### Prerequisites\n\n- SVF framework (with LLVM backend)\n- LLVM 21 toolchain\n- Z3 solver\n\n### Compile Bitcode\n\n```bash\n# C test program\n/root/src/SVF/llvm-21.1.0.obj/bin/clang -O0 -g -emit-llvm -c test_prog.c -o test_prog.bc\n\n# C++ test program\n/root/src/SVF/llvm-21.1.0.obj/bin/clang++ -std=c++17 -O0 -g -emit-llvm -c test_complex.cpp -o test_complex.bc\n```\n\n### Build Analyzer\n\n```bash\ng++ -std=c++17 -c test.cpp -o test.o \\\n  -I/root/src/SVF/svf/include \\\n  -I/root/src/SVF/svf-llvm/include \\\n  -I/root/src/SVF/Release-build/include \\\n  -I/root/src/SVF/llvm-21.1.0.obj/include\n\ng++ -std=c++17 -c a.cpp -o a.o \\\n  -I/root/src/SVF/svf/include \\\n  -I/root/src/SVF/svf-llvm/include \\\n  -I/root/src/SVF/Release-build/include \\\n  -I/root/src/SVF/llvm-21.1.0.obj/include\n\ng++ test.o a.o -o test_svf \\\n  -L/root/src/SVF/Release-build/lib -lSvfCore -lSvfLLVM \\\n  -L/root/src/SVF/llvm-21.1.0.obj/lib -lLLVM-21 \\\n  -lz3 -lpthread -ldl\n```\n\n### Run Analysis\n\nThe analyzer supports multiple analysis modes via CLI flags:\n\n| Flag | Description |\n|------|-------------|\n| *(default)* | AndersenWaveDiff — flow-insensitive, context-insensitive |\n| `--fs` | FlowSensitive (FSSPARSE_WPA) — sparse flow-sensitive analysis |\n| `--vfs` | VersionedFlowSensitive (VFS_WPA) — versioned flow-sensitive |\n| `--cs` | Context-sensitive SVFG (default is already context-sensitive) |\n| `--heap-model` | Heap object model (`ModelConsts`, `ModelArrays`) |\n\n```bash\n# Default: flow-insensitive, context-insensitive\nLD_LIBRARY_PATH=/root/src/SVF/Release-build/lib:/root/src/SVF/llvm-21.1.0.obj/lib \\\n  ./test_svf test_complex.bc\n\n# Flow-sensitive\nLD_LIBRARY_PATH=/root/src/SVF/Release-build/lib:/root/src/SVF/llvm-21.1.0.obj/lib \\\n  ./test_svf --fs test_complex.bc\n\n# Flow-sensitive + context-sensitive SVFG + heap object model\nLD_LIBRARY_PATH=/root/src/SVF/Release-build/lib:/root/src/SVF/llvm-21.1.0.obj/lib \\\n  ./test_svf --fs --cs --heap-model test_complex.bc\n\n# Versioned flow-sensitive (object versioning)\nLD_LIBRARY_PATH=/root/src/SVF/Release-build/lib:/root/src/SVF/llvm-21.1.0.obj/lib \\\n  ./test_svf --vfs test_complex.bc\n```\n\n### Run Test Program\n\n```bash\n./test_complex\n```\n\n## Example Output\n\n### Call Graph Topology\n\n```\n===== Call Graph Topology =====\nmain\n    ├── directCall()\n    │   └── printf\n    ├── testFuncPtr()\n    │   └── [Indirect]\n    │       └── calleeViaPtr()\n    │           └── printf\n    ├── testOverloaded()\n    │   ├── overloaded(int)\n    │   │   └── printf\n    │   └── overloaded(double)\n    │       └── printf\n    ├── testVirtual()\n    │   ├── operator new(unsigned long)\n    │   ├── Derived::Derived()\n    │   │   └── Base::Base()\n    │   ├── [Indirect]\n    │   │   └── Derived::virtualMethod()\n    │   │       └── printf\n    │   └── [Indirect]\n    │       └── Derived::~Derived()\n    │           ├── Derived::~Derived()\n    │           │   └── Base::~Base()\n    │           └── operator delete(void*, unsigned long)\n    ├── testLambda()\n    │   └── testLambda()::$_0::operator()() const\n    │       └── printf\n    ├── testCallbackParam()\n    │   └── sortWithCallback(int*, int, int (*)(int, int))\n    │       ├── [Indirect] → compareAsc(int, int)\n    │       └── [Indirect] → compareDesc(int, int)\n    ├── testPtrToFuncPtr()\n    │   └── [Indirect] → targetViaDoublePtr() → printf\n    ├── testStructFuncPtr()\n    │   └── [Indirect] → handleEventA(int) → printf\n    ├── testReturnFuncPtr()\n    │   └── chooseHandler(int)\n    │       └── [Indirect] → fa() → printf\n    └── testNestedCallback()\n        └── middleWare(int, int, int (*)(int, int), void (*)(int))\n            ├── [Indirect] → compareAsc(int, int)\n            ├── [Indirect] → compareDesc(int, int)\n            └── [Indirect] → reportResult(int) → printf\n```\n\nIndirect calls (function pointers, virtual dispatch) are marked `[Indirect]`. The tree uses `├──`/`└──` connectors with `│` vertical lines for hierarchy. If a call graph cycle is detected, `[cycle]` is printed to prevent infinite recursion.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyucl80%2Fllvm-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyucl80%2Fllvm-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyucl80%2Fllvm-parser/lists"}