Changes to allow unique names
[repair.git] / Repair / RepairCompiler / MCC / IR / DotExpr.java
index 901b523d2b7730348490b26cd63b8c9c1e0c4d48..6998d3a3f001d8edb46ff6c5196380631c77ef97 100755 (executable)
@@ -1,13 +1,93 @@
 package MCC.IR;
 
 import java.util.*;
+import MCC.Compiler;
 
 public class DotExpr extends Expr {
-    
+
     Expr left;
     String field;
     Expr index;
 
+    static boolean DOMEMCHECKS=false;
+    static boolean DOTYPECHECKS=false;
+    static boolean DONULL=false;
+
+
+    public DotExpr(Expr left, String field, Expr index) {
+        this.left = left;
+        this.field = field;
+        this.index = index;
+    }
+
+    public boolean isInvariant(Set vars) {
+       if (!left.isInvariant(vars))
+           return false;
+       if (intindex!=null)
+           return intindex.isInvariant(vars);
+       else
+           return true;
+    }
+
+    public Set findInvariants(Set vars) {
+       if (isInvariant(vars)) {
+           Set s=new HashSet();
+           s.add(this);
+           return s;
+       } else {
+           Set ls=left.findInvariants(vars);
+           if (intindex!=null) {
+               ls.addAll(intindex.findInvariants(vars));
+               Expr indexbound=((ArrayDescriptor)this.fd).getIndexBound();
+               ls.addAll(indexbound.findInvariants(vars));
+               if ((!(intindex instanceof IntegerLiteralExpr))||
+                   ((IntegerLiteralExpr) intindex).getValue() != 0) {
+                   FieldDescriptor fd=this.fd;
+                   if (fd instanceof ArrayDescriptor)
+                       fd=((ArrayDescriptor)fd).getField();
+                   Expr basesize = fd.getBaseSizeExpr();
+                   ls.addAll(basesize.findInvariants(vars));
+               }
+           }
+           return ls;
+       }
+    }
+
+
+    public boolean isSafe() {
+       if (!left.isSafe())
+           return false;
+
+       FieldDescriptor tmpfd=fd;
+
+       if (tmpfd.getPtr()) // Pointers cound be invalid
+           return false;
+
+       if (tmpfd instanceof ArrayDescriptor) {
+            Expr arrayindex=((ArrayDescriptor)tmpfd).getIndexBound();
+            if (index instanceof IntegerLiteralExpr&&arrayindex instanceof IntegerLiteralExpr) {
+                int indexvalue=((IntegerLiteralExpr)index).getValue();
+                int arrayindexvalue=((IntegerLiteralExpr)arrayindex).getValue();
+                if (indexvalue>=0&&indexvalue<arrayindexvalue)
+                    return true;
+            }
+           return false; // Otherwise, arrays could be out of bounds
+        }
+        return true;
+    }
+
+    public Set freeVars() {
+       Set lset=left.freeVars();
+       Set iset=null;
+       if (intindex!=null)
+           iset=intindex.freeVars();
+       if (lset==null)
+           return iset;
+       if (iset!=null)
+           lset.addAll(iset);
+       return lset;
+    }
+
     /*
     static int memoryindents = 0;
 
@@ -23,34 +103,62 @@ public class DotExpr extends Expr {
     FieldDescriptor fd;
     TypeDescriptor fieldtype;
     Expr intindex;
-    
-    public DotExpr(Expr left, String field, Expr index) {
-        this.left = left;
-        this.field = field;
-        this.index = index;
-        StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();        
-        FieldDescriptor fd = struct.getField(field);
-        LabelDescriptor ld = struct.getLabel(field);
-       if (ld != null) { /* label */
-            assert fd == null;
-            fieldtype = ld.getType(); // d.s ==> Superblock, while,  d.b ==> Block
-            fd = ld.getField();
-            assert fd != null;
-            assert intindex == null;
-            intindex = ld.getIndex();
-        } else {
-            fieldtype = fd.getType();
-           intindex=index;
-        }
-       this.fd=fd;
+
+    public String name() {
+       String name=left.name()+"."+field;
+       if (index!=null)
+           name+="["+index.name()+"]";
+       return name;
+    }
+
+    public void findmatch(Descriptor d, Set s) {
+       if (d==fd)
+           s.add(this);
+       left.findmatch(d,s);
+       if (intindex!=null)
+           intindex.findmatch(d,s);
+    }
+
+    public Set useDescriptor(Descriptor d) {
+       HashSet newset=new HashSet();
+       if (d==fd)
+           newset.add(this);
+       newset.addAll(left.useDescriptor(d));
+       if (intindex!=null)
+           newset.addAll(intindex.useDescriptor(d));
+       return newset;
+    }
+
+    public boolean usesDescriptor(Descriptor d) {
+       if (d==fd)
+           return true;
+       return left.usesDescriptor(d)||((intindex!=null)&&intindex.usesDescriptor(d));
+    }
+
+    public boolean equals(Map remap, Expr e) {
+       if (e==null||!(e instanceof DotExpr))
+           return false;
+       DotExpr de=(DotExpr)e;
+       if (!de.field.equals(field))
+           return false;
+       if (index==null) {
+           if (de.index!=null)
+               return false;
+       } else if (!index.equals(remap,de.index))
+           return false;
+       if (!left.equals(remap,de.left))
+           return false;
+       return true;
     }
 
+
     public Set getRequiredDescriptors() {
         Set v = left.getRequiredDescriptors();
-        
-        if (index != null) {
-            v.addAll(index.getRequiredDescriptors());
+
+        if (intindex != null) {
+            v.addAll(intindex.getRequiredDescriptors());
         }
+        v.add(fd);
         return v;
     }
 
@@ -66,165 +174,332 @@ public class DotExpr extends Expr {
        return intindex;
     }
 
+    private boolean exactalloc(TypeDescriptor td) {
+        if (!(td instanceof StructureTypeDescriptor))
+            return false;
+        StructureTypeDescriptor std=(StructureTypeDescriptor)td;
+        if (std.size()!=1) /* Just looking for arrays */
+            return false;
+        FieldDescriptor tmpfd=std.get(0);
+        if (!(tmpfd instanceof ArrayDescriptor))
+            return false;
+        ArrayDescriptor afd=(ArrayDescriptor)tmpfd;
+        TypeDescriptor elementdescriptor=afd.getType();
+        Expr sizeexpr=elementdescriptor.getSizeExpr();
+        if (!OpExpr.isInt(sizeexpr))
+            return false;
+        Expr indexbound=afd.getIndexBound();
+        if (indexbound instanceof DotExpr)
+            return true;
+        if ((indexbound instanceof OpExpr)&&
+            (((OpExpr)indexbound).getOpcode()==Opcode.MULT)&&
+            (((OpExpr)indexbound).getLeftExpr() instanceof DotExpr)&&
+            (((OpExpr)indexbound).getRightExpr() instanceof DotExpr))
+            return true;
+        return false;
+    }
+
     public void generate(CodeWriter writer, VarDescriptor dest) {
         VarDescriptor leftd = VarDescriptor.makeNew("left");
 
-        writer.output("// " +  leftd.getSafeSymbol() + " <-- ");
+       if (writer.getInvariantValue()!=null&&
+           writer.getInvariantValue().isInvariant(this)) {
+           writer.addDeclaration(getType().getGenerateType().getSafeSymbol().toString(), dest.getSafeSymbol());
+           writer.outputline(dest.getSafeSymbol()+"="+writer.getInvariantValue().getValue(this).getSafeSymbol()+";");
+           writer.outputline("maybe="+writer.getInvariantValue().getMaybe(this).getSafeSymbol()+";");
+           return;
+       }
+
+        writer.output("/* " +  leftd.getSafeSymbol() + " <-- ");
         left.prettyPrint(writer);
-        writer.outputline("");
+        writer.outputline("*/");
 
         left.generate(writer, leftd);
 
-        writer.output("// " +  leftd.getSafeSymbol() + " = ");
+        writer.output("/* " +  leftd.getSafeSymbol() + " = ");
         left.prettyPrint(writer);
-        writer.outputline("");
-      
-        StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();        
-        Expr intindex = index;
+        writer.outputline("*/");
+
+        StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
         Expr offsetbits;
 
-        // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor obect that is in teh vector list
-        // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array 
+        // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor object that is in the vector list
+        // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
         // descriptor not the underlying field descriptor
 
         /* we calculate the offset in bits */
-        offsetbits = struct.getOffsetExpr(fd);                    
 
-        if (fd instanceof ArrayDescriptor) {
-            fd = ((ArrayDescriptor) fd).getField();
-        } 
-        
+        offsetbits = struct.getOffsetExpr(fd);
+
+       FieldDescriptor fd=this.fd;
+       if (fd instanceof ArrayDescriptor)
+           fd=((ArrayDescriptor)fd).getField();
+       boolean doboundscheck=true;
+       boolean performedboundscheck=false;
+
+       writer.addDeclaration(getType().getGenerateType().toString(),dest.getSafeSymbol());
+       writer.outputline(dest.getSafeSymbol()+"=0;");
+
         if (intindex != null) {
             if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) {
-                /* short circuit for constant 0 */                
+                /* short circuit for constant 0 */
             } else {
                 Expr basesize = fd.getBaseSizeExpr();
-                offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
+               if (doboundscheck) {
+                   VarDescriptor indexvd=VarDescriptor.makeNew("index");
+                   indexvd.setType(ReservedTypeDescriptor.INT);
+                   writer.getSymbolTable().add(indexvd);
+
+                   writer.output("/* " + indexvd.getSafeSymbol() + " <-- ");
+
+                   intindex.prettyPrint(writer);
+                   writer.outputline("*/");
+                   intindex.generate(writer, indexvd);
+                   writer.output("/* " + indexvd.getSafeSymbol() + " = ");
+                   intindex.prettyPrint(writer);
+                   writer.outputline("*/");
+                   Expr indexbound=((ArrayDescriptor)this.fd).getIndexBound();
+                   VarDescriptor indexboundvd=VarDescriptor.makeNew("indexbound");
+
+                   indexbound.generate(writer,indexboundvd);
+
+                   writer.outputline("if ("+indexvd.getSafeSymbol()+">=0 &&"+indexvd.getSafeSymbol()+"<"+indexboundvd.getSafeSymbol()+")");
+                   writer.startblock();
+                   VarExpr indexve=new VarExpr(indexvd);
+                   offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, indexve));
+
+                   performedboundscheck=true;
+               } else
+                   offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
             }
         }
-        
-        final SymbolTable st = writer.getSymbolTable();
-        TypeDescriptor td = offsetbits.typecheck(new SemanticAnalyzer() {
-                public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
-                public SymbolTable getSymbolTable() { return st; }
-            });
-
-        if (td == null) {
-            throw new IRException();
-        } else if (td != ReservedTypeDescriptor.INT) {
-            throw new IRException();
-        }
-               
-        // #TBD#: ptr's to bits and byte's and stuff are a little iffy... 
-        // right now, a bit* is the same as a int* = short* = byte* (that is there 
-        // is no post-derefernce mask)
-        
-        // #ATTN#: do we handle int* correctly? what is the correct behavior? we automatically 
-        // dereference pointers, but for structures that means that if we have a nested structure
-        // we return an integer address to that nested structure. if we have a pointer to a 
-        // structure else where we want that base address ... yeah so we *(int *) it... ok we are
-        // correct
 
-        boolean dotypecheck = false;
+       final SymbolTable st = writer.getSymbolTable();
+        TypeDescriptor td2 = offsetbits.typecheck(new SemanticAnalyzer() {
+               public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
+               public SymbolTable getSymbolTable() { return st; }
+           });
 
-        if (offsetbits instanceof IntegerLiteralExpr) {
-            int offsetinbits = ((IntegerLiteralExpr) offsetbits).getValue();
-            int offset = offsetinbits >> 3; /* offset in bytes */
-
-            if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
-                int shift = offsetinbits - (offset << 3);            
-                int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
-                               
-                /* type var = ((*(int *) (base + offset)) >> shift) & mask */
-                writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol() + 
-                                  " = ((*(int *)" + 
-                                  "(" + leftd.getSafeSymbol() + " + " + offset + ")) " + 
-                                  " >> " + shift + ") & 0x" + Integer.toHexString(mask) + ";");  
-            } else { /* a structure address or a ptr! */
-                String ptr = fd.getPtr() ? "*(int *)" : "";
-                /* type var = [*(int *)] (base + offset) */
-
-                // #ATTN: was 'getType.getGeneratedType()' instead of 'int' but all pointers are represented
-                // by integers
-                writer.outputline("int " + dest.getSafeSymbol() + 
-                                  " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset + ");");  
-
-                dotypecheck = true;
-            }
-        } else { /* offset in bits is an expression that must be generated */                        
-            VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
-            writer.output("// " + ob.getSafeSymbol() + " <-- ");
-            offsetbits.prettyPrint(writer);
-            writer.outputline("");
-            offsetbits.generate(writer, ob);
-            writer.output("// " + ob.getSafeSymbol() + " = ");
-            offsetbits.prettyPrint(writer);
-            writer.outputline("");
-
-            /* derive offset in bytes */
-            VarDescriptor offset = VarDescriptor.makeNew("offset");
-            writer.outputline("int " + offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
-            
-            if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
-                VarDescriptor shift = VarDescriptor.makeNew("shift");
-                writer.outputline("int " + shift.getSafeSymbol() + " = " + ob.getSafeSymbol() + 
-                                  " - (" + offset.getSafeSymbol() + " << 3);");
-                int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
-                
-                /* type var = ((*(int *) (base + offset)) >> shift) & mask */
-                writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol() + 
-                                  " = ((*(int *)" + 
-                                  "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " + 
-                                  " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");  
-            } else { /* a structure address or a ptr */
-                String ptr = fd.getPtr() ? "*(int *)" : "";
-                /* type var = [*(int *)] (base + offset) */
-
-                // #ATTN: was 'getType.getGeneratedType()' instead of 'int' but all pointers are represented
-                // by integers
-                writer.outputline("int " + dest.getSafeSymbol() + 
-                                  " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");  
-                dotypecheck = true;
-            }            
-        }
+        if (td2 == null) {
+           throw new IRException();
+        } else if (td2 != ReservedTypeDescriptor.INT) {
+           throw new IRException();
+       }
 
+        boolean dotypecheck = false;
 
-        if (dotypecheck) { /* typemap checks! */
-            // dest is 'low'
-            // high is 'low' + sizeof(fd.getDataStructure) <<< can be cached!!
-
-            // #ATTN#: we need to get the size of the fieldtype (if its a label the type of the label, not the 
-            // underlying field's type
-
-            Expr sizeofexpr = fieldtype.getSizeExpr();
-            VarDescriptor sizeof = VarDescriptor.makeNew("sizeof");
-            sizeofexpr.generate(writer, sizeof);
-
-            String low = dest.getSafeSymbol();
-            String high = VarDescriptor.makeNew("high").getSafeSymbol();
-            writer.outputline("int " + high + " = " + low + " + " + sizeof.getSafeSymbol() + ";");            
-            writer.outputline("assertvalidmemory(" + low + ", " + high + ");");            
+       VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
+       writer.output("/* " + ob.getSafeSymbol() + " <-- ");
+       offsetbits.prettyPrint(writer);
+       writer.outputline("*/");
+       offsetbits.generate(writer, ob);
+       writer.output("/* " + ob.getSafeSymbol() + " = ");
+       offsetbits.prettyPrint(writer);
+       writer.outputline("*/");
+
+       /* derive offset in bytes */
+       VarDescriptor offset = VarDescriptor.makeNew("offset");
+       writer.addDeclaration("int", offset.getSafeSymbol());
+       writer.outputline(offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
+
+       if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
+           VarDescriptor shift = VarDescriptor.makeNew("shift");
+           writer.addDeclaration("int", shift.getSafeSymbol());
+           writer.outputline(shift.getSafeSymbol() + " = " + ob.getSafeSymbol() +
+                             " - (" + offset.getSafeSymbol() + " << 3);");
+           int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
+
+           /* type var = ((*(int *) (base + offset)) >> shift) & mask */
+           writer.outputline("if ("+leftd.getSafeSymbol()+")");
+           writer.outputline(dest.getSafeSymbol() + " = ((*(int *)" +
+                             "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " +
+                             " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");
+           writer.outputline("else maybe=1;");
+       } else { /* a structure address or a ptr */
+           String ptr = fd.getPtr() ? "*(int *)" : "";
+           /* type var = [*(int *)] (base + offset) */
+           writer.outputline("if ("+leftd.getSafeSymbol()+")");
+           writer.startblock();
+           writer.outputline(dest.getSafeSymbol() +
+                             " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");
+           if (fd.getPtr()) {
+               writer.outputline("if ("+dest.getSafeSymbol()+")");
+               writer.startblock();
+
+
+               if (DOTYPECHECKS||DOMEMCHECKS) {
+                    /* NEED TO CHECK IF THERE ARE VARIABLES TO PLAY WITH IN THE STRUCT!!!! */
+                    if (Compiler.EXACTALLOCATION&&exactalloc(td)) {
+                        writer.outputline("if (!assertexactmemory("+dest.getSafeSymbol()+", "+this.td.getId()+"))");
+                        {
+                            writer.startblock();
+                            /* Okay, we've failed to fit it in here */
+
+                            VarDescriptor highptr=VarDescriptor.makeNew("highptr");
+                            writer.addDeclaration("int", highptr.getSafeSymbol());
+                            writer.outputline(highptr.getSafeSymbol()+"=getendofblock("+dest.getSafeSymbol()+");");
+                            VarDescriptor size=VarDescriptor.makeNew("size");
+                            writer.addDeclaration("int", size.getSafeSymbol());
+                            writer.outputline(size.getSafeSymbol()+"="+highptr.getSafeSymbol()+"-"+dest.getSafeSymbol()+";");
+
+                            StructureTypeDescriptor std=(StructureTypeDescriptor)this.td;
+                            ArrayDescriptor afd=(ArrayDescriptor)std.get(0);
+                            TypeDescriptor elementdescriptor=afd.getType();
+                            Expr sizeexpr=elementdescriptor.getSizeExpr();
+                            int elementsize=OpExpr.getInt(sizeexpr);
+                            //convert size to bytes
+                            if (elementsize%8==0)
+                                elementsize=elementsize/8;
+                            else
+                                elementsize=(elementsize/8)+1;
+                            /* Basic sanity check */
+                            writer.outputline("if ("+size.getSafeSymbol()+"%"+
+                                              elementsize+"==0)");
+                            {
+                                writer.startblock();
+                                VarDescriptor numElements=VarDescriptor.makeNew("numberofelements");
+                                writer.addDeclaration("int", numElements.getSafeSymbol());
+                                writer.outputline(numElements.getSafeSymbol()+"="+size.getSafeSymbol()+"/"+elementsize+";");
+                                Expr indexbound=afd.getIndexBound();
+                                if  (indexbound instanceof DotExpr) {
+                                /* NEED TO IMPLEMENT */
+
+                                    VarExpr ve=new VarExpr(numElements);
+                                    numElements.setType(ReservedTypeDescriptor.INT);
+                                    ve.td=ReservedTypeDescriptor.INT;
+                                    Updates u=new Updates(indexbound,ve);
+                                    UpdateNode un=new UpdateNode(null);
+                                    un.addUpdate(u);
+                                    un.generate(writer,false,false,null,null,null,null);
+                                   writer.outputline("free"+RepairGenerator.name+"("+RepairGenerator.newmodel.getSafeSymbol()+");");
+                                   writer.outputline("computesizes(thisvar);");
+                                   writer.outputline(RepairGenerator.name+"_staterecomputesizes(thisvar);");
+                                   writer.outputline("goto rebuild;");
+
+                                   //                                    writer.outputline("break;");
+                                   
+                                } else if ((indexbound instanceof OpExpr)&&
+                                           (((OpExpr)indexbound).getOpcode()==Opcode.MULT)&&
+                                           (((OpExpr)indexbound).getLeftExpr() instanceof DotExpr)&&
+                                           (((OpExpr)indexbound).getRightExpr() instanceof DotExpr)) {
+
+                                    DotExpr leftexpr=(DotExpr)(((OpExpr)indexbound).getLeftExpr());
+                                    VarDescriptor leftside=VarDescriptor.makeNew("leftvalue");
+                                    writer.addDeclaration("int", leftside.getSafeSymbol());
+                                    leftexpr.generate(writer,leftside);
+                                    DotExpr rightexpr=(DotExpr)(((OpExpr)indexbound).getRightExpr());
+                                    VarDescriptor rightside=VarDescriptor.makeNew("rightvalue");
+                                    writer.addDeclaration("int", rightside.getSafeSymbol());
+                                    rightexpr.generate(writer,rightside);
+                                    writer.outputline("if (("+leftside.getSafeSymbol()+"!=0) &&("+numElements.getSafeSymbol()+"%"+leftside.getSafeSymbol()+"==0))");
+                                    {
+                                        writer.startblock();
+                                        VarDescriptor newvalue=VarDescriptor.makeNew("newvalue");
+                                        writer.addDeclaration("int", newvalue.getSafeSymbol());
+                                        writer.outputline(newvalue.getSafeSymbol()+"="+numElements.getSafeSymbol()+"/"+leftside.getSafeSymbol()+";");
+                                        VarExpr ve=new VarExpr(newvalue);
+                                        newvalue.setType(ReservedTypeDescriptor.INT);
+                                        ve.td=ReservedTypeDescriptor.INT;
+                                        Updates u=new Updates(rightexpr,ve);
+                                        UpdateNode un=new UpdateNode(null);
+                                        un.addUpdate(u);
+                                        un.generate(writer,false,false,null,null,null,null);
+                                       writer.outputline("free"+RepairGenerator.name+"("+RepairGenerator.newmodel.getSafeSymbol()+");");
+                                       writer.outputline("computesizes(thisvar);");
+                                       writer.outputline(RepairGenerator.name+"_staterecomputesizes(thisvar);");
+                                       writer.outputline("goto rebuild;");
+                                       //                                        writer.outputline("break;");
+                                        writer.endblock();
+                                    }
+                                    writer.outputline("else if (("+rightside.getSafeSymbol()+"!=0)&&("+numElements.getSafeSymbol()+"%"+rightside.getSafeSymbol()+"==0))");
+                                    {
+                                        writer.startblock();
+                                        VarDescriptor newvalue=VarDescriptor.makeNew("newvalue");
+                                        writer.addDeclaration("int", newvalue.getSafeSymbol());
+                                        writer.outputline(newvalue.getSafeSymbol()+"="+numElements.getSafeSymbol()+"/"+rightside.getSafeSymbol()+";");
+                                        VarExpr ve=new VarExpr(newvalue);
+                                        newvalue.setType(ReservedTypeDescriptor.INT);
+                                        ve.td=ReservedTypeDescriptor.INT;
+                                        Updates u=new Updates(leftexpr,ve);
+                                        UpdateNode un=new UpdateNode(null);
+                                        un.addUpdate(u);
+                                        un.generate(writer,false,false,null,null,null,null);
+                                       writer.outputline("free"+RepairGenerator.name+"("+RepairGenerator.newmodel.getSafeSymbol()+");");
+                                       writer.outputline("computesizes(thisvar);");
+                                       writer.outputline(RepairGenerator.name+"_staterecomputesizes(thisvar);");
+                                       writer.outputline("goto rebuild;");
+                                       //                                        writer.outputline("break;");
+                                        writer.endblock();
+                                    }
+
+
+                                } else throw new Error("Should be here");
+
+                                writer.endblock();
+                            }
+
+                            writer.endblock();
+                        }
+                            /*
+
+                              if (indexbound instanceof DotExpr)
+                              return true;
+                              if ((indexbound instanceof OpExpr)&&
+                              (((OpExpr)indexbound).getOpcode()==Opcode.MULT)&&
+                              (((OpExpr)indexbound).getLeftExpr() instanceof DotExpr)&&
+                              (((OpExpr)indexbound).getRightExpr() instanceof DotExpr))
+                              return true;
+                              return false;
+                            */
+
+
+                            /* Give up and null out bad pointer */
+                    }
+                    VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
+                    if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
+                        writer.addDeclaration("bool", typevar.getSafeSymbol());
+                        writer.outputline(typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
+                        dotypecheck = true;
+                    } else if (DOTYPECHECKS) {
+                        writer.addDeclaration("bool", typevar.getSafeSymbol());
+                        writer.outputline(typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
+                    }
+                    if (DOMEMCHECKS||DOTYPECHECKS) {
+                        writer.outputline("if (!"+typevar.getSafeSymbol()+")");
+                        writer.startblock();
+                        writer.outputline(dest.getSafeSymbol()+"=0;");
+                        if (DONULL)
+                            writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")=0;");
+                        writer.endblock();
+                    }
+                }
 
-            // we need to null value check and conditionalize the rest of the rule... we'll use a hack
-            // here where we store the number of indents in this class... and then provide a static 
-            // method to unwind...
-            //writer.outputline("// assertvalidmemory ");
-            //DotExpr.memoryindents++;
-            //writer.outputline("if (" + dest.getSafeSymbol() + " != NULL)");
-            //writer.startblock();           
+               writer.endblock();
+           }
+           writer.endblock();
+           writer.outputline("else maybe=1;");
         }
-
+       if (performedboundscheck) {
+           writer.endblock();
+           writer.outputline(" else ");
+           writer.startblock();
+           writer.outputline(dest.getSafeSymbol()+"=0;");
+           writer.outputline("maybe=1;");
+           if (!Compiler.REPAIR)
+               writer.outputline("printf(\"Array Index Out of Bounds\");");
+           writer.endblock();
+       }
     }
 
     private int bitmask(int bits) {
         int mask = 0;
-        
+
         for (int i = 0; i < bits; i++) {
             mask <<= 1;
             mask += 1;
         }
 
-        return mask;            
+        return mask;
     }
 
     public void prettyPrint(PrettyPrinter pp) {
@@ -237,10 +512,52 @@ public class DotExpr extends Expr {
         }
     }
 
+    public boolean isValue(TypeDescriptor td) {
+       FieldDescriptor tmpfd=fd;
+       if (tmpfd instanceof ArrayDescriptor)
+           tmpfd=((ArrayDescriptor)tmpfd).getField();
+       return (tmpfd.getPtr()||(tmpfd.getType() instanceof ReservedTypeDescriptor));
+    }
+
+    public boolean isPtr() {
+       FieldDescriptor tmpfd=fd;
+       if (tmpfd instanceof ArrayDescriptor)
+           tmpfd=((ArrayDescriptor)tmpfd).getField();
+       return tmpfd.getPtr();
+    }
+
+    boolean typechecked=false;
     public TypeDescriptor typecheck(SemanticAnalyzer sa) {
+       if (typechecked)
+           return this.td;
+       else typechecked=true;
         TypeDescriptor lefttype = left.typecheck(sa);
         TypeDescriptor indextype = index == null ? null : index.typecheck(sa);
 
+       {
+           /* finished typechecking...so we can fill the fields in */
+           StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
+           FieldDescriptor fd = struct.getField(field);
+           LabelDescriptor ld = struct.getLabel(field);
+           if (ld != null) { /* label */
+               assert fd == null;
+               fieldtype = ld.getType(); // d.s ==> Superblock, while,  d.b ==> Block
+               fd = ld.getField();
+               assert fd != null;
+               assert intindex == null;
+               intindex = ld.getIndex();
+           } else {
+                if (fd==null) {
+                    throw new Error("Null fd for: "+field);
+                }
+               fieldtype = fd.getType();
+               intindex=index;
+           }
+           this.fd=fd;
+           if (fieldtype instanceof MissingTypeDescriptor)
+               throw new Error(fieldtype.getSymbol()+" type undefined!");
+       }
+
         if ((lefttype == null) || (index != null && indextype == null)) {
             return null;
         }
@@ -252,7 +569,7 @@ public class DotExpr extends Expr {
             }
         }
 
-        if (lefttype instanceof StructureTypeDescriptor) {            
+        if (lefttype instanceof StructureTypeDescriptor) {
             StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype;
             FieldDescriptor fd = struct.getField(field);
             LabelDescriptor ld = struct.getLabel(field);
@@ -262,21 +579,21 @@ public class DotExpr extends Expr {
 
                 if (indextype == null && fd instanceof ArrayDescriptor) {
                     sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
-                    return null;                
+                    return null;
                 } else if (indextype != null && !(fd instanceof ArrayDescriptor)) {
                     sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
                     return null;
                 }
-                
+
                 this.td = fd.getType();
             } else if (ld != null) { /* label */
                 assert fd == null;
 
-                if (index != null) { 
+                if (index != null) {
                     sa.getErrorReporter().report(null, "A label cannot be accessed as an array");
                     return null;
                 }
-                
+
                 this.td = ld.getType();
             } else {
                 sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'");
@@ -295,9 +612,5 @@ public class DotExpr extends Expr {
             sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'");
             return null;
         }
-        
-        
     }
-
 }
-