about summary refs log tree commit diff stats
path: root/tutorial
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-10-26 23:39:36 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-10-26 23:39:36 -0700
commita3f73278b198d0366c590ec8bd7fb8cad5c2931d (patch)
tree1b4868e06faa11a5bd1fc09555afe78d60dfbe8b /tutorial
parent0ccfd0156f8129df0959b51593bf2a9116e03a37 (diff)
downloadmu-a3f73278b198d0366c590ec8bd7fb8cad5c2931d.tar.gz
task: juggling function outputs between registers
Diffstat (limited to 'tutorial')
-rw-r--r--tutorial/index.md42
-rw-r--r--tutorial/task9-solution.mu23
-rw-r--r--tutorial/task9.mu22
3 files changed, 87 insertions, 0 deletions
diff --git a/tutorial/index.md b/tutorial/index.md
index 0967b059..62577a5f 100644
--- a/tutorial/index.md
+++ b/tutorial/index.md
@@ -354,6 +354,48 @@ the precise register a function header specifies. The return value can even be
 a literal integer or in memory somewhere. The `return` is really just a `copy`
 to the appropriate register(s). This is why the second example above is legal.
 
+## Task 9: juggling registers between function calls
+
+Here's a program:
+
+```
+fn f -> _/eax: int {
+  return 2
+}
+
+fn g -> _/eax: int {
+  return 3
+}
+
+fn add-f-and-g -> _/eax: int {
+  var x/eax: int <- f
+  var y/eax: int <- g
+  x <- add y
+  return x
+}
+```
+
+What's wrong with this program? How can you fix it and pass all tests by
+modifying just function `add-f-and-g`?
+
+By convention, most functions in Mu return their results in register `eax`.
+That creates a fair bit of contention for this register, and we often end up
+having to move the output of a function call around to some other location to
+free up space for the next function we need to call.
+
+An alternative approach would be to distribute the load between registers so
+that different functions use different output registers. That would reduce the
+odds of conflict, but not eradicate them entirely. It would also add some
+difficulty in calling functions; now you have to remember what register they
+write their outputs to. It's unclear if the benefits of this alternative
+outweigh the costs, so Mu follows long-established conventions in other
+Assembly languages. I do, however, violate the `eax` convention in some cases
+where a helper function is only narrowly useful in a single sort of
+circumstance and registers are at a premium. See, for example, the definition
+of the helper `_read-dithering-error` [when rendering images](http://akkartik.github.io/mu/html/511image.mu.html).
+The leading underscore indicates that it's an internal detail of
+`render-image`, and not really intended to be called by itself.
+
 ## Task 10: operating with fractional numbers
 
 All our variables so far have had type `int` (integer), but there are limits
diff --git a/tutorial/task9-solution.mu b/tutorial/task9-solution.mu
new file mode 100644
index 00000000..9ecf0ee8
--- /dev/null
+++ b/tutorial/task9-solution.mu
@@ -0,0 +1,23 @@
+fn f -> _/eax: int {
+  return 2
+}
+
+fn g -> _/eax: int {
+  return 3
+}
+
+fn add-f-and-g -> _/eax: int {
+  var _x/eax: int <- f
+  var x/ecx: int <- copy _x
+  var y/eax: int <- g
+  x <- add y
+  return x
+}
+
+fn test-add-f-and-g {
+  var result/eax: int <- add-f-and-g
+  check-ints-equal result, 5, "F - test-add-f-and-g\n"
+}
+
+fn main {
+}
diff --git a/tutorial/task9.mu b/tutorial/task9.mu
new file mode 100644
index 00000000..427c420b
--- /dev/null
+++ b/tutorial/task9.mu
@@ -0,0 +1,22 @@
+fn f -> _/eax: int {
+  return 2
+}
+
+fn g -> _/eax: int {
+  return 3
+}
+
+fn add-f-and-g -> _/eax: int {
+  var x/eax: int <- f
+  var y/eax: int <- g
+  x <- add y
+  return x
+}
+
+fn test-add-f-and-g {
+  var result/eax: int <- add-f-and-g
+  check-ints-equal result, 5, "F - test-add-f-and-g\n"
+}
+
+fn main {
+}