XCODX |

LLVM IR Online Compiler & Interpreter

Select Language
Online Code Compiler
Full HTML IDE
Py main.py
Program Output Ready
  Welcome to XCODX Online Compiler

  Quick Start:
  Ctrl+Enter  Run code
  Ctrl+S      Save / Download
  Ctrl+L      Clear output

  Select a language and start coding.
Success
Operation completed

About LLVM IR

LLVM IR is the intermediate representation at the heart of modern compilation: Clang, Rust, Swift, Julia, and dozens of other compilers lower source code into this typed, SSA-form assembly-like language before optimizing and emitting machine code. Reading and writing IR by hand is a standard exercise in compiler construction courses and the fastest way to understand what optimization passes actually do. Recent LLVM releases use opaque pointers (the ptr type), a change worth knowing when older tutorials show typed pointers like i8*. On this page your module is executed directly through LLVM's JIT tooling in a real terminal, so you can hand-craft functions and immediately watch calls, branches, and printf output happen.

Hello World in LLVM IR

; A hand-written LLVM IR module
@.hello = private constant [18 x i8] c"Hello from LLVM!\0A\00"
@.fmt = private constant [15 x i8] c"square(%d)=%d\0A\00"

declare i32 @printf(ptr, ...)

define i32 @square(i32 %x) {
entry:
  %r = mul nsw i32 %x, %x
  ret i32 %r
}

define i32 @main() {
entry:
  %c0 = call i32 (ptr, ...) @printf(ptr @.hello)
  br label %loop

loop:
  %i = phi i32 [ 1, %entry ], [ %next, %loop ]
  %sq = call i32 @square(i32 %i)
  %c1 = call i32 (ptr, ...) @printf(ptr @.fmt, i32 %i, i32 %sq)
  %next = add nsw i32 %i, 1
  %done = icmp sgt i32 %next, 4
  br i1 %done, label %exit, label %loop

exit:
  ret i32 0
}

When to use LLVM IR

Hand-written IR is bread and butter in university compiler courses, where assignments ask students to lower expressions, implement phi nodes for loops, or predict what mem2reg and constant folding will produce. Compiler engineers use a quick IR scratchpad to minimize bug reproductions before filing LLVM issues, and language designers prototyping a new frontend verify that their intended lowering is valid. It also helps performance-minded developers decode the output of clang -emit-llvm or rustc --emit=llvm-ir when investigating why a hot function did or did not vectorize.

Common questions

Can an LLVM IR program read standard input here?

Yes, by declaring and calling C library functions: declare i32 @getchar() or scanf via a varargs declaration, then call them like any IR function. Because the terminal is attached live, a blocking getchar call waits for your keystroke. Most hand-written learning modules stick to printf output, but interactive input works when you need it.

Should I write ptr or typed pointers like i8*?

Use ptr. LLVM completed its migration to opaque pointers, and releases from version 17 onward reject typed pointer syntax entirely. If you are following an older textbook or blog post showing i8* and getelementptr with pointee types, mechanically replacing pointer types with ptr and adjusting getelementptr's explicit type argument brings examples up to date.

Is my IR being interpreted or compiled to machine code?

The module is executed with LLVM's JIT-based tooling, which verifies the IR, compiles it in memory, and runs the result natively, so semantic errors like type mismatches or malformed phi nodes surface as verifier messages before anything executes. This mirrors exactly how course autograders and LLVM's own lli tool treat handwritten modules.

How LLVM IR runs on XCODX

Sandbox filename
main.ll
Entry point
single main source file
Editor grammar
plain text — no highlighter ships for this language
Reading stdin
@getchar / @scanf
Input delivery
live WebSocket stream
Prompt flushing
flush manually before reading input
Compile limit
10 s
Run limit
3 s batch · up to 3 min live
Memory
256 MB per stage
Max source
50,000 characters

Default program on this page

@.str = private unnamed_addr constant [15 x i8] c"Hello, World!\0A\00"
declare i32 @printf(i8*, ...)
define i32 @main() {
  %1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i32 0, i32 0))
  ret i32 0
}