6 public class DotExpr extends Expr {
12 static boolean DOMEMCHECKS=false;
13 static boolean DOTYPECHECKS=false;
14 static boolean DONULL=false;
17 public DotExpr(Expr left, String field, Expr index) {
23 public boolean isInvariant(Set vars) {
24 if (!left.isInvariant(vars))
27 return intindex.isInvariant(vars);
32 public Set findInvariants(Set vars) {
33 if (isInvariant(vars)) {
38 Set ls=left.findInvariants(vars);
40 ls.addAll(intindex.findInvariants(vars));
41 Expr indexbound=((ArrayDescriptor)this.fd).getIndexBound();
42 ls.addAll(indexbound.findInvariants(vars));
43 if ((!(intindex instanceof IntegerLiteralExpr))||
44 ((IntegerLiteralExpr) intindex).getValue() != 0) {
45 FieldDescriptor fd=this.fd;
46 if (fd instanceof ArrayDescriptor)
47 fd=((ArrayDescriptor)fd).getField();
48 Expr basesize = fd.getBaseSizeExpr();
49 ls.addAll(basesize.findInvariants(vars));
57 public boolean isSafe() {
61 FieldDescriptor tmpfd=fd;
63 if (tmpfd.getPtr()) // Pointers cound be invalid
66 if (tmpfd instanceof ArrayDescriptor) {
67 Expr arrayindex=((ArrayDescriptor)tmpfd).getIndexBound();
68 if (index instanceof IntegerLiteralExpr&&arrayindex instanceof IntegerLiteralExpr) {
69 int indexvalue=((IntegerLiteralExpr)index).getValue();
70 int arrayindexvalue=((IntegerLiteralExpr)arrayindex).getValue();
71 if (indexvalue>=0&&indexvalue<arrayindexvalue)
74 return false; // Otherwise, arrays could be out of bounds
79 public Set freeVars() {
80 Set lset=left.freeVars();
83 iset=intindex.freeVars();
92 static int memoryindents = 0;
94 public static void generate_memory_endblocks(CodeWriter cr) {
95 while (memoryindents > 0) {
104 TypeDescriptor fieldtype;
107 public String name() {
108 String name=left.name()+"."+field;
110 name+="["+index.name()+"]";
114 public void findmatch(Descriptor d, Set s) {
119 intindex.findmatch(d,s);
122 public Set useDescriptor(Descriptor d) {
123 HashSet newset=new HashSet();
126 newset.addAll(left.useDescriptor(d));
128 newset.addAll(intindex.useDescriptor(d));
132 public boolean usesDescriptor(Descriptor d) {
135 return left.usesDescriptor(d)||((intindex!=null)&&intindex.usesDescriptor(d));
138 public boolean equals(Map remap, Expr e) {
139 if (e==null||!(e instanceof DotExpr))
141 DotExpr de=(DotExpr)e;
142 if (!de.field.equals(field))
147 } else if (!index.equals(remap,de.index))
149 if (!left.equals(remap,de.left))
155 public Set getRequiredDescriptors() {
156 Set v = left.getRequiredDescriptors();
158 if (intindex != null) {
159 v.addAll(intindex.getRequiredDescriptors());
165 public Expr getExpr() {
169 public FieldDescriptor getField() {
173 public Expr getIndex() {
177 private boolean exactalloc(TypeDescriptor td) {
178 if (!(td instanceof StructureTypeDescriptor))
180 StructureTypeDescriptor std=(StructureTypeDescriptor)td;
181 if (std.size()!=1) /* Just looking for arrays */
183 FieldDescriptor tmpfd=std.get(0);
184 if (!(tmpfd instanceof ArrayDescriptor))
186 ArrayDescriptor afd=(ArrayDescriptor)tmpfd;
187 TypeDescriptor elementdescriptor=afd.getType();
188 Expr sizeexpr=elementdescriptor.getSizeExpr();
189 if (!OpExpr.isInt(sizeexpr))
191 Expr indexbound=afd.getIndexBound();
192 if (indexbound instanceof DotExpr)
194 if ((indexbound instanceof OpExpr)&&
195 (((OpExpr)indexbound).getOpcode()==Opcode.MULT)&&
196 (((OpExpr)indexbound).getLeftExpr() instanceof DotExpr)&&
197 (((OpExpr)indexbound).getRightExpr() instanceof DotExpr))
202 public void generate(CodeWriter writer, VarDescriptor dest) {
203 VarDescriptor leftd = VarDescriptor.makeNew("left");
205 if (writer.getInvariantValue()!=null&&
206 writer.getInvariantValue().isInvariant(this)) {
207 writer.addDeclaration(getType().getGenerateType().getSafeSymbol().toString(), dest.getSafeSymbol());
208 writer.outputline(dest.getSafeSymbol()+"="+writer.getInvariantValue().getValue(this).getSafeSymbol()+";");
209 writer.outputline("maybe="+writer.getInvariantValue().getMaybe(this).getSafeSymbol()+";");
213 writer.output("/* " + leftd.getSafeSymbol() + " <-- ");
214 left.prettyPrint(writer);
215 writer.outputline("*/");
217 left.generate(writer, leftd);
219 writer.output("/* " + leftd.getSafeSymbol() + " = ");
220 left.prettyPrint(writer);
221 writer.outputline("*/");
223 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
226 // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor object that is in the vector list
227 // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
228 // descriptor not the underlying field descriptor
230 /* we calculate the offset in bits */
232 offsetbits = struct.getOffsetExpr(fd);
234 FieldDescriptor fd=this.fd;
235 if (fd instanceof ArrayDescriptor)
236 fd=((ArrayDescriptor)fd).getField();
237 boolean doboundscheck=true;
238 boolean performedboundscheck=false;
240 writer.addDeclaration(getType().getGenerateType().toString(),dest.getSafeSymbol());
241 writer.outputline(dest.getSafeSymbol()+"=0;");
243 if (intindex != null) {
244 if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) {
245 /* short circuit for constant 0 */
247 Expr basesize = fd.getBaseSizeExpr();
249 VarDescriptor indexvd=VarDescriptor.makeNew("index");
250 indexvd.setType(ReservedTypeDescriptor.INT);
251 writer.getSymbolTable().add(indexvd);
253 writer.output("/* " + indexvd.getSafeSymbol() + " <-- ");
255 intindex.prettyPrint(writer);
256 writer.outputline("*/");
257 intindex.generate(writer, indexvd);
258 writer.output("/* " + indexvd.getSafeSymbol() + " = ");
259 intindex.prettyPrint(writer);
260 writer.outputline("*/");
261 Expr indexbound=((ArrayDescriptor)this.fd).getIndexBound();
262 VarDescriptor indexboundvd=VarDescriptor.makeNew("indexbound");
264 indexbound.generate(writer,indexboundvd);
266 writer.outputline("if ("+indexvd.getSafeSymbol()+">=0 &&"+indexvd.getSafeSymbol()+"<"+indexboundvd.getSafeSymbol()+")");
268 VarExpr indexve=new VarExpr(indexvd);
269 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, indexve));
271 performedboundscheck=true;
273 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
277 final SymbolTable st = writer.getSymbolTable();
278 TypeDescriptor td2 = offsetbits.typecheck(new SemanticAnalyzer() {
279 public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
280 public SymbolTable getSymbolTable() { return st; }
284 throw new IRException();
285 } else if (td2 != ReservedTypeDescriptor.INT) {
286 throw new IRException();
289 boolean dotypecheck = false;
291 VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
292 writer.output("/* " + ob.getSafeSymbol() + " <-- ");
293 offsetbits.prettyPrint(writer);
294 writer.outputline("*/");
295 offsetbits.generate(writer, ob);
296 writer.output("/* " + ob.getSafeSymbol() + " = ");
297 offsetbits.prettyPrint(writer);
298 writer.outputline("*/");
300 /* derive offset in bytes */
301 VarDescriptor offset = VarDescriptor.makeNew("offset");
302 writer.addDeclaration("int", offset.getSafeSymbol());
303 writer.outputline(offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
305 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
306 VarDescriptor shift = VarDescriptor.makeNew("shift");
307 writer.addDeclaration("int", shift.getSafeSymbol());
308 writer.outputline(shift.getSafeSymbol() + " = " + ob.getSafeSymbol() +
309 " - (" + offset.getSafeSymbol() + " << 3);");
310 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
312 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
313 writer.outputline("if ("+leftd.getSafeSymbol()+")");
314 writer.outputline(dest.getSafeSymbol() + " = ((*(int *)" +
315 "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " +
316 " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");
317 writer.outputline("else maybe=1;");
318 } else { /* a structure address or a ptr */
319 String ptr = fd.getPtr() ? "*(int *)" : "";
320 /* type var = [*(int *)] (base + offset) */
321 writer.outputline("if ("+leftd.getSafeSymbol()+")");
323 writer.outputline(dest.getSafeSymbol() +
324 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");
326 writer.outputline("if ("+dest.getSafeSymbol()+")");
330 if (DOTYPECHECKS||DOMEMCHECKS) {
331 /* NEED TO CHECK IF THERE ARE VARIABLES TO PLAY WITH IN THE STRUCT!!!! */
332 if (Compiler.EXACTALLOCATION&&exactalloc(td)) {
333 writer.outputline("if (!assertexactmemory("+dest.getSafeSymbol()+", "+this.td.getId()+"))");
336 /* Okay, we've failed to fit it in here */
338 VarDescriptor highptr=VarDescriptor.makeNew("highptr");
339 writer.addDeclaration("int", highptr.getSafeSymbol());
340 writer.outputline(highptr.getSafeSymbol()+"=getendofblock("+dest.getSafeSymbol()+");");
341 VarDescriptor size=VarDescriptor.makeNew("size");
342 writer.addDeclaration("int", size.getSafeSymbol());
343 writer.outputline(size.getSafeSymbol()+"="+highptr.getSafeSymbol()+"-"+dest.getSafeSymbol()+";");
345 StructureTypeDescriptor std=(StructureTypeDescriptor)this.td;
346 ArrayDescriptor afd=(ArrayDescriptor)std.get(0);
347 TypeDescriptor elementdescriptor=afd.getType();
348 Expr sizeexpr=elementdescriptor.getSizeExpr();
349 int elementsize=OpExpr.getInt(sizeexpr);
350 //convert size to bytes
351 if (elementsize%8==0)
352 elementsize=elementsize/8;
354 elementsize=(elementsize/8)+1;
355 /* Basic sanity check */
356 writer.outputline("if ("+size.getSafeSymbol()+"%"+
360 VarDescriptor numElements=VarDescriptor.makeNew("numberofelements");
361 writer.addDeclaration("int", numElements.getSafeSymbol());
362 writer.outputline(numElements.getSafeSymbol()+"="+size.getSafeSymbol()+"/"+elementsize+";");
363 Expr indexbound=afd.getIndexBound();
364 if (indexbound instanceof DotExpr) {
365 /* NEED TO IMPLEMENT */
367 VarExpr ve=new VarExpr(numElements);
368 numElements.setType(ReservedTypeDescriptor.INT);
369 ve.td=ReservedTypeDescriptor.INT;
370 Updates u=new Updates(indexbound,ve);
371 UpdateNode un=new UpdateNode(null);
373 un.generate(writer,false,false,null,null,null,null);
374 writer.outputline("free"+RepairGenerator.name+"("+RepairGenerator.newmodel.getSafeSymbol()+");");
375 writer.outputline("computesizes(thisvar);");
376 writer.outputline(RepairGenerator.name+"_staterecomputesizes(thisvar);");
377 writer.outputline("goto rebuild;");
379 // writer.outputline("break;");
381 } else if ((indexbound instanceof OpExpr)&&
382 (((OpExpr)indexbound).getOpcode()==Opcode.MULT)&&
383 (((OpExpr)indexbound).getLeftExpr() instanceof DotExpr)&&
384 (((OpExpr)indexbound).getRightExpr() instanceof DotExpr)) {
386 DotExpr leftexpr=(DotExpr)(((OpExpr)indexbound).getLeftExpr());
387 VarDescriptor leftside=VarDescriptor.makeNew("leftvalue");
388 writer.addDeclaration("int", leftside.getSafeSymbol());
389 leftexpr.generate(writer,leftside);
390 DotExpr rightexpr=(DotExpr)(((OpExpr)indexbound).getRightExpr());
391 VarDescriptor rightside=VarDescriptor.makeNew("rightvalue");
392 writer.addDeclaration("int", rightside.getSafeSymbol());
393 rightexpr.generate(writer,rightside);
394 writer.outputline("if (("+leftside.getSafeSymbol()+"!=0) &&("+numElements.getSafeSymbol()+"%"+leftside.getSafeSymbol()+"==0))");
397 VarDescriptor newvalue=VarDescriptor.makeNew("newvalue");
398 writer.addDeclaration("int", newvalue.getSafeSymbol());
399 writer.outputline(newvalue.getSafeSymbol()+"="+numElements.getSafeSymbol()+"/"+leftside.getSafeSymbol()+";");
400 VarExpr ve=new VarExpr(newvalue);
401 newvalue.setType(ReservedTypeDescriptor.INT);
402 ve.td=ReservedTypeDescriptor.INT;
403 Updates u=new Updates(rightexpr,ve);
404 UpdateNode un=new UpdateNode(null);
406 un.generate(writer,false,false,null,null,null,null);
407 writer.outputline("free"+RepairGenerator.name+"("+RepairGenerator.newmodel.getSafeSymbol()+");");
408 writer.outputline("computesizes(thisvar);");
409 writer.outputline(RepairGenerator.name+"_staterecomputesizes(thisvar);");
410 writer.outputline("goto rebuild;");
411 // writer.outputline("break;");
414 writer.outputline("else if (("+rightside.getSafeSymbol()+"!=0)&&("+numElements.getSafeSymbol()+"%"+rightside.getSafeSymbol()+"==0))");
417 VarDescriptor newvalue=VarDescriptor.makeNew("newvalue");
418 writer.addDeclaration("int", newvalue.getSafeSymbol());
419 writer.outputline(newvalue.getSafeSymbol()+"="+numElements.getSafeSymbol()+"/"+rightside.getSafeSymbol()+";");
420 VarExpr ve=new VarExpr(newvalue);
421 newvalue.setType(ReservedTypeDescriptor.INT);
422 ve.td=ReservedTypeDescriptor.INT;
423 Updates u=new Updates(leftexpr,ve);
424 UpdateNode un=new UpdateNode(null);
426 un.generate(writer,false,false,null,null,null,null);
427 writer.outputline("free"+RepairGenerator.name+"("+RepairGenerator.newmodel.getSafeSymbol()+");");
428 writer.outputline("computesizes(thisvar);");
429 writer.outputline(RepairGenerator.name+"_staterecomputesizes(thisvar);");
430 writer.outputline("goto rebuild;");
431 // writer.outputline("break;");
436 } else throw new Error("Should be here");
445 if (indexbound instanceof DotExpr)
447 if ((indexbound instanceof OpExpr)&&
448 (((OpExpr)indexbound).getOpcode()==Opcode.MULT)&&
449 (((OpExpr)indexbound).getLeftExpr() instanceof DotExpr)&&
450 (((OpExpr)indexbound).getRightExpr() instanceof DotExpr))
456 /* Give up and null out bad pointer */
458 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
459 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
460 writer.addDeclaration("bool", typevar.getSafeSymbol());
461 writer.outputline(typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
463 } else if (DOTYPECHECKS) {
464 writer.addDeclaration("bool", typevar.getSafeSymbol());
465 writer.outputline(typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
467 if (DOMEMCHECKS||DOTYPECHECKS) {
468 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
470 writer.outputline(dest.getSafeSymbol()+"=0;");
472 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")=0;");
480 writer.outputline("else maybe=1;");
482 if (performedboundscheck) {
484 writer.outputline(" else ");
486 writer.outputline(dest.getSafeSymbol()+"=0;");
487 writer.outputline("maybe=1;");
488 if (!Compiler.REPAIR)
489 writer.outputline("printf(\"Array Index Out of Bounds\");");
494 private int bitmask(int bits) {
497 for (int i = 0; i < bits; i++) {
505 public void prettyPrint(PrettyPrinter pp) {
506 left.prettyPrint(pp);
507 pp.output("." + field);
510 index.prettyPrint(pp);
515 public boolean isValue(TypeDescriptor td) {
516 FieldDescriptor tmpfd=fd;
517 if (tmpfd instanceof ArrayDescriptor)
518 tmpfd=((ArrayDescriptor)tmpfd).getField();
519 return (tmpfd.getPtr()||(tmpfd.getType() instanceof ReservedTypeDescriptor));
522 public boolean isPtr() {
523 FieldDescriptor tmpfd=fd;
524 if (tmpfd instanceof ArrayDescriptor)
525 tmpfd=((ArrayDescriptor)tmpfd).getField();
526 return tmpfd.getPtr();
529 boolean typechecked=false;
530 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
533 else typechecked=true;
534 TypeDescriptor lefttype = left.typecheck(sa);
535 TypeDescriptor indextype = index == null ? null : index.typecheck(sa);
538 /* finished typechecking...so we can fill the fields in */
539 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
540 FieldDescriptor fd = struct.getField(field);
541 LabelDescriptor ld = struct.getLabel(field);
542 if (ld != null) { /* label */
544 fieldtype = ld.getType(); // d.s ==> Superblock, while, d.b ==> Block
547 assert intindex == null;
548 intindex = ld.getIndex();
551 throw new Error("Null fd for: "+field);
553 fieldtype = fd.getType();
557 if (fieldtype instanceof MissingTypeDescriptor)
558 throw new Error(fieldtype.getSymbol()+" type undefined!");
561 if ((lefttype == null) || (index != null && indextype == null)) {
565 if (indextype != null) {
566 if (indextype != ReservedTypeDescriptor.INT) {
567 sa.getErrorReporter().report(null, "Index must be of type 'int' not '" + indextype.getSymbol() + "'");
572 if (lefttype instanceof StructureTypeDescriptor) {
573 StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype;
574 FieldDescriptor fd = struct.getField(field);
575 LabelDescriptor ld = struct.getLabel(field);
577 if (fd != null) { /* field */
580 if (indextype == null && fd instanceof ArrayDescriptor) {
581 sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
583 } else if (indextype != null && !(fd instanceof ArrayDescriptor)) {
584 sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
588 this.td = fd.getType();
589 } else if (ld != null) { /* label */
593 sa.getErrorReporter().report(null, "A label cannot be accessed as an array");
597 this.td = ld.getType();
599 sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'");
603 /* we promote bit, byte and short to integer types */
604 if (this.td == ReservedTypeDescriptor.BIT ||
605 this.td == ReservedTypeDescriptor.BYTE ||
606 this.td == ReservedTypeDescriptor.SHORT) {
607 this.td = ReservedTypeDescriptor.INT;
612 sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'");