mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-10-20 18:56:17 +00:00
Adds `make coverage` (cargo-llvm-cov over the full workspace including revive-llvm-builder), a new "Code coverage" book chapter that briefly explains how to run it, and a PR workflow that runs coverage and comments on the PR (it updates the same comment if it already exists) when the `measure code coverage` label is applied (see e.g. [this comment](https://github.com/paritytech/revive/pull/529#issuecomment-4966136441)). Building instrumented LLVM and generating an LLVM C++ coverage report is also possible, see accompanying [PR description #575](https://github.com/paritytech/revive/pull/575) for more details. --------- Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com> Signed-off-by: xermicus <bigcyrill@hotmail.com> Co-authored-by: Cyrill Leutwiler <bigcyrill@hotmail.com> Co-authored-by: xermicus <cyrill@parity.io> Co-authored-by: elle-j <linnea@parity.io> Co-authored-by: LJ <81748770+elle-j@users.noreply.github.com>
4034 lines
204 KiB
HTML
4034 lines
204 KiB
HTML
<!DOCTYPE HTML>
|
||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||
<head>
|
||
<!-- Book generated using mdBook -->
|
||
<meta charset="UTF-8">
|
||
<title>IR reference - revive compiler book</title>
|
||
|
||
|
||
<!-- Custom HTML head -->
|
||
|
||
<meta name="description" content="">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta name="theme-color" content="#ffffff">
|
||
|
||
<link rel="icon" href="../favicon-de23e50b.svg">
|
||
<link rel="shortcut icon" href="../favicon-8114d1fc.png">
|
||
<link rel="stylesheet" href="../css/variables-8adf115d.css">
|
||
<link rel="stylesheet" href="../css/general-2459343d.css">
|
||
<link rel="stylesheet" href="../css/chrome-ae938929.css">
|
||
<link rel="stylesheet" href="../css/print-9e4910d8.css" media="print">
|
||
|
||
<!-- Fonts -->
|
||
<link rel="stylesheet" href="../fonts/fonts-9644e21d.css">
|
||
|
||
<!-- Highlight.js Stylesheets -->
|
||
<link rel="stylesheet" id="mdbook-highlight-css" href="../highlight-493f70e1.css">
|
||
<link rel="stylesheet" id="mdbook-tomorrow-night-css" href="../tomorrow-night-4c0ae647.css">
|
||
<link rel="stylesheet" id="mdbook-ayu-highlight-css" href="../ayu-highlight-3fdfc3ac.css">
|
||
|
||
<!-- Custom theme stylesheets -->
|
||
|
||
|
||
<!-- Provide site root and default themes to javascript -->
|
||
<script>
|
||
const path_to_root = "../";
|
||
const default_light_theme = "light";
|
||
const default_dark_theme = "navy";
|
||
window.path_to_searchindex_js = "../searchindex-57ec751f.js";
|
||
</script>
|
||
<!-- Start loading toc.js asap -->
|
||
<script src="../toc-f74aae8e.js"></script>
|
||
</head>
|
||
<body>
|
||
<div id="mdbook-help-container">
|
||
<div id="mdbook-help-popup">
|
||
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
|
||
<div>
|
||
<p>Press <kbd>←</kbd> or <kbd>→</kbd> to navigate between chapters</p>
|
||
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
|
||
<p>Press <kbd>?</kbd> to show this help</p>
|
||
<p>Press <kbd>Esc</kbd> to hide this help</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="mdbook-body-container">
|
||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||
<script>
|
||
try {
|
||
let theme = localStorage.getItem('mdbook-theme');
|
||
let sidebar = localStorage.getItem('mdbook-sidebar');
|
||
|
||
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||
}
|
||
|
||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||
}
|
||
} catch (e) { }
|
||
</script>
|
||
|
||
<!-- Set the theme before any content is loaded, prevents flash -->
|
||
<script>
|
||
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
|
||
let theme;
|
||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||
const html = document.documentElement;
|
||
html.classList.remove('light')
|
||
html.classList.add(theme);
|
||
html.classList.add("js");
|
||
</script>
|
||
|
||
<input type="checkbox" id="mdbook-sidebar-toggle-anchor" class="hidden">
|
||
|
||
<!-- Hide / unhide sidebar before it is displayed -->
|
||
<script>
|
||
let sidebar = null;
|
||
const sidebar_toggle = document.getElementById("mdbook-sidebar-toggle-anchor");
|
||
if (document.body.clientWidth >= 1080) {
|
||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||
sidebar = sidebar || 'visible';
|
||
} else {
|
||
sidebar = 'hidden';
|
||
sidebar_toggle.checked = false;
|
||
}
|
||
if (sidebar === 'visible') {
|
||
sidebar_toggle.checked = true;
|
||
} else {
|
||
html.classList.remove('sidebar-visible');
|
||
}
|
||
</script>
|
||
|
||
<nav id="mdbook-sidebar" class="sidebar" aria-label="Table of contents">
|
||
<!-- populated by js -->
|
||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
||
<noscript>
|
||
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
||
</noscript>
|
||
<div id="mdbook-sidebar-resize-handle" class="sidebar-resize-handle">
|
||
<div class="sidebar-resize-indicator"></div>
|
||
</div>
|
||
</nav>
|
||
|
||
<div id="mdbook-page-wrapper" class="page-wrapper">
|
||
|
||
<div class="page">
|
||
<div id="mdbook-menu-bar-hover-placeholder"></div>
|
||
<div id="mdbook-menu-bar" class="menu-bar sticky">
|
||
<div class="left-buttons">
|
||
<label id="mdbook-sidebar-toggle" class="icon-button" for="mdbook-sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="mdbook-sidebar">
|
||
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg></span>
|
||
</label>
|
||
<button id="mdbook-theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="mdbook-theme-list">
|
||
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M371.3 367.1c27.3-3.9 51.9-19.4 67.2-42.9L600.2 74.1c12.6-19.5 9.4-45.3-7.6-61.2S549.7-4.4 531.1 9.6L294.4 187.2c-24 18-38.2 46.1-38.4 76.1L371.3 367.1zm-19.6 25.4l-116-104.4C175.9 290.3 128 339.6 128 400c0 3.9 .2 7.8 .6 11.6c1.8 17.5-10.2 36.4-27.8 36.4H96c-17.7 0-32 14.3-32 32s14.3 32 32 32H240c61.9 0 112-50.1 112-112c0-2.5-.1-5-.2-7.5z"/></svg></span>
|
||
</button>
|
||
<ul id="mdbook-theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-default_theme">Auto</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-light">Light</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-rust">Rust</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-coal">Coal</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-navy">Navy</button></li>
|
||
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-ayu">Ayu</button></li>
|
||
</ul>
|
||
<button id="mdbook-search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="mdbook-searchbar">
|
||
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352c79.5 0 144-64.5 144-144s-64.5-144-144-144S64 128.5 64 208s64.5 144 144 144z"/></svg></span>
|
||
</button>
|
||
</div>
|
||
|
||
<h1 class="menu-title">revive compiler book</h1>
|
||
|
||
<div class="right-buttons">
|
||
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||
<span class=fa-svg id="print-button"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M128 0C92.7 0 64 28.7 64 64v96h64V64H354.7L384 93.3V160h64V93.3c0-17-6.7-33.3-18.7-45.3L400 18.7C388 6.7 371.7 0 354.7 0H128zM384 352v32 64H128V384 368 352H384zm64 32h32c17.7 0 32-14.3 32-32V256c0-35.3-28.7-64-64-64H64c-35.3 0-64 28.7-64 64v96c0 17.7 14.3 32 32 32H64v64c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V384zm-16-88c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24z"/></svg></span>
|
||
</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div id="mdbook-search-wrapper" class="hidden">
|
||
<form id="mdbook-searchbar-outer" class="searchbar-outer">
|
||
<div class="search-wrapper">
|
||
<input type="search" id="mdbook-searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="mdbook-searchresults-outer" aria-describedby="searchresults-header">
|
||
<div class="spinner-wrapper">
|
||
<span class=fa-svg id="fa-spin"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M304 48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zm0 416c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM48 304c26.5 0 48-21.5 48-48s-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48zm464-48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM142.9 437c18.7-18.7 18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zm0-294.2c18.7-18.7 18.7-49.1 0-67.9S93.7 56.2 75 75s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zM369.1 437c18.7 18.7 49.1 18.7 67.9 0s18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9z"/></svg></span>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
<div id="mdbook-searchresults-outer" class="searchresults-outer hidden">
|
||
<div id="mdbook-searchresults-header" class="searchresults-header"></div>
|
||
<ul id="mdbook-searchresults">
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||
<script>
|
||
document.getElementById('mdbook-sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||
document.getElementById('mdbook-sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||
Array.from(document.querySelectorAll('#mdbook-sidebar a')).forEach(function(link) {
|
||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||
});
|
||
</script>
|
||
|
||
<div id="mdbook-content" class="content">
|
||
<main>
|
||
<h1 id="newyork-ir-reference"><a class="header" href="#newyork-ir-reference">newyork IR reference</a></h1>
|
||
<p>A per-operation reference for the newyork IR: textual syntax, operand and result types, purity, region and static-slot annotations, and examples.</p>
|
||
<h2 id="how-to-read-this-reference"><a class="header" href="#how-to-read-this-reference">How to read this reference</a></h2>
|
||
<p>This reference page enumerates every operation the newyork IR supports. It is a lookup, not a walkthrough: each entry is self-contained and intended to be reachable by anchor.</p>
|
||
<p>Operations are grouped by function (memory and storage writes, pure expressions, control flow, and so on) rather than alphabetically. Jump to a specific operation from the <a href="#operation-index">operation index</a> below, or use the sidebar.</p>
|
||
<p>Every operation appears in two places in the codebase. The canonical Rust definition is a variant of either <code>Expression</code> or <code>Statement</code> in <code>ir.rs</code>. The textual rendering used by debug dumps and by this reference page is produced by the printer in <code>printer.rs</code>.</p>
|
||
<blockquote class="blockquote-tag blockquote-tag-note">
|
||
<p class="blockquote-tag-title"><svg viewbox="0 0 16 16" width="18" height="18"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>Note</p>
|
||
<p>Treat the printed syntax as a debug surface, not a stable input language: there is no parser for it, and printer details change when passes add new annotations.</p>
|
||
</blockquote>
|
||
<h3 id="entry-format"><a class="header" href="#entry-format">Entry format</a></h3>
|
||
<p>Each operation entry has the same shape:</p>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Field</th><th>What it shows</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><strong>Heading</strong></td><td>The printed operation name (e.g. <code>mstore</code>) followed by the <code>Expression</code> or <code>Statement</code> variant it corresponds to in <code>ir.rs</code>.</td></tr>
|
||
<tr><td><strong>Description</strong></td><td>A short prose summary of what the operation does and any semantic notes worth knowing before reading the rest of the entry.</td></tr>
|
||
<tr><td><strong>Syntax</strong></td><td>The literal printer output, including any optional debug annotations (region tags, static-slot comments). Anything inside <code>/* ... */</code> is a debug-only annotation and is not part of the operation itself.</td></tr>
|
||
<tr><td><strong>Example</strong></td><td>A minimal printed snippet, using the printer’s actual <code>v0</code>/<code>v1</code>/… naming.</td></tr>
|
||
<tr><td><strong>Operands</strong></td><td>One row per input or structural participant in the printed syntax. Value operands list the narrowest type the operation guarantees (default <code>i256</code>; narrower widths only appear when type inference has narrowed an upstream definition). Vector-of-operands fields show <code>Vec<…></code> as the type. Non-value participants such as nested regions are listed with an em-dash type to mark them as structural rather than as operands.</td></tr>
|
||
<tr><td><strong>Result and purity</strong></td><td>The type the operation produces (or <em>none</em> for statements that bind no value), followed by a purity label, either <em>Pure</em> or <em>Effectful</em>. Pure operations may be reordered, deduplicated, or eliminated by the simplifier; effectful ones may not. Effectful entries may carry a parenthetical describing the nature of the side effect when informative (e.g. “control flow”, “terminator”, or a note about revert/trap behavior).</td></tr>
|
||
<tr><td><strong>Annotations</strong></td><td>Operation-specific fields the printer surfaces as <code>/* ... */</code> comments in the dump (region tag for memory ops, static-slot hint for storage ops, type suffix for non-default widths). Listed here as a table of <em>source field</em> → <em>printed form</em>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="syntax-notation"><a class="header" href="#syntax-notation">Syntax notation</a></h3>
|
||
<p>Syntax templates in each entry use the following conventions:</p>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Notation</th><th>Meaning</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>add</code>, <code>mload</code>, <code>if</code>, <code>else</code>, <code>case</code>, <code>let</code>, <code>yield</code>, …</td><td>Literal printer tokens: bare lowercase identifiers and keywords that the printer emits verbatim.</td></tr>
|
||
<tr><td><code>$offset</code>, <code>$value</code>, <code>$key</code>, <code>$lhs</code>, <code>$rhs</code>, …</td><td>Role names (<code>$</code>-prefixed): placeholders for SSA value references the printer renders as <code>v</code> followed by a decimal id (<code>v0</code>, <code>v1</code>, …).</td></tr>
|
||
<tr><td><code><type></code>, <code><region></code>, <code><hex></code>, <code><id></code>, <code><bits></code>, <code><func_name></code>, <code><N></code>, <code><length></code>, …</td><td>Metavariables: stand for compile-time fields (type tags, hex values, identifier strings, integer counts), not SSA values. The concrete values they take are enumerated in the Annotations section of each entry or in the type system reference.</td></tr>
|
||
<tr><td><code>[…]</code></td><td>Optional parts. Anything inside the brackets may or may not appear in any given dump, depending on the conditions described in the operation’s Annotations section.</td></tr>
|
||
<tr><td><code>[: <type>]</code></td><td>Optional type suffix on a value reference. Suppressed when the value’s type is the default <code>i256</code> integer; present otherwise (<code>: i32</code>, <code>: ptr<heap></code>, …).</td></tr>
|
||
<tr><td><code>/* … */</code></td><td>Debug-only annotations the printer attaches to certain operations (memory region tag, static-slot hint, etc.).</td></tr>
|
||
<tr><td><code>…</code></td><td>Repetition: “more entries of the same shape.” Used in vector operand lists (<code>$arg_0, $arg_1, …</code>) and in multi-line block bodies (<code>{ … }</code>).</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p>For instance, this template:</p>
|
||
<pre><code class="language-text">let $result[: <type>] := and($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<p>prints as:</p>
|
||
<pre><code class="language-text">let v2: i8 := and(v0, v1: i8)
|
||
</code></pre>
|
||
<p><code>$result</code> rendered as <code>v2</code> with an <code>i8</code> type suffix, <code>$lhs</code> as <code>v0</code> at the default <code>i256</code> (type suffix omitted), and <code>$rhs</code> as <code>v1</code> with an <code>i8</code> type suffix.</p>
|
||
<blockquote class="blockquote-tag blockquote-tag-note">
|
||
<p class="blockquote-tag-title"><svg viewbox="0 0 16 16" width="18" height="18"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>Note</p>
|
||
<p><strong>A value’s printed width is use-driven.</strong> Type inference assigns each value a forward width from its definition, then widens it to satisfy its uses. The type suffix shown for a value in an example (such as <code>i8</code>) is therefore only illustrative — a short example may not show the uses that determine it, and the same operation can appear with a wider suffix, or none (it is omitted for the default <code>i256</code>), in another program.</p>
|
||
<p>For instance, a value used as a memory offset widens to <code>i64</code>; as an address (a <code>call</code> target, <code>extcodesize</code>) to <code>i160</code>; stored as a full word (an <code>mstore</code>/<code>sstore</code> value) to <code>i256</code>; and an <code>add</code>/<code>mul</code> operand up to the <code>i64</code> register width.</p>
|
||
</blockquote>
|
||
<h3 id="operation-index"><a class="header" href="#operation-index">Operation index</a></h3>
|
||
<h4 id="pure-expressions"><a class="header" href="#pure-expressions">Pure expressions</a></h4>
|
||
<h5 id="constants-and-variables"><a class="header" href="#constants-and-variables">Constants and variables</a></h5>
|
||
<ul>
|
||
<li><a href="#0xhex"><code>0x<hex></code></a></li>
|
||
<li><a href="#vid"><code>v<id></code></a></li>
|
||
</ul>
|
||
<h5 id="arithmetic"><a class="header" href="#arithmetic">Arithmetic</a></h5>
|
||
<ul>
|
||
<li><a href="#add"><code>add</code></a></li>
|
||
<li><a href="#sub"><code>sub</code></a></li>
|
||
<li><a href="#mul"><code>mul</code></a></li>
|
||
<li><a href="#div"><code>div</code></a></li>
|
||
<li><a href="#sdiv"><code>sdiv</code></a></li>
|
||
<li><a href="#mod"><code>mod</code></a></li>
|
||
<li><a href="#smod"><code>smod</code></a></li>
|
||
<li><a href="#exp"><code>exp</code></a></li>
|
||
<li><a href="#and"><code>and</code></a></li>
|
||
<li><a href="#or"><code>or</code></a></li>
|
||
<li><a href="#xor"><code>xor</code></a></li>
|
||
<li><a href="#shl"><code>shl</code></a></li>
|
||
<li><a href="#shr"><code>shr</code></a></li>
|
||
<li><a href="#sar"><code>sar</code></a></li>
|
||
<li><a href="#lt"><code>lt</code></a></li>
|
||
<li><a href="#gt"><code>gt</code></a></li>
|
||
<li><a href="#slt"><code>slt</code></a></li>
|
||
<li><a href="#sgt"><code>sgt</code></a></li>
|
||
<li><a href="#eq"><code>eq</code></a></li>
|
||
<li><a href="#byte"><code>byte</code></a></li>
|
||
<li><a href="#signextend"><code>signextend</code></a></li>
|
||
<li><a href="#addmod"><code>addmod</code></a></li>
|
||
<li><a href="#mulmod"><code>mulmod</code></a></li>
|
||
<li><a href="#iszero"><code>iszero</code></a></li>
|
||
<li><a href="#not"><code>not</code></a></li>
|
||
<li><a href="#clz"><code>clz</code></a></li>
|
||
</ul>
|
||
<h5 id="bit-width-conversions"><a class="header" href="#bit-width-conversions">Bit-width conversions</a></h5>
|
||
<ul>
|
||
<li><a href="#truncateibits"><code>truncate<i<bits>></code></a></li>
|
||
<li><a href="#zextibits"><code>zext<i<bits>></code></a></li>
|
||
<li><a href="#sextibits"><code>sext<i<bits>></code></a></li>
|
||
</ul>
|
||
<h5 id="hashing"><a class="header" href="#hashing">Hashing</a></h5>
|
||
<ul>
|
||
<li><a href="#keccak256"><code>keccak256</code></a></li>
|
||
<li><a href="#keccak256_pair"><code>keccak256_pair</code></a></li>
|
||
<li><a href="#keccak256_single"><code>keccak256_single</code></a></li>
|
||
</ul>
|
||
<h5 id="environment-reads"><a class="header" href="#environment-reads">Environment reads</a></h5>
|
||
<ul>
|
||
<li><a href="#caller"><code>caller</code></a></li>
|
||
<li><a href="#callvalue"><code>callvalue</code></a></li>
|
||
<li><a href="#origin"><code>origin</code></a></li>
|
||
<li><a href="#address"><code>address</code></a></li>
|
||
<li><a href="#chainid"><code>chainid</code></a></li>
|
||
<li><a href="#gas"><code>gas</code></a></li>
|
||
<li><a href="#msize"><code>msize</code></a></li>
|
||
<li><a href="#coinbase"><code>coinbase</code></a></li>
|
||
<li><a href="#timestamp"><code>timestamp</code></a></li>
|
||
<li><a href="#number"><code>number</code></a></li>
|
||
<li><a href="#difficulty"><code>difficulty</code></a></li>
|
||
<li><a href="#gaslimit"><code>gaslimit</code></a></li>
|
||
<li><a href="#basefee"><code>basefee</code></a></li>
|
||
<li><a href="#blobbasefee"><code>blobbasefee</code></a></li>
|
||
<li><a href="#blobhash"><code>blobhash</code></a></li>
|
||
<li><a href="#blockhash"><code>blockhash</code></a></li>
|
||
<li><a href="#selfbalance"><code>selfbalance</code></a></li>
|
||
<li><a href="#gasprice"><code>gasprice</code></a></li>
|
||
</ul>
|
||
<h5 id="calldata-returndata-and-code"><a class="header" href="#calldata-returndata-and-code">Calldata, returndata, and code</a></h5>
|
||
<ul>
|
||
<li><a href="#calldataload"><code>calldataload</code></a></li>
|
||
<li><a href="#calldatasize"><code>calldatasize</code></a></li>
|
||
<li><a href="#returndatasize"><code>returndatasize</code></a></li>
|
||
<li><a href="#codesize"><code>codesize</code></a></li>
|
||
<li><a href="#extcodesize"><code>extcodesize</code></a></li>
|
||
<li><a href="#extcodehash"><code>extcodehash</code></a></li>
|
||
<li><a href="#balance"><code>balance</code></a></li>
|
||
</ul>
|
||
<h5 id="memory-and-storage-loads"><a class="header" href="#memory-and-storage-loads">Memory and storage loads</a></h5>
|
||
<ul>
|
||
<li><a href="#mload"><code>mload</code></a></li>
|
||
<li><a href="#sload"><code>sload</code></a></li>
|
||
<li><a href="#tload"><code>tload</code></a></li>
|
||
<li><a href="#mapping_sload"><code>mapping_sload</code></a></li>
|
||
</ul>
|
||
<h5 id="linker"><a class="header" href="#linker">Linker</a></h5>
|
||
<ul>
|
||
<li><a href="#dataoffset"><code>dataoffset</code></a></li>
|
||
<li><a href="#datasize"><code>datasize</code></a></li>
|
||
<li><a href="#loadimmutable"><code>loadimmutable</code></a></li>
|
||
<li><a href="#linkersymbol"><code>linkersymbol</code></a></li>
|
||
</ul>
|
||
<h5 id="function-call"><a class="header" href="#function-call">Function call</a></h5>
|
||
<ul>
|
||
<li><a href="#func_name"><code><func_name></code></a></li>
|
||
</ul>
|
||
<h4 id="memory-and-storage-writes"><a class="header" href="#memory-and-storage-writes">Memory and storage writes</a></h4>
|
||
<ul>
|
||
<li><a href="#mstore"><code>mstore</code></a></li>
|
||
<li><a href="#mstore8"><code>mstore8</code></a></li>
|
||
<li><a href="#mcopy"><code>mcopy</code></a></li>
|
||
<li><a href="#sstore"><code>sstore</code></a></li>
|
||
<li><a href="#tstore"><code>tstore</code></a></li>
|
||
<li><a href="#mapping_sstore"><code>mapping_sstore</code></a></li>
|
||
</ul>
|
||
<h4 id="bulk-copies"><a class="header" href="#bulk-copies">Bulk copies</a></h4>
|
||
<ul>
|
||
<li><a href="#codecopy"><code>codecopy</code></a></li>
|
||
<li><a href="#extcodecopy"><code>extcodecopy</code></a></li>
|
||
<li><a href="#returndatacopy"><code>returndatacopy</code></a></li>
|
||
<li><a href="#datacopy"><code>datacopy</code></a></li>
|
||
<li><a href="#calldatacopy"><code>calldatacopy</code></a></li>
|
||
</ul>
|
||
<h4 id="bindings-and-wrappers"><a class="header" href="#bindings-and-wrappers">Bindings and wrappers</a></h4>
|
||
<ul>
|
||
<li><a href="#let"><code>let</code></a></li>
|
||
<li><a href="#expression-statement">expression statement</a></li>
|
||
<li><a href="#setimmutable"><code>setimmutable</code></a></li>
|
||
</ul>
|
||
<h4 id="structured-control-flow"><a class="header" href="#structured-control-flow">Structured control flow</a></h4>
|
||
<ul>
|
||
<li><a href="#if"><code>if</code></a></li>
|
||
<li><a href="#switch"><code>switch</code></a></li>
|
||
<li><a href="#for"><code>for</code></a></li>
|
||
<li><a href="#break"><code>break</code></a></li>
|
||
<li><a href="#continue"><code>continue</code></a></li>
|
||
<li><a href="#leave"><code>leave</code></a></li>
|
||
<li><a href="#nested-block">nested block</a></li>
|
||
</ul>
|
||
<h4 id="external-interaction"><a class="header" href="#external-interaction">External interaction</a></h4>
|
||
<ul>
|
||
<li><a href="#call"><code>call</code></a></li>
|
||
<li><a href="#callcode"><code>callcode</code></a></li>
|
||
<li><a href="#delegatecall"><code>delegatecall</code></a></li>
|
||
<li><a href="#staticcall"><code>staticcall</code></a></li>
|
||
<li><a href="#create"><code>create</code></a></li>
|
||
<li><a href="#create2"><code>create2</code></a></li>
|
||
<li><a href="#logn"><code>log<N></code></a></li>
|
||
</ul>
|
||
<h4 id="termination"><a class="header" href="#termination">Termination</a></h4>
|
||
<ul>
|
||
<li><a href="#return"><code>return</code></a></li>
|
||
<li><a href="#revert"><code>revert</code></a></li>
|
||
<li><a href="#stop"><code>stop</code></a></li>
|
||
<li><a href="#invalid"><code>invalid</code></a></li>
|
||
<li><a href="#selfdestruct"><code>selfdestruct</code></a></li>
|
||
<li><a href="#panic_revert"><code>panic_revert</code></a></li>
|
||
<li><a href="#error_string_revert"><code>error_string_revert</code></a></li>
|
||
<li><a href="#custom_error_revert"><code>custom_error_revert</code></a></li>
|
||
</ul>
|
||
<h2 id="type-system"><a class="header" href="#type-system">Type system</a></h2>
|
||
<p>Every value in the IR carries a <code>Type</code>. The operation entries below refer to widths (<code>i1</code>…<code>i256</code>), address spaces (<code>ptr<heap></code>, etc.), and memory regions (<code>scratch</code>, etc.) by their printed form; this section is the reference for those names.</p>
|
||
<h3 id="type"><a class="header" href="#type"><code>Type</code></a></h3>
|
||
<p>The umbrella enum, with these variants:</p>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Variant</th><th>Printed as</th><th>Description</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>Int(BitWidth)</code></td><td><code>i1</code>, <code>i8</code>, …, <code>i256</code></td><td>An integer at one of the <a href="#bitwidth">BitWidth</a> widths.</td></tr>
|
||
<tr><td><code>Ptr(AddressSpace)</code></td><td><code>ptr<heap></code>, <code>ptr<stack></code>, <code>ptr<storage></code>, <code>ptr<code></code></td><td>A pointer tagged with its address space; see <a href="#addressspace">AddressSpace</a>.</td></tr>
|
||
<tr><td><code>Void</code></td><td><code>void</code></td><td>Unit type. Used for statements that produce no value and for <code>void</code>-returning functions.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="bitwidth"><a class="header" href="#bitwidth"><code>BitWidth</code></a></h3>
|
||
<p>The rungs of integer width. Newly minted values default to <code>I256</code>; type inference narrows them down to one of the lower rungs when it can prove the upper bits are zero or unused.</p>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Variant</th><th>Printed as</th><th>Typical use</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>I1</code></td><td><code>i1</code></td><td>Boolean. Result type of every comparison and <code>iszero</code>.</td></tr>
|
||
<tr><td><code>I8</code></td><td><code>i8</code></td><td>Byte values. The narrowest meaningful integer.</td></tr>
|
||
<tr><td><code>I32</code></td><td><code>i32</code></td><td>PolkaVM pointer width (XLEN); minimum width for function parameters under the rv64e ABI.</td></tr>
|
||
<tr><td><code>I64</code></td><td><code>i64</code></td><td>PolkaVM native register width; most narrowed values land here.</td></tr>
|
||
<tr><td><code>I128</code></td><td><code>i128</code></td><td>Two registers; arithmetic that overflows <code>i64</code> but doesn’t need full 256-bit emulation.</td></tr>
|
||
<tr><td><code>I160</code></td><td><code>i160</code></td><td>Ethereum addresses; result of <code>caller</code>, <code>origin</code>, mapping keys.</td></tr>
|
||
<tr><td><code>I256</code></td><td><code>i256</code></td><td>EVM word width. The default and conservative ceiling.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="addressspace"><a class="header" href="#addressspace"><code>AddressSpace</code></a></h3>
|
||
<p>The address space a pointer points into. Carried on every <code>Ptr</code> value so the codegen can lower loads and stores without a separate alias-analysis pass.</p>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Variant</th><th>Printed as</th><th>Points into</th><th>Endianness</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>Heap</code></td><td><code>ptr<heap></code></td><td>Emulated EVM linear memory (the simulated <code>mload</code>/<code>mstore</code> region).</td><td>Big-endian (by EVM contract).</td></tr>
|
||
<tr><td><code>Stack</code></td><td><code>ptr<stack></code></td><td>Native PolkaVM stack allocations.</td><td>Little-endian (no swap).</td></tr>
|
||
<tr><td><code>Storage</code></td><td><code>ptr<storage></code></td><td>Contract storage; key/value with 256-bit slots.</td><td>Big-endian on the wire.</td></tr>
|
||
<tr><td><code>Code</code></td><td><code>ptr<code></code></td><td>Read-only code/data segment.</td><td>Big-endian.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="memoryregion"><a class="header" href="#memoryregion"><code>MemoryRegion</code></a></h3>
|
||
<p>A refinement carried by every memory load and store on top of <code>AddressSpace::Heap</code>. The tag tells later passes what kind of heap address an offset is hitting, which drives both free-memory-pointer propagation and byte-swap elimination.</p>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Variant</th><th>Address range</th><th>Printed as</th><th>Meaning</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>Scratch</code></td><td><code>0x00</code>–<code>0x3f</code></td><td><code>/* scratch */</code></td><td>EVM scratch space; safe to touch without consulting the free memory pointer.</td></tr>
|
||
<tr><td><code>FreePointerSlot</code></td><td>exactly <code>0x40</code></td><td><code>/* free_ptr */</code></td><td>Slot that stores the free memory pointer itself.</td></tr>
|
||
<tr><td><code>Dynamic</code></td><td><code>0x80</code> and above</td><td><code>/* dynamic */</code></td><td>Real heap allocations.</td></tr>
|
||
<tr><td><code>Unknown</code></td><td>everything else (constants in <code>0x41</code>–<code>0x7f</code>, plus all non-constant offsets)</td><td>(suppressed)</td><td>Conservative fallback used when the offset isn’t a constant or doesn’t slot cleanly.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h2 id="pure-expressions-1"><a class="header" href="#pure-expressions-1">Pure expressions</a></h2>
|
||
<p>Pure expressions produce values without side effects. The simplifier may freely reorder, deduplicate, and eliminate them. They appear on the right-hand side of a <code>let</code> binding, or as operands of other expressions and effectful statements; the operand positions accept SSA value references only, so any pure expression that is consumed elsewhere is first bound by a <code>let</code>. Examples in this section wrap each expression in a <code>let v := …</code> to give it somewhere to land.</p>
|
||
<h3 id="0xhex"><a class="header" href="#0xhex"><code>0x<hex></code></a></h3>
|
||
<p>(<code>Expression::Literal</code>)</p>
|
||
<h4 id="description"><a class="header" href="#description">Description</a></h4>
|
||
<p>A compile-time constant value with a declared type. New literals minted by the translator default to <code>Int(I256)</code>; passes that synthesize constants at narrower widths (e.g. a one-bit boolean from a constant comparison) attach the narrower type directly.</p>
|
||
<h4 id="syntax"><a class="header" href="#syntax">Syntax</a></h4>
|
||
<pre><code class="language-text">0x<hex>[: <type>]
|
||
</code></pre>
|
||
<h4 id="example"><a class="header" href="#example">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i8 := 0x2a
|
||
let v1: i1 := 0x1 // boolean true
|
||
let v2: i64 := 0x80
|
||
</code></pre>
|
||
<h4 id="operands"><a class="header" href="#operands">Operands</a></h4>
|
||
<p>None — literals are leaves.</p>
|
||
<h4 id="result-and-purity"><a class="header" href="#result-and-purity">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>Same as the literal’s <code>value_type</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations"><a class="header" href="#annotations">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>value: BigUint</code></td><td><code>0x<hex></code> in the syntax position (not a comment annotation; it is the expression itself)</td></tr>
|
||
<tr><td><code>value_type:</code> <a href="#type"><code>Type</code></a></td><td><code>: <type></code> suffix when <code>value_type</code> is not the default <code>Int(I256)</code>; suppressed otherwise</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="vid"><a class="header" href="#vid"><code>v<id></code></a></h3>
|
||
<p>(<code>Expression::Var</code>)</p>
|
||
<h4 id="description-1"><a class="header" href="#description-1">Description</a></h4>
|
||
<p>A reference to an existing SSA value, used as the entire right-hand side of a <code>let</code>. In a typical dump this is rare because the simplifier collapses <code>let v := v<id></code> into the consumers of <code>v</code> via copy propagation; expect to see it only in dumps taken before simplification has run.</p>
|
||
<h4 id="syntax-1"><a class="header" href="#syntax-1">Syntax</a></h4>
|
||
<pre><code class="language-text">v<id>
|
||
</code></pre>
|
||
<h4 id="example-1"><a class="header" href="#example-1">Example</a></h4>
|
||
<pre><code class="language-text">let v5 := v3 // copy; usually eliminated by simplify
|
||
</code></pre>
|
||
<h4 id="operands-1"><a class="header" href="#operands-1">Operands</a></h4>
|
||
<p>None — the expression is the value reference itself.</p>
|
||
<h4 id="result-and-purity-1"><a class="header" href="#result-and-purity-1">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>Same as the referenced value’s type</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-1"><a class="header" href="#annotations-1">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="add"><a class="header" href="#add"><code>add</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Add</code>)</p>
|
||
<h4 id="description-2"><a class="header" href="#description-2">Description</a></h4>
|
||
<p>Modular addition. Wraps on overflow; per EVM, the result is <code>(lhs + rhs) mod 2^N</code> where <code>N</code> is the operand width.</p>
|
||
<h4 id="syntax-2"><a class="header" href="#syntax-2">Syntax</a></h4>
|
||
<pre><code class="language-text">add($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-2"><a class="header" href="#example-2">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := add(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-2"><a class="header" href="#operands-2">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-2"><a class="header" href="#result-and-purity-2">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>widen_by_one(max(width(lhs), width(rhs)))</code> — one tier above the wider operand to account for the carry bit</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-2"><a class="header" href="#annotations-2">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="sub"><a class="header" href="#sub"><code>sub</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Sub</code>)</p>
|
||
<h4 id="description-3"><a class="header" href="#description-3">Description</a></h4>
|
||
<p>Modular subtraction. Wraps on underflow; the result is <code>(lhs - rhs) mod 2^256</code> regardless of operand widths.</p>
|
||
<h4 id="syntax-3"><a class="header" href="#syntax-3">Syntax</a></h4>
|
||
<pre><code class="language-text">sub($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-3"><a class="header" href="#example-3">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := sub(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-3"><a class="header" href="#operands-3">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-3"><a class="header" href="#result-and-purity-3">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> — conservative; underflow on narrower operands could borrow into upper bits</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-3"><a class="header" href="#annotations-3">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="mul"><a class="header" href="#mul"><code>mul</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Mul</code>)</p>
|
||
<h4 id="description-4"><a class="header" href="#description-4">Description</a></h4>
|
||
<p>Modular multiplication. The result is <code>(lhs * rhs) mod 2^256</code>.</p>
|
||
<h4 id="syntax-4"><a class="header" href="#syntax-4">Syntax</a></h4>
|
||
<pre><code class="language-text">mul($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-4"><a class="header" href="#example-4">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := mul(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-4"><a class="header" href="#operands-4">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-4"><a class="header" href="#result-and-purity-4">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>double_width(max(width(lhs), width(rhs)))</code> — the tier holding twice the wider operand’s bits (skipping <code>i160</code> at the <code>i128</code> → <code>i256</code> transition)</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-4"><a class="header" href="#annotations-4">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="div"><a class="header" href="#div"><code>div</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Div</code>)</p>
|
||
<h4 id="description-5"><a class="header" href="#description-5">Description</a></h4>
|
||
<p>Unsigned integer division. Per EVM, <code>div(x, 0) = 0</code> (no trap on division by zero).</p>
|
||
<h4 id="syntax-5"><a class="header" href="#syntax-5">Syntax</a></h4>
|
||
<pre><code class="language-text">div($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-5"><a class="header" href="#example-5">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := div(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-5"><a class="header" href="#operands-5">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>Dividend.</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>Divisor; <code>0</code> yields a result of <code>0</code>, not a trap.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-5"><a class="header" href="#result-and-purity-5">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>width(lhs)</code> — the quotient cannot exceed the dividend</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-5"><a class="header" href="#annotations-5">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="sdiv"><a class="header" href="#sdiv"><code>sdiv</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::SDiv</code>)</p>
|
||
<h4 id="description-6"><a class="header" href="#description-6">Description</a></h4>
|
||
<p>Signed two’s-complement integer division. Per EVM, <code>sdiv(x, 0) = 0</code>; quotient is truncated toward zero.</p>
|
||
<h4 id="syntax-6"><a class="header" href="#syntax-6">Syntax</a></h4>
|
||
<pre><code class="language-text">sdiv($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-6"><a class="header" href="#example-6">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := sdiv(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-6"><a class="header" href="#operands-6">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>Dividend, treated as signed.</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>Divisor, treated as signed; <code>0</code> yields <code>0</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-6"><a class="header" href="#result-and-purity-6">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>max(width(lhs), width(rhs))</code> — a negative divisor can push the result to full width</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-6"><a class="header" href="#annotations-6">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="mod"><a class="header" href="#mod"><code>mod</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Mod</code>)</p>
|
||
<h4 id="description-7"><a class="header" href="#description-7">Description</a></h4>
|
||
<p>Unsigned modulo. Per EVM, <code>mod(x, 0) = 0</code>.</p>
|
||
<h4 id="syntax-7"><a class="header" href="#syntax-7">Syntax</a></h4>
|
||
<pre><code class="language-text">mod($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-7"><a class="header" href="#example-7">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := mod(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-7"><a class="header" href="#operands-7">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>Dividend.</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>Divisor; <code>0</code> yields <code>0</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-7"><a class="header" href="#result-and-purity-7">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>width(lhs)</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-7"><a class="header" href="#annotations-7">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="smod"><a class="header" href="#smod"><code>smod</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::SMod</code>)</p>
|
||
<h4 id="description-8"><a class="header" href="#description-8">Description</a></h4>
|
||
<p>Signed modulo. Per EVM, <code>smod(x, 0) = 0</code>; the result takes the sign of the dividend.</p>
|
||
<h4 id="syntax-8"><a class="header" href="#syntax-8">Syntax</a></h4>
|
||
<pre><code class="language-text">smod($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-8"><a class="header" href="#example-8">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := smod(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-8"><a class="header" href="#operands-8">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>Dividend, treated as signed.</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>Divisor, treated as signed; <code>0</code> yields <code>0</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-8"><a class="header" href="#result-and-purity-8">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>width(lhs)</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-8"><a class="header" href="#annotations-8">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="exp"><a class="header" href="#exp"><code>exp</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Exp</code>)</p>
|
||
<h4 id="description-9"><a class="header" href="#description-9">Description</a></h4>
|
||
<p>Modular exponentiation: <code>(base ^ exponent) mod 2^256</code>. The most expensive arithmetic opcode in EVM (variable gas cost proportional to the byte length of <code>exponent</code>).</p>
|
||
<h4 id="syntax-9"><a class="header" href="#syntax-9">Syntax</a></h4>
|
||
<pre><code class="language-text">exp($base[: <type>], $exponent[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-9"><a class="header" href="#example-9">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := exp(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-9"><a class="header" href="#operands-9">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>base</code></td><td><code>i256</code></td><td>Base.</td></tr>
|
||
<tr><td><code>exponent</code></td><td><code>i256</code></td><td>Exponent.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-9"><a class="header" href="#result-and-purity-9">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> — conservative; exponentiation can fill any width</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-9"><a class="header" href="#annotations-9">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="and"><a class="header" href="#and"><code>and</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::And</code>)</p>
|
||
<h4 id="description-10"><a class="header" href="#description-10">Description</a></h4>
|
||
<p>Bitwise AND. The common idiom for type narrowing: a constant mask on the right lets forward analysis pick up a tight result width.</p>
|
||
<h4 id="syntax-10"><a class="header" href="#syntax-10">Syntax</a></h4>
|
||
<pre><code class="language-text">and($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-10"><a class="header" href="#example-10">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := and(v0, v1)
|
||
let v3: i8 := 0xff
|
||
let v4: i8 := and(v0, v3: i8)
|
||
</code></pre>
|
||
<h4 id="operands-10"><a class="header" href="#operands-10">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-10"><a class="header" href="#result-and-purity-10">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>min(width(lhs), width(rhs))</code> — AND can only clear bits, so the result fits in the narrower operand</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-10"><a class="header" href="#annotations-10">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="or"><a class="header" href="#or"><code>or</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Or</code>)</p>
|
||
<h4 id="description-11"><a class="header" href="#description-11">Description</a></h4>
|
||
<p>Bitwise OR.</p>
|
||
<h4 id="syntax-11"><a class="header" href="#syntax-11">Syntax</a></h4>
|
||
<pre><code class="language-text">or($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-11"><a class="header" href="#example-11">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := or(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-11"><a class="header" href="#operands-11">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-11"><a class="header" href="#result-and-purity-11">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>max(width(lhs), width(rhs))</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-11"><a class="header" href="#annotations-11">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="xor"><a class="header" href="#xor"><code>xor</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Xor</code>)</p>
|
||
<h4 id="description-12"><a class="header" href="#description-12">Description</a></h4>
|
||
<p>Bitwise XOR.</p>
|
||
<h4 id="syntax-12"><a class="header" href="#syntax-12">Syntax</a></h4>
|
||
<pre><code class="language-text">xor($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-12"><a class="header" href="#example-12">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := xor(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-12"><a class="header" href="#operands-12">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-12"><a class="header" href="#result-and-purity-12">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>max(width(lhs), width(rhs))</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-12"><a class="header" href="#annotations-12">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="shl"><a class="header" href="#shl"><code>shl</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Shl</code>)</p>
|
||
<h4 id="description-13"><a class="header" href="#description-13">Description</a></h4>
|
||
<p>Logical left shift. Operand order follows EVM: <code>shl(shift, value)</code> computes <code>value << shift</code>. Shifts ≥ 256 produce <code>0</code>.</p>
|
||
<h4 id="syntax-13"><a class="header" href="#syntax-13">Syntax</a></h4>
|
||
<pre><code class="language-text">shl($shift[: <type>], $value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-13"><a class="header" href="#example-13">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := shl(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-13"><a class="header" href="#operands-13">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>shift</code></td><td><code>i256</code></td><td>Shift amount in bits.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Value to shift.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-13"><a class="header" href="#result-and-purity-13">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> — conservative; bits may shift into any width</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-13"><a class="header" href="#annotations-13">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="shr"><a class="header" href="#shr"><code>shr</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Shr</code>)</p>
|
||
<h4 id="description-14"><a class="header" href="#description-14">Description</a></h4>
|
||
<p>Logical right shift. Operand order follows EVM: <code>shr(shift, value)</code> computes <code>value >> shift</code> with zero-fill from the left. Shifts ≥ 256 produce <code>0</code>.</p>
|
||
<h4 id="syntax-14"><a class="header" href="#syntax-14">Syntax</a></h4>
|
||
<pre><code class="language-text">shr($shift[: <type>], $value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-14"><a class="header" href="#example-14">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := shr(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-14"><a class="header" href="#operands-14">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>shift</code></td><td><code>i256</code></td><td>Shift amount in bits.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Value to shift.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-14"><a class="header" href="#result-and-purity-14">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>If <code>shift</code> is a known constant <code>k</code>: tier holding <code>256 - k</code> bits (or <code>i1</code> for <code>k ≥ 256</code>). Otherwise: <code>width(value)</code>.</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-14"><a class="header" href="#annotations-14">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="sar"><a class="header" href="#sar"><code>sar</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Sar</code>)</p>
|
||
<h4 id="description-15"><a class="header" href="#description-15">Description</a></h4>
|
||
<p>Arithmetic (signed) right shift. Operand order follows EVM: <code>sar(shift, value)</code> shifts <code>value</code> right by <code>shift</code> bits, preserving the sign bit. Shifts ≥ 256 saturate to <code>0</code> for non-negative values and to <code>-1</code> (all-ones) for negative values.</p>
|
||
<h4 id="syntax-15"><a class="header" href="#syntax-15">Syntax</a></h4>
|
||
<pre><code class="language-text">sar($shift[: <type>], $value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-15"><a class="header" href="#example-15">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := sar(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-15"><a class="header" href="#operands-15">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>shift</code></td><td><code>i256</code></td><td>Shift amount in bits.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Value to shift, treated as signed.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-15"><a class="header" href="#result-and-purity-15">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>width(value)</code> — unlike <a href="#shr"><code>shr</code></a>, sign-extension means a constant shift cannot narrow the result</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-15"><a class="header" href="#annotations-15">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="lt"><a class="header" href="#lt"><code>lt</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Lt</code>)</p>
|
||
<h4 id="description-16"><a class="header" href="#description-16">Description</a></h4>
|
||
<p>Unsigned less-than comparison. Returns <code>1</code> if <code>lhs < rhs</code>, else <code>0</code>.</p>
|
||
<h4 id="syntax-16"><a class="header" href="#syntax-16">Syntax</a></h4>
|
||
<pre><code class="language-text">lt($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-16"><a class="header" href="#example-16">Example</a></h4>
|
||
<pre><code class="language-text">let v2: i1 := lt(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-16"><a class="header" href="#operands-16">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>Compared unsigned.</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>Compared unsigned.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-16"><a class="header" href="#result-and-purity-16">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i1</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-16"><a class="header" href="#annotations-16">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="gt"><a class="header" href="#gt"><code>gt</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Gt</code>)</p>
|
||
<h4 id="description-17"><a class="header" href="#description-17">Description</a></h4>
|
||
<p>Unsigned greater-than comparison. Returns <code>1</code> if <code>lhs > rhs</code>, else <code>0</code>.</p>
|
||
<h4 id="syntax-17"><a class="header" href="#syntax-17">Syntax</a></h4>
|
||
<pre><code class="language-text">gt($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-17"><a class="header" href="#example-17">Example</a></h4>
|
||
<pre><code class="language-text">let v2: i1 := gt(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-17"><a class="header" href="#operands-17">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>Compared unsigned.</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>Compared unsigned.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-17"><a class="header" href="#result-and-purity-17">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i1</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-17"><a class="header" href="#annotations-17">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="slt"><a class="header" href="#slt"><code>slt</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Slt</code>)</p>
|
||
<h4 id="description-18"><a class="header" href="#description-18">Description</a></h4>
|
||
<p>Signed less-than comparison. Operands are treated as two’s complement.</p>
|
||
<h4 id="syntax-18"><a class="header" href="#syntax-18">Syntax</a></h4>
|
||
<pre><code class="language-text">slt($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-18"><a class="header" href="#example-18">Example</a></h4>
|
||
<pre><code class="language-text">let v2: i1 := slt(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-18"><a class="header" href="#operands-18">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>Compared signed.</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>Compared signed.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-18"><a class="header" href="#result-and-purity-18">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i1</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-18"><a class="header" href="#annotations-18">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="sgt"><a class="header" href="#sgt"><code>sgt</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Sgt</code>)</p>
|
||
<h4 id="description-19"><a class="header" href="#description-19">Description</a></h4>
|
||
<p>Signed greater-than comparison. Operands are treated as two’s complement.</p>
|
||
<h4 id="syntax-19"><a class="header" href="#syntax-19">Syntax</a></h4>
|
||
<pre><code class="language-text">sgt($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-19"><a class="header" href="#example-19">Example</a></h4>
|
||
<pre><code class="language-text">let v2: i1 := sgt(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-19"><a class="header" href="#operands-19">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>Compared signed.</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>Compared signed.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-19"><a class="header" href="#result-and-purity-19">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i1</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-19"><a class="header" href="#annotations-19">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="eq"><a class="header" href="#eq"><code>eq</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Eq</code>)</p>
|
||
<h4 id="description-20"><a class="header" href="#description-20">Description</a></h4>
|
||
<p>Equality comparison. Returns <code>1</code> if <code>lhs == rhs</code>, else <code>0</code>. Signedness is irrelevant.</p>
|
||
<h4 id="syntax-20"><a class="header" href="#syntax-20">Syntax</a></h4>
|
||
<pre><code class="language-text">eq($lhs[: <type>], $rhs[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-20"><a class="header" href="#example-20">Example</a></h4>
|
||
<pre><code class="language-text">let v2: i1 := eq(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-20"><a class="header" href="#operands-20">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>lhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
<tr><td><code>rhs</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-20"><a class="header" href="#result-and-purity-20">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i1</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-20"><a class="header" href="#annotations-20">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="byte"><a class="header" href="#byte"><code>byte</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::Byte</code>)</p>
|
||
<h4 id="description-21"><a class="header" href="#description-21">Description</a></h4>
|
||
<p>Extract a single byte from a 256-bit word. <code>byte(i, x)</code> returns the <em>i</em>-th byte of <code>x</code> with byte 0 being the most significant. If <code>i ≥ 32</code>, the result is <code>0</code>.</p>
|
||
<h4 id="syntax-21"><a class="header" href="#syntax-21">Syntax</a></h4>
|
||
<pre><code class="language-text">byte($index[: <type>], $word[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-21"><a class="header" href="#example-21">Example</a></h4>
|
||
<pre><code class="language-text">let v2: i8 := byte(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-21"><a class="header" href="#operands-21">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>index</code></td><td><code>i256</code></td><td>Byte position; <code>0</code> = most significant byte. Values <code>≥ 32</code> yield <code>0</code>.</td></tr>
|
||
<tr><td><code>word</code></td><td><code>i256</code></td><td>Source word.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-21"><a class="header" href="#result-and-purity-21">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i8</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-21"><a class="header" href="#annotations-21">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="signextend"><a class="header" href="#signextend"><code>signextend</code></a></h3>
|
||
<p>(<code>Expression::Binary</code> with <code>BinaryOperation::SignExtend</code>)</p>
|
||
<h4 id="description-22"><a class="header" href="#description-22">Description</a></h4>
|
||
<p>Sign-extend an integer from a byte position. Per EVM, <code>signextend(b, x)</code> treats byte <code>b</code> of <code>x</code> as the most significant byte of a smaller signed integer and extends its sign through the upper bytes.</p>
|
||
<h4 id="syntax-22"><a class="header" href="#syntax-22">Syntax</a></h4>
|
||
<pre><code class="language-text">signextend($byte_position[: <type>], $value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-22"><a class="header" href="#example-22">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := signextend(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-22"><a class="header" href="#operands-22">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>byte_position</code></td><td><code>i256</code></td><td>Byte position of the sign byte (0–31).</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Source value.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-22"><a class="header" href="#result-and-purity-22">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> — the extended value occupies the full word</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-22"><a class="header" href="#annotations-22">Annotations</a></h4>
|
||
<p>The width-targeted sign-extension primitive <a href="#sextibits"><code>sext<i<bits>></code></a> (<code>Expression::SignExtendTo</code>) is a separate operation; see the bit-width conversions section.</p>
|
||
<h3 id="addmod"><a class="header" href="#addmod"><code>addmod</code></a></h3>
|
||
<p>(<code>Expression::Ternary</code> with <code>BinaryOperation::AddMod</code>)</p>
|
||
<h4 id="description-23"><a class="header" href="#description-23">Description</a></h4>
|
||
<p>Ternary modular addition: <code>(a + b) mod n</code>, computed without intermediate overflow. Per EVM, <code>n = 0</code> yields <code>0</code>.</p>
|
||
<h4 id="syntax-23"><a class="header" href="#syntax-23">Syntax</a></h4>
|
||
<pre><code class="language-text">addmod($a[: <type>], $b[: <type>], $n[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-23"><a class="header" href="#example-23">Example</a></h4>
|
||
<pre><code class="language-text">let v3 := addmod(v0, v1, v2)
|
||
</code></pre>
|
||
<h4 id="operands-23"><a class="header" href="#operands-23">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>a</code></td><td><code>i256</code></td><td>First addend.</td></tr>
|
||
<tr><td><code>b</code></td><td><code>i256</code></td><td>Second addend.</td></tr>
|
||
<tr><td><code>n</code></td><td><code>i256</code></td><td>Modulus; <code>0</code> yields <code>0</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-23"><a class="header" href="#result-and-purity-23">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> — conservative</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-23"><a class="header" href="#annotations-23">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="mulmod"><a class="header" href="#mulmod"><code>mulmod</code></a></h3>
|
||
<p>(<code>Expression::Ternary</code> with <code>BinaryOperation::MulMod</code>)</p>
|
||
<h4 id="description-24"><a class="header" href="#description-24">Description</a></h4>
|
||
<p>Ternary modular multiplication: <code>(a * b) mod n</code>, computed without intermediate overflow. Per EVM, <code>n = 0</code> yields <code>0</code>.</p>
|
||
<h4 id="syntax-24"><a class="header" href="#syntax-24">Syntax</a></h4>
|
||
<pre><code class="language-text">mulmod($a[: <type>], $b[: <type>], $n[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-24"><a class="header" href="#example-24">Example</a></h4>
|
||
<pre><code class="language-text">let v3 := mulmod(v0, v1, v2)
|
||
</code></pre>
|
||
<h4 id="operands-24"><a class="header" href="#operands-24">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>a</code></td><td><code>i256</code></td><td>First factor.</td></tr>
|
||
<tr><td><code>b</code></td><td><code>i256</code></td><td>Second factor.</td></tr>
|
||
<tr><td><code>n</code></td><td><code>i256</code></td><td>Modulus; <code>0</code> yields <code>0</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-24"><a class="header" href="#result-and-purity-24">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> — conservative</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-24"><a class="header" href="#annotations-24">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="iszero"><a class="header" href="#iszero"><code>iszero</code></a></h3>
|
||
<p>(<code>Expression::Unary</code> with <code>UnaryOperation::IsZero</code>)</p>
|
||
<h4 id="description-25"><a class="header" href="#description-25">Description</a></h4>
|
||
<p>Returns <code>1</code> if the operand is <code>0</code>, else <code>0</code>. Also serves as the logical NOT for boolean values.</p>
|
||
<h4 id="syntax-25"><a class="header" href="#syntax-25">Syntax</a></h4>
|
||
<pre><code class="language-text">iszero($operand[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-25"><a class="header" href="#example-25">Example</a></h4>
|
||
<pre><code class="language-text">let v1: i1 := iszero(v0)
|
||
</code></pre>
|
||
<h4 id="operands-25"><a class="header" href="#operands-25">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>operand</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-25"><a class="header" href="#result-and-purity-25">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i1</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-25"><a class="header" href="#annotations-25">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="not"><a class="header" href="#not"><code>not</code></a></h3>
|
||
<p>(<code>Expression::Unary</code> with <code>UnaryOperation::Not</code>)</p>
|
||
<h4 id="description-26"><a class="header" href="#description-26">Description</a></h4>
|
||
<p>Bitwise complement. Inverts every bit; equivalent to <code>xor(operand, 2^256 - 1)</code>.</p>
|
||
<h4 id="syntax-26"><a class="header" href="#syntax-26">Syntax</a></h4>
|
||
<pre><code class="language-text">not($operand[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-26"><a class="header" href="#example-26">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := not(v0)
|
||
</code></pre>
|
||
<h4 id="operands-26"><a class="header" href="#operands-26">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>operand</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-26"><a class="header" href="#result-and-purity-26">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> — the complement fills the full word regardless of operand width</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-26"><a class="header" href="#annotations-26">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="clz"><a class="header" href="#clz"><code>clz</code></a></h3>
|
||
<p>(<code>Expression::Unary</code> with <code>UnaryOperation::Clz</code>)</p>
|
||
<h4 id="description-27"><a class="header" href="#description-27">Description</a></h4>
|
||
<p>Count leading zeros. Returns the number of leading zero bits in the operand, where a value of <code>0</code> returns <code>256</code> (the full width). Not an EVM opcode; reaches newyork as a Yul builtin (<code>FunctionName::Clz</code>) and is translated directly by the Yul-to-newyork translator.</p>
|
||
<h4 id="syntax-27"><a class="header" href="#syntax-27">Syntax</a></h4>
|
||
<pre><code class="language-text">clz($operand[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-27"><a class="header" href="#example-27">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := clz(v0)
|
||
</code></pre>
|
||
<h4 id="operands-27"><a class="header" href="#operands-27">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>operand</code></td><td><code>i256</code></td><td>—</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-27"><a class="header" href="#result-and-purity-27">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> — in practice the value fits in nine bits (max <code>256</code>), so type inference often narrows further</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-27"><a class="header" href="#annotations-27">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="truncateibits"><a class="header" href="#truncateibits"><code>truncate<i<bits>></code></a></h3>
|
||
<p>(<code>Expression::Truncate</code>)</p>
|
||
<h4 id="description-28"><a class="header" href="#description-28">Description</a></h4>
|
||
<p>Reinterpret a wider integer as a narrower one by discarding the upper bits. The destination width is carried in the IR’s <code>to: BitWidth</code> field and is rendered inside the angle brackets of the printer mnemonic. Narrowing-only; the source width must be greater than or equal to the destination width.</p>
|
||
<h4 id="syntax-28"><a class="header" href="#syntax-28">Syntax</a></h4>
|
||
<pre><code class="language-text">truncate<i<bits>>($value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-28"><a class="header" href="#example-28">Example</a></h4>
|
||
<pre><code class="language-text">let v1: i64 := truncate<i64>(v0)
|
||
let v2: i8 := truncate<i8>(v1: i64)
|
||
</code></pre>
|
||
<h4 id="operands-28"><a class="header" href="#operands-28">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Source value; must be at least as wide as the destination.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-28"><a class="header" href="#result-and-purity-28">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>The destination width from the <code>to</code> field</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-28"><a class="header" href="#annotations-28">Annotations</a></h4>
|
||
<p>None. The destination width is part of the operation name, not a debug annotation.</p>
|
||
<h3 id="zextibits"><a class="header" href="#zextibits"><code>zext<i<bits>></code></a></h3>
|
||
<p>(<code>Expression::ZeroExtend</code>)</p>
|
||
<h4 id="description-29"><a class="header" href="#description-29">Description</a></h4>
|
||
<p>Reinterpret a narrower integer as a wider one by zero-filling the upper bits. The destination width is carried in the IR’s <code>to: BitWidth</code> field. Widening-only.</p>
|
||
<h4 id="syntax-29"><a class="header" href="#syntax-29">Syntax</a></h4>
|
||
<pre><code class="language-text">zext<i<bits>>($value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-29"><a class="header" href="#example-29">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := zext<i256>(v0: i8)
|
||
</code></pre>
|
||
<h4 id="operands-29"><a class="header" href="#operands-29">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Source value; must be no wider than the destination.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-29"><a class="header" href="#result-and-purity-29">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>The destination width from the <code>to</code> field</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-29"><a class="header" href="#annotations-29">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="sextibits"><a class="header" href="#sextibits"><code>sext<i<bits>></code></a></h3>
|
||
<p>(<code>Expression::SignExtendTo</code>)</p>
|
||
<h4 id="description-30"><a class="header" href="#description-30">Description</a></h4>
|
||
<p>Reinterpret a narrower signed integer as a wider one by sign-extending the high bit. The destination width is carried in the IR’s <code>to: BitWidth</code> field. Distinct from <a href="#signextend"><code>signextend</code></a> (<code>Expression::Binary</code>), which is the EVM byte-position primitive; this one specifies the destination width directly and is introduced by passes that produce a sign-extended value at a known target width.</p>
|
||
<h4 id="syntax-30"><a class="header" href="#syntax-30">Syntax</a></h4>
|
||
<pre><code class="language-text">sext<i<bits>>($value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-30"><a class="header" href="#example-30">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := sext<i256>(v0: i64)
|
||
</code></pre>
|
||
<h4 id="operands-30"><a class="header" href="#operands-30">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Source value; must be no wider than the destination.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-30"><a class="header" href="#result-and-purity-30">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>The destination width from the <code>to</code> field</td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-30"><a class="header" href="#annotations-30">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="keccak256"><a class="header" href="#keccak256"><code>keccak256</code></a></h3>
|
||
<p>(<code>Expression::Keccak256</code>)</p>
|
||
<h4 id="description-31"><a class="header" href="#description-31">Description</a></h4>
|
||
<p>Compute the Keccak-256 hash of <code>length</code> bytes of emulated EVM linear memory starting at <code>offset</code>. The general-purpose hashing primitive; the specialized variants below cover the common scratch-space patterns more compactly.</p>
|
||
<h4 id="syntax-31"><a class="header" href="#syntax-31">Syntax</a></h4>
|
||
<pre><code class="language-text">keccak256($offset[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-31"><a class="header" href="#example-31">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := keccak256(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-31"><a class="header" href="#operands-31">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Byte offset into linear memory; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Length of the region to hash, in bytes; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-31"><a class="header" href="#result-and-purity-31">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure — the hash is a deterministic function of the memory contents at evaluation time. Passes that hoist or dedupe must respect intervening memory writes.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-31"><a class="header" href="#annotations-31">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="keccak256_pair"><a class="header" href="#keccak256_pair"><code>keccak256_pair</code></a></h3>
|
||
<p>(<code>Expression::Keccak256Pair</code>)</p>
|
||
<h4 id="description-32"><a class="header" href="#description-32">Description</a></h4>
|
||
<p>Compound hash of two 256-bit words. Equivalent to <code>mstore(0, word0); mstore(32, word1); keccak256(0, 64)</code> but emitted as a single outlined call after <code>mem_opt</code>’s keccak fusion recognizes the pattern. The mapping-key idiom; see also <a href="#mapping_sload"><code>mapping_sload</code></a>.</p>
|
||
<h4 id="syntax-32"><a class="header" href="#syntax-32">Syntax</a></h4>
|
||
<pre><code class="language-text">keccak256_pair($word0[: <type>], $word1[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-32"><a class="header" href="#example-32">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := keccak256_pair(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-32"><a class="header" href="#operands-32">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>word0</code></td><td><code>i256</code></td><td>First word; the high 32 bytes of the hash input.</td></tr>
|
||
<tr><td><code>word1</code></td><td><code>i256</code></td><td>Second word; the low 32 bytes of the hash input.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-32"><a class="header" href="#result-and-purity-32">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-32"><a class="header" href="#annotations-32">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="keccak256_single"><a class="header" href="#keccak256_single"><code>keccak256_single</code></a></h3>
|
||
<p>(<code>Expression::Keccak256Single</code>)</p>
|
||
<h4 id="description-33"><a class="header" href="#description-33">Description</a></h4>
|
||
<p>Compound hash of a single 256-bit word. Equivalent to <code>mstore(0, word0); keccak256(0, 32)</code> but emitted as a single outlined call after <code>mem_opt</code>’s keccak fusion.</p>
|
||
<h4 id="syntax-33"><a class="header" href="#syntax-33">Syntax</a></h4>
|
||
<pre><code class="language-text">keccak256_single($word0[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-33"><a class="header" href="#example-33">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := keccak256_single(v0)
|
||
</code></pre>
|
||
<h4 id="operands-33"><a class="header" href="#operands-33">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>word0</code></td><td><code>i256</code></td><td>The word to hash.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-33"><a class="header" href="#result-and-purity-33">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-33"><a class="header" href="#annotations-33">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="caller"><a class="header" href="#caller"><code>caller</code></a></h3>
|
||
<p>(<code>Expression::Caller</code>)</p>
|
||
<h4 id="description-34"><a class="header" href="#description-34">Description</a></h4>
|
||
<p>Address of the immediate caller of the current call frame.</p>
|
||
<h4 id="syntax-34"><a class="header" href="#syntax-34">Syntax</a></h4>
|
||
<pre><code class="language-text">caller()
|
||
</code></pre>
|
||
<h4 id="example-34"><a class="header" href="#example-34">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i160 := caller()
|
||
</code></pre>
|
||
<h4 id="operands-34"><a class="header" href="#operands-34">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-34"><a class="header" href="#result-and-purity-34">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i160</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-34"><a class="header" href="#annotations-34">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="callvalue"><a class="header" href="#callvalue"><code>callvalue</code></a></h3>
|
||
<p>(<code>Expression::CallValue</code>)</p>
|
||
<h4 id="description-35"><a class="header" href="#description-35">Description</a></h4>
|
||
<p>Value (wei) attached to the current call.</p>
|
||
<h4 id="syntax-35"><a class="header" href="#syntax-35">Syntax</a></h4>
|
||
<pre><code class="language-text">callvalue()
|
||
</code></pre>
|
||
<h4 id="example-35"><a class="header" href="#example-35">Example</a></h4>
|
||
<pre><code class="language-text">let v0 := callvalue()
|
||
</code></pre>
|
||
<h4 id="operands-35"><a class="header" href="#operands-35">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-35"><a class="header" href="#result-and-purity-35">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-35"><a class="header" href="#annotations-35">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="origin"><a class="header" href="#origin"><code>origin</code></a></h3>
|
||
<p>(<code>Expression::Origin</code>)</p>
|
||
<h4 id="description-36"><a class="header" href="#description-36">Description</a></h4>
|
||
<p>Address of the original externally owned account that initiated the transaction.</p>
|
||
<h4 id="syntax-36"><a class="header" href="#syntax-36">Syntax</a></h4>
|
||
<pre><code class="language-text">origin()
|
||
</code></pre>
|
||
<h4 id="example-36"><a class="header" href="#example-36">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i160 := origin()
|
||
</code></pre>
|
||
<h4 id="operands-36"><a class="header" href="#operands-36">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-36"><a class="header" href="#result-and-purity-36">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i160</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-36"><a class="header" href="#annotations-36">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="address"><a class="header" href="#address"><code>address</code></a></h3>
|
||
<p>(<code>Expression::Address</code>)</p>
|
||
<h4 id="description-37"><a class="header" href="#description-37">Description</a></h4>
|
||
<p>Address of the contract executing the current call frame.</p>
|
||
<h4 id="syntax-37"><a class="header" href="#syntax-37">Syntax</a></h4>
|
||
<pre><code class="language-text">address()
|
||
</code></pre>
|
||
<h4 id="example-37"><a class="header" href="#example-37">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i160 := address()
|
||
</code></pre>
|
||
<h4 id="operands-37"><a class="header" href="#operands-37">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-37"><a class="header" href="#result-and-purity-37">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i160</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-37"><a class="header" href="#annotations-37">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="chainid"><a class="header" href="#chainid"><code>chainid</code></a></h3>
|
||
<p>(<code>Expression::ChainId</code>)</p>
|
||
<h4 id="description-38"><a class="header" href="#description-38">Description</a></h4>
|
||
<p>Chain identifier of the network the contract is executing on.</p>
|
||
<h4 id="syntax-38"><a class="header" href="#syntax-38">Syntax</a></h4>
|
||
<pre><code class="language-text">chainid()
|
||
</code></pre>
|
||
<h4 id="example-38"><a class="header" href="#example-38">Example</a></h4>
|
||
<pre><code class="language-text">let v0 := chainid()
|
||
</code></pre>
|
||
<h4 id="operands-38"><a class="header" href="#operands-38">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-38"><a class="header" href="#result-and-purity-38">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-38"><a class="header" href="#annotations-38">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="gas"><a class="header" href="#gas"><code>gas</code></a></h3>
|
||
<p>(<code>Expression::Gas</code>)</p>
|
||
<h4 id="description-39"><a class="header" href="#description-39">Description</a></h4>
|
||
<p>Remaining gas at the point of evaluation. Modeled as a pure expression for IR purposes; in practice it changes between evaluations, so any simplifier that deduplicates pure expressions must respect <code>gas</code> as a barrier.</p>
|
||
<h4 id="syntax-39"><a class="header" href="#syntax-39">Syntax</a></h4>
|
||
<pre><code class="language-text">gas()
|
||
</code></pre>
|
||
<h4 id="example-39"><a class="header" href="#example-39">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i64 := gas()
|
||
</code></pre>
|
||
<h4 id="operands-39"><a class="header" href="#operands-39">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-39"><a class="header" href="#result-and-purity-39">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Pure (per IR; see Description)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-39"><a class="header" href="#annotations-39">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="msize"><a class="header" href="#msize"><code>msize</code></a></h3>
|
||
<p>(<code>Expression::MSize</code>)</p>
|
||
<h4 id="description-40"><a class="header" href="#description-40">Description</a></h4>
|
||
<p>Highest byte offset of emulated EVM linear memory that has been touched, rounded up to the next 32-byte boundary. Unlike <a href="#gas"><code>gas</code></a>, classified as side-effectful by the simplifier: unused <code>msize()</code> bindings are not eliminated, because the result depends on the program’s memory-access history and would change if the surrounding statements were reordered.</p>
|
||
<h4 id="syntax-40"><a class="header" href="#syntax-40">Syntax</a></h4>
|
||
<pre><code class="language-text">msize()
|
||
</code></pre>
|
||
<h4 id="example-40"><a class="header" href="#example-40">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i64 := msize()
|
||
</code></pre>
|
||
<h4 id="operands-40"><a class="header" href="#operands-40">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-40"><a class="header" href="#result-and-purity-40">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Effectful (see Description)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-40"><a class="header" href="#annotations-40">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="coinbase"><a class="header" href="#coinbase"><code>coinbase</code></a></h3>
|
||
<p>(<code>Expression::Coinbase</code>)</p>
|
||
<h4 id="description-41"><a class="header" href="#description-41">Description</a></h4>
|
||
<p>Address of the block’s coinbase (block author).</p>
|
||
<h4 id="syntax-41"><a class="header" href="#syntax-41">Syntax</a></h4>
|
||
<pre><code class="language-text">coinbase()
|
||
</code></pre>
|
||
<h4 id="example-41"><a class="header" href="#example-41">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i160 := coinbase()
|
||
</code></pre>
|
||
<h4 id="operands-41"><a class="header" href="#operands-41">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-41"><a class="header" href="#result-and-purity-41">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i160</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-41"><a class="header" href="#annotations-41">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="timestamp"><a class="header" href="#timestamp"><code>timestamp</code></a></h3>
|
||
<p>(<code>Expression::Timestamp</code>)</p>
|
||
<h4 id="description-42"><a class="header" href="#description-42">Description</a></h4>
|
||
<p>Block timestamp, as a Unix epoch second.</p>
|
||
<h4 id="syntax-42"><a class="header" href="#syntax-42">Syntax</a></h4>
|
||
<pre><code class="language-text">timestamp()
|
||
</code></pre>
|
||
<h4 id="example-42"><a class="header" href="#example-42">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i64 := timestamp()
|
||
</code></pre>
|
||
<h4 id="operands-42"><a class="header" href="#operands-42">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-42"><a class="header" href="#result-and-purity-42">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-42"><a class="header" href="#annotations-42">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="number"><a class="header" href="#number"><code>number</code></a></h3>
|
||
<p>(<code>Expression::Number</code>)</p>
|
||
<h4 id="description-43"><a class="header" href="#description-43">Description</a></h4>
|
||
<p>Current block number.</p>
|
||
<h4 id="syntax-43"><a class="header" href="#syntax-43">Syntax</a></h4>
|
||
<pre><code class="language-text">number()
|
||
</code></pre>
|
||
<h4 id="example-43"><a class="header" href="#example-43">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i64 := number()
|
||
</code></pre>
|
||
<h4 id="operands-43"><a class="header" href="#operands-43">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-43"><a class="header" href="#result-and-purity-43">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-43"><a class="header" href="#annotations-43">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="difficulty"><a class="header" href="#difficulty"><code>difficulty</code></a></h3>
|
||
<p>(<code>Expression::Difficulty</code>)</p>
|
||
<h4 id="description-44"><a class="header" href="#description-44">Description</a></h4>
|
||
<p>Pre-merge block difficulty. On post-merge chains this is the block’s <code>prevrandao</code> value.</p>
|
||
<h4 id="syntax-44"><a class="header" href="#syntax-44">Syntax</a></h4>
|
||
<pre><code class="language-text">difficulty()
|
||
</code></pre>
|
||
<h4 id="example-44"><a class="header" href="#example-44">Example</a></h4>
|
||
<pre><code class="language-text">let v0 := difficulty()
|
||
</code></pre>
|
||
<h4 id="operands-44"><a class="header" href="#operands-44">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-44"><a class="header" href="#result-and-purity-44">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-44"><a class="header" href="#annotations-44">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="gaslimit"><a class="header" href="#gaslimit"><code>gaslimit</code></a></h3>
|
||
<p>(<code>Expression::GasLimit</code>)</p>
|
||
<h4 id="description-45"><a class="header" href="#description-45">Description</a></h4>
|
||
<p>Block gas limit.</p>
|
||
<h4 id="syntax-45"><a class="header" href="#syntax-45">Syntax</a></h4>
|
||
<pre><code class="language-text">gaslimit()
|
||
</code></pre>
|
||
<h4 id="example-45"><a class="header" href="#example-45">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i64 := gaslimit()
|
||
</code></pre>
|
||
<h4 id="operands-45"><a class="header" href="#operands-45">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-45"><a class="header" href="#result-and-purity-45">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-45"><a class="header" href="#annotations-45">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="basefee"><a class="header" href="#basefee"><code>basefee</code></a></h3>
|
||
<p>(<code>Expression::BaseFee</code>)</p>
|
||
<h4 id="description-46"><a class="header" href="#description-46">Description</a></h4>
|
||
<p>Current block’s EIP-1559 base fee per gas.</p>
|
||
<h4 id="syntax-46"><a class="header" href="#syntax-46">Syntax</a></h4>
|
||
<pre><code class="language-text">basefee()
|
||
</code></pre>
|
||
<h4 id="example-46"><a class="header" href="#example-46">Example</a></h4>
|
||
<pre><code class="language-text">let v0 := basefee()
|
||
</code></pre>
|
||
<h4 id="operands-46"><a class="header" href="#operands-46">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-46"><a class="header" href="#result-and-purity-46">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-46"><a class="header" href="#annotations-46">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="blobbasefee"><a class="header" href="#blobbasefee"><code>blobbasefee</code></a></h3>
|
||
<p>(<code>Expression::BlobBaseFee</code>)</p>
|
||
<h4 id="description-47"><a class="header" href="#description-47">Description</a></h4>
|
||
<p>Current block’s EIP-4844 blob base fee per gas.</p>
|
||
<h4 id="syntax-47"><a class="header" href="#syntax-47">Syntax</a></h4>
|
||
<pre><code class="language-text">blobbasefee()
|
||
</code></pre>
|
||
<h4 id="example-47"><a class="header" href="#example-47">Example</a></h4>
|
||
<pre><code class="language-text">let v0 := blobbasefee()
|
||
</code></pre>
|
||
<h4 id="operands-47"><a class="header" href="#operands-47">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-47"><a class="header" href="#result-and-purity-47">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-47"><a class="header" href="#annotations-47">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="blobhash"><a class="header" href="#blobhash"><code>blobhash</code></a></h3>
|
||
<p>(<code>Expression::BlobHash</code>)</p>
|
||
<h4 id="description-48"><a class="header" href="#description-48">Description</a></h4>
|
||
<p>Versioned hash of the blob at the given index in the current transaction’s blob list.</p>
|
||
<h4 id="syntax-48"><a class="header" href="#syntax-48">Syntax</a></h4>
|
||
<pre><code class="language-text">blobhash($index[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-48"><a class="header" href="#example-48">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := blobhash(v0)
|
||
</code></pre>
|
||
<h4 id="operands-48"><a class="header" href="#operands-48">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>index</code></td><td><code>i256</code></td><td>Blob index; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-48"><a class="header" href="#result-and-purity-48">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-48"><a class="header" href="#annotations-48">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="blockhash"><a class="header" href="#blockhash"><code>blockhash</code></a></h3>
|
||
<p>(<code>Expression::BlockHash</code>)</p>
|
||
<h4 id="description-49"><a class="header" href="#description-49">Description</a></h4>
|
||
<p>Hash of the block with the given number. Per EVM, valid only for the most recent 256 blocks; outside that range the result is <code>0</code>.</p>
|
||
<h4 id="syntax-49"><a class="header" href="#syntax-49">Syntax</a></h4>
|
||
<pre><code class="language-text">blockhash($number[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-49"><a class="header" href="#example-49">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := blockhash(v0)
|
||
</code></pre>
|
||
<h4 id="operands-49"><a class="header" href="#operands-49">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>number</code></td><td><code>i256</code></td><td>Block number; forward analysis widens to <code>i256</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-49"><a class="header" href="#result-and-purity-49">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-49"><a class="header" href="#annotations-49">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="selfbalance"><a class="header" href="#selfbalance"><code>selfbalance</code></a></h3>
|
||
<p>(<code>Expression::SelfBalance</code>)</p>
|
||
<h4 id="description-50"><a class="header" href="#description-50">Description</a></h4>
|
||
<p>Balance (in wei) of the contract executing the current call frame. Cheaper than <code>balance(address())</code>.</p>
|
||
<h4 id="syntax-50"><a class="header" href="#syntax-50">Syntax</a></h4>
|
||
<pre><code class="language-text">selfbalance()
|
||
</code></pre>
|
||
<h4 id="example-50"><a class="header" href="#example-50">Example</a></h4>
|
||
<pre><code class="language-text">let v0 := selfbalance()
|
||
</code></pre>
|
||
<h4 id="operands-50"><a class="header" href="#operands-50">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-50"><a class="header" href="#result-and-purity-50">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-50"><a class="header" href="#annotations-50">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="gasprice"><a class="header" href="#gasprice"><code>gasprice</code></a></h3>
|
||
<p>(<code>Expression::GasPrice</code>)</p>
|
||
<h4 id="description-51"><a class="header" href="#description-51">Description</a></h4>
|
||
<p>Effective gas price of the current transaction.</p>
|
||
<h4 id="syntax-51"><a class="header" href="#syntax-51">Syntax</a></h4>
|
||
<pre><code class="language-text">gasprice()
|
||
</code></pre>
|
||
<h4 id="example-51"><a class="header" href="#example-51">Example</a></h4>
|
||
<pre><code class="language-text">let v0 := gasprice()
|
||
</code></pre>
|
||
<h4 id="operands-51"><a class="header" href="#operands-51">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-51"><a class="header" href="#result-and-purity-51">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-51"><a class="header" href="#annotations-51">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="calldataload"><a class="header" href="#calldataload"><code>calldataload</code></a></h3>
|
||
<p>(<code>Expression::CallDataLoad</code>)</p>
|
||
<h4 id="description-52"><a class="header" href="#description-52">Description</a></h4>
|
||
<p>Read 32 bytes from the current call’s calldata at the given offset. Reads past the end of calldata return zero bytes.</p>
|
||
<h4 id="syntax-52"><a class="header" href="#syntax-52">Syntax</a></h4>
|
||
<pre><code class="language-text">calldataload($offset[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-52"><a class="header" href="#example-52">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := calldataload(v0)
|
||
</code></pre>
|
||
<h4 id="operands-52"><a class="header" href="#operands-52">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Byte offset into calldata.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-52"><a class="header" href="#result-and-purity-52">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-52"><a class="header" href="#annotations-52">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="calldatasize"><a class="header" href="#calldatasize"><code>calldatasize</code></a></h3>
|
||
<p>(<code>Expression::CallDataSize</code>)</p>
|
||
<h4 id="description-53"><a class="header" href="#description-53">Description</a></h4>
|
||
<p>Length of the current call’s calldata, in bytes.</p>
|
||
<h4 id="syntax-53"><a class="header" href="#syntax-53">Syntax</a></h4>
|
||
<pre><code class="language-text">calldatasize()
|
||
</code></pre>
|
||
<h4 id="example-53"><a class="header" href="#example-53">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i64 := calldatasize()
|
||
</code></pre>
|
||
<h4 id="operands-53"><a class="header" href="#operands-53">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-53"><a class="header" href="#result-and-purity-53">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-53"><a class="header" href="#annotations-53">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="returndatasize"><a class="header" href="#returndatasize"><code>returndatasize</code></a></h3>
|
||
<p>(<code>Expression::ReturnDataSize</code>)</p>
|
||
<h4 id="description-54"><a class="header" href="#description-54">Description</a></h4>
|
||
<p>Length of the most recently returned data buffer from a sub-call, in bytes. Modeled as pure per IR but reflects the last <code>ExternalCall</code> / <code>Create</code> result; consumers must respect that ordering.</p>
|
||
<h4 id="syntax-54"><a class="header" href="#syntax-54">Syntax</a></h4>
|
||
<pre><code class="language-text">returndatasize()
|
||
</code></pre>
|
||
<h4 id="example-54"><a class="header" href="#example-54">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i64 := returndatasize()
|
||
</code></pre>
|
||
<h4 id="operands-54"><a class="header" href="#operands-54">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-54"><a class="header" href="#result-and-purity-54">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Pure (per IR; see Description)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-54"><a class="header" href="#annotations-54">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="codesize"><a class="header" href="#codesize"><code>codesize</code></a></h3>
|
||
<p>(<code>Expression::CodeSize</code>)</p>
|
||
<h4 id="description-55"><a class="header" href="#description-55">Description</a></h4>
|
||
<p>Size of the currently executing code, in bytes.</p>
|
||
<h4 id="syntax-55"><a class="header" href="#syntax-55">Syntax</a></h4>
|
||
<pre><code class="language-text">codesize()
|
||
</code></pre>
|
||
<h4 id="example-55"><a class="header" href="#example-55">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i64 := codesize()
|
||
</code></pre>
|
||
<h4 id="operands-55"><a class="header" href="#operands-55">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-55"><a class="header" href="#result-and-purity-55">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-55"><a class="header" href="#annotations-55">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="extcodesize"><a class="header" href="#extcodesize"><code>extcodesize</code></a></h3>
|
||
<p>(<code>Expression::ExtCodeSize</code>)</p>
|
||
<h4 id="description-56"><a class="header" href="#description-56">Description</a></h4>
|
||
<p>Size of the code deployed at the given address, in bytes. Returns <code>0</code> for accounts with no deployed code.</p>
|
||
<h4 id="syntax-56"><a class="header" href="#syntax-56">Syntax</a></h4>
|
||
<pre><code class="language-text">extcodesize($address[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-56"><a class="header" href="#example-56">Example</a></h4>
|
||
<pre><code class="language-text">let v1: i64 := extcodesize(v0: i160)
|
||
</code></pre>
|
||
<h4 id="operands-56"><a class="header" href="#operands-56">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>address</code></td><td><code>i256</code></td><td>Account address; forward analysis widens to at least <code>i160</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-56"><a class="header" href="#result-and-purity-56">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-56"><a class="header" href="#annotations-56">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="extcodehash"><a class="header" href="#extcodehash"><code>extcodehash</code></a></h3>
|
||
<p>(<code>Expression::ExtCodeHash</code>)</p>
|
||
<h4 id="description-57"><a class="header" href="#description-57">Description</a></h4>
|
||
<p>Keccak-256 hash of the code deployed at the given address. Returns <code>0</code> for non-existent accounts.</p>
|
||
<h4 id="syntax-57"><a class="header" href="#syntax-57">Syntax</a></h4>
|
||
<pre><code class="language-text">extcodehash($address[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-57"><a class="header" href="#example-57">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := extcodehash(v0: i160)
|
||
</code></pre>
|
||
<h4 id="operands-57"><a class="header" href="#operands-57">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>address</code></td><td><code>i256</code></td><td>Account address; forward analysis widens to at least <code>i160</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-57"><a class="header" href="#result-and-purity-57">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-57"><a class="header" href="#annotations-57">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="balance"><a class="header" href="#balance"><code>balance</code></a></h3>
|
||
<p>(<code>Expression::Balance</code>)</p>
|
||
<h4 id="description-58"><a class="header" href="#description-58">Description</a></h4>
|
||
<p>Balance (in wei) of the given account address. Use <a href="#selfbalance"><code>selfbalance</code></a> for the contract executing the current call frame (cheaper).</p>
|
||
<h4 id="syntax-58"><a class="header" href="#syntax-58">Syntax</a></h4>
|
||
<pre><code class="language-text">balance($address[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-58"><a class="header" href="#example-58">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := balance(v0: i160)
|
||
</code></pre>
|
||
<h4 id="operands-58"><a class="header" href="#operands-58">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>address</code></td><td><code>i256</code></td><td>Account address; forward analysis widens to at least <code>i160</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-58"><a class="header" href="#result-and-purity-58">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-58"><a class="header" href="#annotations-58">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="mload"><a class="header" href="#mload"><code>mload</code></a></h3>
|
||
<p>(<code>Expression::MLoad</code>)</p>
|
||
<h4 id="description-59"><a class="header" href="#description-59">Description</a></h4>
|
||
<p>Read a 32-byte word from emulated EVM linear memory at <code>offset</code>. The word is read big-endian per EVM semantics. Pure per IR, but reads after writes return the new value; the memory passes track read/write dependencies separately.</p>
|
||
<h4 id="syntax-59"><a class="header" href="#syntax-59">Syntax</a></h4>
|
||
<pre><code class="language-text">mload($offset[: <type>]) [/* <region> */]
|
||
</code></pre>
|
||
<h4 id="example-59"><a class="header" href="#example-59">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := mload(v0: i64)
|
||
let v2: i32 := mload(v3: i64) /* free_ptr */
|
||
</code></pre>
|
||
<h4 id="operands-59"><a class="header" href="#operands-59">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Byte offset into linear memory; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-59"><a class="header" href="#result-and-purity-59">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i32</code> when region is <code>FreePointerSlot</code>; <code>i256</code> otherwise</td><td>Pure (per IR; see Description)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-59"><a class="header" href="#annotations-59">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>region:</code> <a href="#memoryregion"><code>MemoryRegion</code></a></td><td><code>/* scratch */</code> · <code>/* free_ptr */</code> · <code>/* dynamic */</code> (<code>Unknown</code> is suppressed)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p>Same tagging rules as <a href="#mstore"><code>mstore</code></a>. The region also determines the result width: a load from <code>FreePointerSlot</code> produces an <code>i32</code> since the FMP fits in a pointer-sized word.</p>
|
||
<h3 id="sload"><a class="header" href="#sload"><code>sload</code></a></h3>
|
||
<p>(<code>Expression::SLoad</code>)</p>
|
||
<h4 id="description-60"><a class="header" href="#description-60">Description</a></h4>
|
||
<p>Read a 32-byte word from persistent contract storage at the given key. Pure per IR; reads after writes to the same slot return the new value.</p>
|
||
<h4 id="syntax-60"><a class="header" href="#syntax-60">Syntax</a></h4>
|
||
<pre><code class="language-text">sload($key[: <type>]) [/* slot: 0x<hex> */]
|
||
</code></pre>
|
||
<h4 id="example-60"><a class="header" href="#example-60">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := sload(v0)
|
||
let v2 := sload(v3) /* slot: 0x0 */
|
||
</code></pre>
|
||
<h4 id="operands-60"><a class="header" href="#operands-60">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>key</code></td><td><code>i256</code></td><td>Storage slot.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-60"><a class="header" href="#result-and-purity-60">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure (per IR; see Description)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-60"><a class="header" href="#annotations-60">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>static_slot: Option<BigUint></code></td><td><code>/* slot: 0x<hex> */</code> when set; suppressed otherwise</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p>Same tagging rules as <a href="#sstore"><code>sstore</code></a>. The printer renders the annotation whenever the field is <code>Some</code> and the deduplicator’s canonicalizer partitions signatures by slot; no pass currently writes <code>Some(...)</code>, however, so in present-day dumps the annotation is dormant.</p>
|
||
<h3 id="tload"><a class="header" href="#tload"><code>tload</code></a></h3>
|
||
<p>(<code>Expression::TLoad</code>)</p>
|
||
<h4 id="description-61"><a class="header" href="#description-61">Description</a></h4>
|
||
<p>Read a 32-byte word from transient storage at the given key. Transient storage is wiped at the end of the transaction; pair with <a href="#tstore"><code>tstore</code></a>.</p>
|
||
<h4 id="syntax-61"><a class="header" href="#syntax-61">Syntax</a></h4>
|
||
<pre><code class="language-text">tload($key[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-61"><a class="header" href="#example-61">Example</a></h4>
|
||
<pre><code class="language-text">let v1 := tload(v0)
|
||
</code></pre>
|
||
<h4 id="operands-61"><a class="header" href="#operands-61">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>key</code></td><td><code>i256</code></td><td>Transient storage slot.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-61"><a class="header" href="#result-and-purity-61">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure (per IR; see Description)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-61"><a class="header" href="#annotations-61">Annotations</a></h4>
|
||
<p>None. The IR does not track a static slot for <code>tload</code>.</p>
|
||
<h3 id="mapping_sload"><a class="header" href="#mapping_sload"><code>mapping_sload</code></a></h3>
|
||
<p>(<code>Expression::MappingSLoad</code>)</p>
|
||
<h4 id="description-62"><a class="header" href="#description-62">Description</a></h4>
|
||
<p>Compound load for a Solidity mapping element. Equivalent to <code>mstore(0, key); mstore(32, slot); sload(keccak256(0, 64))</code> but emitted as a single outlined call after the <code>mapping_access_outlining</code> pass recognizes the pattern (it fuses a <code>keccak256_pair</code> — itself produced by <code>mem_opt</code>’s keccak fusion — followed by an <code>sload</code> whose key has a single consumer). Only valid when the intermediate hash is used exclusively by this load.</p>
|
||
<h4 id="syntax-62"><a class="header" href="#syntax-62">Syntax</a></h4>
|
||
<pre><code class="language-text">mapping_sload($key[: <type>], $slot[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-62"><a class="header" href="#example-62">Example</a></h4>
|
||
<pre><code class="language-text">let v2 := mapping_sload(v0: i160, v1)
|
||
</code></pre>
|
||
<h4 id="operands-62"><a class="header" href="#operands-62">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>key</code></td><td><code>i256</code></td><td>Mapping key; often narrowed to <code>i160</code> for address keys.</td></tr>
|
||
<tr><td><code>slot</code></td><td><code>i256</code></td><td>The mapping’s declared storage slot.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-62"><a class="header" href="#result-and-purity-62">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure (per IR; see Description)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-62"><a class="header" href="#annotations-62">Annotations</a></h4>
|
||
<p>None. The fused statement’s effective storage slot is the keccak hash of the key and the declared slot, which is never a compile-time constant; no <code>static_slot</code> hint is surfaced.</p>
|
||
<h3 id="dataoffset"><a class="header" href="#dataoffset"><code>dataoffset</code></a></h3>
|
||
<p>(<code>Expression::DataOffset</code>)</p>
|
||
<h4 id="description-63"><a class="header" href="#description-63">Description</a></h4>
|
||
<p>Offset of a named data segment within the deployed code. The identifier is a string carried in the IR’s <code>id: String</code> field; the linker resolves it to a concrete offset.</p>
|
||
<h4 id="syntax-63"><a class="header" href="#syntax-63">Syntax</a></h4>
|
||
<pre><code class="language-text">dataoffset("<id>")
|
||
</code></pre>
|
||
<h4 id="example-63"><a class="header" href="#example-63">Example</a></h4>
|
||
<pre><code class="language-text">let v0 := dataoffset("MyContract_deployed")
|
||
</code></pre>
|
||
<h4 id="operands-63"><a class="header" href="#operands-63">Operands</a></h4>
|
||
<p>None — the identifier is a quoted string literal in the syntax position, not an operand.</p>
|
||
<h4 id="result-and-purity-63"><a class="header" href="#result-and-purity-63">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-63"><a class="header" href="#annotations-63">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>id: String</code></td><td>The quoted identifier in the syntax position (not a comment annotation; it is the expression itself).</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="datasize"><a class="header" href="#datasize"><code>datasize</code></a></h3>
|
||
<p>(<code>Expression::DataSize</code>)</p>
|
||
<h4 id="description-64"><a class="header" href="#description-64">Description</a></h4>
|
||
<p>Size of a named data segment within the deployed code, in bytes. The identifier is resolved by the linker.</p>
|
||
<h4 id="syntax-64"><a class="header" href="#syntax-64">Syntax</a></h4>
|
||
<pre><code class="language-text">datasize("<id>")
|
||
</code></pre>
|
||
<h4 id="example-64"><a class="header" href="#example-64">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i64 := datasize("MyContract_deployed")
|
||
</code></pre>
|
||
<h4 id="operands-64"><a class="header" href="#operands-64">Operands</a></h4>
|
||
<p>None — the identifier is a quoted string literal in the syntax position, not an operand.</p>
|
||
<h4 id="result-and-purity-64"><a class="header" href="#result-and-purity-64">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i64</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-64"><a class="header" href="#annotations-64">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>id: String</code></td><td>The quoted identifier in the syntax position.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="loadimmutable"><a class="header" href="#loadimmutable"><code>loadimmutable</code></a></h3>
|
||
<p>(<code>Expression::LoadImmutable</code>)</p>
|
||
<h4 id="description-65"><a class="header" href="#description-65">Description</a></h4>
|
||
<p>Read the value of a named immutable variable. Immutables are written once during contract construction by <code>SetImmutable</code> and read afterwards via this expression.</p>
|
||
<h4 id="syntax-65"><a class="header" href="#syntax-65">Syntax</a></h4>
|
||
<pre><code class="language-text">loadimmutable("<key>")
|
||
</code></pre>
|
||
<h4 id="example-65"><a class="header" href="#example-65">Example</a></h4>
|
||
<pre><code class="language-text">let v0 := loadimmutable("MyContract.owner")
|
||
</code></pre>
|
||
<h4 id="operands-65"><a class="header" href="#operands-65">Operands</a></h4>
|
||
<p>None — the key is a quoted string literal in the syntax position.</p>
|
||
<h4 id="result-and-purity-65"><a class="header" href="#result-and-purity-65">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-65"><a class="header" href="#annotations-65">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>key: String</code></td><td>The quoted identifier in the syntax position.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="linkersymbol"><a class="header" href="#linkersymbol"><code>linkersymbol</code></a></h3>
|
||
<p>(<code>Expression::LinkerSymbol</code>)</p>
|
||
<h4 id="description-66"><a class="header" href="#description-66">Description</a></h4>
|
||
<p>Address of an external library, resolved by the linker. The path encodes the library’s source location and identifier.</p>
|
||
<h4 id="syntax-66"><a class="header" href="#syntax-66">Syntax</a></h4>
|
||
<pre><code class="language-text">linkersymbol("<path>")
|
||
</code></pre>
|
||
<h4 id="example-66"><a class="header" href="#example-66">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i160 := linkersymbol("contracts/Library.sol:L")
|
||
</code></pre>
|
||
<h4 id="operands-66"><a class="header" href="#operands-66">Operands</a></h4>
|
||
<p>None — the path is a quoted string literal in the syntax position.</p>
|
||
<h4 id="result-and-purity-66"><a class="header" href="#result-and-purity-66">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i160</code></td><td>Pure</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-66"><a class="header" href="#annotations-66">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>path: String</code></td><td>The quoted path in the syntax position.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="func_name"><a class="header" href="#func_name"><code><func_name></code></a></h3>
|
||
<p>(<code>Expression::Call</code>; the printer emits <code>func_<id></code> when no function name is registered)</p>
|
||
<h4 id="description-67"><a class="header" href="#description-67">Description</a></h4>
|
||
<p>Internal function call. Invokes a user-defined function declared earlier in the same object; the mnemonic is the function’s Yul-level name, or <code>func_<id></code> if the printer has no name registered for the <code>FunctionId</code>. Distinct from <a href="#call"><code>call</code></a> and the other EVM call-opcode statements, which cross the contract boundary.</p>
|
||
<h4 id="syntax-67"><a class="header" href="#syntax-67">Syntax</a></h4>
|
||
<pre><code class="language-text"><func_name>([$argument_0[: <type>], $argument_1[: <type>], …])
|
||
</code></pre>
|
||
<h4 id="example-67"><a class="header" href="#example-67">Example</a></h4>
|
||
<pre><code class="language-text">let v3 := abi_decode_uint256(v0, v1, v2)
|
||
let v4, v5 := returns_two(v0) // multi-return via let multi-binding
|
||
</code></pre>
|
||
<h4 id="operands-67"><a class="header" href="#operands-67">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>arguments</code></td><td><code>Vec<Value></code></td><td>Zero or more argument values, in declaration order; each operand may carry a <code>: <type></code> suffix.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-67"><a class="header" href="#result-and-purity-67">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>One or more values, widths taken from the callee’s declared return types (or the inferred return widths, narrowed via the interprocedural pass). Falls back to <code>i256</code> when the callee’s returns are unknown to type inference.</td><td>Effectful — the simplifier treats every call as side-effectful regardless of callee body, so unused call bindings are not DCE’d. The transitive purity of the callee is not tracked at the IR level.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-67"><a class="header" href="#annotations-67">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>function: FunctionId</code></td><td>The callee’s name in the syntax position (or <code>func_<id></code> if the printer has no name registered).</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h2 id="memory-and-storage-writes-1"><a class="header" href="#memory-and-storage-writes-1">Memory and storage writes</a></h2>
|
||
<p>The operations in this section all modify external state: emulated EVM linear memory, persistent storage, or transient storage. They are statements (not expressions) and they are never pure. Simplification and deduplication never reorder them with respect to each other or with respect to reverts; the memory passes treat them as the side-effect boundary for their analyses.</p>
|
||
<h3 id="mstore"><a class="header" href="#mstore"><code>mstore</code></a></h3>
|
||
<p>(<code>Statement::MStore</code>)</p>
|
||
<h4 id="description-68"><a class="header" href="#description-68">Description</a></h4>
|
||
<p>Write a 32-byte word to emulated EVM linear memory at <code>offset</code>. The word is stored big-endian, matching EVM semantics; the codegen handles the byte swap on PolkaVM’s little-endian RISC-V target.</p>
|
||
<h4 id="syntax-68"><a class="header" href="#syntax-68">Syntax</a></h4>
|
||
<pre><code class="language-text">mstore($offset[: <type>], $value[: <type>]) [/* <region> */]
|
||
</code></pre>
|
||
<h4 id="example-68"><a class="header" href="#example-68">Example</a></h4>
|
||
<pre><code class="language-text">mstore(v0, v1) // Unknown region; no annotation printed
|
||
mstore(v2, v3) /* scratch */ // offset proven to land in 0x00..0x3f
|
||
mstore(v4, v5) /* free_ptr */ // offset is exactly 0x40
|
||
</code></pre>
|
||
<h4 id="operands-68"><a class="header" href="#operands-68">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Byte offset into linear memory; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>The 32-byte word to store. Narrower values are zero-extended at codegen time.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-68"><a class="header" href="#result-and-purity-68">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-68"><a class="header" href="#annotations-68">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>region:</code> <a href="#memoryregion"><code>MemoryRegion</code></a></td><td><code>/* scratch */</code> · <code>/* free_ptr */</code> · <code>/* dynamic */</code> (<code>Unknown</code> is suppressed)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p>Assigned at translation time from the constant offset (if any); consumed by mem_opt, FMP propagation, and byte-swap mode selection.</p>
|
||
<h3 id="mstore8"><a class="header" href="#mstore8"><code>mstore8</code></a></h3>
|
||
<p>(<code>Statement::MStore8</code>)</p>
|
||
<h4 id="description-69"><a class="header" href="#description-69">Description</a></h4>
|
||
<p>Write a single byte to emulated EVM linear memory at <code>offset</code>. The low 8 bits of <code>value</code> are stored; the upper bits are ignored. The operation is otherwise identical to <code>mstore</code>: same operand shape, same region tag, same side-effect classification.</p>
|
||
<h4 id="syntax-69"><a class="header" href="#syntax-69">Syntax</a></h4>
|
||
<pre><code class="language-text">mstore8($offset[: <type>], $value[: <type>]) [/* <region> */]
|
||
</code></pre>
|
||
<h4 id="example-69"><a class="header" href="#example-69">Example</a></h4>
|
||
<pre><code class="language-text">mstore8(v0, v1: i8)
|
||
</code></pre>
|
||
<h4 id="operands-69"><a class="header" href="#operands-69">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Byte offset into linear memory; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Only the low 8 bits are stored. Often narrowed to <code>i8</code> by type inference.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-69"><a class="header" href="#result-and-purity-69">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-69"><a class="header" href="#annotations-69">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>region:</code> <a href="#memoryregion"><code>MemoryRegion</code></a></td><td><code>/* scratch */</code> · <code>/* free_ptr */</code> · <code>/* dynamic */</code> (<code>Unknown</code> is suppressed)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p>Same tagging rules as <a href="#mstore"><code>mstore</code></a>. Most <code>mstore8</code>s carry an <code>Unknown</code> region in practice because single-byte writes typically target offsets the translator cannot prove constant.</p>
|
||
<h3 id="mcopy"><a class="header" href="#mcopy"><code>mcopy</code></a></h3>
|
||
<p>(<code>Statement::MCopy</code>)</p>
|
||
<h4 id="description-70"><a class="header" href="#description-70">Description</a></h4>
|
||
<p>Copy <code>length</code> bytes from <code>src</code> to <code>dest</code> within emulated EVM linear memory. The Yul builtin <code>mcopy</code> maps directly onto this statement; unlike <code>mstore</code>, it does not carry a region tag because the source and destination ranges may straddle multiple regions.</p>
|
||
<h4 id="syntax-70"><a class="header" href="#syntax-70">Syntax</a></h4>
|
||
<pre><code class="language-text">mcopy($dest[: <type>], $src[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-70"><a class="header" href="#example-70">Example</a></h4>
|
||
<pre><code class="language-text">mcopy(v0, v1, v2)
|
||
</code></pre>
|
||
<h4 id="operands-70"><a class="header" href="#operands-70">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>dest</code></td><td><code>i256</code></td><td>Destination byte offset in linear memory.</td></tr>
|
||
<tr><td><code>src</code></td><td><code>i256</code></td><td>Source byte offset in linear memory.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Number of bytes to copy. Overlapping ranges follow EVM-defined memmove semantics.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-70"><a class="header" href="#result-and-purity-70">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-70"><a class="header" href="#annotations-70">Annotations</a></h4>
|
||
<p>None. <code>mcopy</code> carries no region tag because the source and destination ranges may straddle multiple regions, and no static-slot hint because the copy is not storage-bound.</p>
|
||
<h3 id="sstore"><a class="header" href="#sstore"><code>sstore</code></a></h3>
|
||
<p>(<code>Statement::SStore</code>)</p>
|
||
<h4 id="description-71"><a class="header" href="#description-71">Description</a></h4>
|
||
<p>Write a 32-byte word to persistent contract storage at <code>key</code>. The operation is the durable counterpart of <code>mstore</code>: the value survives across transactions and is observable to subsequent calls to the contract.</p>
|
||
<h4 id="syntax-71"><a class="header" href="#syntax-71">Syntax</a></h4>
|
||
<pre><code class="language-text">sstore($key[: <type>], $value[: <type>]) [/* slot: 0x<hex> */]
|
||
</code></pre>
|
||
<h4 id="example-71"><a class="header" href="#example-71">Example</a></h4>
|
||
<pre><code class="language-text">sstore(v0, v1)
|
||
sstore(v2, v3) /* slot: 0x0 */
|
||
</code></pre>
|
||
<h4 id="operands-71"><a class="header" href="#operands-71">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>key</code></td><td><code>i256</code></td><td>Storage slot. May be a constant slot, a keccak-derived slot for mappings or dynamic arrays, or an arbitrary expression.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>The 256-bit word to store.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-71"><a class="header" href="#result-and-purity-71">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-71"><a class="header" href="#annotations-71">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>static_slot: Option<BigUint></code></td><td><code>/* slot: 0x<hex> */</code> when set; suppressed otherwise</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p>The printer renders the annotation whenever the field is <code>Some</code>, and the deduplicator’s canonicalizer and mapping-fusion analyses consume it as part of the signature. No pass currently writes <code>Some(...)</code>, so the annotation is dormant in present-day dumps; when absent, alias and dedup analyses fall back to the conservative “may alias any slot” assumption.</p>
|
||
<h3 id="tstore"><a class="header" href="#tstore"><code>tstore</code></a></h3>
|
||
<p>(<code>Statement::TStore</code>)</p>
|
||
<h4 id="description-72"><a class="header" href="#description-72">Description</a></h4>
|
||
<p>Write a 32-byte word to transient storage at <code>key</code>. Transient storage is wiped at the end of the transaction, so <code>tstore</code> is the right primitive for per-transaction bookkeeping (reentrancy guards, cached results) without the gas cost of <code>sstore</code> on EVM. On PolkaVM the transient backing store is provided by pallet-revive.</p>
|
||
<h4 id="syntax-72"><a class="header" href="#syntax-72">Syntax</a></h4>
|
||
<pre><code class="language-text">tstore($key[: <type>], $value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-72"><a class="header" href="#example-72">Example</a></h4>
|
||
<pre><code class="language-text">tstore(v0, v1)
|
||
</code></pre>
|
||
<h4 id="operands-72"><a class="header" href="#operands-72">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>key</code></td><td><code>i256</code></td><td>Transient storage slot.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>The 256-bit word to store.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-72"><a class="header" href="#result-and-purity-72">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-72"><a class="header" href="#annotations-72">Annotations</a></h4>
|
||
<p>None. Unlike <code>sstore</code>, the IR does not track a static slot for <code>tstore</code>: transient storage’s short-lived lifetime makes the slot-aware optimizations less valuable, and the translator does not produce the annotation.</p>
|
||
<h3 id="mapping_sstore"><a class="header" href="#mapping_sstore"><code>mapping_sstore</code></a></h3>
|
||
<p>(<code>Statement::MappingSStore</code>)</p>
|
||
<h4 id="description-73"><a class="header" href="#description-73">Description</a></h4>
|
||
<p>Compound store for a Solidity mapping element. Equivalent to <code>mstore(0, key); mstore(32, slot); sstore(keccak256(0, 64), value)</code> but emitted as a single outlined statement after the <code>mapping_access_outlining</code> pass recognizes the pattern (it fuses a <code>keccak256_pair</code> followed by an <code>sstore</code> whose key has a single consumer). Only valid when the intermediate hash is not observed by any other statement.</p>
|
||
<h4 id="syntax-73"><a class="header" href="#syntax-73">Syntax</a></h4>
|
||
<pre><code class="language-text">mapping_sstore($key[: <type>], $slot[: <type>], $value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-73"><a class="header" href="#example-73">Example</a></h4>
|
||
<pre><code class="language-text">mapping_sstore(v0, v1, v2)
|
||
</code></pre>
|
||
<h4 id="operands-73"><a class="header" href="#operands-73">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>key</code></td><td><code>i256</code></td><td>Mapping key. The outlining pass force-widens it to <code>i256</code>, so it always prints at full width, even for address keys.</td></tr>
|
||
<tr><td><code>slot</code></td><td><code>i256</code></td><td>The mapping’s declared storage slot. Typically a small constant.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>The value to store at the computed storage location.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-73"><a class="header" href="#result-and-purity-73">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-73"><a class="header" href="#annotations-73">Annotations</a></h4>
|
||
<p>None. <code>mapping_sstore</code> deliberately drops the <code>static_slot</code> annotation that the original <code>sstore</code> may have carried, because the fused statement’s effective slot is the keccak hash of the key and the declared slot, which is never a compile-time constant.</p>
|
||
<h2 id="bulk-copies-1"><a class="header" href="#bulk-copies-1">Bulk copies</a></h2>
|
||
<p>Multi-byte memory copies from the EVM-accessible byte sources (code, external code, returndata, embedded data, and calldata) into emulated EVM linear memory. They all take the same shape: a destination memory offset, a source offset, and a length. They are effectful and act as opaque barriers to the memory passes.</p>
|
||
<h3 id="codecopy"><a class="header" href="#codecopy"><code>codecopy</code></a></h3>
|
||
<p>(<code>Statement::CodeCopy</code>)</p>
|
||
<h4 id="description-74"><a class="header" href="#description-74">Description</a></h4>
|
||
<p>Copy <code>length</code> bytes from the currently executing code at <code>offset</code> into emulated EVM linear memory at <code>dest</code>. Reads past the end of code yield zero bytes.</p>
|
||
<h4 id="syntax-74"><a class="header" href="#syntax-74">Syntax</a></h4>
|
||
<pre><code class="language-text">codecopy($dest[: <type>], $offset[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-74"><a class="header" href="#example-74">Example</a></h4>
|
||
<pre><code class="language-text">codecopy(v0, v1, v2)
|
||
</code></pre>
|
||
<h4 id="operands-74"><a class="header" href="#operands-74">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>dest</code></td><td><code>i256</code></td><td>Destination byte offset in linear memory.</td></tr>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Source byte offset in the executing code.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Number of bytes to copy.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-74"><a class="header" href="#result-and-purity-74">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-74"><a class="header" href="#annotations-74">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="extcodecopy"><a class="header" href="#extcodecopy"><code>extcodecopy</code></a></h3>
|
||
<p>(<code>Statement::ExtCodeCopy</code>)</p>
|
||
<h4 id="description-75"><a class="header" href="#description-75">Description</a></h4>
|
||
<p>Copy <code>length</code> bytes from the code at <code>address</code> starting at <code>offset</code> into emulated EVM linear memory at <code>dest</code>. Reads beyond the code yield zero bytes; non-existent accounts yield all zeros.</p>
|
||
<h4 id="syntax-75"><a class="header" href="#syntax-75">Syntax</a></h4>
|
||
<pre><code class="language-text">extcodecopy($address[: <type>], $dest[: <type>], $offset[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-75"><a class="header" href="#example-75">Example</a></h4>
|
||
<pre><code class="language-text">extcodecopy(v0: i160, v1, v2, v3)
|
||
</code></pre>
|
||
<h4 id="operands-75"><a class="header" href="#operands-75">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>address</code></td><td><code>i256</code></td><td>Account whose code to read; forward analysis widens to at least <code>i160</code>.</td></tr>
|
||
<tr><td><code>dest</code></td><td><code>i256</code></td><td>Destination byte offset in linear memory.</td></tr>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Source byte offset in the external code.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Number of bytes to copy.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-75"><a class="header" href="#result-and-purity-75">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-75"><a class="header" href="#annotations-75">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="returndatacopy"><a class="header" href="#returndatacopy"><code>returndatacopy</code></a></h3>
|
||
<p>(<code>Statement::ReturnDataCopy</code>)</p>
|
||
<h4 id="description-76"><a class="header" href="#description-76">Description</a></h4>
|
||
<p>Copy <code>length</code> bytes from the most recent sub-call’s return data starting at <code>offset</code> into emulated EVM linear memory at <code>dest</code>. Per EVM, reads past the return data’s end revert; the memory passes treat this as a potential trap site.</p>
|
||
<h4 id="syntax-76"><a class="header" href="#syntax-76">Syntax</a></h4>
|
||
<pre><code class="language-text">returndatacopy($dest[: <type>], $offset[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-76"><a class="header" href="#example-76">Example</a></h4>
|
||
<pre><code class="language-text">returndatacopy(v0, v1, v2)
|
||
</code></pre>
|
||
<h4 id="operands-76"><a class="header" href="#operands-76">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>dest</code></td><td><code>i256</code></td><td>Destination byte offset in linear memory.</td></tr>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Source byte offset in the return-data buffer.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Number of bytes to copy.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-76"><a class="header" href="#result-and-purity-76">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful (may revert on out-of-range reads, per EVM)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-76"><a class="header" href="#annotations-76">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="datacopy"><a class="header" href="#datacopy"><code>datacopy</code></a></h3>
|
||
<p>(<code>Statement::DataCopy</code>)</p>
|
||
<h4 id="description-77"><a class="header" href="#description-77">Description</a></h4>
|
||
<p>Copy <code>length</code> bytes from an embedded data segment starting at <code>offset</code> into emulated EVM linear memory at <code>dest</code>. The source segment is resolved by the linker, typically used to pull constants compiled into the bytecode into runtime memory.</p>
|
||
<h4 id="syntax-77"><a class="header" href="#syntax-77">Syntax</a></h4>
|
||
<pre><code class="language-text">datacopy($dest[: <type>], $offset[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-77"><a class="header" href="#example-77">Example</a></h4>
|
||
<pre><code class="language-text">datacopy(v0, v1, v2)
|
||
</code></pre>
|
||
<h4 id="operands-77"><a class="header" href="#operands-77">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>dest</code></td><td><code>i256</code></td><td>Destination byte offset in linear memory.</td></tr>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Source byte offset in the data segment.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Number of bytes to copy.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-77"><a class="header" href="#result-and-purity-77">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-77"><a class="header" href="#annotations-77">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="calldatacopy"><a class="header" href="#calldatacopy"><code>calldatacopy</code></a></h3>
|
||
<p>(<code>Statement::CallDataCopy</code>)</p>
|
||
<h4 id="description-78"><a class="header" href="#description-78">Description</a></h4>
|
||
<p>Copy <code>length</code> bytes from the current call’s calldata starting at <code>offset</code> into emulated EVM linear memory at <code>dest</code>. Reads past the end of calldata yield zero bytes.</p>
|
||
<h4 id="syntax-78"><a class="header" href="#syntax-78">Syntax</a></h4>
|
||
<pre><code class="language-text">calldatacopy($dest[: <type>], $offset[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-78"><a class="header" href="#example-78">Example</a></h4>
|
||
<pre><code class="language-text">calldatacopy(v0, v1, v2)
|
||
</code></pre>
|
||
<h4 id="operands-78"><a class="header" href="#operands-78">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>dest</code></td><td><code>i256</code></td><td>Destination byte offset in linear memory.</td></tr>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Source byte offset in calldata.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Number of bytes to copy.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-78"><a class="header" href="#result-and-purity-78">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-78"><a class="header" href="#annotations-78">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h2 id="bindings-and-wrappers-1"><a class="header" href="#bindings-and-wrappers-1">Bindings and wrappers</a></h2>
|
||
<p>The statements that bind SSA values, hold loose expressions evaluated for their side effects, and write to immutable storage. Every pure expression in this reference’s earlier sections appears on the right-hand side of one of these statements (almost always <code>let</code>).</p>
|
||
<h3 id="let"><a class="header" href="#let"><code>let</code></a></h3>
|
||
<p>(<code>Statement::Let</code>)</p>
|
||
<h4 id="description-79"><a class="header" href="#description-79">Description</a></h4>
|
||
<p>SSA binding: evaluate an expression and bind its result(s) to a list of fresh value ids. The <code>let</code> statement is the only mechanism by which pure expressions enter the value namespace; every <code>v<id></code> in a dump was produced by a <code>let</code> (or by a value-yielding control-flow statement or by a parameter at function entry).</p>
|
||
<h4 id="syntax-79"><a class="header" href="#syntax-79">Syntax</a></h4>
|
||
<pre><code class="language-text">let $binding_0[, $binding_1, …] := $expression
|
||
</code></pre>
|
||
<h4 id="example-79"><a class="header" href="#example-79">Example</a></h4>
|
||
<pre><code class="language-text">let v3 := add(v0, v1)
|
||
let v4, v5 := if v2 [v0, v1] { … } else { … } // multi-binding from a value-yielding If
|
||
</code></pre>
|
||
<h4 id="operands-79"><a class="header" href="#operands-79">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>bindings</code></td><td><code>Vec<ValueId></code></td><td>One or more fresh SSA ids to bind. Most expressions produce one value; control-flow statements may produce several.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>Expression</code></td><td>The right-hand side; see any of the Pure expression entries.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-79"><a class="header" href="#result-and-purity-79">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None directly — the bound ids carry the expression’s result(s)</td><td>Effectful (binding establishment); the right-hand side’s purity is independent</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-79"><a class="header" href="#annotations-79">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="expression-statement"><a class="header" href="#expression-statement">Expression statement</a></h3>
|
||
<p>(<code>Statement::Expression</code>)</p>
|
||
<h4 id="description-80"><a class="header" href="#description-80">Description</a></h4>
|
||
<p>Wraps an expression evaluated for its observable consequences but whose value is not bound. Typically a zero-return (void) user-defined function call (<code>Expression::Call</code>) evaluated for its side effects, or the discarded void result of a Yul builtin used as a statement (a value-producing expression is bound by a <code>let</code> instead). EVM external calls (<code>call</code>, <code>delegatecall</code>, etc.) and contract creation (<code>create</code>, <code>create2</code>) translate to dedicated <code>Statement::ExternalCall</code> and <code>Statement::Create</code> variants, not through this wrapper.</p>
|
||
<h4 id="syntax-80"><a class="header" href="#syntax-80">Syntax</a></h4>
|
||
<pre><code class="language-text">$expression
|
||
</code></pre>
|
||
<h4 id="example-80"><a class="header" href="#example-80">Example</a></h4>
|
||
<pre><code class="language-text">update_balance(v0) // void function called for its side effects
|
||
</code></pre>
|
||
<h4 id="operands-80"><a class="header" href="#operands-80">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>expression</code></td><td><code>Expression</code></td><td>Any expression; result is discarded.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-80"><a class="header" href="#result-and-purity-80">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful (per its statement position)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-80"><a class="header" href="#annotations-80">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="setimmutable"><a class="header" href="#setimmutable"><code>setimmutable</code></a></h3>
|
||
<p>(<code>Statement::SetImmutable</code>)</p>
|
||
<h4 id="description-81"><a class="header" href="#description-81">Description</a></h4>
|
||
<p>Write an immutable variable during contract construction. Immutables are written once in the constructor and read later via <a href="#loadimmutable"><code>loadimmutable</code></a>. The key is a string identifier resolved by the linker.</p>
|
||
<h4 id="syntax-81"><a class="header" href="#syntax-81">Syntax</a></h4>
|
||
<pre><code class="language-text">setimmutable("<key>", $value[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-81"><a class="header" href="#example-81">Example</a></h4>
|
||
<pre><code class="language-text">setimmutable("MyContract.owner", v0)
|
||
</code></pre>
|
||
<h4 id="operands-81"><a class="header" href="#operands-81">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>The value to store; the key is a quoted string literal in the syntax position.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-81"><a class="header" href="#result-and-purity-81">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-81"><a class="header" href="#annotations-81">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>key: String</code></td><td>The quoted identifier in the syntax position.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h2 id="structured-control-flow-1"><a class="header" href="#structured-control-flow-1">Structured control flow</a></h2>
|
||
<p>The IR’s control flow is structured: <code>if</code>, <code>switch</code>, and <code>for</code> are statements with explicit nested regions, each carrying input values and yielding output values. The jump-like statements (<code>break</code>, <code>continue</code>, <code>leave</code>) are scoped to their nearest enclosing construct. Nested blocks create lexical scope without otherwise changing control flow.</p>
|
||
<h3 id="if"><a class="header" href="#if"><code>if</code></a></h3>
|
||
<p>(<code>Statement::If</code>)</p>
|
||
<h4 id="description-82"><a class="header" href="#description-82">Description</a></h4>
|
||
<p>Conditional execution with optional value yields. The <code>then</code> region runs when <code>condition</code> is non-zero; the <code>else</code> region runs otherwise. If <code>outputs</code> is non-empty, both regions must yield the same number of values and the statement is bound by a <code>let</code>.</p>
|
||
<h4 id="syntax-82"><a class="header" href="#syntax-82">Syntax</a></h4>
|
||
<pre><code class="language-text">if $condition[: <type>] [[$input_0, $input_1, …]] { … } [else { … }]
|
||
</code></pre>
|
||
<h4 id="example-82"><a class="header" href="#example-82">Example</a></h4>
|
||
<pre><code class="language-text">if v0: i1 {
|
||
sstore(v1, v2)
|
||
}
|
||
|
||
let v5, v6 := if v3: i1 [v1, v2] {
|
||
let v7: i64 := 0x1 // add widens its operands to the i64 register width
|
||
let v8 := add(v2, v7: i64)
|
||
yield v1, v8
|
||
} else {
|
||
yield v1, v2
|
||
}
|
||
</code></pre>
|
||
<h4 id="operands-82"><a class="header" href="#operands-82">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>condition</code></td><td><code>i256</code></td><td>Branch selector; non-zero takes the <code>then</code> region. Often narrowed to <code>i1</code>.</td></tr>
|
||
<tr><td><code>inputs</code></td><td><code>Vec<Value></code></td><td>Values threaded into both regions, printed in square brackets after the condition.</td></tr>
|
||
<tr><td>(regions)</td><td>—</td><td>The <code>then_region</code> is mandatory; the <code>else_region</code> is optional and, when absent, implicitly yields the inputs unchanged.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-82"><a class="header" href="#result-and-purity-82">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None for the statement form; for the value-yielding form, one value per <code>outputs</code> binding, types taken from the yielded values</td><td>Effectful (control flow)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-82"><a class="header" href="#annotations-82">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="switch"><a class="header" href="#switch"><code>switch</code></a></h3>
|
||
<p>(<code>Statement::Switch</code>)</p>
|
||
<h4 id="description-83"><a class="header" href="#description-83">Description</a></h4>
|
||
<p>Multi-way dispatch on a scrutinee value. Each case matches a specific constant and runs its region; an optional <code>default</code> region catches non-matching values. Like <code>if</code>, switch may yield values via <code>outputs</code> and accept thread-through values via <code>inputs</code>.</p>
|
||
<h4 id="syntax-83"><a class="header" href="#syntax-83">Syntax</a></h4>
|
||
<pre><code class="language-text">switch $scrutinee[: <type>] [[$input_0, …]]
|
||
case 0x<hex> {
|
||
…
|
||
}
|
||
[case 0x<hex> {
|
||
…
|
||
} …]
|
||
[default {
|
||
…
|
||
}]
|
||
</code></pre>
|
||
<h4 id="example-83"><a class="header" href="#example-83">Example</a></h4>
|
||
<pre><code class="language-text">switch v0
|
||
case 0x0 {
|
||
sstore(v1, v2)
|
||
}
|
||
case 0x1 {
|
||
sstore(v1, v3)
|
||
}
|
||
default {
|
||
invalid()
|
||
}
|
||
</code></pre>
|
||
<h4 id="operands-83"><a class="header" href="#operands-83">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>scrutinee</code></td><td><code>i256</code></td><td>The value to compare against each case.</td></tr>
|
||
<tr><td><code>inputs</code></td><td><code>Vec<Value></code></td><td>Values threaded into every case and default region.</td></tr>
|
||
<tr><td><code>cases</code></td><td><code>Vec<SwitchCase></code></td><td>Each case carries a constant <code>value: BigUint</code> and a region.</td></tr>
|
||
<tr><td>(default)</td><td>—</td><td>Optional fall-through region.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-83"><a class="header" href="#result-and-purity-83">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None for the statement form; one value per <code>outputs</code> binding for the value-yielding form</td><td>Effectful (control flow)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-83"><a class="header" href="#annotations-83">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="for"><a class="header" href="#for"><code>for</code></a></h3>
|
||
<p>(<code>Statement::For</code>)</p>
|
||
<h4 id="description-84"><a class="header" href="#description-84">Description</a></h4>
|
||
<p>Structured loop with explicit loop-carried variables. Each iteration evaluates <code>condition_statements</code> followed by <code>condition</code>; if the condition is non-zero, the <code>body</code> region runs, then the <code>post</code> region runs, and the loop iterates. Loop-carried variables are passed as SSA values through each region. <code>break</code> exits the loop and <code>continue</code> jumps to the post region.</p>
|
||
<h4 id="syntax-84"><a class="header" href="#syntax-84">Syntax</a></h4>
|
||
<pre><code class="language-text">for { $variable_0 := $initial_0[, …] }
|
||
[// condition statements:
|
||
…]
|
||
condition: $condition
|
||
post [($post_input_variable_0[, …])] {
|
||
…
|
||
}
|
||
body {
|
||
… body …
|
||
}
|
||
</code></pre>
|
||
<h4 id="example-84"><a class="header" href="#example-84">Example</a></h4>
|
||
<pre><code class="language-text">let v0: i1 := 0x0
|
||
let v6 := for { v1 := v0: i1 }
|
||
// condition statements:
|
||
let v2: i8 := 0xa
|
||
condition: lt(v1, v2: i8)
|
||
post (v3) {
|
||
let v4: i64 := 0x1
|
||
let v5 := add(v3, v4: i64)
|
||
yield v5
|
||
}
|
||
body {
|
||
sstore(v1, v1)
|
||
0x0: void
|
||
yield v1
|
||
}
|
||
</code></pre>
|
||
<h4 id="operands-84"><a class="header" href="#operands-84">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>initial_values</code></td><td><code>Vec<Value></code></td><td>Starting values for the loop-carried variables.</td></tr>
|
||
<tr><td><code>loop_variables</code></td><td><code>Vec<ValueId></code></td><td>SSA ids visible inside condition, body, and post.</td></tr>
|
||
<tr><td><code>condition_statements</code></td><td><code>Vec<Statement></code></td><td>Statements evaluated each iteration <em>before</em> the condition expression; emitted into the loop header block. Printed only when non-empty, behind a <code>// condition statements:</code> comment.</td></tr>
|
||
<tr><td><code>condition</code></td><td><code>Expression</code></td><td>Re-evaluated each iteration; non-zero continues, zero exits.</td></tr>
|
||
<tr><td><code>body</code></td><td><code>Region</code></td><td>Loop body; yields current loop-carried values.</td></tr>
|
||
<tr><td><code>post_input_variables</code></td><td><code>Vec<ValueId></code></td><td>Input SSA ids for the post region (one per loop-carried variable); receive the body’s yielded values merged with continue-site values via phi nodes in the LLVM codegen.</td></tr>
|
||
<tr><td><code>post</code></td><td><code>Region</code></td><td>Runs after each body iteration (and after <code>continue</code>); yields updated loop-carried values.</td></tr>
|
||
<tr><td><code>outputs</code></td><td><code>Vec<ValueId></code></td><td>Final loop-carried values after exit.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-84"><a class="header" href="#result-and-purity-84">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None for the statement form; one value per <code>outputs</code> binding for the value-yielding form</td><td>Effectful (control flow)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-84"><a class="header" href="#annotations-84">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="break"><a class="header" href="#break"><code>break</code></a></h3>
|
||
<p>(<code>Statement::Break</code>)</p>
|
||
<h4 id="description-85"><a class="header" href="#description-85">Description</a></h4>
|
||
<p>Exit the innermost enclosing <code>for</code> loop. Carries the current values of loop-carried variables at the break point; these become the loop’s outputs.</p>
|
||
<h4 id="syntax-85"><a class="header" href="#syntax-85">Syntax</a></h4>
|
||
<pre><code class="language-text">break
|
||
</code></pre>
|
||
<h4 id="example-85"><a class="header" href="#example-85">Example</a></h4>
|
||
<pre><code class="language-text">if v0 { break [v1, v2] }
|
||
</code></pre>
|
||
<h4 id="operands-85"><a class="header" href="#operands-85">Operands</a></h4>
|
||
<p>The loop-carried <code>values: Vec<Value></code> print in brackets when non-empty (e.g. <code>break [v1, v2]</code>).</p>
|
||
<h4 id="result-and-purity-85"><a class="header" href="#result-and-purity-85">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful (control flow)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-85"><a class="header" href="#annotations-85">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="continue"><a class="header" href="#continue"><code>continue</code></a></h3>
|
||
<p>(<code>Statement::Continue</code>)</p>
|
||
<h4 id="description-86"><a class="header" href="#description-86">Description</a></h4>
|
||
<p>Skip to the post region of the innermost enclosing <code>for</code> loop. Like <code>break</code>, carries the current values of loop-carried variables internally.</p>
|
||
<h4 id="syntax-86"><a class="header" href="#syntax-86">Syntax</a></h4>
|
||
<pre><code class="language-text">continue
|
||
</code></pre>
|
||
<h4 id="example-86"><a class="header" href="#example-86">Example</a></h4>
|
||
<pre><code class="language-text">if v0 { continue [v1, v2] }
|
||
</code></pre>
|
||
<h4 id="operands-86"><a class="header" href="#operands-86">Operands</a></h4>
|
||
<p>The loop-carried <code>values</code> print in brackets when non-empty (e.g. <code>continue [v1, v2]</code>).</p>
|
||
<h4 id="result-and-purity-86"><a class="header" href="#result-and-purity-86">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful (control flow)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-86"><a class="header" href="#annotations-86">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="leave"><a class="header" href="#leave"><code>leave</code></a></h3>
|
||
<p>(<code>Statement::Leave</code>)</p>
|
||
<h4 id="description-87"><a class="header" href="#description-87">Description</a></h4>
|
||
<p>Exit the current function, returning the listed values as the function’s return values. The Yul-level <code>leave</code> keyword translates directly to this statement; the inlining pass eliminates intra-function <code>leave</code>s where possible via the exit-flag transformation.</p>
|
||
<h4 id="syntax-87"><a class="header" href="#syntax-87">Syntax</a></h4>
|
||
<pre><code class="language-text">leave [[$value_0[: <type>], $value_1[: <type>], …]]
|
||
</code></pre>
|
||
<h4 id="example-87"><a class="header" href="#example-87">Example</a></h4>
|
||
<pre><code class="language-text">leave [v0, v1] // returns v0 and v1 from the function
|
||
leave // returns nothing (void function)
|
||
</code></pre>
|
||
<h4 id="operands-87"><a class="header" href="#operands-87">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>return_values</code></td><td><code>Vec<Value></code></td><td>Empty for void functions; otherwise one entry per declared return.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-87"><a class="header" href="#result-and-purity-87">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful (control flow)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-87"><a class="header" href="#annotations-87">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="nested-block"><a class="header" href="#nested-block">Nested block</a></h3>
|
||
<p>(<code>Statement::Block</code>)</p>
|
||
<h4 id="description-88"><a class="header" href="#description-88">Description</a></h4>
|
||
<p>A lexical scope without conditional or iterative behavior. The body is a region; control falls through after the region’s statements complete. Used to bound the visibility of inner bindings.</p>
|
||
<h4 id="syntax-88"><a class="header" href="#syntax-88">Syntax</a></h4>
|
||
<pre><code class="language-text">{
|
||
…
|
||
}
|
||
</code></pre>
|
||
<h4 id="example-88"><a class="header" href="#example-88">Example</a></h4>
|
||
<pre><code class="language-text">{
|
||
let v0 := add(v1, v2)
|
||
sstore(v3, v0)
|
||
} // v0 is no longer in scope here
|
||
</code></pre>
|
||
<h4 id="operands-88"><a class="header" href="#operands-88">Operands</a></h4>
|
||
<p>None — the body is a region, not an operand.</p>
|
||
<h4 id="result-and-purity-88"><a class="header" href="#result-and-purity-88">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful (per the body’s contents)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-88"><a class="header" href="#annotations-88">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h2 id="external-interaction-1"><a class="header" href="#external-interaction-1">External interaction</a></h2>
|
||
<p>Statements that cross the contract boundary: external calls, contract creation, and event log emission. All produce or rely on external state and act as barriers to memory and storage analyses.</p>
|
||
<h3 id="call"><a class="header" href="#call"><code>call</code></a></h3>
|
||
<p>(<code>Statement::ExternalCall</code> with <code>CallKind::Call</code>)</p>
|
||
<h4 id="description-89"><a class="header" href="#description-89">Description</a></h4>
|
||
<p>Standard external call that may transfer value. Reads <code>args_length</code> bytes from emulated EVM linear memory at <code>args_offset</code> as calldata, executes the target, and writes up to <code>ret_length</code> bytes of return data into linear memory at <code>ret_offset</code>. The boolean result indicates success.</p>
|
||
<h4 id="syntax-89"><a class="header" href="#syntax-89">Syntax</a></h4>
|
||
<pre><code class="language-text">let $result := call($gas[: <type>], $address[: <type>], $value[: <type>], $args_offset[: <type>], $args_length[: <type>], $ret_offset[: <type>], $ret_length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-89"><a class="header" href="#example-89">Example</a></h4>
|
||
<pre><code class="language-text">let v8 := call(v0: i64, v1: i160, v2, v3: i64, v4: i64, v5: i64, v6: i64)
|
||
</code></pre>
|
||
<h4 id="operands-89"><a class="header" href="#operands-89">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>gas</code></td><td><code>i256</code></td><td>Gas to forward to the target; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>address</code></td><td><code>i256</code></td><td>Callee address; forward analysis widens to at least <code>i160</code>.</td></tr>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Wei to transfer with the call.</td></tr>
|
||
<tr><td><code>args_offset</code></td><td><code>i256</code></td><td>Calldata source offset in linear memory; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>args_length</code></td><td><code>i256</code></td><td>Calldata length in bytes; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>ret_offset</code></td><td><code>i256</code></td><td>Return-data destination offset in linear memory; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>ret_length</code></td><td><code>i256</code></td><td>Maximum return-data length; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-89"><a class="header" href="#result-and-purity-89">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> (success flag: <code>1</code> on success, <code>0</code> on revert/error; narrowable to <code>i1</code>)</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-89"><a class="header" href="#annotations-89">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="callcode"><a class="header" href="#callcode"><code>callcode</code></a></h3>
|
||
<p>(<code>Statement::ExternalCall</code> with <code>CallKind::CallCode</code>)</p>
|
||
<h4 id="description-90"><a class="header" href="#description-90">Description</a></h4>
|
||
<p>Deprecated EVM opcode that executes the callee’s code in the caller’s context but with the callee’s storage. Not supported by the newyork backend (codegen rejects it); use <a href="#delegatecall"><code>delegatecall</code></a> instead.</p>
|
||
<h4 id="syntax-90"><a class="header" href="#syntax-90">Syntax</a></h4>
|
||
<pre><code class="language-text">let $result := callcode($gas[: <type>], $address[: <type>], $value[: <type>], $args_offset[: <type>], $args_length[: <type>], $ret_offset[: <type>], $ret_length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-90"><a class="header" href="#example-90">Example</a></h4>
|
||
<pre><code class="language-text">let v8 := callcode(v0: i64, v1: i160, v2, v3: i64, v4: i64, v5: i64, v6: i64)
|
||
</code></pre>
|
||
<h4 id="operands-90"><a class="header" href="#operands-90">Operands</a></h4>
|
||
<p>Same shape as <a href="#call"><code>call</code></a>.</p>
|
||
<h4 id="result-and-purity-90"><a class="header" href="#result-and-purity-90">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> (success flag; narrowable to <code>i1</code>)</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-90"><a class="header" href="#annotations-90">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="delegatecall"><a class="header" href="#delegatecall"><code>delegatecall</code></a></h3>
|
||
<p>(<code>Statement::ExternalCall</code> with <code>CallKind::DelegateCall</code>)</p>
|
||
<h4 id="description-91"><a class="header" href="#description-91">Description</a></h4>
|
||
<p>Execute the callee’s code in the caller’s context: same storage, same sender, same call value. The standard mechanism for library calls and proxy patterns. No <code>value</code> operand (the caller’s call value is inherited).</p>
|
||
<h4 id="syntax-91"><a class="header" href="#syntax-91">Syntax</a></h4>
|
||
<pre><code class="language-text">let $result := delegatecall($gas[: <type>], $address[: <type>], $args_offset[: <type>], $args_length[: <type>], $ret_offset[: <type>], $ret_length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-91"><a class="header" href="#example-91">Example</a></h4>
|
||
<pre><code class="language-text">let v7 := delegatecall(v0: i64, v1: i160, v2: i64, v3: i64, v4: i64, v5: i64)
|
||
</code></pre>
|
||
<h4 id="operands-91"><a class="header" href="#operands-91">Operands</a></h4>
|
||
<p>Same shape as <a href="#call"><code>call</code></a> minus the <code>value</code> operand.</p>
|
||
<h4 id="result-and-purity-91"><a class="header" href="#result-and-purity-91">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> (success flag; narrowable to <code>i1</code>)</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-91"><a class="header" href="#annotations-91">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="staticcall"><a class="header" href="#staticcall"><code>staticcall</code></a></h3>
|
||
<p>(<code>Statement::ExternalCall</code> with <code>CallKind::StaticCall</code>)</p>
|
||
<h4 id="description-92"><a class="header" href="#description-92">Description</a></h4>
|
||
<p>Read-only external call. Any state modification in the callee (including nested calls) causes the call to revert. No <code>value</code> operand.</p>
|
||
<h4 id="syntax-92"><a class="header" href="#syntax-92">Syntax</a></h4>
|
||
<pre><code class="language-text">let $result := staticcall($gas[: <type>], $address[: <type>], $args_offset[: <type>], $args_length[: <type>], $ret_offset[: <type>], $ret_length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-92"><a class="header" href="#example-92">Example</a></h4>
|
||
<pre><code class="language-text">let v7 := staticcall(v0: i64, v1: i160, v2: i64, v3: i64, v4: i64, v5: i64)
|
||
</code></pre>
|
||
<h4 id="operands-92"><a class="header" href="#operands-92">Operands</a></h4>
|
||
<p>Same shape as <a href="#call"><code>call</code></a> minus the <code>value</code> operand.</p>
|
||
<h4 id="result-and-purity-92"><a class="header" href="#result-and-purity-92">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> (success flag; narrowable to <code>i1</code>)</td><td>Effectful (no state writes, but still an external boundary and may revert)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-92"><a class="header" href="#annotations-92">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="create"><a class="header" href="#create"><code>create</code></a></h3>
|
||
<p>(<code>Statement::Create</code> with <code>CreateKind::Create</code>)</p>
|
||
<h4 id="description-93"><a class="header" href="#description-93">Description</a></h4>
|
||
<p>Deploy a new contract with the given init-code bytes, transferring <code>value</code> wei from the caller. The new contract’s address is derived from the caller’s address and nonce; on failure the result is <code>0</code>.</p>
|
||
<h4 id="syntax-93"><a class="header" href="#syntax-93">Syntax</a></h4>
|
||
<pre><code class="language-text">let $result := create($value[: <type>], $offset[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-93"><a class="header" href="#example-93">Example</a></h4>
|
||
<pre><code class="language-text">let v4 := create(v0, v1: i64, v2: i64)
|
||
</code></pre>
|
||
<h4 id="operands-93"><a class="header" href="#operands-93">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>value</code></td><td><code>i256</code></td><td>Wei to transfer to the new contract.</td></tr>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Linear-memory offset of the init code; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Length of the init code in bytes; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-93"><a class="header" href="#result-and-purity-93">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> (created address; narrowable to <code>i160</code> on success, <code>0</code> on failure)</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-93"><a class="header" href="#annotations-93">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="create2"><a class="header" href="#create2"><code>create2</code></a></h3>
|
||
<p>(<code>Statement::Create</code> with <code>CreateKind::Create2</code>)</p>
|
||
<h4 id="description-94"><a class="header" href="#description-94">Description</a></h4>
|
||
<p>Deploy a new contract with a deterministic address derived from the caller’s address, the salt, and the init-code hash. Same operand shape as <a href="#create"><code>create</code></a> plus an additional <code>salt</code>.</p>
|
||
<h4 id="syntax-94"><a class="header" href="#syntax-94">Syntax</a></h4>
|
||
<pre><code class="language-text">let $result := create2($value[: <type>], $offset[: <type>], $length[: <type>], $salt[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-94"><a class="header" href="#example-94">Example</a></h4>
|
||
<pre><code class="language-text">let v5 := create2(v0, v1: i64, v2: i64, v3)
|
||
</code></pre>
|
||
<h4 id="operands-94"><a class="header" href="#operands-94">Operands</a></h4>
|
||
<p>Same as <a href="#create"><code>create</code></a> plus <code>salt: i256</code>.</p>
|
||
<h4 id="result-and-purity-94"><a class="header" href="#result-and-purity-94">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>i256</code> (created address; narrowable to <code>i160</code> on success, <code>0</code> on failure)</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-94"><a class="header" href="#annotations-94">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="logn"><a class="header" href="#logn"><code>log<N></code></a></h3>
|
||
<p>(<code>Statement::Log</code>)</p>
|
||
<h4 id="description-95"><a class="header" href="#description-95">Description</a></h4>
|
||
<p>Emit an event log entry. The mnemonic suffix <code><N></code> is the number of indexed topics (<code>0</code> through <code>4</code>), determined by the length of the IR’s <code>topics</code> field. The data portion is read from <code>length</code> bytes of emulated EVM linear memory at <code>offset</code>.</p>
|
||
<h4 id="syntax-95"><a class="header" href="#syntax-95">Syntax</a></h4>
|
||
<pre><code class="language-text">log<N>($offset[: <type>], $length[: <type>][, $topic_0[: <type>], …])
|
||
</code></pre>
|
||
<h4 id="example-95"><a class="header" href="#example-95">Example</a></h4>
|
||
<pre><code class="language-text">log0(v0: i64, v1: i64) // no topics
|
||
log2(v0: i64, v1: i64, v2, v3) // two topics
|
||
</code></pre>
|
||
<h4 id="operands-95"><a class="header" href="#operands-95">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Data source offset in linear memory; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Data length in bytes; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>topics</code></td><td><code>Vec<Value></code></td><td>Zero to four indexed topic values; the length determines the mnemonic suffix.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-95"><a class="header" href="#result-and-purity-95">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None</td><td>Effectful</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-95"><a class="header" href="#annotations-95">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h2 id="termination-1"><a class="header" href="#termination-1">Termination</a></h2>
|
||
<p>Statements that end the current call frame. Plain forms (<code>return</code>, <code>revert</code>, <code>stop</code>), unconditional traps (<code>invalid</code>, <code>selfdestruct</code>), and outlined revert variants (<code>panic_revert</code>, <code>error_string_revert</code>, <code>custom_error_revert</code>) that encode common Solidity error patterns into single nodes that can be deduplicated across call sites.</p>
|
||
<h3 id="return"><a class="header" href="#return"><code>return</code></a></h3>
|
||
<p>(<code>Statement::Return</code>)</p>
|
||
<h4 id="description-96"><a class="header" href="#description-96">Description</a></h4>
|
||
<p>End the current call frame successfully, returning <code>length</code> bytes from emulated EVM linear memory at <code>offset</code> as the return data.</p>
|
||
<h4 id="syntax-96"><a class="header" href="#syntax-96">Syntax</a></h4>
|
||
<pre><code class="language-text">return($offset[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-96"><a class="header" href="#example-96">Example</a></h4>
|
||
<pre><code class="language-text">return(v0: i64, v1: i64)
|
||
</code></pre>
|
||
<h4 id="operands-96"><a class="header" href="#operands-96">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Return-data source offset; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Return-data length; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-96"><a class="header" href="#result-and-purity-96">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None — terminates the call frame</td><td>Effectful (terminator)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-96"><a class="header" href="#annotations-96">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="revert"><a class="header" href="#revert"><code>revert</code></a></h3>
|
||
<p>(<code>Statement::Revert</code>)</p>
|
||
<h4 id="description-97"><a class="header" href="#description-97">Description</a></h4>
|
||
<p>End the current call frame with a revert, undoing all state changes made during the call, and returning <code>length</code> bytes of revert data from emulated EVM linear memory at <code>offset</code>.</p>
|
||
<h4 id="syntax-97"><a class="header" href="#syntax-97">Syntax</a></h4>
|
||
<pre><code class="language-text">revert($offset[: <type>], $length[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-97"><a class="header" href="#example-97">Example</a></h4>
|
||
<pre><code class="language-text">revert(v0: i64, v1: i64)
|
||
</code></pre>
|
||
<h4 id="operands-97"><a class="header" href="#operands-97">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>offset</code></td><td><code>i256</code></td><td>Revert-data source offset; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
<tr><td><code>length</code></td><td><code>i256</code></td><td>Revert-data length; forward analysis widens to at least <code>i64</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-97"><a class="header" href="#result-and-purity-97">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None — terminates the call frame</td><td>Effectful (terminator)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-97"><a class="header" href="#annotations-97">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="stop"><a class="header" href="#stop"><code>stop</code></a></h3>
|
||
<p>(<code>Statement::Stop</code>)</p>
|
||
<h4 id="description-98"><a class="header" href="#description-98">Description</a></h4>
|
||
<p>End the current call frame successfully with empty return data.</p>
|
||
<h4 id="syntax-98"><a class="header" href="#syntax-98">Syntax</a></h4>
|
||
<pre><code class="language-text">stop()
|
||
</code></pre>
|
||
<h4 id="example-98"><a class="header" href="#example-98">Example</a></h4>
|
||
<pre><code class="language-text">stop()
|
||
</code></pre>
|
||
<h4 id="operands-98"><a class="header" href="#operands-98">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-98"><a class="header" href="#result-and-purity-98">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None — terminates the call frame</td><td>Effectful (terminator)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-98"><a class="header" href="#annotations-98">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="invalid"><a class="header" href="#invalid"><code>invalid</code></a></h3>
|
||
<p>(<code>Statement::Invalid</code>)</p>
|
||
<h4 id="description-99"><a class="header" href="#description-99">Description</a></h4>
|
||
<p>Unconditional invalid-opcode trap. Consumes all remaining gas and reverts. Used for unreachable branches and assertion failures.</p>
|
||
<h4 id="syntax-99"><a class="header" href="#syntax-99">Syntax</a></h4>
|
||
<pre><code class="language-text">invalid()
|
||
</code></pre>
|
||
<h4 id="example-99"><a class="header" href="#example-99">Example</a></h4>
|
||
<pre><code class="language-text">invalid()
|
||
</code></pre>
|
||
<h4 id="operands-99"><a class="header" href="#operands-99">Operands</a></h4>
|
||
<p>None.</p>
|
||
<h4 id="result-and-purity-99"><a class="header" href="#result-and-purity-99">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None — terminates the call frame</td><td>Effectful (terminator)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-99"><a class="header" href="#annotations-99">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="selfdestruct"><a class="header" href="#selfdestruct"><code>selfdestruct</code></a></h3>
|
||
<p>(<code>Statement::SelfDestruct</code>)</p>
|
||
<h4 id="description-100"><a class="header" href="#description-100">Description</a></h4>
|
||
<p>End the current call frame and transfer the contract’s remaining balance to <code>address</code>. Post-Cancun, the contract storage is not deleted (selfdestruct is effectively deprecated; the opcode still exists for legacy compatibility).</p>
|
||
<h4 id="syntax-100"><a class="header" href="#syntax-100">Syntax</a></h4>
|
||
<pre><code class="language-text">selfdestruct($address[: <type>])
|
||
</code></pre>
|
||
<h4 id="example-100"><a class="header" href="#example-100">Example</a></h4>
|
||
<pre><code class="language-text">selfdestruct(v0: i160)
|
||
</code></pre>
|
||
<h4 id="operands-100"><a class="header" href="#operands-100">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>address</code></td><td><code>i256</code></td><td>Recipient of the contract’s balance; forward analysis widens to at least <code>i160</code>.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-100"><a class="header" href="#result-and-purity-100">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None — terminates the call frame</td><td>Effectful (terminator)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-100"><a class="header" href="#annotations-100">Annotations</a></h4>
|
||
<p>None.</p>
|
||
<h3 id="panic_revert"><a class="header" href="#panic_revert"><code>panic_revert</code></a></h3>
|
||
<p>(<code>Statement::PanicRevert</code>)</p>
|
||
<h4 id="description-101"><a class="header" href="#description-101">Description</a></h4>
|
||
<p>Outlined Solidity panic revert. Equivalent to writing the <code>Panic(uint256)</code> ABI encoding (selector <code>0x4e487b71</code> plus the panic code) into emulated EVM linear memory and reverting, but emitted as a single statement that lowers to one outlined helper call. Common panic codes: <code>0x01</code> assertion failure, <code>0x11</code> arithmetic overflow, <code>0x12</code> division by zero, <code>0x32</code> array-out-of-bounds, <code>0x41</code> memory overflow.</p>
|
||
<h4 id="syntax-101"><a class="header" href="#syntax-101">Syntax</a></h4>
|
||
<pre><code class="language-text">panic_revert(0x<hex>)
|
||
</code></pre>
|
||
<h4 id="example-101"><a class="header" href="#example-101">Example</a></h4>
|
||
<pre><code class="language-text">panic_revert(0x11) // arithmetic overflow
|
||
</code></pre>
|
||
<h4 id="operands-101"><a class="header" href="#operands-101">Operands</a></h4>
|
||
<p>None — the panic code is stored as a <code>u8</code> field on the IR, not an SSA operand.</p>
|
||
<h4 id="result-and-purity-101"><a class="header" href="#result-and-purity-101">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None — terminates the call frame</td><td>Effectful (terminator)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-101"><a class="header" href="#annotations-101">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>code: u8</code></td><td>The panic code in <code>0x<hex></code> form (two hex digits, zero-padded).</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="error_string_revert"><a class="header" href="#error_string_revert"><code>error_string_revert</code></a></h3>
|
||
<p>(<code>Statement::ErrorStringRevert</code>)</p>
|
||
<h4 id="description-102"><a class="header" href="#description-102">Description</a></h4>
|
||
<p>Outlined Solidity <code>Error(string)</code> revert. Equivalent to writing the <code>Error</code> selector (<code>0x08c379a0</code>), the string offset and length, and up to four 32-byte data words into emulated EVM linear memory and reverting. The string length and the data words are stored as compile-time fields; no SSA operands.</p>
|
||
<h4 id="syntax-102"><a class="header" href="#syntax-102">Syntax</a></h4>
|
||
<pre><code class="language-text">error_string_revert(<length>, <N>_words)
|
||
</code></pre>
|
||
<h4 id="example-102"><a class="header" href="#example-102">Example</a></h4>
|
||
<pre><code class="language-text">error_string_revert(12, 1_words) // 12-byte string in one 32-byte word
|
||
</code></pre>
|
||
<h4 id="operands-102"><a class="header" href="#operands-102">Operands</a></h4>
|
||
<p>None — the string length and data are compile-time fields, not SSA operands.</p>
|
||
<h4 id="result-and-purity-102"><a class="header" href="#result-and-purity-102">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None — terminates the call frame</td><td>Effectful (terminator)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-102"><a class="header" href="#annotations-102">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>length: u8</code></td><td>The string length in bytes, in the first syntax position.</td></tr>
|
||
<tr><td><code>data: Vec<BigUint></code></td><td>The number of 32-byte data words (1–4), printed as <code><N>_words</code> in the second syntax position. The actual data is stored separately and not shown in the printed form.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h3 id="custom_error_revert"><a class="header" href="#custom_error_revert"><code>custom_error_revert</code></a></h3>
|
||
<p>(<code>Statement::CustomErrorRevert</code>)</p>
|
||
<h4 id="description-103"><a class="header" href="#description-103">Description</a></h4>
|
||
<p>Outlined Solidity custom-error revert. Encodes the error selector (left-shifted by 224 bits) and zero or more argument values into scratch memory and reverts. No FMP load is needed; the encoding uses the scratch region at offset <code>0</code>.</p>
|
||
<h4 id="syntax-103"><a class="header" href="#syntax-103">Syntax</a></h4>
|
||
<pre><code class="language-text">custom_error_revert(0x<hex>, [$arg_0, $arg_1, …])
|
||
</code></pre>
|
||
<h4 id="example-103"><a class="header" href="#example-103">Example</a></h4>
|
||
<pre><code class="language-text">custom_error_revert(0xa28c4c11, [v0, v1])
|
||
</code></pre>
|
||
<h4 id="operands-103"><a class="header" href="#operands-103">Operands</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Name</th><th>Type</th><th>Notes</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>arguments</code></td><td><code>Vec<Value></code></td><td>Zero or more argument values; the selector is a compile-time field.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="result-and-purity-103"><a class="header" href="#result-and-purity-103">Result and purity</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Result</th><th>Purity</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>None — terminates the call frame</td><td>Effectful (terminator)</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<h4 id="annotations-103"><a class="header" href="#annotations-103">Annotations</a></h4>
|
||
<div class="table-wrapper">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Source field</th><th>Printed as</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td><code>selector: BigUint</code></td><td>The 4-byte error selector in hex, in the first syntax position. The selector is stored left-shifted by 224 bits; the printer right-shifts it back and prints the bare 4-byte value.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
</main>
|
||
|
||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||
<!-- Mobile navigation buttons -->
|
||
<a rel="prev" href="../developer_guide/newyork_optimizer.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span>
|
||
</a>
|
||
|
||
<a rel="next prefetch" href="../developer_guide/target.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span>
|
||
</a>
|
||
|
||
<div style="clear: both"></div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||
<a rel="prev" href="../developer_guide/newyork_optimizer.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span>
|
||
</a>
|
||
|
||
<a rel="next prefetch" href="../developer_guide/target.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span>
|
||
</a>
|
||
</nav>
|
||
|
||
</div>
|
||
|
||
<template id=fa-eye><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z"/></svg></span></template>
|
||
<template id=fa-eye-slash><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z"/></svg></span></template>
|
||
<template id=fa-copy><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z"/></svg></span></template>
|
||
<template id=fa-play><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80V432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z"/></svg></span></template>
|
||
<template id=fa-clock-rotate-left><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M75 75L41 41C25.9 25.9 0 36.6 0 57.9V168c0 13.3 10.7 24 24 24H134.1c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24V256c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65V152c0-13.3-10.7-24-24-24z"/></svg></span></template>
|
||
|
||
<!-- Livereload script (if served using the cli tool) -->
|
||
<script>
|
||
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
|
||
const socket = new WebSocket(wsAddress);
|
||
socket.onmessage = function (event) {
|
||
if (event.data === "reload") {
|
||
socket.close();
|
||
location.reload();
|
||
}
|
||
};
|
||
|
||
window.onbeforeunload = function() {
|
||
socket.close();
|
||
}
|
||
</script>
|
||
|
||
|
||
<script>
|
||
window.playground_copyable = true;
|
||
</script>
|
||
|
||
|
||
<script src="../elasticlunr-ef4e11c1.min.js"></script>
|
||
<script src="../mark-09e88c2c.min.js"></script>
|
||
<script src="../searcher-c2a407aa.js"></script>
|
||
|
||
<script src="../clipboard-1626706a.min.js"></script>
|
||
<script src="../highlight-abc7f01d.js"></script>
|
||
<script src="../book-a0b12cfe.js"></script>
|
||
|
||
<!-- Custom JS scripts -->
|
||
|
||
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|