From 1efb9b89acd3aeda0814540a5d96c49bb8b172c4 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Thu, 7 Nov 2019 17:53:54 +0000 Subject: [PATCH] Generate code for for loops Our for loops are like C style for loops, with an initial value, condition and step. We begin generating code by setting up the loop in the preheader. Here we generate the initial value and compare it to the condition, finishing early if we need to. The main loop begins with choosing either the initial value, or the incremented value for the loop variable (usually called the induction variable). We can then put this inside the binding environment whenever we generate the body expression with the `runReaderT` function: This lets the body access the induction variable with the associated name, without having to change our Reader transformer into a State transformer. Once we've generated the body, we just need to increment the induction variable by the step, and check if the condition is met. Then depending on the result of that we either branch back up to the top of the loop, or to the after block to exit. You might have noticed that we don't have any side-effects at the moment, so you can't tell what went on inside a loop - it always evaluates to zero. We're going to add something to do inside these loops next. --- Main.hs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Main.hs b/Main.hs index 749f771..97407fe 100644 --- a/Main.hs +++ b/Main.hs @@ -163,3 +163,39 @@ buildExpr (If cond thenE elseE) = mdo mergeB <- block `named` "ifcont" phi [(thenOp, thenB), (elseOp, elseB)] + +buildExpr (For name init cond mStep body) = mdo + preheaderB <- block `named` "preheader" + + initV <- buildExpr init `named` "init" + + -- build the condition expression with 'i' in the bindings + initCondV <- withReaderT (Map.insert name initV) $ + (buildExpr cond >>= fcmp ONE zero) `named` "initcond" + + -- skip the loop if we don't meet the condition with the init + condBr initCondV loopB afterB + + loopB <- block `named` "loop" + i <- phi [(initV, preheaderB), (nextVar, loopB)] `named` "i" + + -- build the body expression with 'i' in the bindings + withReaderT (Map.insert name i) $ buildExpr body `named` "body" + + -- default to 1 if there's no step defined + stepV <- case mStep of + Just step -> buildExpr step + Nothing -> return $ ConstantOperand (Float (Double 1)) + + nextVar <- fadd i stepV `named` "nextvar" + + let zero = ConstantOperand (Float (Double 0)) + -- again we need 'i' in the bindings + condV <- withReaderT (Map.insert name i) $ + (buildExpr cond >>= fcmp ONE zero) `named` "cond" + condBr condV loopB afterB + + afterB <- block `named` "after" + -- since a for loop doesn't really have a value, return 0 + return $ ConstantOperand (Float (Double 0)) + -- 2.30.2