Compilers Interview Guide

What each question actually discriminates, what a strong answer covers, and the specific plausible-sounding wrong answers a confident candidate really gives.

What happens between source code and machine code?beginner

TestsWhether the candidate carries a staged model of compilation or one opaque box — and, more discriminating, whether they know their model describes one implementation rather than all of them. Almost everyone can list phases; far fewer can say which phases their favourite language actually has.

Why use an AST instead of compiling tokens directly?beginner

TestsWhether the candidate understands that structure is the thing being computed, not a convenience. The discriminating detail is whether they can name a question that a flat token list *cannot* answer at all, as opposed to one it answers awkwardly.

What does a static type system give you?intermediate

TestsWhether the candidate can state what a type system actually proves, versus what people hope it proves. The tell is precision about scope: a strong candidate volunteers the properties their type system does *not* model before being asked.

Why is SSA useful?advanced

TestsWhether the candidate can connect a representation choice to the cost of the analyses built on it. The discriminator is whether they can name an analysis that becomes trivial and say what it used to cost.

Why not inline every function?intermediate

TestsWhether the candidate reasons about optimization as a budget rather than a good deed. The discriminator is whether they can name a case where inlining makes the program measurably slower, not merely bigger.

Why can a JIT sometimes outperform static compilation?advanced

TestsWhether the candidate understands that the JIT's advantage is *information*, not cleverness — and whether they immediately supply the other half of the ledger. A candidate who only says "it can specialize" has half an answer.

Why does undefined behavior matter to compiler optimization?advanced

TestsWhether the candidate understands undefined behavior as a licence the optimizer holds rather than as an outcome the program suffers. The discriminator is whether they can trace a transformation from the assumption to the deleted code.

What happens when there are more live values than registers?intermediate

TestsWhether the candidate knows what a spill is and can reason about which value to spill. Anyone can say "it uses memory"; the discriminator is the choice function and the fact that spilling changes the problem it was solving.

What does a linker do?beginner

TestsWhether the candidate has a model of separate compilation at all. The discriminating detail is relocation: candidates who have only read about linking say "it joins the files"; candidates who have debugged a link error know addresses had to be patched.

What is the difference between an interpreted and a compiled language?beginner

TestsWhether the candidate has a category error baked in. This is the single most reliable question in the bank because the wrong answer is the one almost everybody was taught, and the recovery — noticing that the question presupposes something false — is the signal.

Here is a grammar for arithmetic expressions with `+` and `*` and no precedence. What is wrong with it, and how do you fix it?intermediate

TestsWhether the candidate can recognise ambiguity as a property of the grammar rather than a bug in the parser, and whether they know the two distinct ways to remove it and what each costs.

A lexer sees `x+++y`. What does it produce, and why?intermediate

TestsWhether the candidate knows that lexing is greedy by rule rather than by intent, and can predict the consequence when the greedy choice is the wrong one. It also separates people who have written a lexer from people who have read about one.

When would you choose an LL parser over an LR parser, or the other way round?advanced

TestsWhether the candidate weighs parsing techniques by engineering consequences — diagnostics, maintainability, grammar flexibility — rather than by expressive power alone. Nearly everyone knows LR is more powerful; the discriminator is whether they know why hand-written recursive descent won in practice.

Two variables in the same function are both called `x`. How does the compiler decide which one a use refers to?intermediate

TestsWhether the candidate has a working model of scope as a structure the compiler builds, not a rule it applies. The discriminator is whether they realise the answer is a data structure with a lifetime, and can say what happens after resolution.

How does type inference work, and where does it stop working?advanced

TestsWhether the candidate can describe inference as constraint generation plus solving rather than as guessing, and whether they know the specific features that break complete inference. Naming the occurs check is a strong signal; naming why subtyping complicates inference is stronger.

If `Dog` is a subtype of `Animal`, is `List<Dog>` a subtype of `List<Animal>`?advanced

TestsWhether the candidate can derive variance from mutability instead of memorising a rule. The discriminator is whether they reach for the counterexample — writing a Cat into the list — rather than reciting "generics are invariant".

What are the differences between erasing generics and monomorphizing them?advanced

TestsWhether the candidate can trade code size against runtime cost with real numbers in mind, and whether they know which choice their language made and what it forced on the rest of the design.

What does it mean for one basic block to dominate another, and what does a compiler do with that?advanced

TestsWhether the candidate can state a graph property precisely and then name a transformation whose legality depends on it. Reciting the definition is common; connecting it to a specific pass is not.

Liveness, reaching definitions, available expressions and constant propagation are four different analyses. What do they have in common?advanced

TestsWhether the candidate sees the framework or four unrelated algorithms. The discriminator is whether they can place a new analysis into the framework on the spot by naming its direction and meet operator.

I want to move this computation out of the loop. How do I decide whether I am allowed to?expert

TestsWhether the candidate reasons from observable behavior and preconditions instead of from "it looks the same". The discriminator is whether they name the trap and the exception cases without prompting — those are what separate an optimizer from a miscompiler.

Why does alias analysis limit what an optimizer can do?expert

TestsWhether the candidate understands that most missed optimizations in real code are memory questions the compiler could not answer, and can name the mechanisms languages provide to answer them.

What is a calling convention, and what happens if two pieces of code disagree about one?intermediate

TestsWhether the candidate knows there is a contract there at all, and can predict the failure mode. The discriminator is that ABI mismatches do not produce clean errors, and a candidate who expects one has never debugged a real one.

What does dynamic linking buy you, and what does it cost?advanced

TestsWhether the candidate can argue both directions. Most people have one strong opinion here; the discriminator is whether they can state the case against their own position and name a concrete failure it causes.

A JIT compiled a method assuming a value was always an integer, and then a string arrives. What has to happen?expert

TestsWhether the candidate understands speculation as a two-part mechanism — the assumption and the escape route — and can describe the state reconstruction. This is the question that separates people who have used a JIT from people who have worked on one.

Your stack trace points at line 1, column 84210 of a bundle. What has to exist for a debugger to show you the original source, and why does it so often get it slightly wrong?intermediate

TestsWhether the candidate understands debug information as a separate artifact with its own correctness problem, and knows that every transformation in the chain has to maintain it or the mapping degrades.

How does a build system know what to recompile after a one-line change?advanced

TestsWhether the candidate can reason about dependency granularity and correctness, not just timestamps. The discriminator is whether they raise the two failure directions — rebuilding too much and rebuilding too little — and know which one is dangerous.

What is the difference between LTO and PGO, and can you use both?advanced

TestsWhether the candidate can separate two orthogonal things people habitually confuse — seeing more code versus knowing more about execution — and whether they know what a bad profile costs.

A team wants to replace a configuration file format with a small language of their own. Talk them through it.intermediate

TestsWhether the candidate prices the whole thing rather than the parser. Everyone can write a parser in a weekend; the discriminator is whether they know what the second year costs.

Why do compilers have an intermediate representation at all, instead of going from AST to machine code?intermediate

TestsWhether the candidate can name what the AST is bad at, rather than repeating the M-frontends-times-N-backends argument. That argument is correct and everyone has it; the discriminator is the analysis argument underneath.

A model returns a plan: a list of tool calls with arguments and dependencies. What does treating that as a program buy you?advanced

TestsWhether the candidate can transfer compiler discipline to a new setting rather than reaching for prompt engineering. The discriminator is whether they put the checks before execution rather than in a retry loop.