mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
An initial description of the compact unwind encoding.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135955 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
54134708f5
commit
66bc5c602a
@ -1805,7 +1805,115 @@ $ llc -regalloc=pbqp file.bc -o pbqp.s;
|
||||
<h3>
|
||||
<a name="proepicode">Prolog/Epilog Code Insertion</a>
|
||||
</h3>
|
||||
<div><p>To Be Written</p></div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="compact_unwind">Compact Unwind</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Unwinding out of a function is done virually via DWARF encodings. These
|
||||
encodings exist in two forms: a Common Information Entry (CIE) and a Frame
|
||||
Description Entry (FDE). These two tables contain the information necessary
|
||||
for the unwinder to restore the state of the computer to before the function
|
||||
was called. However, the tables themselves are rather large. LLVM can use a
|
||||
"compact unwind" encoding to represent the virtual unwinding.</p>
|
||||
|
||||
<p>The compact unwind encoding is a 32-bit value, which is encoded in an
|
||||
architecture-specific way. It specifies which registers to restore and from
|
||||
where, and how to unwind out of the funciton. When the linker creates a final
|
||||
linked image, it will create a <code>__TEXT,__unwind_info</code>
|
||||
section. This section is a small and fast way for the runtime to access
|
||||
unwind info for any given function. If we emit compact unwind info for the
|
||||
function, that compact unwind info will be encoded in
|
||||
the <code>__TEXT,__unwind_info</code> section. If we emit DWARF unwind info,
|
||||
the <code>__TEXT,__unwind_info</code> section will contain the offset of the
|
||||
FDE in the <code>__TEXT,__eh_frame</code> section in the final linked
|
||||
image.</p>
|
||||
|
||||
<p>For X86, there are three modes for the compact unwind encoding:</p>
|
||||
|
||||
<ul>
|
||||
<dt><i>Function with a Frame Pointer (<code>EBP</code> or <code>RBP</code>)</i></dt>
|
||||
<dd><p><code>EBP/RBP</code>-based frame, where <code>EBP/RBP</code> is pushed
|
||||
onto the stack immediately after the return address,
|
||||
then <code>ESP/RSP</code> is moved to <code>EBP/RBP</code>. Thus to
|
||||
unwind, <code>ESP/RSP</code> is restored with the
|
||||
current <code>EBP/RBP</code> value, then <code>EBP/RBP</code> is restored
|
||||
by popping the stack, and the return is done by popping the stack once
|
||||
more into the PC. All non-volatile registers that need to be restored must
|
||||
have been saved in a small range on the stack that
|
||||
starts <code>EBP-4</code> to <code>EBP-1020</code> (<code>RBP-8</code>
|
||||
to <code>RBP-1020</code>). The offset (divided by 4) is encoded in bits
|
||||
16-23 (mask: <code>0x00FF0000</code>). The registers saved are encoded in
|
||||
bits 0-14 (mask: <code>0x00007FFF</code>) as five 3-bit entries from the
|
||||
following table:</p>
|
||||
<table border="1" cellspacing="0">
|
||||
<tr>
|
||||
<th>Compact Number</th>
|
||||
<th>i386 Register</th>
|
||||
<th>x86-64 Regiser</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td><code>EBX</code></td>
|
||||
<td><code>RBX</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td><code>ECX</code></td>
|
||||
<td><code>R12</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td><code>EDX</code></td>
|
||||
<td><code>R13</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td><code>EDI</code></td>
|
||||
<td><code>R14</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td><code>ESI</code></td>
|
||||
<td><code>R15</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td><code>EBP</code></td>
|
||||
<td><code>RBP</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</dd>
|
||||
|
||||
<dt><i>Frameless with a Small Constant Stack Size (EBP or RBP is not used as a frame pointer)</i></dt>
|
||||
<dd><p>To return, a constant (encoded in the compact unwind encoding) is added
|
||||
to the <code>ESP/RSP</code>. Then the return is done by popping the stack
|
||||
into the PC. All non-volatile registers that need to be restored must have
|
||||
been saved on the stack immediately after the return address. The stack
|
||||
size (divided by 4) is encoded in bits 16-23
|
||||
(mask: <code>0x00FF0000</code>). There is a maximum stack size of 1024
|
||||
bytes. The number of registers saved is encoded in bits 9-12
|
||||
(mask: <code>0x00001C00</code>). Bits 0-9 (mask:
|
||||
<code>0x000003FF</code>) contain which registers were saved and their
|
||||
order. (See the <code>encodeCompactUnwindRegistersWithoutFrame()</code>
|
||||
function in <code>lib/Target/X86FrameLowering.cpp</code> for the encoding
|
||||
algorithm.)</p></dd>
|
||||
|
||||
<dt><i>Frameless with a Large Constant Stack Size (EBP or RBP is not used as a frame pointer)</i></dt>
|
||||
<dd><p>This case is like the "Frameless with a Small Constant Stack Size"
|
||||
case, but the stack size is too larget to encode in the compact unwind
|
||||
encoding. Instead it requires that the function contains "<code>subl
|
||||
$nnnnnn, %esp</code>" in its prolog. The compact encoding contains the
|
||||
offset to the <code>$nnnnnn</code> value in the funciton in bits 9-12
|
||||
(mask: <code>0x00001C00</code>).</p></dd>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="latemco">Late Machine Code Optimizations</a>
|
||||
|
Loading…
Reference in New Issue
Block a user