LLVM IR — 18 Operations for AI Agents
LLVM IR is the common tongue of modern compilers — the lowered form where optimizations and codegen bugs live. act101 navigates functions and basic blocks structurally, so agents inspect compiler output without scrolling through SSA noise.
This page is the canonical reference an AI coding agent uses to refactor, query, and analyze LLVM IR code through the act MCP server. 18 operations available: 0 refactor, 18 query, 0 analysis. Each operation is callable from Claude Code, Cursor, Codex, OpenCode, or any MCP-compatible agent host. Click any operation for a stable anchor link suitable for citation.
Worked LLVM IR examples
act101 reads an LLVM IR module's function definitions, function declarations, global variable/constant definitions, and named type aliases as top-level declarations: skeleton tags a defined function and a declared-only function alike as function, and a global variable and a named struct type alike as variable, deriving each kind from the surrounding LLVM construct rather than from the construct's own keyword. symbols covers the same four constructs and adds each function's own basic-block labels, but every entry it reports — declarations, globals, functions, and labels alike — comes back kind: unknown, since its rules bind the kind-determining capture to the bare identifier or label node rather than to the construct around it. The unit of structure in this grammar is the top-level definition or declaration; neither query descends into a function's own instructions. Each example below is the verbatim output of the command shown, run against the file shown. Query outputs are pretty-printed with the timing block omitted.
Read the module's functions, global, and type alias as a skeleton
fnv_hash.ll implements an FNV-1a hash over a byte buffer: a %struct.HashState type alias, a @seed_table global constant, a declared-only @printf, and the @fnv1a_hash function that does the hashing.
$ act query skeleton fnv_hash.ll
Before
; ModuleID = 'fnv_hash'
%struct.HashState = type { i64, i32 }
@seed_table = global [4 x i32] [i32 1, i32 2, i32 3, i32 5]
declare i32 @printf(i8*, ...)
define i64 @fnv1a_hash(i8* %data, i64 %len) {
entry:
br label %loop
loop:
%i = phi i64 [ 0, %entry ], [ %next_i, %loop ]
%hash = phi i64 [ -3750763034362895579, %entry ], [ %mul, %loop ]
%ptr = getelementptr i8, i8* %data, i64 %i
%byte = load i8, i8* %ptr
%byte64 = zext i8 %byte to i64
%xored = xor i64 %hash, %byte64
%mul = mul i64 %xored, 1099511628211
%next_i = add i64 %i, 1
%done = icmp eq i64 %next_i, %len
br i1 %done, label %exit, label %loop
exit:
ret i64 %mul
}
Output
{
"type": "Skeleton",
"declarations": [
{
"kind": "variable",
"name": "%struct.HashState",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 3,
"column": 1,
"byte_offset": 25
},
"end": {
"file": "fnv_hash.ll",
"line": 3,
"column": 38,
"byte_offset": 62
}
},
"name_range": {
"start": {
"file": "fnv_hash.ll",
"line": 3,
"column": 1,
"byte_offset": 25
},
"end": {
"file": "fnv_hash.ll",
"line": 3,
"column": 18,
"byte_offset": 42
}
}
},
{
"kind": "variable",
"name": "@seed_table",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 5,
"column": 1,
"byte_offset": 64
},
"end": {
"file": "fnv_hash.ll",
"line": 5,
"column": 60,
"byte_offset": 123
}
},
"name_range": {
"start": {
"file": "fnv_hash.ll",
"line": 5,
"column": 1,
"byte_offset": 64
},
"end": {
"file": "fnv_hash.ll",
"line": 5,
"column": 12,
"byte_offset": 75
}
}
},
{
"kind": "function",
"name": "@printf",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 7,
"column": 1,
"byte_offset": 125
},
"end": {
"file": "fnv_hash.ll",
"line": 7,
"column": 30,
"byte_offset": 154
}
},
"name_range": {
"start": {
"file": "fnv_hash.ll",
"line": 7,
"column": 13,
"byte_offset": 137
},
"end": {
"file": "fnv_hash.ll",
"line": 7,
"column": 20,
"byte_offset": 144
}
}
},
{
"kind": "function",
"name": "@fnv1a_hash",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 9,
"column": 1,
"byte_offset": 156
},
"end": {
"file": "fnv_hash.ll",
"line": 27,
"column": 2,
"byte_offset": 654
}
},
"name_range": {
"start": {
"file": "fnv_hash.ll",
"line": 9,
"column": 12,
"byte_offset": 167
},
"end": {
"file": "fnv_hash.ll",
"line": 9,
"column": 23,
"byte_offset": 178
}
}
}
]
}
The skeleton reports four declarations: %struct.HashState and @seed_table both come back kind variable, and the declared @printf and the defined @fnv1a_hash both come back kind function — skeleton does not distinguish a declaration from a definition.
List every symbol, including the function's basic-block labels
@fnv1a_hash's body is split into three basic blocks — entry, loop, and exit — with loop folding one byte of the buffer into the running hash per iteration.
$ act query symbols fnv_hash.ll
Before
; ModuleID = 'fnv_hash'
%struct.HashState = type { i64, i32 }
@seed_table = global [4 x i32] [i32 1, i32 2, i32 3, i32 5]
declare i32 @printf(i8*, ...)
define i64 @fnv1a_hash(i8* %data, i64 %len) {
entry:
br label %loop
loop:
%i = phi i64 [ 0, %entry ], [ %next_i, %loop ]
%hash = phi i64 [ -3750763034362895579, %entry ], [ %mul, %loop ]
%ptr = getelementptr i8, i8* %data, i64 %i
%byte = load i8, i8* %ptr
%byte64 = zext i8 %byte to i64
%xored = xor i64 %hash, %byte64
%mul = mul i64 %xored, 1099511628211
%next_i = add i64 %i, 1
%done = icmp eq i64 %next_i, %len
br i1 %done, label %exit, label %loop
exit:
ret i64 %mul
}
Output
{
"type": "Symbols",
"symbols": [
{
"name": "%struct.HashState",
"kind": "unknown",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 3,
"column": 1,
"byte_offset": 25
},
"end": {
"file": "fnv_hash.ll",
"line": 3,
"column": 18,
"byte_offset": 42
}
},
"visibility": "unknown"
},
{
"name": "@seed_table",
"kind": "unknown",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 5,
"column": 1,
"byte_offset": 64
},
"end": {
"file": "fnv_hash.ll",
"line": 5,
"column": 12,
"byte_offset": 75
}
},
"visibility": "unknown"
},
{
"name": "@printf",
"kind": "unknown",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 7,
"column": 13,
"byte_offset": 137
},
"end": {
"file": "fnv_hash.ll",
"line": 7,
"column": 20,
"byte_offset": 144
}
},
"visibility": "unknown"
},
{
"name": "@fnv1a_hash",
"kind": "unknown",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 9,
"column": 12,
"byte_offset": 167
},
"end": {
"file": "fnv_hash.ll",
"line": 9,
"column": 23,
"byte_offset": 178
}
},
"visibility": "unknown"
},
{
"name": "entry:",
"kind": "unknown",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 10,
"column": 1,
"byte_offset": 202
},
"end": {
"file": "fnv_hash.ll",
"line": 10,
"column": 7,
"byte_offset": 208
}
},
"visibility": "unknown"
},
{
"name": "loop:",
"kind": "unknown",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 13,
"column": 1,
"byte_offset": 227
},
"end": {
"file": "fnv_hash.ll",
"line": 13,
"column": 6,
"byte_offset": 232
}
},
"visibility": "unknown"
},
{
"name": "exit:",
"kind": "unknown",
"range": {
"start": {
"file": "fnv_hash.ll",
"line": 25,
"column": 1,
"byte_offset": 632
},
"end": {
"file": "fnv_hash.ll",
"line": 25,
"column": 6,
"byte_offset": 637
}
},
"visibility": "unknown"
}
]
}
symbols adds all three block labels to the same four top-level names, for seven entries total, but reports every one of them — the struct, the global, both functions, and all three labels — as kind: unknown.
Query
18 query tools, the same on every supported language. Descriptions live in the shared reference: /docs/query-tools.
callers control_flow data_flow definition diagnostics effect_closure effect_summary fix_auto get_type graph import_organize interface mutations references repo_outline skeleton symbols symbols_batch