From a3f73278b198d0366c590ec8bd7fb8cad5c2931d Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Tue, 26 Oct 2021 23:39:36 -0700 Subject: [PATCH] task: juggling function outputs between registers --- 511image.mu | 4 ++-- tutorial/index.md | 42 ++++++++++++++++++++++++++++++++++++++ tutorial/task9-solution.mu | 23 +++++++++++++++++++++ tutorial/task9.mu | 22 ++++++++++++++++++++ 4 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 tutorial/task9-solution.mu create mode 100644 tutorial/task9.mu diff --git a/511image.mu b/511image.mu index f2df9424..8e61183f 100644 --- a/511image.mu +++ b/511image.mu @@ -368,12 +368,12 @@ fn dither-pgm-unordered-monochrome _src: (addr image), _dest: (addr image) { curr-int <- shift-left 0x10 # we have 32 bits; we'll use 16 bits for the fraction and leave 8 for unanticipated overflow var error/esi: int <- _read-dithering-error errors, x, y, src-width error <- add curr-int - $_dither-pgm-unordered-monochrome:update-error: { + $dither-pgm-unordered-monochrome:update-error: { compare error, 0x800000 { break-if->= _write-raw-buffer dest-data, x, y, src-width, 0/black - break $_dither-pgm-unordered-monochrome:update-error + break $dither-pgm-unordered-monochrome:update-error } _write-raw-buffer dest-data, x, y, src-width, 1/white error <- subtract 0xff0000 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 { +}