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 public void generate(CodeWriter writer, VarDescriptor dest) {
178 VarDescriptor leftd = VarDescriptor.makeNew("left");
180 if (writer.getInvariantValue()!=null&&
181 writer.getInvariantValue().isInvariant(this)) {
182 writer.addDeclaration(getType().getGenerateType().getSafeSymbol().toString(), dest.getSafeSymbol());
183 writer.outputline(dest.getSafeSymbol()+"="+writer.getInvariantValue().getValue(this).getSafeSymbol()+";");
184 writer.outputline("maybe="+writer.getInvariantValue().getMaybe(this).getSafeSymbol()+";");
188 writer.output("/* " + leftd.getSafeSymbol() + " <-- ");
189 left.prettyPrint(writer);
190 writer.outputline("*/");
192 left.generate(writer, leftd);
194 writer.output("/* " + leftd.getSafeSymbol() + " = ");
195 left.prettyPrint(writer);
196 writer.outputline("*/");
198 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
201 // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor object that is in the vector list
202 // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
203 // descriptor not the underlying field descriptor
205 /* we calculate the offset in bits */
207 offsetbits = struct.getOffsetExpr(fd);
209 FieldDescriptor fd=this.fd;
210 if (fd instanceof ArrayDescriptor)
211 fd=((ArrayDescriptor)fd).getField();
212 boolean doboundscheck=true;
213 boolean performedboundscheck=false;
215 writer.addDeclaration(getType().getGenerateType().toString(),dest.getSafeSymbol());
216 writer.outputline(dest.getSafeSymbol()+"=0;");
218 if (intindex != null) {
219 if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) {
220 /* short circuit for constant 0 */
222 Expr basesize = fd.getBaseSizeExpr();
224 VarDescriptor indexvd=VarDescriptor.makeNew("index");
225 indexvd.setType(ReservedTypeDescriptor.INT);
226 writer.getSymbolTable().add(indexvd);
228 writer.output("/* " + indexvd.getSafeSymbol() + " <-- ");
230 intindex.prettyPrint(writer);
231 writer.outputline("*/");
232 intindex.generate(writer, indexvd);
233 writer.output("/* " + indexvd.getSafeSymbol() + " = ");
234 intindex.prettyPrint(writer);
235 writer.outputline("*/");
236 Expr indexbound=((ArrayDescriptor)this.fd).getIndexBound();
237 VarDescriptor indexboundvd=VarDescriptor.makeNew("indexbound");
239 indexbound.generate(writer,indexboundvd);
241 writer.outputline("if ("+indexvd.getSafeSymbol()+">=0 &&"+indexvd.getSafeSymbol()+"<"+indexboundvd.getSafeSymbol()+")");
243 VarExpr indexve=new VarExpr(indexvd);
244 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, indexve));
246 performedboundscheck=true;
248 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
252 final SymbolTable st = writer.getSymbolTable();
253 TypeDescriptor td2 = offsetbits.typecheck(new SemanticAnalyzer() {
254 public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
255 public SymbolTable getSymbolTable() { return st; }
259 throw new IRException();
260 } else if (td2 != ReservedTypeDescriptor.INT) {
261 throw new IRException();
264 boolean dotypecheck = false;
266 VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
267 writer.output("/* " + ob.getSafeSymbol() + " <-- ");
268 offsetbits.prettyPrint(writer);
269 writer.outputline("*/");
270 offsetbits.generate(writer, ob);
271 writer.output("/* " + ob.getSafeSymbol() + " = ");
272 offsetbits.prettyPrint(writer);
273 writer.outputline("*/");
275 /* derive offset in bytes */
276 VarDescriptor offset = VarDescriptor.makeNew("offset");
277 writer.addDeclaration("int", offset.getSafeSymbol());
278 writer.outputline(offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
280 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
281 VarDescriptor shift = VarDescriptor.makeNew("shift");
282 writer.addDeclaration("int", shift.getSafeSymbol());
283 writer.outputline(shift.getSafeSymbol() + " = " + ob.getSafeSymbol() +
284 " - (" + offset.getSafeSymbol() + " << 3);");
285 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
287 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
288 writer.outputline("if ("+leftd.getSafeSymbol()+")");
289 writer.outputline(dest.getSafeSymbol() + " = ((*(int *)" +
290 "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " +
291 " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");
292 writer.outputline("else maybe=1;");
293 } else { /* a structure address or a ptr */
294 String ptr = fd.getPtr() ? "*(int *)" : "";
295 /* type var = [*(int *)] (base + offset) */
296 writer.outputline("if ("+leftd.getSafeSymbol()+")");
298 writer.outputline(dest.getSafeSymbol() +
299 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");
301 writer.outputline("if ("+dest.getSafeSymbol()+")");
303 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
304 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
305 writer.addDeclaration("bool", typevar.getSafeSymbol());
306 writer.outputline(typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
308 } else if (DOTYPECHECKS) {
309 writer.addDeclaration("bool", typevar.getSafeSymbol());
310 writer.outputline(typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
313 if (DOTYPECHECKS||DOMEMCHECKS) {
314 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
316 writer.outputline(dest.getSafeSymbol()+"=0;");
318 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")=0;");
325 writer.outputline("else maybe=1;");
327 if (performedboundscheck) {
329 writer.outputline(" else ");
331 writer.outputline(dest.getSafeSymbol()+"=0;");
332 writer.outputline("maybe=1;");
333 if (!Compiler.REPAIR)
334 writer.outputline("printf(\"Array Index Out of Bounds\");");
339 private int bitmask(int bits) {
342 for (int i = 0; i < bits; i++) {
350 public void prettyPrint(PrettyPrinter pp) {
351 left.prettyPrint(pp);
352 pp.output("." + field);
355 index.prettyPrint(pp);
360 public boolean isValue(TypeDescriptor td) {
361 FieldDescriptor tmpfd=fd;
362 if (tmpfd instanceof ArrayDescriptor)
363 tmpfd=((ArrayDescriptor)tmpfd).getField();
364 return (tmpfd.getPtr()||(tmpfd.getType() instanceof ReservedTypeDescriptor));
367 public boolean isPtr() {
368 FieldDescriptor tmpfd=fd;
369 if (tmpfd instanceof ArrayDescriptor)
370 tmpfd=((ArrayDescriptor)tmpfd).getField();
371 return tmpfd.getPtr();
374 boolean typechecked=false;
375 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
378 else typechecked=true;
379 TypeDescriptor lefttype = left.typecheck(sa);
380 TypeDescriptor indextype = index == null ? null : index.typecheck(sa);
383 /* finished typechecking...so we can fill the fields in */
384 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
385 FieldDescriptor fd = struct.getField(field);
386 LabelDescriptor ld = struct.getLabel(field);
387 if (ld != null) { /* label */
389 fieldtype = ld.getType(); // d.s ==> Superblock, while, d.b ==> Block
392 assert intindex == null;
393 intindex = ld.getIndex();
396 throw new Error("Null fd for: "+field);
398 fieldtype = fd.getType();
402 if (fieldtype instanceof MissingTypeDescriptor)
403 throw new Error(fieldtype.getSymbol()+" type undefined!");
406 if ((lefttype == null) || (index != null && indextype == null)) {
410 if (indextype != null) {
411 if (indextype != ReservedTypeDescriptor.INT) {
412 sa.getErrorReporter().report(null, "Index must be of type 'int' not '" + indextype.getSymbol() + "'");
417 if (lefttype instanceof StructureTypeDescriptor) {
418 StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype;
419 FieldDescriptor fd = struct.getField(field);
420 LabelDescriptor ld = struct.getLabel(field);
422 if (fd != null) { /* field */
425 if (indextype == null && fd instanceof ArrayDescriptor) {
426 sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
428 } else if (indextype != null && !(fd instanceof ArrayDescriptor)) {
429 sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
433 this.td = fd.getType();
434 } else if (ld != null) { /* label */
438 sa.getErrorReporter().report(null, "A label cannot be accessed as an array");
442 this.td = ld.getType();
444 sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'");
448 /* we promote bit, byte and short to integer types */
449 if (this.td == ReservedTypeDescriptor.BIT ||
450 this.td == ReservedTypeDescriptor.BYTE ||
451 this.td == ReservedTypeDescriptor.SHORT) {
452 this.td = ReservedTypeDescriptor.INT;
457 sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'");