From 22568e03e11f5c3e88fecf644a7e0462c1b98e17 Mon Sep 17 00:00:00 2001 From: Zhixun Tan Date: Thu, 12 Feb 2026 07:17:47 +0000 Subject: [PATCH] add rfc post --- docs/astexplorer.png | Bin 0 -> 79007 bytes docs/rfc.md | 571 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 571 insertions(+) create mode 100644 docs/astexplorer.png create mode 100644 docs/rfc.md diff --git a/docs/astexplorer.png b/docs/astexplorer.png new file mode 100644 index 0000000000000000000000000000000000000000..fba16b773d6f79871873cea97ab869a070e8504c GIT binary patch literal 79007 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 literal 0 HcmV?d00001 diff --git a/docs/rfc.md b/docs/rfc.md new file mode 100644 index 0000000..ef73cb7 --- /dev/null +++ b/docs/rfc.md @@ -0,0 +1,571 @@ +# \[RFC\] JSIR: A High-Level IR for JavaScript + +> **NOTE:** This is intended to be posted at the +> [LLVM Discourse Forum](https://discourse.llvm.org/c/mlir/31). + +This RFC introduces JSIR, a high-level IR for JavaScript: + +* JSIR preserves all information from the AST and supports high-fidelity + round-trip between source ↔ AST ↔ JSIR; +* JSIR uses MLIR regions to represent control flow structures; +* JSIR supports dataflow analysis. + +JSIR is developed and deployed in production at Google for code analysis and +transform use cases. + +JSIR is open source here: https://github.com/google/jsir. + +## Motivation + +### Industry trend of building high-level language-specific IRs + +The compiler industry is moving towards building high-level language-specific +IRs. For example, the Rust and Swift compilers perform certain analyses on their +high-level IRs before lowering down to LLVM. There are also a number of ongoing +projects in this direction, such as [Clang IR](https://github.com/llvm/clangir), +[Mojo](https://www.modular.com/mojo), and +[Carbon](https://github.com/carbon-language/carbon-lang). + +### The need for a high-level JavaScript IR + +Why do we need a high-level IR **for JavaScript** specifically? While much of +JavaScript tooling relies on ASTs (like ESTree), complex analyses require a +control flow graph (CFG) and dataflow analysis capabilities, which JSIR +provides by using the MLIR framework. + +#### Source-to-source transformations + +Many JavaScript tooling use cases require emitting JavaScript code as output. + +For example: + +* **Transpilation:** [Babel](https://babeljs.io) converts newer versions of + JavaScript to older versions of JavaScript, to maximize browser + compatibility. + +* **Optimization:** + [Closure compiler](https://github.com/google/closure-compiler) optimizes + JavaScript into shorter and faster JavaScript, to minimize download time and + maximize performance. + +* **Bundling:** [Webpack](https://webpack.js.org) bundles multiple JavaScript + files into a single JavaScript file. + +These tools all need to operate on a representation that allows code generation +back to JavaScript. As a result, they all operate on an AST. + +#### There are tons of AST-based open-source tools, but no IR-based ones + +The JavaScript community has a lot of AST-based open-source tools. For example, +[Babel](https://babeljs.io) provides, as its public APIs, an AST with traversal +and scope utils; [ESLint](https://eslint.org) depends on espree which also +provides an AST and relevant utils. + +To get a sense of how many JavaScript ASTs there are, here is a list on +[AST Explorer](https://astexplorer.net): + +![astexplorer](./astexplorer.png) + +There is even a standard for JavaScript ASTs - +[ESTree](https://github.com/estree/estree). + +However, there is no tool that exposes an IR instead of an AST. JSIR seeks to +fill this gap. + +## Use cases at Google + +JSIR is used at Google for code analysis and transform use cases. For example: + +* **Decompilation** + + JSIR is used for decompiling the + [Hermes](https://github.com/facebook/hermes) bytecode all the way to + JavaScript code, by utilizing its ability to be fully lifted back to source + code. + +* **Deobfuscation**: + + JSIR is used for deobfuscating JavaScript by utilizing its source-to-source + transformation capability. + + See our latest [paper](https://arxiv.org/abs/2507.17691) on how we combine + the Gemini LLM and JSIR for deobfuscation. + +## JSIR design goals + +### A public and stable IR definition + +JSIR seeks to fill a gap in the JavaScript community for a public, open-source +IR-based tool. To achieve this goal, the definition of JSIR is **public, stable, +and comprehensive**. In particular, it closely follows +[ESTree](https://github.com/estree/estree), to the extent that most, if not all, +JSIR operations have 1-1 mappings from ESTree nodes. + +### Captures all source-level information + +JSIR is not intended to be used for low-level optimization (for example, a JIT +is expected to define lower-level IRs, even though they might be lowered from +JSIR). Instead, JSIR is a high-level IR that represents all source-level +information, in order to support use cases like source-to-source transformation +and decompilation. + +One design goal for JSIR is that we can convert JSIR back to the JavaScript AST +perfectly. In other words, the following round-trip should be lossless: + +``` +Source ↔ AST ↔ JSIR +``` + +### Easy to use + +The key benefit of an IR over an AST is that we can perform dataflow analysis. +Therefore, we need to expose a dataflow analysis framework (built on top of the +MLIR dataflow analysis framework). Such framework must provide an easy way of +defining lattices and transfer functions. + +Other considerations: + +* Can we provide an easy IR traversal util like @babel/traverse for AST? +* Can we manipulate the IR in JavaScript / TypeScript? +* Can we integrate JSIR into godbolt.org? + +## Why JSIR is interesting to the MLIR community + +### Battle-test MLIR functionalities + +JSIR's success would provide solid proof that MLIR is capable of defining IRs +for general purpose languages. Currently, the core "IR definition" part has been +proven to be effective, as demonstrated by JSIR and other projects like ClangIR +and Mojo. + +Now, we seek to battle-test more "advanced" MLIR functionalities. For example, +we have made a wrapper dataflow analysis API on top of MLIR to provide +ease-of-use improvements, and hope to contribute our learnings by upstreaming +some of these improvements. We also seek to use and potentially improve symbol +table, memory effects, etc.. All of these will make MLIR truly the go-to option +for building any compiler in the future. + +### Use MLIR to “represent AST” + +There have been discussions on whether MLIR can be used to represent the AST +([reference](https://discourse.llvm.org/t/rfc-region-based-control-flow-with-early-exits-in-mlir/76998/10)), +and Mojo is pioneering the idea of parsing directly to MLIR. + +JSIR is aiming at something even more extreme - an IR that can lift back to +source. If JSIR is successful, then it really proves that MLIR can represent +ASTs, and that the boundary between AST and IR is perhaps very blurry. + +### Eliminate the need for ASTs + +If a high-level IR can preserve all information from an AST, then we can start +to question whether we need ASTs at all. + +The fact that Mojo and Carbon perform all analyses on IRs suggest that IRs +already have all the analysis capabilities to replace ASTs. However, our +experience has shown that developers (especially those unfamiliar with +compilers) find ASTs much easier to understand and work with compared to IRs. + +## JSIR design highlights + +> **NOTE:** This section is taken from +> [intermediate_representation_design.md](https://github.com/google/jsir/blob/main/docs/intermediate_representation_design.md) +> in the repo. + +A critical goal of JSIR is to ensure an accurate conversion of the IR back to +the AST. Paired with [Babel](https://babeljs.io)'s AST → source printer, this +means we can lift the IR back to source. This "reversible" IR design enables +source-to-source transformations - we perform IR transformations then lift the +transformed IR to source. + +Internal evaluations on billions of JavaScript samples showed that AST - IR +round-trips achieved 99.9%+ success resulting in the same source. + +In the following sections, we will describe important design decisions that +achieve this high-fidelity round-trip. + +### Post-order traversal of AST + +Let’s start from the simplest case - straight-line code, i.e. a list of +statements with no control flow structures like `if`-statements. + +Each of these simple expression / statement AST nodes is mapped to a +corresponding JSIR operation. Therefore, JSIR for straight-line code is +equivalent to a post-order traversal dump of the AST. + +For example, for the following JavaScript statements: + +```js +1 + 2 + 3; +4 * 5; +``` + +The corresponding AST is as follows (see +[astexplorer](https://astexplorer.net/#/gist/8de510a68663424455bb9c175698cd38/f3e6d96bfe1bfa8ab11783eae0e2e7e22209ece9) +for the full AST): + +```c++ +[ + ExpressionStatement { + expression: BinaryExpression { + op: '+', + left: BinaryExpression { + op: '+', + left: NumericLiteral { value: 1 }, + right: NumericLiteral { value: 2 } + }, + right: NumericLiteral { value: 3 } + } + }, + ExpressionStatement { + expression: BinaryExpression { + op: '*', + left: NumericLiteral { value: 4 }, + right: NumericLiteral { value: 5 } + } + }, +] +``` + +The corresponding JSIR is as follows: + +```c++ +%1 = jsir.numeric_literal {1} +%2 = jsir.numeric_literal {2} +%1_plus_2 = jsir.binary_expression {'+'} (%1, %2) +%3 = jsir.numeric_literal {3} +%1_plus_2_plus_3 = jsir.binary_expression {'+'} (%1_plus_2, %3) +jsir.expression_statement (%1_plus_2_plus_3) +%4 = jsir.numeric_literal {4} +%5 = jsir.numeric_literal {5} +%4_mult_5 = jsir.binary_expression {'*'} (%4, %5) +jsir.expression_statement (%4_mult_5) +``` + +Perhaps the one-to-one mapping from AST nodes to JSIR operations is more obvious +if we add some indentations: + +```mlir + %1 = jsir.numeric_literal {1} + %2 = jsir.numeric_literal {2} + %1_plus_2 = jsir.binary_expression {'+'} (%1, %2) + %3 = jsir.numeric_literal {3} + %1_plus_2_plus_3 = jsir.binary_expression {'+'} (%1_plus_2, %3) +jsir.expression_statement (%1_plus_2_plus_3) + %4 = jsir.numeric_literal {4} + %5 = jsir.numeric_literal {5} + %4_mult_5 = jsir.binary_expression {'*'} (%4, %5) +jsir.expression_statement (%4_mult_5) +``` + +To convert this IR back to the AST, we **cannot** treat each op as a separate +statement, because that would cause every SSA value (e.g. `%1`) to become a +local variable: + +```js {.bad} +// Too many local variables! +var $1 = 1; +var $2 = 2; +var $1_plus_2 = $1 + $2; +var $3 = 3; +var $1_plus_2_plus_3 = $1_plus_2 + $3; +$1_plus_2_plus_3; // jsir.expression_statement +var $4 = 4; +var $5 = 5; +var $4_mult_5 = $4 * $5; +$4_mult_5; // jsir.expression_statement +``` + +However, we can detect the two statement-level ops (i.e. the two +`jsir.expression_statement` ops) and recursively traverse their use-def chains: + +```js {.good} + 1 + 2 + 3 ; +// ~ %1 = jsir.numeric_literal {1} +// ~ %2 = jsir.numeric_literal {2} +// ~~~~~ %1_plus_2 = jsir.binary_expression {'+'} (%1, %2) +// ~ %3 = jsir.numeric_literal {3} +// ~~~~~~~~~ %1_plus_2_plus_3 = jsir.binary_expression {'+'} (%1_plus_2, %3) +// ~~~~~~~~~~~ jsir.expression_statement (%1_plus_2_plus_3) + + 4 * 5 ; +// ~ %4 = jsir.numeric_literal {4} +// ~ %5 = jsir.numeric_literal {5} +// ~~~~~ %4_mult_5 = jsir.binary_expression {'*'} (%4, %5) +// ~~~~~~~ jsir.expression_statement (%4_mult_5) +``` + +When we try to convert a basic block (`mlir::Block`) of JSIR ops we always know +ahead of time what "kind" of content it holds: + +* If the block holds **a statement**, then we find the single statement-level + op and traverse its use-def chain to generate a `JsStatement` AST node. + +* If the block holds **a list of statements**, then we find all the + statement-level ops and traverse their use-def chains to generate a list of + `JsStatement` AST nodes. + +* If the block holds **an expression**, then it always ends with a + `jsir.expr_region_end (%expr)` op. We traverse the use-def chain of `%expr` + to generate a `JsExpression` AST node. + +* If the block holds **a list of expressions**, then it always ends with a + `jsir.exprs_region_end (%e1, %e2, ...)` op. We traverse the use-def chains + of `%e1, %e2, ...` to generate a list of `JsExpression` AST nodes. + +### Symbols, l-values and r-values + +We distinguish between l-values and r-values in JSIR. For example, consider the +following assignment: + +```js +a = b; +``` + +`a` is an l-value, and `b` is an r-value. + +L-values and r-values are represented in the **same** way in the AST: + +```c++ +ExpressionStatement { + expression: AssignmentExpression { + left: Identifier {"a"}, + right: Identifier {"b"} + } +} +``` + +However, they are represented **differently** in the IR: + +```c++ +%a_ref = jsir.identifier_ref {"a"} // l-value +%b = jsir.identifier {"b"} // r-value +%assign = jsir.assignment_expression (%a_ref, %b) +jsir.expression_statement (%assign) +``` + +The reason for this distinction is to explicitly represent the different +semantic meanings: + +* An l-value is a reference to some object / some memory location; + +* An r-value is some value. + +> **NOTE:** We will likely revisit how we represent symbols. + +### Representing control flows + +As mentioned above, JSIR seeks to have a nearly one-to-one mapping from the AST. +Therefore, to preserve all information about the original control flow +structures, we define a separate op for each control flow structure (e.g. +`jshir.if_statement`, `jshir.while_statement`, etc.). The nested code blocks are +represented as MLIR [regions](https://mlir.llvm.org/docs/LangRef/#regions). + +#### Example: `if`-statement + +Consider the following `if`-statement: + +```js +if (cond) + a; +else + b; +``` + +Its corresponding AST is as follows +([astexplorer](https://astexplorer.net/#/gist/58e3ca121e8bc97d9d1987766f4df96a/37b0de0e94073d24f40aede05b14e1c480b7b39a)): + +```c++ +IfStatement { + test: Identifier { name: "cond" }, + consequent: ExpressionStatement { + expression: Identifier { name: "a" } + }, + alternate: ExpressionStatement { + expression: Identifier { name: "b" } + } +} +``` + +And, its corresponding JSIR is as follows: + +```mlir +%cond = jsir.identifier {"cond"} +jshir.if_statement (%cond) ({ + %a = jsir.identifier {"a"} + jsir.expression_statement (%a) +}, { + %b = jsir.identifier {"b"} + jsir.expression_statement (%b) +}) +``` + +Since nested structure is fully preserved, converting JSIR back to the AST is +achieved by a standard recursive traversal. + +#### Example: `while`-statement + +Consider the following `while`-statement: + +```js +while (cond()) + x++; +``` + +Its corresponding AST is as follows +([astexplorer](https://astexplorer.net/#/gist/58e3ca121e8bc97d9d1987766f4df96a/6ce08d84210afbacdf99732366e04eafcd6b3ab5)): + +```c++ +WhileStatement { + test: CallExpression { + callee: Identifier { name: "cond" }, + arguments: [] + }, + body: ExpressionStatement { + expression: UpdateExpression { + operator: "++", + prefix: false, + argument: Identifier { name: "x" } + } + } +} +``` + +Its corresponding JSIR is as follows: + +```mlir +jshir.while_statement ({ + %cond_id = jsir.identifier {"cond"} + %cond_call = jsir.call_expression (%cond_id) + jsir.expr_region_end (%cond_call) +}, { + %x_ref = jsir.identifier_ref {"x"} + %update = jsir.update_expression {"++"} (%x_ref) + jsir.expression_statement (%update) +}) +``` + +Note that unlike `jshir.if_statement`, the condition in a +`jshir.while_statement` is represented as a region rather than a normal SSA +value (`%cond`). This is because the condition is evaluated in each iteration +**within** the `while`-statement, whereas the condition is evaluated only once +**before** the `if`-statement. + +#### Example: logical expression + +Consider the following statement with a logical expression: + +```js +x = a && b; +``` + +Its corresponding AST is as follows +([astexplorer](https://astexplorer.net/#/gist/58e3ca121e8bc97d9d1987766f4df96a/c7fbec034a61bcbb66959714b7d95dbd9ca86e32)): + +```c++ +ExpressionStatement { + expression: AssignmentExpression { + left: Identifier { name: "x" }, + right: LogicalExpression { + left: Identifier { name: "a" }, + right: Identifier { name: "b" } + } + } +} +``` + +Its corresponding JSIR is as follows: + +```mlir +%x_ref = jsir.identifier_ref {"x"} +%a = jsir.identifier {"a"} +%and = jshir.logical_expression (%a) ({ + %b = jsir.identifier {"b"} + jsir.expr_region_end (%b) +}) +%assign = jsir.assignment_expression (%x_ref, %and) +jsir.expression_statement (%assign) +``` + +Note that in `jshir.logical_expression`, `left` is an SSA value, and `right` is +a region. This is because `left` is always evaluated first, whereas `right` is +only evaluated if the result of `left` is truthy, and omitted if `left` is falsy +due to the short-circuit behavior. + +## Dataflow analysis in JSIR + +JSIR provides a dataflow analysis API, built on top of the upstream MLIR +dataflow analysis API, with usability improvements: + +* We define a class `JsirStateRef` that encapsulates all writes to + `AnalysisState`s, so that dependent `WorkItem`s are automatically pushed to + the worklist. + + **Benefit:** Unlike the upstream MLIR API, the user never has to remember to + call `propagateIfChanged()`. + +* We define base classes like `JsirDataFlowAnalysis` and + `JsirConditionalForwardDataFlowAnalysis` for analyses that use both sparse + (attached to `mlir::Value`s) and dense (attached to `mlir::ProgramPoint`s) + states. + + **Benefit:** Unlike the upstream MLIR API, the user does not have to write + two analyses, one deriving `SparseAnalysis` and one deriving + `DenseAnalysis`. + +* We define a struct `JsirGeneralCfgEdge` to unify branches between + `mlir::Block`s and region branches, including early exits (break and + continue statements). + + **Benefit:** Unlike the upstream MLIR API, the user does not need to load + `ConstantPropagation` and `DeadCodeAnalysis` for every analysis. + +## What's next + +### Adopt more MLIR built-in functionalities + +Until now, we haven't spent too much time trying to use MLIR’s built-in +dialects, ops and functionalities. For example: + +* We could replace jsir.identifier and jsir.identifier_ref with memref. +* We could use MLIR’s built-in symbol table. This is possible now since we + adopt region-based control flow and scopes are mapped to regions. + +### Contribute to MLIR region-based dataflow analysis + +We believe that the ease-of-use improvements in JSIR's dataflow analysis API can +be upstreamed to MLIR's built-in dataflow analysis API. A direct port is +infeasible, since our API makes certain assumptions that are only true in JSIR, +but the general ideas can be adopted. We hope to write a separate RFC to discuss +these ideas in more detail. + +### Upstream JSIR? + +We would be very happy to upstream JSIR into MLIR, similar to WasmSSA. However, +there are several **practical issues** that might make this infeasible. We are +eager to see what the community thinks. + +* **Dependency on [QuickJS](https://github.com/bellard/quickjs):** We use + QuickJS for folding constants. This way, we don't need to reimplement + JavaScript semantics (e.g. looking at the + [ECMAScript spec](https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator), + even `a + b` involves many steps due to automatic type conversions). We are + not sure if adding a dependency on a lightweight JavaScript execution engine + to the LLVM repository would be acceptable. + +* **Dependency on [Babel](https://babeljs.io) or [SWC](https://swc.rs):** JSIR + doesn't come with its own parser - we currently use Babel, and we are trying + to migrate to SWC. Babel is written in TypeScript, and we currently run it + in QuickJS from C++; SWC is written in Rust. We are not sure if it's + acceptable to add either of those as a dependency in the MLIR codebase. + +### Contribution welcomed! + +We welcome engagement and contributions from the community! Feel free to try it +out and let us know where and how we can improve. If you are interested in any +of the ideas above, let use know! + +## Acknowledgement + +JSIR couldn't have been possible without the help with many contributors: + +TODO(tzx) A long list here.