Start using lvals and rvals.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index d9be2fd..f5b5923 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -382,8 +382,10 @@
          * argument, addressed relative to FP.
          * else it is an absolute global address.
          *
+         * et is ET_RVALUE for things like string constants, ET_LVALUE for
+         * variables.
          */
-        virtual void leaR0(int ea, Type* pPointerType) = 0;
+        virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) = 0;
 
         /* Load the pc-relative address of a forward-referenced variable to R0.
          * Return the address of the 4-byte constant so that it can be filled
@@ -504,6 +506,12 @@
             return mExpressionStack.size();
         }
 
+        virtual void forceR0RVal() {
+            if (getR0ExpressionType() == ET_LVALUE) {
+                loadR0FromR0();
+            }
+        }
+
     protected:
         /*
          * Output a byte. Handles all values, 0..ff.
@@ -545,6 +553,13 @@
         void setR0Type(Type* pType) {
             assert(pType != NULL);
             mExpressionStack.back().pType = pType;
+            mExpressionStack.back().et = ET_RVALUE;
+        }
+
+        void setR0Type(Type* pType, ExpressionType et) {
+            assert(pType != NULL);
+            mExpressionStack.back().pType = pType;
+            mExpressionStack.back().et = et;
         }
 
         Type* getTOSType() {
@@ -1085,7 +1100,8 @@
                     o4(0xE1C200F0); // strd r0, [r2]
                     break;
                 default:
-                    error("storeR0ToTOS: unimplemented type");
+                    error("storeR0ToTOS: unimplemented type %d",
+                            pDestType->tag);
                     break;
             }
         }
@@ -1112,7 +1128,7 @@
             setR0Type(pPointerType->pHead);
         }
 
-        virtual void leaR0(int ea, Type* pPointerType) {
+        virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) {
             if (ea > -LOCAL && ea < LOCAL) {
                 // Local, fp relative
                 if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) {
@@ -1130,7 +1146,7 @@
                 o4(ea);         // .L1:   .word 0
                                 // .L99:
             }
-            setR0Type(pPointerType);
+            setR0Type(pPointerType, et);
         }
 
         virtual int leaForward(int ea, Type* pPointerType) {
@@ -2089,7 +2105,8 @@
                     o(0x19dd); /* fstpl (%ecx) */
                     break;
                 default:
-                    error("storeR0ToTOS: unsupported type");
+                    error("storeR0ToTOS: unsupported type %d",
+                            pTargetType->tag);
                     break;
             }
         }
@@ -2119,9 +2136,9 @@
             setR0Type(pPointerType->pHead);
         }
 
-        virtual void leaR0(int ea, Type* pPointerType) {
+        virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) {
             gmov(10, ea); /* leal EA, %eax */
-            setR0Type(pPointerType);
+            setR0Type(pPointerType, et);
         }
 
         virtual int leaForward(int ea, Type* pPointerType) {
@@ -2208,6 +2225,7 @@
 
         virtual void callIndirect(int l, Type* pFunc) {
             assert(pFunc->tag == TY_FUNC);
+            popType(); // Get rid of indirect fn pointer type
             setR0Type(pFunc->pHead);
             oad(0x2494ff, l); /* call *xxx(%esp) */
         }
@@ -2495,9 +2513,10 @@
             mpBase->loadR0FromR0();
         }
 
-        virtual void leaR0(int ea, Type* pPointerType) {
-            fprintf(stderr, "leaR0(%d)\n", ea);
-            mpBase->leaR0(ea, pPointerType);
+        virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) {
+            fprintf(stderr, "leaR0(%d, %d, %d)\n", ea,
+                    pPointerType->pHead->tag, et);
+            mpBase->leaR0(ea, pPointerType, et);
         }
 
         virtual int leaForward(int ea, Type* pPointerType) {
@@ -2607,6 +2626,10 @@
         virtual size_t getExpressionStackDepth() {
             return mpBase->getExpressionStackDepth();
         }
+
+        virtual void forceR0RVal() {
+            return mpBase->forceR0RVal();
+        }
     };
 
 #endif // PROVIDE_TRACE_CODEGEN
@@ -3728,7 +3751,7 @@
 
     bool acceptStringLiteral() {
         if (tok == '"') {
-            pGen->leaR0((int) glo, mkpCharPtr);
+            pGen->leaR0((int) glo, mkpCharPtr, ET_RVALUE);
             // This while loop merges multiple adjacent string constants.
             while (tok == '"') {
                 while (ch != '"' && ch != EOF) {
@@ -3799,6 +3822,7 @@
             } else if (c == 2) {
                 /* -, +, !, ~ */
                 unary(false);
+                pGen->forceR0RVal();
                 if (t == '!')
                     pGen->gUnaryCmp(a);
                 else if (t == '+') {
@@ -3812,6 +3836,7 @@
                 if (pCast) {
                     skip(')');
                     unary(false);
+                    pGen->forceR0RVal();
                     pGen->convertR0(pCast);
                 } else {
                     expr();
@@ -3821,6 +3846,7 @@
                 /* This is a pointer dereference.
                  */
                 unary(false);
+                pGen->forceR0RVal();
                 Type* pR0Type = pGen->getR0Type();
                 if (pR0Type->tag != TY_POINTER) {
                     error("Expected a pointer type.");
@@ -3831,6 +3857,7 @@
                     if (accept('=')) {
                         pGen->pushR0();
                         expr();
+                        pGen->forceR0RVal();
                         pGen->storeR0ToTOS();
                     } else if (t) {
                         pGen->loadR0FromR0();
@@ -3840,7 +3867,8 @@
                 // t == 0 to trigger an indirect function call. Hack!
             } else if (t == '&') {
                 VariableInfo* pVI = VI(tok);
-                pGen->leaR0((int) pVI->pAddress, createPtrType(pVI->pType));
+                pGen->leaR0((int) pVI->pAddress, createPtrType(pVI->pType),
+                        ET_RVALUE);
                 next();
             } else if (t == EOF ) {
                 error("Unexpected EOF.");
@@ -3867,9 +3895,11 @@
                 if ((tok == '=') & allowAssignment) {
                     /* assignment */
                     next();
-                    pGen->leaR0(n, createPtrType(pVI->pType));
+                    pGen->leaR0(n, createPtrType(pVI->pType), ET_LVALUE);
+                    checkLVal();
                     pGen->pushR0();
                     expr();
+                    pGen->forceR0RVal();
                     pGen->storeR0ToTOS();
                 } else if (tok != '(') {
                     /* variable */
@@ -3883,7 +3913,7 @@
                     // load a variable
                     if (tokl == 11) {
                         // post inc / post dec
-                        pGen->leaR0(n, createPtrType(pVI->pType));
+                        pGen->leaR0(n, createPtrType(pVI->pType), ET_LVALUE);
 
                         pGen->pushR0();
                         pGen->loadR0FromR0();
@@ -3909,8 +3939,7 @@
                         pGen->popR0();
                         next();
                     } else {
-                        pGen->leaR0(n, createPtrType(pVI->pType));
-                        pGen->loadR0FromR0();
+                        pGen->leaR0(n, createPtrType(pVI->pType), ET_LVALUE);
                     }
                 }
             }
@@ -3934,7 +3963,7 @@
                     pVI->pForward = (void*) pGen->leaForward(
                             (int) pVI->pForward, pFn);
                 } else {
-                    pGen->leaR0(n, pFn);
+                    pGen->leaR0(n, pFn, ET_RVALUE);
                 }
                 pGen->pushR0();
             }
@@ -3949,6 +3978,7 @@
                     error("Unexpected argument.");
                 }
                 expr();
+                pGen->forceR0RVal();
                 Type* pTargetType;
                 if (pArgList) {
                     pTargetType = pArgList->pHead;
@@ -3997,7 +4027,7 @@
             while (level == tokl) {
                 t = tokc;
                 next();
-
+                pGen->forceR0RVal();
                 if (level > 8) {
                     a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */
                     binaryOp(level);
@@ -4010,6 +4040,7 @@
                         // Push a dummy value so we don't fail
                         pGen->li(0);
                     }
+                    pGen->forceR0RVal();
                     if ((level == 4) | (level == 5)) {
                         pGen->gcmp(t);
                     } else {
@@ -4019,6 +4050,7 @@
             }
             /* && and || output code generation */
             if (a && level > 8) {
+                pGen->forceR0RVal();
                 a = pGen->gtst(t == OP_LOGICAL_OR, a);
                 pGen->li(t != OP_LOGICAL_OR);
                 int b = pGen->gjmp(0);
@@ -4035,6 +4067,7 @@
 
     int test_expr() {
         expr();
+        pGen->forceR0RVal();
         return pGen->gtst(0, 0);
     }
 
@@ -4103,6 +4136,7 @@
             if (accept(TOK_RETURN)) {
                 if (tok != ';') {
                     expr();
+                    pGen->forceR0RVal();
                     if (pReturnType->tag == TY_VOID) {
                         error("Must not return a value from a void function");
                     } else {
@@ -4424,6 +4458,12 @@
         return pType;
     }
 
+    void checkLVal() {
+        if (pGen->getR0ExpressionType() != ET_LVALUE) {
+            error("Expected an lval");
+        }
+    }
+
     void addGlobalSymbol(Type* pDecl) {
         tokenid_t t = pDecl->id;
         VariableInfo* pVI = VI(t);
@@ -4466,9 +4506,10 @@
                 VI(pDecl->id)->pAddress = (void*) variableAddress;
                 if (accept('=')) {
                     /* assignment */
-                    pGen->leaR0(variableAddress, createPtrType(pDecl));
+                    pGen->leaR0(variableAddress, createPtrType(pDecl), ET_LVALUE);
                     pGen->pushR0();
                     expr();
+                    pGen->forceR0RVal();
                     pGen->storeR0ToTOS();
                 }
                 if (tok == ',')