From 58ef6727e71283849454ca5c170dc03a3f984d22 Mon Sep 17 00:00:00 2001 From: ith Date: Fri, 19 Jun 2020 21:25:06 -0700 Subject: [PATCH 01/11] update page --- docs/lectures/03-adder.html | 2 +- lectures/03-adder.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/lectures/03-adder.html b/docs/lectures/03-adder.html index fa7061e..ef7e1c2 100644 --- a/docs/lectures/03-adder.html +++ b/docs/lectures/03-adder.html @@ -676,7 +676,7 @@

Example: Let-bindings and Stacks

, y = add1(x) -- [x |-> 1] , z = add1(y) -- [y |-> 2, x |-> 1] in - add1(z) -- [z |- 3, y |-> 2, x |-> 1] + add1(z) -- [z |-> 3, y |-> 2, x |-> 1]

QUIZ

At what position on the stack do we store variable c ?

                          -- []
diff --git a/lectures/03-adder.md b/lectures/03-adder.md
index adb3ad1..ab88104 100644
--- a/lectures/03-adder.md
+++ b/lectures/03-adder.md
@@ -629,7 +629,7 @@ let x = 1           -- []
   , y = add1(x)     -- [x |-> 1]
   , z = add1(y)     -- [y |-> 2, x |-> 1]
 in
-    add1(z)         -- [z |- 3, y |-> 2, x |-> 1]
+    add1(z)         -- [z |-> 3, y |-> 2, x |-> 1]
 ```
 
 ### QUIZ

From 677403a5d6520f6f7bb2db075fab116f2eb10457 Mon Sep 17 00:00:00 2001
From: ith 
Date: Sun, 21 Jun 2020 00:22:17 -0700
Subject: [PATCH 02/11] typo with sub1()

---
 lectures/04-boa.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lectures/04-boa.md b/lectures/04-boa.md
index b858674..1e705c0 100644
--- a/lectures/04-boa.md
+++ b/lectures/04-boa.md
@@ -55,7 +55,7 @@ else:
 ### Example: `If2`
 
 ```haskell
-if sub(1):
+if sub1(1):
   22
 else:
   sub1(0)
@@ -64,7 +64,7 @@ else:
 
 
 
-* Since `sub(1)` _is_ `0` we evaluate the "else" case to get `-1`
+* Since `sub1(1)` _is_ `0` we evaluate the "else" case to get `-1`
 
 ### QUIZ: `If3`
 
@@ -73,7 +73,7 @@ else:
 What should the following evaluate to?
 
 ```haskell
-let x = if sub(1):
+let x = if sub1(1):
           22
         else:
           sub1(0)

From e45ee976d9ed30cab983308ddb34b9c0d3cb30ca Mon Sep 17 00:00:00 2001
From: ith 
Date: Sun, 21 Jun 2020 00:22:40 -0700
Subject: [PATCH 03/11] update page

---
 docs/lectures/04-boa.html | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/lectures/04-boa.html b/docs/lectures/04-boa.html
index f0e767e..24de3e5 100644
--- a/docs/lectures/04-boa.html
+++ b/docs/lectures/04-boa.html
@@ -267,17 +267,17 @@ 

Example: If1

  • Since 10 is not 0 we evaluate the “then” case to get 22
  • Example: If2

    -
    if sub(1):
    +
     
      -
    • Since sub(1) is 0 we evaluate the “else” case to get -1
    • +
    • Since sub1(1) is 0 we evaluate the “else” case to get -1

    QUIZ: If3

    if-else is also an expression so we can nest them:

    What should the following evaluate to?

    -
    let x = if sub(1):
    +
    let x = if sub1(1):
               22
             else:
               sub1(0)
    
    From 85d53ade41f7b0202454a560c54d9892dcc0be82 Mon Sep 17 00:00:00 2001
    From: ith 
    Date: Sun, 21 Jun 2020 00:37:01 -0700
    Subject: [PATCH 04/11] missing ':'
    
    ---
     lectures/04-boa.md | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lectures/04-boa.md b/lectures/04-boa.md
    index 1e705c0..323c6a5 100644
    --- a/lectures/04-boa.md
    +++ b/lectures/04-boa.md
    @@ -136,7 +136,7 @@ Which of the following is a valid x86 encoding of
     ```python
     if 10:
       22
    -else
    +else:
       33
     ```
     
    
    From d28d30d098f4aa16a23ee986dafa5eec1bfa955c Mon Sep 17 00:00:00 2001
    From: ith 
    Date: Sun, 21 Jun 2020 00:37:24 -0700
    Subject: [PATCH 05/11] update page
    
    ---
     docs/lectures/04-boa.html | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/docs/lectures/04-boa.html b/docs/lectures/04-boa.html
    index 24de3e5..53eac89 100644
    --- a/docs/lectures/04-boa.html
    +++ b/docs/lectures/04-boa.html
    @@ -325,7 +325,7 @@ 

    QUIZ

    Which of the following is a valid x86 encoding of

    QUIZ: Compiling if-else
    QUIZ: Compiling if-else
    From 1b80f8353982ea94d7fbd0a98e2c7a3c89e723a3 Mon Sep 17 00:00:00 2001 From: ith Date: Sun, 21 Jun 2020 02:34:48 -0700 Subject: [PATCH 06/11] update page --- docs/lectures/04-boa.html | 2 +- lectures/04-boa.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/lectures/04-boa.html b/docs/lectures/04-boa.html index 53eac89..d7f9085 100644 --- a/docs/lectures/04-boa.html +++ b/docs/lectures/04-boa.html @@ -502,7 +502,7 @@

    Transforms: CodeGen

    , IJe (BranchFalse i) -- if-zero then jump to 'False'-block ] ++ compile env eTrue ++ -- code for `True`-block - [ IJmp lExit ] -- jump to exit (don't execute `False`-block!) + [ IJmp (BranchExit i) ] -- jump to exit (don't execute `False`-block!) ++ ILabel (BranchFalse i) -- start of `False`-block : compile env eFalse ++ -- code for `False`-block diff --git a/lectures/04-boa.md b/lectures/04-boa.md index 323c6a5..b0b4780 100644 --- a/lectures/04-boa.md +++ b/lectures/04-boa.md @@ -354,7 +354,7 @@ compile env (If eCond eTrue eFalse i) , IJe (BranchFalse i) -- if-zero then jump to 'False'-block ] ++ compile env eTrue ++ -- code for `True`-block - [ IJmp lExit ] -- jump to exit (don't execute `False`-block!) + [ IJmp (BranchExit i) ] -- jump to exit (don't execute `False`-block!) ++ ILabel (BranchFalse i) -- start of `False`-block : compile env eFalse ++ -- code for `False`-block From 0968a4e50b060f502ded9b60b45156a791baa607 Mon Sep 17 00:00:00 2001 From: ith Date: Sun, 21 Jun 2020 16:12:12 -0700 Subject: [PATCH 07/11] update page --- docs/lectures/04-boa.html | 2 +- lectures/04-boa.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/lectures/04-boa.html b/docs/lectures/04-boa.html index d7f9085..a3e1712 100644 --- a/docs/lectures/04-boa.html +++ b/docs/lectures/04-boa.html @@ -774,7 +774,7 @@

    QUIZ

    compile env (Prim1 op e) = compile env e ++ [ (prim1Asm op (Reg EAX) (Const 1)] compile env (Prim2 op v1 v2) = [ compileImm env v1 - , prim2asm o (Reg EAX) (immArg env v2) + , prim2Asm o (Reg EAX) (immArg env v2) ] prim2Asm Add2 = IAdd diff --git a/lectures/04-boa.md b/lectures/04-boa.md index b0b4780..fc1de72 100644 --- a/lectures/04-boa.md +++ b/lectures/04-boa.md @@ -784,7 +784,7 @@ compile env v@(Id _ _) = compileImm env v compile env (Prim1 op e) = compile env e ++ [ (prim1Asm op (Reg EAX) (Const 1)] compile env (Prim2 op v1 v2) = [ compileImm env v1 - , prim2asm o (Reg EAX) (immArg env v2) + , prim2Asm o (Reg EAX) (immArg env v2) ] prim2Asm Add2 = IAdd From 3e7148518558145a18fcbffd0985e5d1557cd6cb Mon Sep 17 00:00:00 2001 From: ith Date: Sun, 21 Jun 2020 16:39:42 -0700 Subject: [PATCH 08/11] update page --- docs/lectures/04-boa.html | 4 ++-- lectures/04-boa.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/lectures/04-boa.html b/docs/lectures/04-boa.html index a3e1712..f5d4907 100644 --- a/docs/lectures/04-boa.html +++ b/docs/lectures/04-boa.html @@ -993,8 +993,8 @@

    ANF: Making Arguments Immediate
  • anf the relevant expressions,
  • bind them to a fresh variable.
  • -
    imm e@(If _ _ _) = immExp e
    -imm e@(If _ _ _) = immExp e
    +
    imm e@(If  _ _ _) = immExp e
    +imm e@(Let _ _ _) = immExp e
     
     immExp :: AnfE -> ([(Id, AnfE)], ImmE)
     immExp e = ([(t, e')], t)
    diff --git a/lectures/04-boa.md b/lectures/04-boa.md
    index fc1de72..2bc5e49 100644
    --- a/lectures/04-boa.md
    +++ b/lectures/04-boa.md
    @@ -1091,8 +1091,8 @@ That is, simply
     * bind them to a fresh variable.
     
     ```haskell
    -imm e@(If _ _ _) = immExp e
    -imm e@(If _ _ _) = immExp e
    +imm e@(If  _ _ _) = immExp e
    +imm e@(Let _ _ _) = immExp e
     
     immExp :: AnfE -> ([(Id, AnfE)], ImmE)
     immExp e = ([(t, e')], t)
    
    From ad13fc8f39259a7ea8c1ed039947e09849abbf37 Mon Sep 17 00:00:00 2001
    From: ith 
    Date: Sun, 21 Jun 2020 16:52:13 -0700
    Subject: [PATCH 09/11] update page
    
    ---
     docs/lectures/04-boa.html | 135 +++++++++++++++++++-------------------
     lectures/04-boa.md        |   5 +-
     2 files changed, 73 insertions(+), 67 deletions(-)
    
    diff --git a/docs/lectures/04-boa.html b/docs/lectures/04-boa.html
    index f5d4907..4d2c162 100644
    --- a/docs/lectures/04-boa.html
    +++ b/docs/lectures/04-boa.html
    @@ -763,74 +763,77 @@ 

    QUIZ

    Use the above function to test our ANF conversion.

    immArg :: Env -> ImmExpr -> Arg
     immArg env (Number n _) = Const n
    -immArg env (Id x _)     = RegOffset EBP (lookupEnv env x)
    -
    -compileImm :: Env -> ImmExpr Tag -> [Instruction]
    -compileImm env v  = [IMov (Reg EAX) (immArg env v) ]
    +immArg env (Id x _)     = RegOffset EBP i
    +  where
    +    i                   = fromMaybe err (lookupEnv env x)
    +    err                 = error (printf "Error: Variable '%s' is unbound" x)
     
    -compile :: Env -> AnfExpr Tag -> [Instruction]
    -compile env v@(Number {})  = compileImm env v
    -compile env v@(Id _ _)     = compileImm env v 
    -compile env (Prim1 op e)   = compile env e
    -                          ++ [ (prim1Asm op (Reg EAX) (Const 1)]
    -compile env (Prim2 op v1 v2) = [ compileImm env v1 
    -                               , prim2Asm o (Reg EAX) (immArg env v2) 
    -                               ]
    -
    -prim2Asm Add2 = IAdd
    -prim2Asm Sub2 = ISub
    -prim2Asm Mul2 = IMul
    -
    -prim1Asm Add1 = IAdd
    -prim1Asm Sub1 = ISub
    +compileImm :: Env -> ImmExpr Tag -> [Instruction]
    +compileImm env v  = [IMov (Reg EAX) (immArg env v) ]
    +
    +compile :: Env -> AnfExpr Tag -> [Instruction]
    +compile env v@(Number {})  = compileImm env v
    +compile env v@(Id _ _)     = compileImm env v 
    +compile env (Prim1 op e)   = compile env e
    +                          ++ [ (prim1Asm op (Reg EAX) (Const 1)]
    +compile env (Prim2 op v1 v2) = [ compileImm env v1 
    +                               , prim2Asm o (Reg EAX) (immArg env v2) 
    +                               ]
    +
    +prim2Asm Add2 = IAdd
    +prim2Asm Sub2 = ISub
    +prim2Asm Mul2 = IMul
     
    -
    -anf :: Int -> Expr a -> (Int, AnfExpr a)
    -anf i p@(Number {}) = (i, p)
    -anf i v@(Id {})     = (i, v)
    -anf i (Prim1 o e)   = (i', Prim1 o e') 
    -  where 
    -    (i', e')        = anf i e
    -
    -anf i (Prim2 o e1 e2) = (i2, mkLet (bs1 ++ bs2) (Prim2 o v1 v2))
    -  where
    -     (i1, (bs1, v1))  = imm i  e1
    -     (i2, (bs2, v2))  = imm i1 e2
    -
    -anf i (Let x  e1 e2)  = (i2, Let x e1' e2')
    -  where 
    -     (i1, e1')        = anf i e1
    -     (i2, e2')        = anf i1 e2
    -
    -anf i (If  e1 e2 e3)  = (i3, If e1' e2' e3')
    -  where 
    -     (i1, e1')        = anf i e1
    -     (i2, e2')        = anf i1 e2
    -     (i3, e3')        = anf i2 e3
    -
    -imm :: Int -> Expr a -> (Int, ([(Id , AnfExpr a)] , ImmExpr a))
    -imm i e@(Number {}) = (i, ([], e))
    -imm i e@(Id {})     = (i, ([], e))
    -imm i e@(Prim1 {})  = immExp i e
    -imm i e@(If {})     = immExp i e
    -imm i e@(Let {})    = immExp i e
    -
    -imm i (Prim2 o e1 e2) = (i2+1, ((v, Prim2 o v1 v2) : bs2 ++ bs1, Id v))
    -  where
    -    (i1, (bs1, v1)) = imm i e1
    -    (i2, (bs2, v2)) = imm i1 e2
    -    v               = mkTmpVar i2
    -
    -mkTmpVar i = "tmp" ++ show i
    -
    -mkLet :: [(Id , AnfExpr a)] -> AnfExpr a -> AnfExpr a
    -mkLet []              e = e
    -mkLet ((x1, e1) : bs) e = Let x1 e1 (mkLet bs e)
    -
    -immExp i e  = (i' + 1, ([(v, e')], v))
    -  where
    -    (i',e') = anf e
    -    v       = mkTmpVar i'
    +prim1Asm Add1 = IAdd +prim1Asm Sub1 = ISub + + +anf :: Int -> Expr a -> (Int, AnfExpr a) +anf i p@(Number {}) = (i, p) +anf i v@(Id {}) = (i, v) +anf i (Prim1 o e) = (i', Prim1 o e') + where + (i', e') = anf i e + +anf i (Prim2 o e1 e2) = (i2, mkLet (bs1 ++ bs2) (Prim2 o v1 v2)) + where + (i1, (bs1, v1)) = imm i e1 + (i2, (bs2, v2)) = imm i1 e2 + +anf i (Let x e1 e2) = (i2, Let x e1' e2') + where + (i1, e1') = anf i e1 + (i2, e2') = anf i1 e2 + +anf i (If e1 e2 e3) = (i3, If e1' e2' e3') + where + (i1, e1') = anf i e1 + (i2, e2') = anf i1 e2 + (i3, e3') = anf i2 e3 + +imm :: Int -> Expr a -> (Int, ([(Id , AnfExpr a)] , ImmExpr a)) +imm i e@(Number {}) = (i, ([], e)) +imm i e@(Id {}) = (i, ([], e)) +imm i e@(Prim1 {}) = immExp i e +imm i e@(If {}) = immExp i e +imm i e@(Let {}) = immExp i e + +imm i (Prim2 o e1 e2) = (i2+1, ((v, Prim2 o v1 v2) : bs2 ++ bs1, Id v)) + where + (i1, (bs1, v1)) = imm i e1 + (i2, (bs2, v2)) = imm i1 e2 + v = mkTmpVar i2 + +mkTmpVar i = "tmp" ++ show i + +mkLet :: [(Id , AnfExpr a)] -> AnfExpr a -> AnfExpr a +mkLet [] e = e +mkLet ((x1, e1) : bs) e = Let x1 e1 (mkLet bs e) + +immExp i e = (i' + 1, ([(v, e')], v)) + where + (i',e') = anf e + v = mkTmpVar i'

    Types & Strategy

    Writing the type aliases:

    type BareE   = Expr ()
    diff --git a/lectures/04-boa.md b/lectures/04-boa.md
    index 2bc5e49..386389b 100644
    --- a/lectures/04-boa.md
    +++ b/lectures/04-boa.md
    @@ -773,7 +773,10 @@ Use the above function to **test** our ANF conversion.
     ```haskell 
     immArg :: Env -> ImmExpr -> Arg
     immArg env (Number n _) = Const n
    -immArg env (Id x _)     = RegOffset EBP (lookupEnv env x)
    +immArg env (Id x _)     = RegOffset EBP i
    +  where
    +    i                   = fromMaybe err (lookupEnv env x)
    +    err                 = error (printf "Error: Variable '%s' is unbound" x)
     
     compileImm :: Env -> ImmExpr Tag -> [Instruction]
     compileImm env v  = [IMov (Reg EAX) (immArg env v) ]
    
    From f8f53b16798781643a8bf25df888c5451fdbc037 Mon Sep 17 00:00:00 2001
    From: ith 
    Date: Sun, 21 Jun 2020 23:23:26 -0700
    Subject: [PATCH 10/11] update page
    
    ---
     docs/lectures/05-cobra.html | 10 +++++-----
     lectures/05-cobra.md        | 10 +++++-----
     2 files changed, 10 insertions(+), 10 deletions(-)
    
    diff --git a/docs/lectures/05-cobra.html b/docs/lectures/05-cobra.html
    index 537a9ce..96fe7d6 100644
    --- a/docs/lectures/05-cobra.html
    +++ b/docs/lectures/05-cobra.html
    @@ -285,11 +285,11 @@ 

    Option 1: Use Two Words

    12 -[0x000000000][0x0000000c] +[0x000000000][0x00000018] 42 -[0x000000000][0x0000002a] +[0x000000000][0x00000054] false @@ -459,11 +459,11 @@

    Types

    Number 12 -HexConst 0x0000000c +HexConst 0x00000018 Number 42 -HexConst 0x0000002a +HexConst 0x00000054 @@ -625,7 +625,7 @@

    Shifted Representation and Mu n1 * n2 -2*n1 * 2*n2 = 4*(n1 + n2) +2*n1 * 2*n2 = 4*(n1 * n2) diff --git a/lectures/05-cobra.md b/lectures/05-cobra.md index 44582b0..a84a42b 100644 --- a/lectures/05-cobra.md +++ b/lectures/05-cobra.md @@ -57,8 +57,8 @@ First word is `0` means `bool`, is `1` means `number`, `2` means pointer etc. |---------:|------------------------------:| | `3`| `[0x000000000][0x00000003]`| | `5`| `[0x000000000][0x00000005]`| -| `12`| `[0x000000000][0x0000000c]`| -| `42`| `[0x000000000][0x0000002a]`| +| `12`| `[0x000000000][0x00000018]`| +| `42`| `[0x000000000][0x00000054]`| | `false`| `[0x000000001][0x00000000]`| | `true`| `[0x000000001][0x00000001]`| @@ -157,8 +157,8 @@ So, our examples become: | `Boolean True`| `HexConst 0x80000001`| | `Number 3`| `HexConst 0x00000006`| | `Number 5`| `HexConst 0x0000000a`| -| `Number 12`| `HexConst 0x0000000c`| -| `Number 42`| `HexConst 0x0000002a`| +| `Number 12`| `HexConst 0x00000018`| +| `Number 42`| `HexConst 0x00000054`| ### Transforms @@ -353,7 +353,7 @@ Thus, our _source values_ have the following _representations: | `3`| `6` | | `5`| `10` | | `3 * 5 = 15`| `6 * 10 = 60` | -| `n1 * n2`| `2*n1 * 2*n2 = 4*(n1 + n2)` | +| `n1 * n2`| `2*n1 * 2*n2 = 4*(n1 * n2)` | Thus, multiplication ends up accumulating the factor of 2. * Result is _two times_ the desired one. From d53a099a8294aac4fbe78e0d53ffe24ca5f64366 Mon Sep 17 00:00:00 2001 From: ith Date: Mon, 22 Jun 2020 00:39:24 -0700 Subject: [PATCH 11/11] update page --- docs/lectures/05-cobra.html | 3 ++- lectures/05-cobra.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/lectures/05-cobra.html b/docs/lectures/05-cobra.html index 96fe7d6..962292f 100644 --- a/docs/lectures/05-cobra.html +++ b/docs/lectures/05-cobra.html @@ -777,7 +777,8 @@

    4. Dynamic Checking

    or

    In fact, lets try to see what happens with our code on the above:

    - +

    Oops.

    Checking Tags at Run-Time

    Later, we will look into adding a static type system that will reject such meaningless programs at compile time. For now, lets see how to extend the compilation to abort execution when the wrong types of operands are found when the code is executing.

    diff --git a/lectures/05-cobra.md b/lectures/05-cobra.md index a84a42b..8090c95 100644 --- a/lectures/05-cobra.md +++ b/lectures/05-cobra.md @@ -567,6 +567,7 @@ In fact, lets try to see what happens with our code on the above: ```haskell ghci> exec "2 + true" +Unknown value: 0x80000005 ``` Oops.