download 2021 site

This commit is contained in:
Jana Dönszelmann 2025-09-29 16:03:30 +02:00
commit dd6e4afb13
No known key found for this signature in database
138 changed files with 37730 additions and 0 deletions

550
lab/9.html Normal file
View file

@ -0,0 +1,550 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="Eelco Visser">
<meta name="generator" content="Jekyll v3.8.5">
<title>Lab 9: A Basic Compiler Pipeline</title>
<!-- <base href="/2021"> -->
<!--link rel="canonical" href="https://getbootstrap.com/docs/4.3/examples/starter-template/"-->
<link rel="icon" href="../img/logo/pl_ico2_2B3_icon.ico" type="image/x-icon">
<!-- Bootstrap core CSS -->
<!--link href="https://getbootstrap.com/docs/4.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"-->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<!-- Custom styles for this template -->
<link href="../css/main.css" rel="stylesheet">
<link href="../css/borders-responsive.css" rel="stylesheet">
<link rel="stylesheet" href="../css/pl.css">
</head>
<body>
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="../index.html">
TU Delft | CS4200
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="../lectures/index.html" tabindex="-1" aria-disabled="true">Lectures</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../homework/index.html" tabindex="-1" aria-disabled="true">Homework</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../project/index.html" tabindex="-1" aria-disabled="true">Project</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../news/index.html" tabindex="-1" aria-disabled="true">News</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../blog/index.html" tabindex="-1" aria-disabled="true">Blog</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-12">
<div class="mt-3 mb-3 pt-3 pb-3 text-dark border-top border-bottom border-grey">
<div class="text-dark font-weight-bold">
<h1>
Lab 9: A Basic Compiler Pipeline
</h1>
</div>
<div>
</div>
<div>
Project
</div>
<div>
November 19, 2021
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-9 border-lg-right border-grey">
<p>In this lab you make a start with compiling ChocoPy to RISC-V code using Stratego.
You translate expression statements with expressions containing constants, operators, and variables.
While it would be possible to completely compute the values of such expressions using constant folding, this is not the aim of this lab.
Rather, we want the basis for a translation of expressions using variables and function calls as well.</p>
<h3 id="a-minimial-viable-example">A Minimial Viable Example</h3>
<p>The following is a minimal ChocoPy program:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>y : int = 3
1 + y
</code></pre></div></div>
<p>Aim to get the complete compiler pipeline working for this example first.
Then work on extending the various stages.</p>
<h3 id="nano-pass-compiler-architecture">Nano-Pass Compiler Architecture</h3>
<p>Follow the setup of the pipeline in <em>Essentials of Compiling</em> consisting of the following strategies:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>compile =
compile-cpy-to-cir
; compile-cir-to-rv32im
; compile-rv32im
compile-cpy-to-cir =
explicate-types
; desugar
; uniquify
; remove-complex-operands
; explicate-control
compile-cir-to-rv32im =
select-instructions-cprogram
compile-rv32im =
assign-homes
; patch-instructions
</code></pre></div></div>
<p>Be sure to replace the <code class="language-plaintext highlighter-rouge">compile</code> rule in <code class="language-plaintext highlighter-rouge">src/compile.str2</code> with the above <code class="language-plaintext highlighter-rouge">compile</code> strategy.</p>
<h3 id="risc-v-resources">RISC-V Resources</h3>
<p>Consult the following resources as documentation on the RISC-V architecture and instruction set:</p>
<ul>
<li>
<p><a href="https://github.com/jameslzhu/riscv-card/blob/master/riscv-card.pdf">RISC-V Reference</a> by James Zhu. Provides a concise overview of the instruction set.</p>
</li>
<li>
<p><a href="https://chocopy.org/venus.html">Venus Editor</a> on ChocoPy site.</p>
</li>
<li>
<p><a href="https://chocopy.org/">ChocoPy Reference Compiler</a> on the ChocoPy site. Produces RISC-V code with annotations.</p>
</li>
<li>
<p><a href="https://riscv.org/technical/specifications/">RISC-V Specifications</a>. The offical specification.</p>
</li>
<li>
<p><a href="https://github.com/riscv/riscv-isa-manual">RISC-V Instruction Set Manual</a></p>
</li>
<li>
<p><a href="https://github.com/riscv/riscv-asm-manual/blob/master/riscv-asm.md">RISC-V Assembly Programmers Manual</a> for an overview of the instruction set.</p>
</li>
</ul>
<h3 id="prebuilt">Prebuilt</h3>
<p>The <code class="language-plaintext highlighter-rouge">prebuilt</code> directory of your project template should have</p>
<ul>
<li>The ChocoPy signature and pretty-printer</li>
<li>The RV32IM signature and pretty-printer</li>
</ul>
<p>The template should also have implementations of the ChocoPy parser and type checker.</p>
<h3 id="compiler-testing">Compiler Testing</h3>
<p>Develop tests in SPT to test your compiler.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>module test
language chocopy
test 1+1 [[
1+1
]] transform "To RV32IM and execute" to "2"
</code></pre></div></div>
<!-- See the slides of [Lecture 12](/2021/lecture/12/) on code generation for an approach to get started. -->
<!-- ### Objectives
1. Develop tests for your compiler that explore the edge cases.
2. Define a transformation strategy that translates ChocoPy constant expressions to RISC-V code. I.e. including integer and boolean constants and operators.
3. Develop a simplification transformation that transforms expressions such that more concise code can be generated.
### Basic Compiler Pipeline
Follow the slides of [Lecture 12](/2021/lecture/12) to set up a basic compiler pipeline for translating statement expressions and print the resulting value.
```
program-to-rv32im:
ast@Program(definitions, [stat]) -> Program(instrs2)
where
a := <stx-get-ast-analysis>
; <stat-to-instrs(|"a1", <registers>)> stat => instrs1
; instrs2 := <concat> [
[PSText()]
, instrs1
, [Li("a0", "1"),
Ecall()]
]
```
Note that you will eventually have to extend this rule to cover all of ChocoPy.
The `stat-to-instrs` strategy transforms statements. For now, we are only defining it for expression statements:
```
stat-to-instrs(|r, regs) :
Exp(e) -> instrs
where <exp-to-instrs(|r, regs)> e => instrs
```
The strategy is parameterized with a register in which it expects the value of the expression to be stored and a list of registers that can be used as temporaries. For now this is defined as follows:
```
registers = !["t0", "t1", "t2", "t3", "t4", "t5", "t6"]
```
That is, the `t` registers can all be used as temporaries. You will probably have to adjust this in the future.
### Translating Expressions
Define a strategy that transforms expressions to lists of instructions. The example rules below show how to do this for integer constants and integer additions. These rules use registers to store the intermediate values of sub-expressions, by drawing from a list of registers. Note that this a naive approach that does not scale to arbitrary expressions. You will have to discover the limitations and figure out how to overcome those.
#### Debugging
The following strategy definition defines `exp-to-instrs` in terms of an auxiliary rule `exp-to-instrs-`:
```
exp-to-instrs(|r, regs) =
exp-to-instrs-(|r, regs)
<+ (debug(!"exp-to-instr fails: "); fail)
```
This is a useful pattern in Stratego, as it catches a possible failure of the `exp-to-instrs-` rule and reports it in the Eclipse Console. For example, this strategy will report when you apply the compiler to an operator that is not (yet) supported.
You can also debug your generated code, by creating a `.cpy` file, transforming it to an `.rv32im` file using the `Spoofax > Generation` menu, and copying the generated output to the online Venus editor, where you can use the `Simulator` tab to run your code or step through each line, and inspect the memory and registers.
#### Translating Constants
Integer constants are translated to instructions that load the constant value into a register:
```
exp-to-instrs-(|r, regs) :
Int(i) -> [Li(r, i)]
```
Can other types of constants be treated similarly?
#### Translating Operators
Operators combine expressions into new expressions. In order to translate an operator, its sub-expressions should be translated recursively the lists of instructions. Furthermore, while the value of the second sub-expression is computed, the value of the first sub-expression should be stored. This typically requires a new register. Thus, integer addition can be translated as follows:
```
exp-to-instrs-(|r, regs@[r2 | regs']) :
add@Add(e1, e2) -> <concat> [
instrs1
, instrs2
, [Add(r, r, r2)]
]
where <stx-get-ast-analysis> add => a
; <get-type(|a)> add => INT()
; <exp-to-instrs(|r, regs)> e1 => instrs1
; <exp-to-instrs(|r2, regs')> e2 => instrs2
```
Note that the list of registers is used to obtain a fresh register.
Define transformation rules for all operators of ChocoPy expressions.
#### Special Cases
RISC-V provides specialized instructions for some operations. For example, the `addi` instruction allows directly adding an integer constant (between -2048 and 2047) to a register. A compiler can make use of such instructions, by detecting special patterns in the source language. For example, the following rule (when listed before the general rule for addition above), detects additions with an integer constant, and translates those to applications of `addi`, avoiding the use of an extra register.
```
exp-to-instrs-(|r, regs) :
add@Add(e, Int(i)) -> <concat> [
instrs
, [Addi(r, r, i)]
]
where <gtS>(i, "-2049"); <ltS>(i, "2048")
; <stx-get-ast-analysis> add => a
; <get-type(|a)> add => INT()
; <exp-to-instrs(|r, regs)> e => instrs
```
Can you detect other specialized instructions and corresponding source language patterns that provide a more concise and/or faster target code?
### Simplification
To improve the result of code generation, it can be useful to transform the source language expression. For example, left-associative additions produce a better result with the rules for addition above. Another useful transformation is to type specialize the constructors of the AST, such that the analysis results are no longer needed. That is useful when applying transformations, since preserving those annotations cannot be done for all transformations. **The following `simplify-all` transformation should be invoked on the AST before invoking the compiler transformation.**
```
signature
constructors
AddInt : Exp * Exp -> Exp
rules
simplify-all =
innermost(type-specialize <+ simplify)
type-specialize :
add@Add(e1, e2) -> AddInt(e1, e2)
where <stx-get-ast-analysis> add => a
; <get-type(|a)> add => INT()
simplify :
AddInt(e1, AddInt(e2, e3)) -> AddInt(AddInt(e1, e2), e3)
```
Note that the rules for translating integer additions should be adapted to reflect the change in constructors.
This simplification can include constant folding, eventually. However, do not yet include constant folding rules, since you want to test the translation of operators. That is, your code generator should be able to translate arbitrary combinations of operators, so be prepared for the general case.
Think about (and try out in the online compiler!) the differences between adding integers and concatenating strings in RISC-V. In ChocoPy, they initially both use the `Add(...)` constructor, so make sure to disambiguate them into separate constructors you will later use for code generation. The same holds for other operations, but you have to think about those yourself.
### Booleans
In ChocoPy we compile the Booleans `True` and `False` to integers in RISC-V (`1` and `0`, respectively). Implement the Boolean operators `and`, `or` and `not`, and integer comparison operators `==`, `!=`, `<`, `>`, `<=`, `>=` (you can ignore `is` for now since it operates on objects).
You can make use of the online compiler, or the RISC-V instruction set to find the proper instructions in RISC-V.
Also implement the ternary operator `... if ... else ...`. (See [Short-circuit Boolean operations](#shortcircuit) to get an idea on how to implement it.)
### Challenges
#### Running out of registers
The approach sketched above does not generalize to arbitrary expressions.
Create test cases that require more temporary registers than are available.
Start thinking about solutions for this limitation. Two standard solutions are using the stack for temporaries (which is slow since it involves writing to and reading from memory), and register allocation (which requires a program analysis on the generated code).
#### <a name="shortcircuit"></a>Short-circuit Boolean operations.
When encountering a Boolean operation of the form `False and ...`, do we really care about the right side of the operator? Similarly, when we encounter `True or ...`?
Think about how we can use conditional jumps in RISC-V to short-circuit (any) Boolean operators. Have a look at the instruction set and online compiler.
A conditional jump in RISC-V takes a label, which represents an address in memory. In Stratego, labels can be generated using `<newname> "L" => label`. (Note that `"L"` can be anything you want, as long as it is a string.) -->
</div>
<div class="col-sm-12 col-md-12 col-lg-3 col-xl-3 " >
<div class="sticky-top top70 d-none d-lg-block d-xl-block">
<div class="pb4 mb3 border-bottom border-grey ">
<nav>
<ul class="pagination justify-content-left">
<li class="page-item">
<a class="page-link" href="8.html">
&laquo;
</a>
</li>
<li class="page-item">
<a class="page-link" href="../project/index.html">
^
</a>
</li>
<li class="page-item">
<a class="page-link" href="10.html">&raquo;</a>
</li>
</ul>
</nav>
</div>
<ul id="my_toc" class="toc list-group list-group-flush d-none d-lg-block d-xl-block p-0 ml-0 mt-3">
<li class="list-group-item pl-0 ml-0 border-0 pl-0 pt-0 pb-1 pr-0 m-0 mr-3"><a href="9.html#a-minimial-viable-example">A Minimial Viable Example</a></li>
<li class="list-group-item pl-0 ml-0 border-0 pl-0 pt-0 pb-1 pr-0 m-0 mr-3"><a href="9.html#nano-pass-compiler-architecture">Nano-Pass Compiler Architecture</a></li>
<li class="list-group-item pl-0 ml-0 border-0 pl-0 pt-0 pb-1 pr-0 m-0 mr-3"><a href="9.html#risc-v-resources">RISC-V Resources</a></li>
<li class="list-group-item pl-0 ml-0 border-0 pl-0 pt-0 pb-1 pr-0 m-0 mr-3"><a href="9.html#prebuilt">Prebuilt</a></li>
<li class="list-group-item pl-0 ml-0 border-0 pl-0 pt-0 pb-1 pr-0 m-0 mr-3"><a href="9.html#compiler-testing">Compiler Testing</a></li>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="border-top border-bottom border-grey mt-3 pt-3">
<nav>
<ul class="pagination justify-content-center">
<li class="page-item">
<a class="page-link" href="8.html">
Previous
</a>
</li>
<li class="page-item">
<a class="page-link" href="10.html">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="../project/index.html">
Index
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>