Chris Lattner on LLVM, Swift, and Mojo: Building Blank-Canvas Systems

Open on YouTube ↗
Overview

Chris Lattner created the LLVM compiler infrastructure and the Swift programming language, worked on AI infrastructure at Tesla and Google, and now leads Modular, the company behind the Mojo language. In this conversation with Gergely Orosz of The Pragmatic Engineer, Lattner explains how each project began and what it took to get adopted inside large organizations. He also describes the mistakes he carried forward into the next project. His central argument is that the tooling he has spent his career on exists to widen access: Swift brought people into iOS development, and Mojo aims to open up GPU and accelerator programming, which Lattner sees as gatekept by aging, vendor-specific tools.

29 min read

The compiler landscape before LLVM

Lattner started with Linux in the mid-1990s, when GCC was the compiler that standardized much of the software ecosystem. Before GCC, he explains, every hardware vendor built its own compiler. In the late 1980s and early 1990s there was far more diversity in instruction sets, with HP, Intel, and the new RISC designs all competing. The C standard existed, but like most specifications it was incomplete. Each vendor's compiler had its own bugs, misfeatures, and missing capabilities. Software of that era relied on tools like autoconf, which Lattner calls "this really weird macro processing thingy," to work around the differences, and he describes the result as "a gigantic nightmare."

GCC cleaned that up. Chipmakers adopted it, it was free software, and Linux built on it. Lattner says open source owes GCC "a debt of gratitude." By around 2000, though, GCC was over 20 years old and its architecture was old-school. It was built to do one thing: take C in and emit assembly for a given chip. It was not modular, so it could not do just-in-time (JIT) compilation. At the time it also could not optimize across files, so a function in one C file could not be inlined into another.

LLVM as a university project nobody expected to succeed

Lattner began LLVM around 2000 while studying compilers at university. It started as a code generation system that could target multiple architectures, but he frames it as a way to learn by building. He stresses that successful systems look obvious only in hindsight. Most university research projects go nowhere, and the default assumption was that LLVM would go nowhere too.

His advisor, Vikram Adve, encouraged the group to keep building it, and it was used in a couple of classes. At that stage LLVM was only an optimizer and code generator. It plugged into GCC and used GCC's parser for C and C++, so it was useful to compiler researchers but not to application developers. When it was open-sourced, it attracted "two or three people," mostly other compiler enthusiasts.

Lattner's approach to building a community was to treat outside contributors like members of the research group. That meant open development, answering questions, and treating people with respect. The community grew very slowly, drawing people interested in esoteric languages, in performance, and in other niches.

LLVM also differed from GCC in being written in C++. That was controversial because GCC was written in C and Richard Stallman opposed C++. Lattner describes a "parallel universe": after joining Apple in 2005, he proposed to the GCC community that the two projects merge, arguing that LLVM could lift GCC's architecture. The proposal went nowhere, partly because of C++ and partly because of "not invented here." Experienced GCC developers, as he puts it, responded along the lines of "okay kid, why would we listen to you." He says he is glad the merge didn't happen, because LLVM had to grow up on its own.

Making LLVM relevant to Apple

By graduation LLVM was five years old, with releases every six months. Lattner says he deliberately advocated for the project and showed momentum. That caught the attention of an Apple VP and of a few Apple engineers who were adding a PowerPC backend to LLVM. Apple was frustrated with GCC, which was the foundation of its compiler technology, including Objective-C. GCC was hard to extend, performance was lacking, and the GCC community was annoyed with Apple for various reasons. Management told him to come work on LLVM.

He started with one other engineer and little guidance, and spent his early time on PowerPC support and Mac OS integration. Then his manager warned him that the work eventually had to matter to Apple. LLVM wasn't in any product, and it was worse than GCC in several ways. Lattner got the message that if nothing shipped within about a year, he would be asked to work on something else. With his manager's help, which he calls "amazing," he looked for near-term business impact.

The first use turned out to be graphics. OpenGL did just-in-time compilation, and LLVM could handle a small piece of that work. The value was modest, "at least non-zero," but it changed LLVM's standing from science project to something useful. That foothold funded the next set of features, then the next.

Over about five years, the team replaced Apple's developer tools piece by piece: compiler, code generation, and debugger technology. They built Clang, a new C++ parser and Objective-C front end. Lattner points to the first 64-bit iPhone, the iPhone 5S, as a milestone the LLVM work made possible. According to Lattner, the industry thought 64-bit phones were pointless, asking why a phone would ever need more than 4 GB of RAM. He says Apple shipped the iPhone 5S before ARM had even received its own 64-bit chips back for testing. Apple had built the entire toolchain and OS support internally while collaborating with ARM, and ARM "had no idea how far ahead we were."

Asked how a side project reached the core of Apple, Lattner credits a combination of forces. There was top-down support from people frustrated with GCC. There was bottom-up success, with something new working every six months. And he built a reputation for getting things done, which brought more scope: he went from engineer to manager, second-line manager, and eventually senior director. Because the work happened in the open, other organizations adopted LLVM as well. Cray used it for a supercomputer, Google adopted it around 2010, and companies such as Intel and ARM eventually cancelled their internal compilers and moved to LLVM. Today, he says, LLVM has a community of thousands.

On motivation, Lattner says he doesn't start from a picture of eventual success. What he loves is doing the work and "figuring out that really obscure thing" that makes an architecture compose and scale. As a result, he says, most of the time he works on things people don't understand, and he has "normalized to this." Projects click for others only when they map onto a value system people can measure.

Asked how he got Apple to accept open source, Lattner says Clang was easy: "we didn't really ask too many people for permission. We just kind of did it." The hard one was Swift.

Swift's origin: nights and weekends

By WWDC 2010, Lattner's team had shipped a full-stack replacement of Apple's C, C++, and Objective-C toolchain. Building a complete C++ compiler was a major technical achievement, but Lattner found it demotivating because C++ is "a beast of a language." Coming out of that project, he wondered whether something better was possible, and with the infrastructure now in place, the team could build almost anything.

He started Swift on nights and weekends without asking permission. For the first year and a half he was the only person working on it, while also holding a day job managing a team of about 40 people. His first step was a survey of other languages: Java and C++, functional languages like OCaml and Haskell, esoteric languages, and newer ones such as TypeScript, Dart, and Go.

He defined success as a language that was easy to use and scalable. JavaScript shaped that thinking. It started as a simple hack for onclick handlers, gained adoption, and developers then carried it into other domains until people were running web servers on it. His conclusion was that a successful language will be pulled into domains it wasn't designed for, so it should be designed for generality from the start. For Swift, that meant scaling down to embedded systems and up to something close to scripting.

Objective-C also shaped the design. It combined a Smalltalk-inspired object model with C for performance, which Lattner calls a beautiful combination because it offered both high-level APIs and a path to the metal. His insight was that "they didn't have to be two languages." A single language could be easier to teach, more memory-safe, and more modern, with good type inference and cleaner syntax. He notes that Python today has the same "two world problem," with a pleasant object layer on top of C, C++, and Rust.

How to approach a blank canvas

Asked how he designs a language from nothing, Lattner says most of his major projects have been blank-canvas work: LLVM, MLIR, Swift, and Mojo. His process starts with reflection on what success should look like, followed by a survey of what exists. He believes that even systems he dislikes contain good ideas that can be separated from the rest. His example is Java. He didn't like garbage collection or finalizers, but JIT compilation was powerful, and he calls Java a big step forward overall.

After that, he expects to design, redesign, and iterate. He validates specific assumptions one at a time, keeping most parts deliberately simple. He compares this to the "draw two circles, then draw the rest of the owl" meme, where the circles stay circles for now. He invests in proving one piece at a time, pins down its interfaces, and then moves on. Throughout, he says, you have to be "unafraid to go massively change and flip over the table and try again."

Four years of research and internal persuasion

After a year and a half, Lattner told management about Swift. He says their response was roughly "why would we want a new language? Objective-C is what made the iPhone successful." He was allowed to tell one or two people on his team, but no resources were committed. Because of his track record, he says, he was given "a little bit more rope" than others would get, and he started building demos.

About three years in, most of the feedback was still: if you don't like Objective-C, make Objective-C better, since you own it. Lattner calls this a sensible business reaction, because improving the language the whole community already uses is low-risk. So he did improve it, but in a way that moved Objective-C toward Swift. Objective-C memory management relied on manual retain and release, which he calls "a nightmare." His team invented ARC (automatic reference counting), which made the language safer and easier to teach. They then added modules and literals. Each feature moved everyday Objective-C programming closer to what Swift would be, so that Swift would feel like less of an abrupt leap.

He describes the four years as discovery, research, and "socialization process with executive leadership," not a fully staffed build. About three years in, by which time he was running Xcode and the developer tools organization of roughly 250 people, a large executive review took place. Lattner asked that bringing Swift to market become the department's focus. At that point Swift could not yet talk to iOS, lacked many object features, and had no apps built with it. The final year involved finishing the language and integrating it with the debugger, Xcode, code formatting, and the iOS SDK.

The 1.0 mistake and the break-your-code promise

Lattner says it was a mistake to call the 2014 release 1.0. Apple does not launch 0.5 releases, so it had to be 1.0. The team also needed real-world use, because at launch only about 250 people at Apple knew Swift existed, and a language can't be designed well in a vacuum behind an NDA. His lesson is not to call something 1.0 until it has been validated through real usage, and he says Modular applies that lesson to Mojo.

What went well, in his view, was communication. Apple told developers they could ship Swift apps to the App Store, but that their source code would break as the language changed. The host recalls Uber's 2016 app rewrite, done on Swift 1.2. The platform team took a significant risk on it, trusting that Apple was committed, and the host credits open-sourcing Swift with building trust. Swift 1 and Swift 2 broke source, and only Swift 3 declared stability. Lattner is glad of that: otherwise the language would still carry all of its early mistakes.

Asked why Xcode Playgrounds and a REPL shipped on day one, Lattner says every group wanted something from the new language. The documentation team wanted a book, so Swift launched with one. Management and marketing wanted interactive programming, which led to Playgrounds. Lattner wanted a REPL built on the debugger because a modern language should have one. The vision was right, he says, but the team was "massively overextended." Many of these features were still unbaked at 1.0 and 1.2, and waiting for a later version might have been better. He adds that such judgments are easy in hindsight.

Why experts resist new tools

Many developers rejected Swift outright. The host recalls a survey of Uber's iOS engineers in early 2016, two years after launch, that split roughly 50/50 between Objective-C and Swift, with the two camps "violently disagreeing."

Lattner's explanation is that experts don't like change. An expert Objective-C programmer has spent five or ten years learning the language's tricks and edge cases and is the person others go to for help. A new language resets that person to day one, the same as everyone else. Protecting that prior investment, he says, is "sensible human behavior." Some people are intellectually flexible or simply like new things, but many need a compelling reason to switch. For some of Swift's long-tail holdouts, that reason was SwiftUI, which arrived years later. He describes adoption as technology diffusion along an S-curve, from early adopters to people who have to be dragged along. He sees the same pattern playing out with Mojo and with AI.

The part of the Swift story Lattner is proudest of is how it widened access. After launch, he says, people stopped him to thank him. They had tried building apps in Objective-C but couldn't manage the pointers and square brackets, and their apps crashed. Swift made app development easy enough that they became app developers, and in some cases the experts at their companies. He sees GPUs today in the same position: CUDA, C++, and related tools, in his view, gatekeep many developers from this kind of computing. "I believe in the power of programmers," he says, and that belief is what drives his work.

Swift's technical debt, in Lattner's words

Lattner says he can't know whether Swift would be better or worse if he had stayed at Apple, so he talks only about his own mistakes. Swift was the first language he had built. Clang had implemented a language with a spec; Swift did not have one. "I didn't know what I was doing," he says. He adds that he is not "a math guy." He takes responsibility for Swift's "expression too complex to type check in reasonable amount of time" error, which he says comes from specific features and is very hard to fix.

His second mistake was adding features faster than the compiler's architecture could absorb them. Features worked 80 or 90 percent of the way but didn't fit together. As more were added, the mismatches compounded into complexity that developers can feel, which is why people now joke about Swift having too many keywords. He attributes this to prioritizing a fast path to app development over refactoring and getting the core right. He says C++ has the same problem.

He also gives an example Swift got right. In C++, int and float are hardcoded into the language, while complex numbers are library templates. That's because C++ inherited C's built-in types before templates existed and can't go back. Swift made int and float library types, which makes the whole system more uniform. His general rule: "make new mistakes, not old mistakes," fix mistakes where possible, and avoid painting yourself into a corner.

From Apple to AI: Tesla, Google, and SiFive

Lattner calls his Apple years "1.0" of his career: developer tools, CPUs, OpenCL, and GPU compilers. Around 2016 he "fell in love with AI" when the Photos app began telling cats from dogs. He owned developer tools and knew programming well, yet had no idea how to write an algorithm that detects a cat.

At Tesla, working on self-driving, he learned Caffe and TensorFlow. He concluded that TensorFlow could be much better, which led him to Google. There he owned the lower layers of TensorFlow (CPU, GPU, TPU, and several internal ASICs) and scaled the TPU software platform. His main lesson was how hard it is to build AI software without CUDA, Nvidia's roughly 20-year-old programming toolkit, which he says the entire AI ecosystem is heavily biased toward. A new accelerator like the TPU starts with no software at all, and TensorFlow and PyTorch had to be taught to use it. He credits his time at Google with teaching him the algorithms and frontier applications, noting that the "Attention Is All You Need" work was done on TPUs during that period. He built components he describes as now widespread, including MLIR, a compiler framework for domain-specific chips that he loosely calls "LLVM 2.0." He says it could not have been built without the mistakes learned from LLVM, and that it has been adopted by roughly every AI chip company.

At SiFive, which builds RISC-V hardware, he wanted to work on the hardware side of the boundary. He learned about physical design, verification, and the IP business model. When SiFive set out to build AI IP, he ran into the same gap he kept finding: "where's the software?" No end-to-end AI stack existed that a chipmaker could simply plug into.

Modular's thesis: an LLVM for AI

Lattner and his co-founder, whom he met at Google, started Modular to build "something like LLVM, but for AI." He argues that AI software today looks the way compilers looked before GCC, with every chipmaker building its own vertical stack: XLA for Google TPUs, Metal and MLX for Apple, ROCm for AMD. These stacks share very little code. The host notes that Anthropic is hiring separate CUDA, TPU, and Trainium kernel engineers. Lattner says companies end up writing the same models three times, and he cites an Anthropic engineering blog post describing the resulting bugs, quality problems, and outages when three parallel implementations drift apart.

Lattner says no existing project, including PyTorch and ONNX Runtime, was on the right path. At Google, he says, every year brought a new chip, while product teams such as Search, Ads, and YouTube needed the best engineers to fight fires on the current one. Nothing fundamentally new could be done if it took longer than a 6- or 12-month performance review cycle. In his view, research progress came from brilliant engineers "hacking the daylights out of" every layer of the stack, not from anything designed to scale, compose, or bring up new hardware quickly. Matching CUDA's 20 years of investment requires years of work and a very specialized team. A venture-funded startup, he says, was the only way to recruit people away from Apple, Nvidia, Meta, and Google.

Why kernels and compilers both fell short

Lattner describes two earlier approaches. TensorFlow and PyTorch, both dating to around 2015, put Python APIs on top of hand-written CUDA and Intel MKL kernels. Kernels were so easy to write that thousands accumulated, and all of them had to be rewritten for each new chip.

For TPUs, Google instead used compilers to generate kernels automatically, with benefits such as automatic fusion of adjacent kernels. The problem, according to Lattner, is that compiler engineers are scarce. When a new algorithm such as FlashAttention, a new sparsity pattern, or a new float format appeared, it couldn't be supported until compiler engineers found time for it. He says this bottleneck held back TPUs, and that the arrival of generative AI "really invalidated that technology approach."

Modular therefore bet on a two-level stack. Mojo, a new programming language, sits at the base, designed to provide full control over the hardware and "all of the performance," not a simplified model that gets most of it. Compiler techniques are then built into the language so that Mojo programmers get "the power of compilers without having to be a compiler engineer." Many more people can write code than can write compilers, and Lattner sees this as the way to address the talent shortage.

Predictability over "sufficiently smart" compilers

Lattner says compiler engineers, including himself around 2005, like to show off clever optimizations. That makes sense for benchmarks, where the source code is fixed and all the cleverness has to live in the compiler. His example of how this fails users is loop vectorization. It can make code four times faster using SIMD, but only when pattern matching and pointer analysis line up. Fix a bug in a way that breaks the pattern, and you get a sudden 4x slowdown that only a compiler engineer can diagnose. Report it, and you may be told you're "holding it wrong." The "sufficiently smart compiler," he says, "never works"; it becomes a leaky abstraction and makes the programming model unpredictable. In AI, where GPUs are expensive and frontier labs need peak performance, that unpredictability is unacceptable.

Mojo instead uses a simpler, more predictable compiler, which Lattner describes as more modern than what Swift and Rust are built on, and moves control into libraries. Instead of hoping for auto-vectorization, you call a library feature that vectorizes explicitly. SIMD, bfloat16, and compressed floating-point formats are native to the language. For productivity, Mojo has powerful compile-time metaprogramming, which Lattner says was "roughly stole[n]" from Zig and improved, with thanks to the Zig community. A vectorize function takes a higher-order function and stamps it out across vector lanes.

He contrasts this with C++, where templates and constexpr form a separate meta-language. It is nearly impossible to debug, can barely accept a string, and certainly can't take a binary tree as a template argument. Mojo, like Zig, unifies the program and the meta-program: ordinary code runs at compile time, so it can be debugged by running the same code at runtime. Mojo goes further by allowing heap-allocating structures such as lists and dictionaries to be built at compile time and embedded in the program. Lattner describes the resulting high-level algorithms as "mini compilers" that specialize on dimensions and constants.

Getting started: from slow Python to GPUs

Lattner deliberately avoids "the rabbit hole of really weird technical things only Chris understands," such as linear types. His pitch is that Mojo belongs to the Python family, so it's easy to learn, and AI coding tools make learning a new language easier than ever. The simplest entry point is speeding up an existing Python module. The usual route, rewriting hot code in Rust or C++, requires bindings that are mechanical and error-prone. Mojo, he says, extends Python without bindings, much as Swift and Objective-C interoperated natively, and it integrates with pip packages and build systems. Mojo also runs on CPUs, which he says are complex machines worth optimizing, so no special hardware is required.

His favorite example is a community member who introduced themselves as "merely a geneticist." This person moved Python DNA-sequencing code to Mojo and, after learning threads and vectorization, got roughly a 100x speedup. Having read that Mojo worked on GPUs, and without any GPU experience, they got the code running on a GPU in an afternoon and reported it was "a million times faster." Lattner contrasts this with CUDA, which he respects but describes as 20-year-old C++ that wasn't designed for modern architectures and "can't even acknowledge" tensor cores.

Mojo currently runs on AMD, Nvidia, and Apple GPUs. Modular's website offers "GPU puzzles" for learning, and Lattner invites open-source contributions. He argues that accelerators matter well beyond AI, citing bioinformatics, chemistry, oil and gas exploration, and HPC generally, but that the surrounding software is "really weird" and inconsistent across vendors. Making it consistent and teachable could bring a new generation into high-paying work.

Modular today

Modular turns four in January. Lattner says it is an unusually large and expensive startup, with just over 140 people. It supports seven architectures from three vendors: Nvidia Ampere, Hopper, and Blackwell; AMD's 300, 325, and 355 series plus consumer parts; and Apple GPUs, which are in beta. He hints that more is coming. Applying the Swift lesson, he wants Mojo 1.0 to be meaningful and to provide the stability Swift 1 didn't. He expects it in early summer of next year, with detailed dates still being scoped.

Commercially, Modular makes money mainly from a cloud platform, not from Mojo, which Lattner describes as something they had to build to scale across hardware. Enterprise customers want something that is easy to use, reliable, and scalable, and many want the option to buy the best chip for each workload from multiple vendors without rewriting their code three times. He predicts a lot of new silicon from many vendors in 2026 and says the company is still "at the beginning."

How Modular uses AI coding tools

Modular encourages AI tools such as Claude Code and Cursor. Lattner still writes code and uses Cursor as his daily driver. He estimates about a 10% productivity gain for him, mostly on mechanical rewrites. Even if the gain were smaller, he says, it increases his enjoyment. For prototypes and for PMs building wireframes, he calls AI "transformative," potentially a 10x gain. For production code he is unsure: he has seen agents "grind and grind" through huge numbers of tokens on tasks a person could have finished sooner, and he doesn't know how the gains and losses net out.

He insists that engineers not "turn their brains off." AI should assist humans, not replace them, and code must be reviewed and its architecture understood. Vibe coding in production "terrifies" him, less because of jobs than because of what happens six months later when the architecture needs to change and no one understands how anything works. He has seen AI tools duplicate logic in several places, which leads to bugs when only some copies are updated. The tools, he says, "still need adult supervision."

Hiring and the question of LLM-first languages

Modular hires deep specialists, such as compiler experts and GPU matrix-multiplication experts with ten years of experience, and also new graduates, who "haven't learned all the bad things yet." For early-career candidates, Lattner looks for hunger, intellectual curiosity, willingness to work hard, and fearlessness in a fast-changing field, instead of freezing up. Open-source contributions are his favorite signal because they show a person can work with a team. Because interviews make people nervous, Modular lets candidates use their normal tools, including AI for mechanical coding, since a whiteboard-only interview would be "very strange."

Asked whether languages should be designed for LLMs, Lattner rejects the idea. He hears the question more bluntly as "if AI writes all the code, why build a language?" His answer is that code has always been read more than it is written, and AI makes writing even cheaper. What matters is the intersection of expressivity (can you express the full power of the hardware? JavaScript, for example, never will for GPU kernels) and readability, the ability to understand code and build scalable abstractions. Assembly has full expressivity but not readability. Mojo keeps Python's widely known syntax and replaces "basically the entire implementation." He expects LLMs to keep improving at handling unfamiliar languages and finds them an excellent way to learn one. On making error messages better for agents, he asks what would be better for an agent that isn't also better for a human. The most important thing for AI-assisted coding, in his view, is a large open-source corpus. Modular has open-sourced roughly 700,000 lines of Mojo, with full history, which tools can index.

Why learn compilers

Lattner closes with why he loves compilers. In his university course, each project built on the last: a lexer, then a parser built on the lexer, then a type checker built on both. Mistakes had to be fixed because everything above depended on them. Unlike classes where you "build a thing, turn it in, throw it away," this resembled real software development. For newcomers, he points to LLVM's Kaleidoscope tutorial, which he wrote about 15 years ago; to the Rust community, which has many compiler enthusiasts and compiler projects; and to books and courses. He doesn't think everyone should become a compiler engineer, but he believes compilers "don't get the credit they deserve," that there are good jobs in the field, and that it needs more people.