1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 10:04:21 +03:00
inform7/docs/codegen-module/2-erl.html

183 lines
14 KiB
HTML
Raw Normal View History

2019-06-11 02:38:15 +03:00
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>2/erm</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '2/erl' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">codegen</a></li><li><a href="index.html#2">Chapter 2: Miscellaneous Pipeline Stages</a></li><li><b>Eliminate Redundant Labels</b></li></ul><p class="purpose">To remove labels which are defined but never jumped to.</p>
2019-06-11 02:38:15 +03:00
<ul class="toc"><li><a href="#SP1">&#167;1. Pipeline stage</a></li><li><a href="#SP1_1">&#167;1.1. Peephole optimisation</a></li></ul><hr class="tocbar">
2019-06-11 02:38:15 +03:00
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Pipeline stage. </b>I7 tends to produce a lot of labels when compiling complicated text
substitutions, but many (around 2000 in a typical run) are never branched to,
either by a jump invocation or by assembly language.
</p>
<p class="inwebparagraph">These spurious labels cause no real problem except untidiness, but removing
them provides a simple example of how peephole optimisation can be performed
on the Inter functions in a repository.
</p>
2019-06-11 02:38:15 +03:00
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CodeGen::Labels::create_pipeline_stage</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">CodeGen::Stage::new</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"eliminate-redundant-labels"</span><span class="plain">, </span><span class="functiontext">CodeGen::Labels::run_pipeline_stage</span><span class="plain">, </span><span class="constant">NO_STAGE_ARG</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
2019-06-11 02:38:15 +03:00
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CodeGen::Labels::run_pipeline_stage</span><span class="plain">(</span><span class="reserved">pipeline_step</span><span class="plain"> *</span><span class="identifier">step</span><span class="plain">) {</span>
2019-07-24 22:29:29 +03:00
<span class="identifier">Inter::Tree::traverse</span><span class="plain">(</span><span class="identifier">step</span><span class="plain">-</span><span class="element">&gt;repository</span><span class="plain">, </span><span class="functiontext">CodeGen::Labels::visitor</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, 0);</span>
2019-06-11 02:38:15 +03:00
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
2019-07-24 22:29:29 +03:00
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CodeGen::Labels::visitor</span><span class="plain">(</span><span class="identifier">inter_tree</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">inter_tree_node</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="plain">-&gt;</span><span class="identifier">W</span><span class="plain">.</span><span class="identifier">data</span><span class="plain">[</span><span class="identifier">ID_IFLD</span><span class="plain">] == </span><span class="identifier">PACKAGE_IST</span><span class="plain">) {</span>
2019-07-13 16:17:48 +03:00
<span class="identifier">inter_package</span><span class="plain"> *</span><span class="identifier">pack</span><span class="plain"> = </span><span class="identifier">Inter::Package::defined_by_frame</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Inter::Packages::is_codelike</span><span class="plain">(</span><span class="identifier">pack</span><span class="plain">)) </span>&lt;<span class="cwebmacro">Perform peephole optimisation on this block</span> <span class="cwebmacronumber">1.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
2019-06-11 02:38:15 +03:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CodeGen::Labels::create_pipeline_stage is used in 1/stg (<a href="1-stg.html#SP2">&#167;2</a>).</p>
2019-06-11 02:38:15 +03:00
<p class="endnote">The function CodeGen::Labels::run_pipeline_stage appears nowhere else.</p>
2019-07-13 16:17:48 +03:00
<p class="endnote">The function CodeGen::Labels::visitor appears nowhere else.</p>
2019-06-11 02:38:15 +03:00
<p class="inwebparagraph"><a id="SP1_1"></a><b>&#167;1.1. Peephole optimisation. </b>We can now forget about the larger package structure, and just look through
the peephole at a single function in Inter. It has its own symbols table, for
local variables and label names, and also has a tree of code to define what
it does.
</p>
2019-06-11 02:38:15 +03:00
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Perform peephole optimisation on this block</span> <span class="cwebmacronumber">1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">inter_symbols_table</span><span class="plain"> *</span><span class="identifier">local_symbols</span><span class="plain"> = </span><span class="identifier">Inter::Packages::scope</span><span class="plain">(</span><span class="identifier">pack</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Mark all the labels for this function as being unused</span> <span class="cwebmacronumber">1.1.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Look through the function for mentions of labels, marking those as used</span> <span class="cwebmacronumber">1.1.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Remove the label declarations for any that are still marked unused</span> <span class="cwebmacronumber">1.1.3</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_1"></a><b>&#167;1.1.1. </b>The symbol flag <code class="display"><span class="extract">USED_MARK_BIT</span></code> is free for us to use, but its value for
any given symbol is undefined when we begin. We'll clear it for all labels.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Mark all the labels for this function as being unused</span> <span class="cwebmacronumber">1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOOP_OVER_SYMBOLS_TABLE</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">local_symbols</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Inter::Symbols::is_label</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">))</span>
<span class="identifier">Inter::Symbols::clear_flag</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">USED_MARK_BIT</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1">&#167;1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_2"></a><b>&#167;1.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Look through the function for mentions of labels, marking those as used</span> <span class="cwebmacronumber">1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
2019-07-26 21:20:27 +03:00
<span class="identifier">inter_tree_node</span><span class="plain"> *</span><span class="identifier">D</span><span class="plain"> = </span><span class="identifier">Inter::Packages::definition</span><span class="plain">(</span><span class="identifier">pack</span><span class="plain">);</span>
<span class="functiontext">CodeGen::Labels::traverse_code_tree</span><span class="plain">(</span><span class="identifier">D</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1">&#167;1.1</a>.</p>
<p class="inwebparagraph"><a id="SP1_1_3"></a><b>&#167;1.1.3. </b>Anything not marked used must be unused, so we can get rid of it. We do this
by striking its definition; the definition of a label symbol is the line
which shows where it belongs in the function (written <code class="display"><span class="extract">.Example</span></code> in Inter
syntax). Striking this does two things: it removes the definition line; and
it renders the symbol undefined. It still lives on in the function's symbols
table, though, and (since we have made sure there are no references to it from
anywhere) we may as well remove it.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Remove the label declarations for any that are still marked unused</span> <span class="cwebmacronumber">1.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">LOOP_OVER_SYMBOLS_TABLE</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">local_symbols</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Inter::Symbols::is_label</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Inter::Symbols::get_flag</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">USED_MARK_BIT</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">Inter::Symbols::strike_definition</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
<span class="identifier">Inter::Symbols::remove_from_table</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
2019-06-11 02:38:15 +03:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1_1">&#167;1.1</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>The following visits every line of code in the function, in the same order
it would be written out in a listing.
</p>
<pre class="display">
2019-07-24 22:29:29 +03:00
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CodeGen::Labels::traverse_code_tree</span><span class="plain">(</span><span class="identifier">inter_tree_node</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain">) {</span>
<span class="identifier">LOOP_THROUGH_INTER_CHILDREN</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Examine a line of code in the function</span> <span class="cwebmacronumber">2.1</span>&gt;<span class="plain">;</span>
<span class="functiontext">CodeGen::Labels::traverse_code_tree</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
2019-06-11 02:38:15 +03:00
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CodeGen::Labels::traverse_code_tree is used in <a href="#SP1_1_2">&#167;1.1.2</a>.</p>
<p class="inwebparagraph"><a id="SP2_1"></a><b>&#167;2.1. </b>If a label is used, there will be line reading <code class="display"><span class="extract">lab Example</span></code> or similar.
We look for such lines.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Examine a line of code in the function</span> <span class="cwebmacronumber">2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
2019-07-24 22:29:29 +03:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">F</span><span class="plain">-&gt;</span><span class="identifier">W</span><span class="plain">.</span><span class="identifier">data</span><span class="plain">[</span><span class="identifier">ID_IFLD</span><span class="plain">] == </span><span class="identifier">LAB_IST</span><span class="plain">) {</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">lab</span><span class="plain"> = </span><span class="identifier">Inter::Lab::label_symbol</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
<span class="identifier">Inter::Symbols::set_flag</span><span class="plain">(</span><span class="identifier">lab</span><span class="plain">, </span><span class="identifier">USED_MARK_BIT</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
2019-06-11 02:38:15 +03:00
<hr class="tocbar">
<ul class="toc"><li><a href="2-erm.html">Back to 'Eliminate Redundant Matter'</a></li><li><i>(This section ends Chapter 2: Miscellaneous Pipeline Stages.)</i></li></ul><hr class="tocbar">
2019-06-11 02:38:15 +03:00
<!--End of weave-->
</body>
</html>