<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[201525] trunk/Websites/webkit.org</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/201525">201525</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-05-31 14:40:18 -0700 (Tue, 31 May 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Air needs documentation
https://bugs.webkit.org/show_bug.cgi?id=153668

Reviewed by Mark Lam, Saam Barati, and Benjamin Poulain.
        
Write documentation for Air!

* docs/b3/assembly-intermediate-representation.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkWebsiteswebkitorgChangeLog">trunk/Websites/webkit.org/ChangeLog</a></li>
<li><a href="#trunkWebsiteswebkitorgdocsb3assemblyintermediaterepresentationhtml">trunk/Websites/webkit.org/docs/b3/assembly-intermediate-representation.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkWebsiteswebkitorgChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Websites/webkit.org/ChangeLog (201524 => 201525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/webkit.org/ChangeLog        2016-05-31 21:24:19 UTC (rev 201524)
+++ trunk/Websites/webkit.org/ChangeLog        2016-05-31 21:40:18 UTC (rev 201525)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-05-31  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Air needs documentation
+        https://bugs.webkit.org/show_bug.cgi?id=153668
+
+        Reviewed by Mark Lam, Saam Barati, and Benjamin Poulain.
+        
+        Write documentation for Air!
+
+        * docs/b3/assembly-intermediate-representation.html:
+
</ins><span class="cx"> 2016-05-23  Jon Davis  &lt;jond@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add syntax highglighting for ES6 &quot;let&quot;, &quot;const&quot; and &quot;of&quot; keywords.
</span></span></pre></div>
<a id="trunkWebsiteswebkitorgdocsb3assemblyintermediaterepresentationhtml"></a>
<div class="modfile"><h4>Modified: trunk/Websites/webkit.org/docs/b3/assembly-intermediate-representation.html (201524 => 201525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/webkit.org/docs/b3/assembly-intermediate-representation.html        2016-05-31 21:24:19 UTC (rev 201524)
+++ trunk/Websites/webkit.org/docs/b3/assembly-intermediate-representation.html        2016-05-31 21:40:18 UTC (rev 201525)
</span><span class="lines">@@ -14,10 +14,341 @@
</span><span class="cx">   &lt;/div&gt;
</span><span class="cx">   &lt;div id=&quot;contents&quot;&gt;
</span><span class="cx">     &lt;h1&gt;&lt;a href=&quot;index.html&quot;&gt;Bare Bones Backend&lt;/a&gt; / Assembly Intermediate Representation&lt;/h1&gt;
</span><del>-    &lt;p&gt;The B3 compiler converts SSA procedures into efficient machine code by first converting
-      them to a form that reveals machine details, like registers. This form is called Assembly
-      Intermediate Representation, or just Air for short.&lt;/p&gt;
-
</del><ins>+    &lt;p&gt;The B3 compiler comprises two intermediate representations: a higher-level
+      &lt;a href=&quot;https://en.wikipedia.org/wiki/Static_single_assignment_form&quot;&gt;SSA&lt;/a&gt;-based
+      representation called &lt;a href=&quot;intermediate-representation.html&quot;&gt;B3 IR&lt;/a&gt; and a lower-level
+      representation that focuses of machine details, like registers. This lower-level form is called
+      Air (Assembly Intermediate Representation).&lt;/p&gt;
+    
+    &lt;p&gt;Air programs are represented using a
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirCode.h&quot;&gt;&lt;code&gt;Air::Code&lt;/code&gt;&lt;/a&gt;
+      object. &lt;code&gt;Code&lt;/code&gt; comprises an array of
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirBasicBlock.h&quot;&gt;basic
+        blocks&lt;/a&gt;. Each basic block comprises an array of
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirInst.h&quot;&gt;&lt;code&gt;Inst&lt;/code&gt;&lt;/a&gt;s.
+      Air has an explicit control flow graph: each basic block has predecessor and successor blocks.
+      Execution always begins at the first basic block (&lt;code&gt;code[0]&lt;/code&gt;). The &lt;code&gt;Inst&lt;/code&gt;s
+      in each block are executed in order. Each &lt;code&gt;Inst&lt;/code&gt; has an opcode, an array of
+      arguments
+      (&lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirArg.h&quot;&gt;&lt;code&gt;Arg&lt;/code&gt;&lt;/a&gt;s),
+      and an origin. The origin is simply a B3 IR
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/B3Value.h&quot;&gt;&lt;code&gt;Value&lt;/code&gt;&lt;/a&gt;.
+      Some opcodes use the origin for additional meta-data. This works because Air code always
+      coexists with the B3 procedure from which it was generated.&lt;/p&gt;
+    
+    &lt;p&gt;This document begins by describing the philosophy of Air. The behavior of &lt;code&gt;Arg&lt;/code&gt;s is
+      central to Air's execution model, which is described in the section that follows. The last
+      section describes the way Air opcodes are defined.&lt;/p&gt;
+    
+    &lt;h2&gt;Philosophy of Air&lt;/h2&gt;
+    
+    &lt;p&gt;B3 is designed to be portable to many kinds of CPUs. Currently, it supports x86-64 and ARM64,
+      which are quite different from each other. In B3 IR, we expose very few instruction set
+      details. Most clients only have to worry about the pointer type varying between Int32 and
+      Int64. It's a goal of B3 IR to ensure that B3 values behave the same way except when the
+      alternative would be prohibitive (like with pointer size or the corner-case behaviors of
+      division). But to effectively compile code to different CPUs, the compiler has to eventually
+      make instruction set details explicit. This is where Air comes in. B3 locks in most
+      CPU-specific details at the moment of conversion to Air, and the Air code is irreversibly tied
+      to some specific CPU.&lt;/p&gt;
+    
+    &lt;p&gt;Air is an instruction &lt;i&gt;superset&lt;/i&gt;: it recognizes all of the instructions from all CPUs
+      that Air may target. In its lowest-level form, Air is simply a way of describing an assembly
+      instruction sequence, and this includes CPU concepts like registers and direct accesses to the
+      stack. Air also has a higher-level form in which the assembly has not yet undergone register
+      or stack allocation. Therefore, Air also supports abstract registers (called
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirTmp.h&quot;&gt;&lt;code&gt;Tmp&lt;/code&gt;&lt;/a&gt;s)
+      and abstract
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirStackSlot.h&quot;&gt;stack
+        slots&lt;/a&gt;.&lt;/p&gt;
+    
+    &lt;h3&gt;Air as an Instruction Superset&lt;/h3&gt;
+    &lt;p&gt;It is possible to speak of an x86-64 instruction while compiling for ARM64,
+      for example. Clients of Air, such as the B3 to Air lowering phase, are allowed to pick with any
+      Air opcode and ask if that opcode would be valid on the current CPU. They are also allowed to
+      check if specific forms of any given opcode are valid. This allows clients to optimize for
+      multiple instruction sets by cascading through the possible opcodes that they know of, starting
+      with the one they think is most efficient. Some of those opcodes may only be available on one
+      CPU while others are available everywhere.&lt;/p&gt;
+    
+    &lt;p&gt;Air opcodes support overloading. For example, the Add32 opcode has both two-operand and
+      three-operand overloads, and those overloads have multiple forms: the first operand may or
+      may not be an immediate and depending on the CPU, some of the other operands may or may not
+      be memory addresses. A fundamental Air operation is &lt;code&gt;Inst::isValidForm()&lt;/code&gt;, which
+      tells the client if the instruction's current form is valid on the current CPU. This may
+      return false either because the Inst is not well-formed for any CPU or because it is not
+      valid for the current CPU even though it may be valid on some other CPU. This allows clients
+      to generate Air by experimenting with various different instruction forms before settling on
+      the one that the current CPU supports.&lt;/p&gt;
+    
+    &lt;h3&gt;Air as a High-Level Assembly&lt;/h3&gt;
+    &lt;p&gt;Air doesn't require the client to perform register or stack allocation. Anywhere that Air
+      accepts a register it will also accept a &lt;code&gt;Tmp&lt;/code&gt;. Anywhere that Air accepts an address
+      it will also accept a stack slot reference. Air code generation comprises a register allocator
+      and a stack allocator, which turn &lt;code&gt;Tmp&lt;/code&gt;s into &lt;code&gt;Reg&lt;/code&gt;s and stack slots into
+      addresses with the frame pointer (or stack pointer) as the base and some integer offset. Air
+      allows clients to speak of registers directly even while also using &lt;code&gt;Tmp&lt;/code&gt;s, and the
+      register allocator will ensure that it avoids clobbering registers that the client code already
+      relies upon. This is possible because Air has precise modeling of how instructions use
+      registers, so it's always possible to determine which registers are live at any point in the
+      Air code.&lt;/p&gt;
+    
+    &lt;p&gt;Air's philosophy allows B3 to use it for converting high-level, CPU-agnostic SSA procedures
+      into code for the current CPU. Air is an instruction superset that allows clients to consider
+      all available instructions on all possible CPUs and query which forms of those instructions are
+      available on the current CPU. Air also supports for high-level concepts like &lt;code&gt;Tmp&lt;/code&gt;s
+      and stack slots, which allows B3 to Air lowering to focus on which instructions to use without
+      worrying about register allocation or stack layout.&lt;/p&gt;
+    
+    &lt;h2&gt;Args and the Air Execution Model&lt;/h2&gt;
+    &lt;p&gt;Air can be thought of as an
+      &lt;a href=&quot;https://en.wikipedia.org/wiki/Orthogonal_instruction_set&quot;&gt;orthogonal instruction
+        set&lt;/a&gt;. It's possible to construct an &lt;code&gt;Inst&lt;/code&gt; with any combination of opcode and
+      arguments. The opcode determines what Air will do to the arguments - it may read from them or
+      write to them, for example. Orthognality implies that any argument that is read may be either
+      a register (or &lt;code&gt;Tmp&lt;/code&gt;), an address, or an immediate; while any argument that is
+      written may be either a register or an address. Air constraints orthognality where the target
+      CPU would. For example, none of Air's target CPUs would support an &lt;code&gt;Add32&lt;/code&gt;
+      instruction that loads its sources from memory &lt;i&gt;and&lt;/i&gt; stores its result into memory. Even
+      x86 doesn't go that far. Either before or after creating an &lt;code&gt;Inst&lt;/code&gt;, the client can
+      query if a particular combination of arguments (for example, three memory addresses) would be
+      valid for a given opcode (for example, &lt;code&gt;Add32&lt;/code&gt;).&lt;/p&gt;
+    
+    &lt;p&gt;Air arguments are represented using the &lt;code&gt;Arg&lt;/code&gt; object. &lt;code&gt;Arg&lt;/code&gt; can
+      represent any of the following assembly operands:&lt;/p&gt;
+    
+    &lt;dl&gt;
+      &lt;dt&gt;Tmp&lt;/dt&gt;
+      &lt;dd&gt;A &lt;code&gt;Tmp&lt;/code&gt; represents either a register or a temporary.&lt;/dd&gt;
+      
+      &lt;dt&gt;Imm, BigImm, BitImm, and BitImm64&lt;/dt&gt;
+      &lt;dd&gt;These are various kinds of immediates. We distinguish between big and small immediates
+        because some instructions only allow immediates within a certain range. We distinguish
+        between immediates for bit operations and immediates for all other operations because ARM
+        has different constraints on the values of immediates depending on whether they are used for
+        bit math.&lt;/dd&gt;
+      
+      &lt;dt&gt;Addr, Stack, CallArg, and Index&lt;/dt&gt;
+      &lt;dd&gt;These are all memory addresses. Addr is a base-offset address, which uses a &lt;code&gt;Tmp&lt;/code&gt;
+        for the base and an immediate for the offset. Stack and CallArg are abstract stack offsets.
+        Index is a base-index address, which has a pair of &lt;code&gt;Tmp&lt;/code&gt;s (base and index) as well
+        as an offset immediate and a scaling immediate for the index.&lt;/dd&gt;
+      
+      &lt;dt&gt;RelCond, ResCond, and DoubleCond&lt;/dt&gt;
+      &lt;dd&gt;These are condition codes for various kinds of branches.&lt;/dd&gt;
+      
+      &lt;dt&gt;Special&lt;/dt&gt;
+      &lt;dd&gt;Air allows certain &lt;code&gt;Inst&lt;/code&gt;s to point to additional meta-data. The Special
+        argument type is used for such meta-data. It holds a &lt;code&gt;Arg::Special*&lt;/code&gt;.&lt;/dd&gt;
+      
+      &lt;dt&gt;WidthArg&lt;/dt&gt;
+      &lt;dd&gt;Some special Air opcodes take operands that describe the width of the operation. Possible
+        values are &lt;code&gt;Width8&lt;/code&gt;, &lt;code&gt;Width16&lt;/code&gt;, &lt;code&gt;Width32&lt;/code&gt;, and
+        &lt;code&gt;Width64&lt;/code&gt;.&lt;/dd&gt;
+    &lt;/dl&gt;
+    
+    &lt;p&gt;The opcode of an &lt;code&gt;Inst&lt;/code&gt; combined with the overload - i.e. the number of arguments
+      - determines what the &lt;code&gt;Inst&lt;/code&gt; will do to each argument. The behavior of arguments
+      comes down to three dimensions that are determined by the opcode and overload:&lt;/p&gt;
+    
+    &lt;dl&gt;
+      &lt;dt&gt;Role&lt;/dt&gt;
+      &lt;dd&gt;The role of an argument is an enum that describes the timing of when the argument is
+        accessed, how it's accessed (use, a.k.a. read; or def, a.k.a write), how important that
+        access is for performance (either &lt;i&gt;warm&lt;/i&gt; or &lt;i&gt;cold&lt;/i&gt;), and how writes affect the top
+        bits (either ignores them or zero-fills them). The timing of an argument role is discussed
+        further below. The performance requirements of an argument are used for register allocation
+        prioritization. A warm argument is counted towards the register allocation priority
+        heuristic, while a cold one isn't.&lt;/dd&gt;
+      
+      &lt;dt&gt;Type&lt;/dt&gt;
+      &lt;dd&gt;Air recognizes two types, &lt;code&gt;GP&lt;/code&gt; (general purpose) and &lt;code&gt;FP&lt;/code&gt; (floating
+        point). Arguments also have type. It's important to remember that there is both a type for
+        the argument as determined by the opcode and overload, and a type of the argument itself.
+        Some arguments are untyped, which means that they may be used regardless of the type desired
+        by the opcode/overload. For example, addresses are untyped. Other arguments have specific
+        type, like registers and &lt;code&gt;Tmp&lt;/code&gt;s. Except for &lt;code&gt;BigImm&lt;/code&gt;, immediates are
+        &lt;code&gt;GP&lt;/code&gt;.&lt;/dd&gt;
+      
+      &lt;dt&gt;Width&lt;/dt&gt;
+      &lt;dd&gt;The amount of bits, starting at lowest-order, that the instruction affects. Possible values
+        are &lt;code&gt;Width8&lt;/code&gt;, &lt;code&gt;Width16&lt;/code&gt;, &lt;code&gt;Width32&lt;/code&gt;, and
+        &lt;code&gt;Width64&lt;/code&gt;.&lt;/dd&gt;
+    &lt;/dl&gt;
+    
+    &lt;p&gt;The timing of an argument role is important, and brings us to the order of execution of an
+      &lt;code&gt;Inst&lt;/code&gt;. Each &lt;code&gt;Inst&lt;/code&gt; can be thought of as executing three
+      steps:&lt;/p&gt;
+    
+    &lt;ol&gt;
+      &lt;li&gt;Perform &lt;i&gt;early&lt;/i&gt; actions.&lt;/li&gt;
+      &lt;li&gt;Perform &lt;i&gt;primary&lt;/i&gt; actions.&lt;/li&gt;
+      &lt;li&gt;Perform &lt;i&gt;late&lt;/i&gt; actions.&lt;/li&gt;
+    &lt;/ol&gt;
+    
+    &lt;p&gt;Note that the early actions of one instruction happen immediately after the late actions of
+      the instruction before it. However, many Air analyses view them as happening at the same time.
+      For example, any register usage in the early action of one instruction interfere with the
+      register usage in the late action of the instruction that came before it. All of Air's
+      liveness and interference analyses reason about the
+      &lt;a href=&quot;https://en.wikipedia.org/wiki/Off-by-one_error#Fencepost_error&quot;&gt;&lt;i&gt;fence posts&lt;/i&gt;&lt;/a&gt;
+      between instructions, where the late actions of the previous instruction and the early actions
+      of the next form an interference clique.&lt;/p&gt;
+    
+    &lt;p&gt;Let's consider a simple example, like &lt;code&gt;Add32&lt;/code&gt; with two arguments. Let's say that
+      the first argument is a memory location and the second argument is a register. Air uses the
+      &lt;a href=&quot;https://en.wikipedia.org/wiki/X86_assembly_language#Syntax&quot;&gt;AT&amp;amp;T style&lt;/a&gt; of
+      placing the destination argument last for most instructions. This Add32 loads from memory and
+      adds the value to the register. Air writes this as:&lt;/p&gt;
+    
+    &lt;pre&gt;&lt;code&gt;Add32 42(%rax), %rcx&lt;/code&gt;&lt;/pre&gt;
+    
+    &lt;p&gt;This instruction will proceed in three steps:&lt;/p&gt;
+    
+    &lt;ol&gt;
+      &lt;li&gt;Load the value at offset 42 from the memory address in &lt;code&gt;%rax&lt;/code&gt;. The result is
+        stored in an internal, hidden CPU location for the remainder of execution. Even if the
+        instruction later stores to memory and overwrites this value, &lt;code&gt;Add32&lt;/code&gt; will still
+        use the original value it had loaded. We say that this is an &lt;i&gt;early use&lt;/i&gt;. At the same
+        time, the CPU will load the value of &lt;code&gt;%rcx&lt;/code&gt; and store it in a hidden CPU
+        location. This is also an early use.&lt;/li&gt;
+      &lt;li&gt;Add the two values together. Store the result in hidden CPU location.&lt;/li&gt;
+      &lt;li&gt;Zero-extend the resulting value and store it into &lt;code&gt;%rcx&lt;/code&gt;. This is a &lt;i&gt;late
+          def with zero extension&lt;/i&gt;.&lt;/li&gt;
+    &lt;/ol&gt;
+    
+    &lt;p&gt;Therefore, the two-argument overload of &lt;code&gt;Add32&lt;/code&gt; ascribes the following to its
+      arguments:&lt;/p&gt;
+    
+    &lt;ul&gt;
+      &lt;li&gt;The roles are &lt;i&gt;early warm use&lt;/i&gt; for the first argument (&lt;code&gt;42(%rax)&lt;/code&gt;) and
+        &lt;i&gt;early warm use with late warm def with zero extension&lt;/i&gt; for the second argument
+        (&lt;code&gt;%rcx&lt;/code&gt;). Early warm use is written as &lt;code&gt;Use&lt;/code&gt; for short. Early warm
+        use with late warm def with zero extension is written as &lt;code&gt;UseZDef&lt;/code&gt; for
+        short.&lt;/li&gt;
+      &lt;li&gt;The types of both arguments are &lt;code&gt;GP&lt;/code&gt;. This matches &lt;code&gt;42(%rax)&lt;/code&gt; because
+        addresses match any type. This matches &lt;code&gt;%rcx&lt;/code&gt; because it's a general-purpose
+        register.&lt;/li&gt;
+      &lt;li&gt;The widths of both arguments are &lt;code&gt;Width32&lt;/code&gt;. Combined with &lt;code&gt;UseZDef&lt;/code&gt;,
+        this means that the instruction will read the low 32 bits of &lt;code&gt;%rcx&lt;/code&gt; in the early
+        actions and it will store to &lt;i&gt;all&lt;/i&gt; bits of &lt;code&gt;%rcx&lt;/code&gt; in the late actions, but it
+        will ensure that all but the low 32 bits are zero.&lt;/li&gt;
+    &lt;/ul&gt;
+    
+    &lt;p&gt;Air can tell you what role, type, and width is ascribed to each argument by using the
+      &lt;code&gt;Inst::forEachArg(func)&lt;/code&gt; operation. It takes a callback of type
+      &lt;code&gt;void(Arg&amp;, Arg::Role, Arg::Type, Arg::Width)&lt;/code&gt;. For our &lt;code&gt;Add32&lt;/code&gt; example,
+      this callback would get called twice:&lt;/p&gt;
+    
+    &lt;ol&gt;
+      &lt;li&gt;&lt;code&gt;func(42(%rax), Use, GP, Width32)&lt;/code&gt;&lt;/li&gt;
+      &lt;li&gt;&lt;code&gt;func(%rcx, UseZDef, GP, Width32)&lt;/code&gt;&lt;/li&gt;
+    &lt;/ol&gt;
+    
+    &lt;p&gt;Air supports exotic roles, such as late uses and early defs. There is even the
+      &lt;code&gt;Scratch&lt;/code&gt; role, which means early def and late use. Speaking of a &lt;code&gt;Tmp&lt;/code&gt;
+      in the &lt;code&gt;Scratch&lt;/code&gt; role means that the &lt;code&gt;Tmp&lt;/code&gt; will be assigned a register
+      that is guaranteed to not interfere with any of the other registers that the instruction
+      speaks of. Late uses and early defs are crucial for patchpoints, which may for example require
+      that one of the incoming values be given a register that does not interfere with whatever
+      register is used for the result. This can be expressed either as giving the inputs a late use
+      role or by giving the outputs an early def role. The full list of possible roles is:&lt;/p&gt;
+    
+    &lt;dl&gt;
+      &lt;dt&gt;Use&lt;/dt&gt;
+      &lt;dd&gt;Early warm use.&lt;/dd&gt;
+      
+      &lt;dt&gt;ColdUse&lt;/dt&gt;
+      &lt;dd&gt;Early cold use.&lt;/dd&gt;
+      
+      &lt;dt&gt;LateUse&lt;/dt&gt;
+      &lt;dd&gt;Late warm use.&lt;/dd&gt;
+      
+      &lt;dt&gt;LateColdUse&lt;/dt&gt;
+      &lt;dd&gt;Late cold use.&lt;/dd&gt;
+      
+      &lt;dt&gt;Def&lt;/dt&gt;
+      &lt;dd&gt;Late def. &lt;i&gt;Note that all defs are warm.&lt;/i&gt;&lt;/dd&gt;
+      
+      &lt;dt&gt;ZDef&lt;/dt&gt;
+      &lt;dd&gt;Late def with zero-extension.&lt;/dd&gt;
+      
+      &lt;dt&gt;UseDef&lt;/dt&gt;
+      &lt;dd&gt;Early warm use and late def.&lt;/dd&gt;
+      
+      &lt;dt&gt;UseZDef&lt;/dt&gt;
+      &lt;dd&gt;Early warm use and late def with zero extension.&lt;/dd&gt;
+      
+      &lt;dt&gt;EarlyDef&lt;/dt&gt;
+      &lt;dd&gt;Early def.&lt;/dd&gt;
+      
+      &lt;dt&gt;Scratch&lt;/dt&gt;
+      &lt;dd&gt;Early def and late warm use.&lt;/dd&gt;
+      
+      &lt;dt&gt;UseAddr&lt;/dt&gt;
+      &lt;dd&gt;Early warm use of the address's components.&lt;/dd&gt;
+    &lt;/dl&gt;
+    
+    &lt;p&gt;&lt;code&gt;UseAddr&lt;/code&gt; is interesting for the &lt;code&gt;Lea&lt;/code&gt; (load effective address)
+      instruction, which evaluates the address and places the result into a temporary or register.
+      The argument must be an address, but &lt;code&gt;UseAddr&lt;/code&gt; means that we don't actually read
+      from the address. Note that using an address in any of the other roles always implies that the
+      components of the address are used early and warm (i.e. &lt;code&gt;Use&lt;/code&gt;).&lt;/p&gt;
+    
+    &lt;p&gt;Air arguments are central to Air's execution model. The early and late actions of an
+      instruction have to do with arguments, and what happens to each argument during the early and
+      late actions is determined by the opcode and the number of arguments (i.e. the overload).
+      Clients of Air may create an &lt;code&gt;Inst&lt;/code&gt; with any combination of opcode and arguments
+      and then query, using &lt;code&gt;Inst::isValidForm()&lt;/code&gt; if the opcode, overload, and specific
+      arguments are valid for the current CPU.&lt;/p&gt;
+    
+    &lt;h2&gt;Defining Air&lt;/h2&gt;
+    &lt;p&gt;Air has many opcodes and the opcodes have many different overloads and forms. Air makes it
+      easy to reason about all of them with helpers like &lt;code&gt;isValidForm()&lt;/code&gt; and
+      &lt;code&gt;forEachArg()&lt;/code&gt;. It also provides a &lt;code&gt;Inst::generate()&lt;/code&gt; function that will
+      generate code for the instruction, provided that it does not use any non-register
+      &lt;code&gt;Tmp&lt;/code&gt;s or any abstract stack slots. If we wrote the
+      code for validating, iterating, and generating each form by hand, we would have a bad time.
+      For this reason, Air comes with an
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/opcode_generator.rb&quot;&gt;opcode code generator&lt;/a&gt;
+      that uses a
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes&quot;&gt;opcode definition file&lt;/a&gt;
+      as input. The opcode definition file use a simple and concise syntax that lets us define many
+      opcodes at once and constrain them to the CPU kinds that support them. Additionally, Air
+      supports &lt;i&gt;custom&lt;/i&gt; opcodes, where the code generator emits calls to
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirCustom.h&quot;&gt;hand-written
+        C++ code&lt;/a&gt;. This section describes the opcode definition language.&lt;/p&gt;
+    
+    &lt;p&gt;It's easiest to understand the opcode definitions with an example. Let's use the two-argument
+      overload of &lt;code&gt;Add32&lt;/code&gt;.&lt;/p&gt;
+    
+    &lt;pre&gt;&lt;code&gt;Add32 U:G:32 UZD:G:32
+    Tmp, Tmp
+    x86: Imm, Addr
+    x86: Imm, Index
+    Imm, Tmp
+    x86: Addr, Tmp
+    x86: Tmp, Addr
+    x86: Tmp, Index&lt;/code&gt;&lt;/pre&gt;
+    
+    &lt;p&gt;The first line defines the overload. It has two arguments. The first argument serves the
+      &lt;code&gt;Use&lt;/code&gt; role, shorted as &lt;code&gt;U&lt;/code&gt;. It is general-purpose, shortened as
+      &lt;code&gt;G&lt;/code&gt;. It has a 32-bit width. Hence the string &lt;code&gt;U:G:32&lt;/code&gt;. Similarly,
+      &lt;code&gt;UZD:G:32&lt;/code&gt; means &lt;code&gt;UseZDef&lt;/code&gt;, &lt;code&gt;GP&lt;/code&gt;, &lt;code&gt;Width32&lt;/code&gt;.&lt;/p&gt;
+    
+    &lt;p&gt;The next lines list the available forms of the overload. A form is a list of possible kinds of
+      arguments. These use the same terminology for &lt;code&gt;Arg&lt;/code&gt; kinds from the previous section,
+      with the caveat that &lt;code&gt;Addr&lt;/code&gt; implies that &lt;code&gt;Addr&lt;/code&gt;, &lt;code&gt;Stack&lt;/code&gt;, or
+      &lt;code&gt;CallArg&lt;/code&gt; would be accepted.&lt;/p&gt;
+    
+    &lt;p&gt;Prefixing any line with &lt;code&gt;x86:&lt;/code&gt; means that this form is only available on x86
+      CPUs, such as x86 or x86-64.&lt;/p&gt;
+    
+    &lt;p&gt;See the header of
+      &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes&quot;&gt;AirOpcode.opcodes&lt;/a&gt;
+      for a complete list of shorthand used by Air's opcode definition language.&lt;/p&gt;
+    
+    &lt;h2&gt;Summary&lt;/h2&gt;
</ins><span class="cx">     &lt;p&gt;Air is designed around JavaScriptCore's existing MacroAssembler. Air has Inst objects,
</span><span class="cx">       which each describe some method call to the MacroAssembler: an Inst's opcode indicates
</span><span class="cx">       which method name to use and its args indicate the arguments to pass to that method. We
</span><span class="lines">@@ -25,8 +356,6 @@
</span><span class="cx">       into actual calls to MacroAssembler. Consequently, we can &quot;add&quot; new instructions to Air
</span><span class="cx">       usually by just editing the &lt;a href=&quot;http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes&quot;&gt;AirOpcode.opcodes&lt;/a&gt;
</span><span class="cx">       file.&lt;/p&gt;
</span><del>-
-    &lt;p&gt;&lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=153668&quot;&gt;FIXME: Add more text here.&lt;/a&gt;&lt;/p&gt;
</del><span class="cx">   &lt;/div&gt;
</span><span class="cx"> &lt;/body&gt;
</span><span class="cx"> &lt;/html&gt;
</span></span></pre>
</div>
</div>

</body>
</html>