StaticLLVM

Documentation for StaticLLVM

StaticLLVM.LLVMBlockType
LLVMBlock(lable::Symbol, index::Int, ir::SubString{String})

Represents a basic block in LLVM IR with its label, index (order), and IR body.

  • label::Symbol:Identifier for the LLVM IR block, e.g. :entry, :L3, etc.
  • index::Int: The order of block in LLVM IR function.
  • ir::SubString{String}: A substring view of the whole block.
source
StaticLLVM.MethodInfoType
MethodInfo(m::Core.Method)
MethodInfo(m::Core.Method, name::Symbol())

A mutable struct that stores metadata and compiled LLVM IR information for a specific Julia method.

Fields

  • name::Symbol: A user-friendly name for the method. Defaults to the mangled name if not provided.
  • mangled::Symbol: The internal compiler name of the method, used for LLVM IR lookup.
  • arg_types::Tuple: A tuple of argument types (excluding the function type), derived from the method signature.
  • method::Core.Method: The original Julia Method object
  • llvm_ir::String: The LLVM IR code generated for the method, extracted as a string.
source
StaticLLVM.ModVarInfoType
ModVarInfo(name::String, mod::Module, mangled::String, llvm_def::String, llvm_decl::String)

Holds metadata for a module-level mutable variable (ModVar):

  • name::Symbol : Julia binding name
  • file::Symbol : file of mod-vars
  • mangled::String : LLVM mangled global name
  • llvm_def::String : LLVM IR global variable definition
  • llvm_decl::String : LLVM IR external declaration
source
StaticLLVM.ModuleInfoType
ModuleInfo

Stores metadata associated with a Julia Module, including referenced methods and global module-level variables.

Fields

  • mod::Module: The Julia module this information is associated with.
  • mangled::String: The mangled name of the module, following the Itanium C++ ABI
  • modvars::IdSet{ModVarInfo}: A set of global static variables (ModVarInfo) used in this module. Identity-based (IdSet) to ensure uniqueness by object reference.
  • methods::Vector{MethodInfo}: A list of methods (MethodInfo) defined or referenced within this module.

Usage

ModuleInfo is typically constructed internally during code analysis or code generation workflows to track both method definitions and global state referenced by a module.

source
StaticLLVM.assemble_modinfoMethod
assemble_modinfo(config::Dict{String,Any}, method_map::IdDict{Core.Method,Symbol}, modvar_map::IdDict{UInt,ModVarInfo}, check_ir::Bool = true) -> IdDict{Module, ModuleInfo}

Constructs ModuleInfo objects that capture method-level (MethodInfo) and global variable (ModVarInfo) metadata within each Julia module.

Each entry in method_map is processed to generate a MethodInfo object containing LLVM IR and related properties. Similarly, each global variable entry in modvar_map is assigned to the appropriate module.

Arguments

  • config::Dict{String,Any}: Configuration dictionary. Must include keys like "debug" and "policy", controlling diagnostics and symbol filtering.
  • method_map::IdDict{Core.Method,Symbol}: Maps Julia Method objects to their LLVM mangled symbol names.
  • modvar_map::IdDict{UInt,ModVarInfo}: Maps raw pointer addresses (as UInt) to their corresponding global variable metadata.

LLVM IR policy Behavior

  • :warn: Emits a warning if non-static LLVM IR is found.
  • :strict: Throws an error.
  • :strip: Attempts to strip the specific GC-related IR allocations
  • :strip_all: Attempts to strip all GC-related IR allocations.

Returns

  • An IdDict{Module, ModuleInfo} mapping each involved Julia Module to its assembled ModuleInfo representation, including static methods and module-level variables.
source
StaticLLVM.buildFunction
build(mod::Module=Main, config::Dict=default_config())

Main build process:

  • Parse arguments if called from Main.
  • Collect global variables and method info.
  • Dump LLVM IR files.
  • Optionally compile with clang.

Arguments

  • mod: The module to process (defaults to Main).
  • config: Build configuration dictionary.

Supported compile modes:

  • :none – Just generate IR
  • :onefile – Compile all IR into a single binary
  • :makefile – (Not implemented)
source
StaticLLVM.clean_cacheMethod
clean_cache(path::String)

Delete cached build files (e.g., .o, .so, .dll, .lib, .a, .dylib) under the given directory. This is useful for cleaning intermediate or compiled files before a fresh build.

Arguments

  • path: Directory where cache files are stored.
source
StaticLLVM.collect_methods!Function
collect_methods!(name_map::IdDict{Method, Symbol}, method::Method)

Recursively collect methods starting from method, ensuring all are precompiled and mapped to mangled names. This function avoids use of global state by requiring an explicit name map to be passed in.

Arguments

  • method::Method: The starting method to process.
  • name_map::IdDict{Method, Symbol}: A dictionary to store original methods and their original names.

Behavior

  • Ensures the method is precompiled.
  • Stores a mapping from the method to its mangled name.
  • Recursively processes Core.MethodInstance objects found in method.roots.
source
StaticLLVM.collect_modvar_pairsMethod
collect_modvars(mod::Module) -> Vector{Tuple{Int, ModVarInfo}}

Recursively collects all mutable, constant global variables defined in a Julia module mod (excluding functions, types, and strings), and returns a list of (pointer, ModVarInfo) pairs.

Each ModVarInfo contains:

  • the original symbol name
  • the module it belongs to
  • its mangled LLVM symbol name
  • its LLVM IR definition and declaration
source
StaticLLVM.compile_llvm_filesMethod
compile_llvm_files(config::Dict)

Compile all LLVM IR files in a specified directory into a single output binary.

Expected keys in config:

  • "module": Name of the output executable.
  • "dir": Directory containing .ll files.
  • "clang": Path to clang compiler.
  • "cflag": Compiler flags (as a single string, e.g. "-O2 -flto").

Prints status messages and compilation result.

source
StaticLLVM.dump_llvm_irMethod
dump_llvm_ir(modinfo::ModuleInfo, output_dir::String, check::Bool)

Write LLVM IR files for a given ModuleInfo instance.

  • Writes the IR of static module variables into one file named after the module.
  • Writes the IR for each method individually into separate files.
  • Skips writing files if content is unchanged (if check is true).
source
StaticLLVM.emit_llvmFunction
emit_llvm(fn::Function, args::Union{Tuple, Nothing}=nothing; clean::Bool=true, dump::Bool=true) -> String

Generate LLVM IR for a specific method of a Julia function specialized on given argument types.

Arguments

  • fn: Julia function whose LLVM IR is requested.
  • args: Tuple of argument types specifying the method specialization; if nothing, expect exactly one method for fn.
  • clean: Remove extraneous comments and optionally add header if true (default: true).
  • dump: Include full LLVM module in output if true (default: true).

Returns

  • LLVM IR string of the matched method, optionally cleaned.

Behavior

  • If args is provided, use which to find the exact method.
  • If args is nothing, expect fn to have exactly one method, or throw an error.
  • Delegates actual IR emission to another emit_llvm method accepting a Method.

Example

ir = emit_llvm(sin, (Float64,); clean=true, dump=false)
println(ir)

add(x::Int) = x + 1
ir = emit_llvm(add)
println(ir)
source
StaticLLVM.emit_llvmMethod
emit_llvm(method::Core.Method; clean::Bool=true, dump::Bool=true) -> String

Generate the LLVM IR for a given Julia method.

Arguments

  • method: The Core.Method object to generate LLVM IR for.
  • clean: If true, strip comments and optionally prepend a header comment. Default is true.
  • dump: If true, include the full LLVM module in the output. Default is true.

Returns

  • A string containing the LLVM IR of the method. When clean is true, comments are stripped.

Details

  • Extracts the function instance and argument types from the method signature.
  • Uses InteractiveUtils.code_llvm to get the LLVM IR as a string.
  • Optionally cleans the IR by removing comments using strip_comments.
  • When cleaning, adds the method signature as a header comment.

Example

ir = emit_llvm(my_method, clean=true, dump=false)
println(ir)
source
StaticLLVM.emit_nativeFunction
emit_native(fn::Function, args::Union{Tuple, Nothing}=nothing; clean::Bool=true, dump::Bool=true) -> String

Generate native LLVM assembly for a specific method of a Julia function given argument types.

Arguments

  • fn: Julia function whose LLVM IR is requested.
  • args: Tuple of argument types specifying the method specialization; if nothing, expect exactly one method for fn.
  • clean: Remove extraneous comments and optionally add header if true (default: true).
  • dump: Include full LLVM module in output if true (default: true).

Returns

  • A string containing the native LLVM assembly code.
  • When clean is true, comments and debug info are removed.

Behavior

  • If args is provided, use which to find the exact method.
  • If args is nothing, expect fn to have exactly one method, or throw an error.
  • Delegates actual IR emission to another emit_llvm method accepting a Method.

Example

ir = emit_native(sin, (Float64,); clean=true, dump=false)
println(ir)

add(x::Int) = x + 1
ir = emit_native(add)
println(ir)
source
StaticLLVM.emit_nativeMethod
emit_native(method::Core.Method; clean::Bool=true, dump::Bool=true) -> String

Generate the native LLVM bitcode (assembly) for a given Julia method.

Arguments

  • method: The Core.Method to generate native code for.
  • clean: If true, remove comments and debug info from the output. Default is true.
  • dump: If true, include the full module dump. Default is true.

Returns

  • A string containing the native LLVM assembly code.
  • When clean is true, comments and debug info are removed.

Details

  • Extracts the function instance and argument types from the method signature.
  • Calls InteractiveUtils.code_native to get native LLVM assembly.
  • Controls debug info level: :none if clean, otherwise :default.
  • Optionally cleans the output by stripping comments.

Example

native_ir = emit_native(my_method, clean=true, dump=false)
println(native_ir)
source
StaticLLVM.extract_llvmFunction
extract_llvm(method::Core.Method, ir::String; main::Bool=false) -> String

Extract and clean up the LLVM IR of a single Julia-compiled function from the full IR string ir.

Arguments

  • method::Core.Method: The Julia method to locate in the LLVM IR.
  • ir::String: The full LLVM IR text to search within.
  • main::Bool=false: If true, rename the function to @main, otherwise use the Julia function name.

Returns

  • String: A cleaned and rewritten IR block for the requested function, including global constants and necessary declarations.

Notes

  • Handles name mangling in @julia_<funcname>_<id> style.
  • Rewrites global constant names for uniqueness.
  • Gathers required declare lines and LLVM attributes for external linkage.
source
StaticLLVM.find_matching_braceFunction
find_matching_brace(s::String, start_pos::Int=1) -> Int

Finds the index of the closing brace '}' that matches the first opening brace '{' found at or after start_pos in the string s.

Returns the index of the matching closing brace, or -1 if:

  • No opening brace is found at or after start_pos, or
  • Braces are unbalanced and a match can't be found.

Arguments

  • s: The input string to search.
  • start_pos: The position in the string to start searching from (1-based). Defaults to 1.

Example

find_matching_brace("a{b{c}d}e")  # returns 9
find_matching_brace("abc", 1)     # returns -1
source
StaticLLVM.get_arg_typesMethod
get_arg_types(m::Core.Method) -> Tuple

Extracts the argument types (excluding the function itself) from the method's signature.

source
StaticLLVM.get_configMethod
get_config(; kwargs...) -> Dict{String, Any}

Return a copy of the default config, with optional keyword overrides.

source
StaticLLVM.get_mod_filepathMethod
get_mod_filepath(mod::Module) -> Symbol

Retrieve the source file path symbol where the given module mod is defined.

Arguments

  • mod::Module : The Julia module to inspect.

Returns

  • Symbol : The source file path as a Symbol if found.

Behavior

  1. Checks if the module has a special field :_source_file_ and returns it if present.
  2. Otherwise, scans module names (excluding some built-ins) to find a function defined solely in this module and returns the file path of that function's method.
  3. Throws an error if no suitable source file path is found.

Notes

  • Skips imported names and private names starting with #.
  • Excludes names like :eval and :include to avoid common standard functions.
source
StaticLLVM.is_static_codeMethod
is_static_code(ir::String)::Bool

Determines whether the given LLVM IR string is "static", i.e., free from dynamic symbols or Julia internal functions.

Returns

  • true if the IR contains no known dynamic patterns.
  • false if any non-static signature (like @ijl_) is found.
source
StaticLLVM.load_pkgMethod
load_pkg() -> Module

Load a Julia package or source file specified by the first command-line argument (ARGS[1]).

Behavior

  • If ARGS[1] is a file path, includes the file and extracts the package name from the filename.
  • Otherwise, attempts to import the package by name.
  • If import fails and a directory with the package name exists, tries to include the source file under ./<package>/src/<package>.
  • Raises an error if the package cannot be found or loaded.
  • Optionally, uses ARGS[2] as the module name to return; defaults to the package name.

Returns

  • The loaded Julia module.

Notes

  • Depends on global ARGS array (command line arguments).
  • Prints status messages indicating loading steps.

Example

```bash julia script.jl MyPackage OptionalModuleName

source
StaticLLVM.make_modvar_defMethod
make_modvar_def(name::String, value::T, is_const::Bool = false) -> (String, String)

Generate LLVM IR global variable definition and external declaration strings for a Julia module variable.

  • name: The variable name to be used in LLVM IR (as @name).
  • value: The Julia module variable value to represent.
  • is_const: If true, the LLVM global is marked constant; otherwise, it's mutable (global).

Returns a tuple (definition::String, declaration::String) where:

  • definition is the LLVM IR global definition string with initialization.
  • declaration is the LLVM IR external global declaration string.

Supported Julia types for value:

  • Floating point: Float64, Float32
  • Integer types: Int8, Int16, Int32, Int64, Int128 and unsigned equivalents
  • Bool
  • Ptr types
  • String
  • Immutable bitstypes (non-primitive)

Throws an error if the type is unsupported.

source
StaticLLVM.patch_memory_alloc!Method
patch_memory_alloc!(block::LLVMBlock, type_map::Vector{Pair{String, Int}}) -> Bool

Replaces the LLVM IR code that performs allocation via jl_alloc_genericmemory with explicit malloc or calloc instructions, based on whether the allocated type is mutable or abstract.

Arguments

  • block: An LLVMBlock containing the IR code.
  • type_map: A list of Pair{String, Int}, mapping type IDs (e.g., "GenericMemory#1222") to an integer flag (0 = mutable/abstract, 1 = concrete/immutable).

Returns

  • true if the replacement occurred, false otherwise.
source
StaticLLVM.patch_memory_instance!Method
patch_memory_instance!(blocks_map::Dict{Symbol, LLVMBlock}, block::LLVMBlock) -> Bool

Patch the LLVM IR of a block to replace a specific Core.GenericMemory atomic load instruction and simplify its associated conditional branch logic.

Arguments

  • blocks_map: A dictionary mapping basic block names (as Symbol) to LLVMBlock objects.
  • block: The LLVM block whose IR may contain a Core.GenericMemory load instruction.

Returns

  • true if the block was modified, false otherwise.

Description

This function searches for a specific pattern in the LLVM IR indicating the use of a hard-coded atomic load from Core.GenericMemory#<id>.jit. If found, the instruction is replaced with a cast from a globally defined pointer @GenericMemoryInstance. The jump logic immediately following the load is also simplified to jump unconditionally to the "success" label.

This is a low-level IR patching utility meant to canonicalize memory access logic.

source
StaticLLVM.pyprintMethod
pyprint(args...; sep=" ", tail="

")

Print multiple arguments joined by a separator and ending with a specified tail string.

Arguments

  • args...: A variable number of arguments to be printed.
  • sep: Separator string inserted between arguments. Default is a single space " ".
  • tail: String appended at the end of the output. Default is newline `"

"`.

Behavior

  • Converts all arguments to strings.
  • Joins them with the separator.
  • Prints the resulting string followed by the tail string.

Example

pyprint("Hello", "world", 123; sep=", ", tail="!
")
# Output: Hello, world, 123!
source
StaticLLVM.recover_heap_objectMethod
recover_heap_object(addr::Integer) -> Any

Given a raw address (e.g. from pointer_from_objref), attempts to reconstruct the original Julia object stored at that memory location.

This function inspects the memory layout:

  • If the tag indicates a String, reconstruct it.
  • If the tag seems to point to a valid heap-allocated DataType, rehydrate the object.

Returns nothing if the tag is not recognizable or unsupported.

source
StaticLLVM.recover_heap_objectMethod
recover_heap_object(p::Ptr) -> Any

Low-level internal logic to reconstruct a Julia object from a raw pointer p. This inspects the memory tag to determine the type of the object.

Used internally by recover_heap_object.

source
StaticLLVM.remove_memoryref_callsMethod
remove_memoryref_calls(block::LLVMBlock) -> Bool

Scans the LLVM IR in block and removes all lines that match calls to @memoryref. Returns true if any modifications were made.

Arguments

  • block: The LLVMBlock to process.

Returns

  • true if the block's IR was modified, false otherwise.
source
StaticLLVM.remove_substringsMethod
remove_substrings(input_str::AbstractString, ranges::Vector{Tuple{Int, Int}}) -> String

Removes substrings from input_str specified by the list of ranges.

Arguments

  • input_str: The original string.
  • ranges: A vector of (start, stop) index tuples indicating substrings to remove.

Returns

  • A new string with the specified substrings removed.

Example

remove_substrings("Hello, world!", [(1,5), (8,8)]) # returns ", orld!"
source
StaticLLVM.replace_memory_allocMethod
replace_memory_alloc(method::MethodInfo)

Scans and patches LLVM IR in the given method to replace allocations related to Core.GenericMemory.

This function:

  • Extracts memory layout sizes for GenericMemory types from method metadata.
  • Iterates over all LLVM functions in the method, splits them into blocks.
  • For each block, attempts to patch GenericMemory instances and allocations, and removes calls to @memoryref.
  • Finally updates the LLVM IR in the method with the patched blocks.

Arguments

  • method: A MethodInfo struct containing LLVM IR and metadata.

Notes

  • Relies on low-level unsafe pointer operations to inspect Julia internal data.
  • Emits a warning if element size exceeds 256 bytes.
  • Throws an error if no GenericMemory alias is found.
source
StaticLLVM.run_commandMethod
run_command(cmd::Cmd; verbose::Bool=false) -> NamedTuple

Run the given command and capture its output.

Arguments

  • cmd: A Cmd object representing the system command to execute.
  • verbose: If true, prints the command before execution.

Returns

A named tuple (success, code, output):

  • success: true if the command succeeded, false otherwise.
  • code: Exit code (0 if success, -1 if error caught).
  • output: Command output or error message as a string.
source
StaticLLVM.split_blocksMethod
split_blocks(ir::AbstractString) -> Vector{LLVMBlock}

Splits a full LLVM IR string into a list of LLVMBlock objects, based on labeled basic blocks (e.g., entry:, L3:).

Arguments

  • ir: A string containing LLVM IR code.

Returns

  • A vector of LLVMBlock objects, each representing a labeled block of IR code.

Example

blocks = split_blocks(ir_string)
source
StaticLLVM.strip_commentsMethod
strip_comments(ir::String) -> String

Removes comments and trailing whitespace from LLVM IR code lines, while preserving leading indentation and empty lines with no code content.

Arguments

  • ir: A multiline string containing LLVM IR code.

Returns

  • A new string where each line has comments (starting with ;) and trailing spaces removed.
  • Lines that contain only whitespace or comments are omitted.

Details

  • The function splits the input text into lines.
  • For each line, it finds the first comment delimiter ;.
  • It keeps only the part of the line before the comment.
  • Trailing whitespace is trimmed, but leading whitespace (indentation) is preserved.
  • Empty or whitespace-only lines after stripping are skipped.
  • The resulting lines are joined back with newline characters.

Example

code = """
define i32 @main() {
  %1 = add i32 1, 2 ; addition
  ret i32 %1 ; return value
}
"""
println(strip_comments(code))
# Output:
# define i32 @main() {
#   %1 = add i32 1, 2
#   ret i32 %1
# }
source
StaticLLVM.strip_gc_allocationsMethod
strip_gc_allocations(ir::String)::String

Clean up Julia IR by removing GC-related stack management and replacing @ijl_gc_pool_alloc_instrumented calls with standard malloc calls for further IR-level optimization or analysis.

Arguments

  • ir::String: The input LLVM IR string generated by Julia.

Returns

  • A cleaned-up IR string with GC stack frames and pool allocation calls removed or replaced.
source
StaticLLVM.write_if_changedMethod
write_if_changed(filepath::String, content::String, check::Bool)::Int

Writes content to filepath only if the file content has changed or doesn't exist. If check is false, no writing occurs.

Returns

  • 1 if the file was written (or would be written).
  • 0 if no writing was done due to check == false.
source