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 isSafe() {
26 FieldDescriptor tmpfd=fd;
27 if (tmpfd instanceof ArrayDescriptor)
28 return false; // Arrays could be out of bounds
29 if (tmpfd.getPtr()) // Pointers cound be invalid
34 public void findmatch(Descriptor d, Set s) {
39 intindex.findmatch(d,s);
42 public Set freeVars() {
43 Set lset=left.freeVars();
46 iset=intindex.freeVars();
55 static int memoryindents = 0;
57 public static void generate_memory_endblocks(CodeWriter cr) {
58 while (memoryindents > 0) {
67 TypeDescriptor fieldtype;
70 public String name() {
71 String name=left.name()+"."+field;
73 name+="["+index.name()+"]";
77 public Set useDescriptor(Descriptor d) {
78 HashSet newset=new HashSet();
81 newset.addAll(left.useDescriptor(d));
83 newset.addAll(intindex.useDescriptor(d));
87 public boolean usesDescriptor(Descriptor d) {
90 return left.usesDescriptor(d)||((intindex!=null)&&intindex.usesDescriptor(d));
93 public boolean equals(Map remap, Expr e) {
94 if (e==null||!(e instanceof DotExpr))
96 DotExpr de=(DotExpr)e;
97 if (!de.field.equals(field))
102 } else if (!index.equals(remap,de.index))
104 if (!left.equals(remap,de.left))
110 public Set getRequiredDescriptors() {
111 Set v = left.getRequiredDescriptors();
113 if (intindex != null) {
114 v.addAll(intindex.getRequiredDescriptors());
119 public Expr getExpr() {
123 public FieldDescriptor getField() {
127 public Expr getIndex() {
131 public void generate(CodeWriter writer, VarDescriptor dest) {
132 VarDescriptor leftd = VarDescriptor.makeNew("left");
134 writer.output("// " + leftd.getSafeSymbol() + " <-- ");
135 left.prettyPrint(writer);
136 writer.outputline("");
138 left.generate(writer, leftd);
140 writer.output("// " + leftd.getSafeSymbol() + " = ");
141 left.prettyPrint(writer);
142 writer.outputline("");
144 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
147 // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor object that is in the vector list
148 // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
149 // descriptor not the underlying field descriptor
151 /* we calculate the offset in bits */
153 offsetbits = struct.getOffsetExpr(fd);
155 FieldDescriptor fd=this.fd;
156 if (fd instanceof ArrayDescriptor)
157 fd=((ArrayDescriptor)fd).getField();
158 boolean doboundscheck=true;
159 boolean performedboundscheck=false;
161 writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol()+"=0;");
163 if (intindex != null) {
164 if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) {
165 /* short circuit for constant 0 */
167 Expr basesize = fd.getBaseSizeExpr();
169 VarDescriptor indexvd=VarDescriptor.makeNew("index");
170 indexvd.setType(ReservedTypeDescriptor.INT);
171 writer.getSymbolTable().add(indexvd);
173 writer.output("// " + indexvd.getSafeSymbol() + " <-- ");
175 intindex.prettyPrint(writer);
176 writer.outputline("");
177 intindex.generate(writer, indexvd);
178 writer.output("// " + indexvd.getSafeSymbol() + " = ");
179 intindex.prettyPrint(writer);
180 writer.outputline("");
181 Expr indexbound=((ArrayDescriptor)this.fd).getIndexBound();
182 VarDescriptor indexboundvd=VarDescriptor.makeNew("indexbound");
184 indexbound.generate(writer,indexboundvd);
186 writer.outputline("if ("+indexvd.getSafeSymbol()+">=0 &&"+indexvd.getSafeSymbol()+"<"+indexboundvd.getSafeSymbol()+")");
188 VarExpr indexve=new VarExpr(indexvd);
189 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, indexve));
191 performedboundscheck=true;
193 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
197 final SymbolTable st = writer.getSymbolTable();
198 TypeDescriptor td2 = offsetbits.typecheck(new SemanticAnalyzer() {
199 public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
200 public SymbolTable getSymbolTable() { return st; }
204 throw new IRException();
205 } else if (td2 != ReservedTypeDescriptor.INT) {
206 throw new IRException();
209 boolean dotypecheck = false;
211 VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
212 writer.output("// " + ob.getSafeSymbol() + " <-- ");
213 offsetbits.prettyPrint(writer);
214 writer.outputline("");
215 offsetbits.generate(writer, ob);
216 writer.output("// " + ob.getSafeSymbol() + " = ");
217 offsetbits.prettyPrint(writer);
218 writer.outputline("");
220 /* derive offset in bytes */
221 VarDescriptor offset = VarDescriptor.makeNew("offset");
222 writer.outputline("int " + offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
224 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
225 VarDescriptor shift = VarDescriptor.makeNew("shift");
226 writer.outputline("int " + shift.getSafeSymbol() + " = " + ob.getSafeSymbol() +
227 " - (" + offset.getSafeSymbol() + " << 3);");
228 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
230 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
231 writer.outputline("if ("+leftd.getSafeSymbol()+")");
232 writer.outputline(dest.getSafeSymbol() + " = ((*(int *)" +
233 "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " +
234 " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");
235 writer.outputline("else maybe=1;");
236 } else { /* a structure address or a ptr */
237 String ptr = fd.getPtr() ? "*(int *)" : "";
238 /* type var = [*(int *)] (base + offset) */
239 writer.outputline("if ("+leftd.getSafeSymbol()+")");
241 writer.outputline(dest.getSafeSymbol() +
242 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");
244 writer.outputline("if ("+dest.getSafeSymbol()+")");
246 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
247 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
248 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
250 } else if (DOTYPECHECKS) {
251 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
254 if (DOTYPECHECKS||DOMEMCHECKS) {
255 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
257 writer.outputline(dest.getSafeSymbol()+"=0;");
259 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")=0;");
266 writer.outputline("else maybe=1;");
268 if (performedboundscheck) {
270 writer.outputline(" else ");
272 writer.outputline(dest.getSafeSymbol()+"=0;");
273 writer.outputline("maybe=1;");
274 if (!Compiler.REPAIR)
275 writer.outputline("printf(\"Array Index Out of Bounds\");");
280 private int bitmask(int bits) {
283 for (int i = 0; i < bits; i++) {
291 public void prettyPrint(PrettyPrinter pp) {
292 left.prettyPrint(pp);
293 pp.output("." + field);
296 index.prettyPrint(pp);
301 public boolean isValue() {
302 FieldDescriptor tmpfd=fd;
303 if (tmpfd instanceof ArrayDescriptor)
304 tmpfd=((ArrayDescriptor)tmpfd).getField();
305 return (tmpfd.getPtr()||(tmpfd.getType() instanceof ReservedTypeDescriptor));
308 boolean typechecked=false;
309 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
312 else typechecked=true;
313 TypeDescriptor lefttype = left.typecheck(sa);
314 TypeDescriptor indextype = index == null ? null : index.typecheck(sa);
317 /* finished typechecking...so we can fill the fields in */
318 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
319 FieldDescriptor fd = struct.getField(field);
320 LabelDescriptor ld = struct.getLabel(field);
321 if (ld != null) { /* label */
323 fieldtype = ld.getType(); // d.s ==> Superblock, while, d.b ==> Block
326 assert intindex == null;
327 intindex = ld.getIndex();
329 fieldtype = fd.getType();
335 if ((lefttype == null) || (index != null && indextype == null)) {
339 if (indextype != null) {
340 if (indextype != ReservedTypeDescriptor.INT) {
341 sa.getErrorReporter().report(null, "Index must be of type 'int' not '" + indextype.getSymbol() + "'");
346 if (lefttype instanceof StructureTypeDescriptor) {
347 StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype;
348 FieldDescriptor fd = struct.getField(field);
349 LabelDescriptor ld = struct.getLabel(field);
351 if (fd != null) { /* field */
354 if (indextype == null && fd instanceof ArrayDescriptor) {
355 sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
357 } else if (indextype != null && !(fd instanceof ArrayDescriptor)) {
358 sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
362 this.td = fd.getType();
363 } else if (ld != null) { /* label */
367 sa.getErrorReporter().report(null, "A label cannot be accessed as an array");
371 this.td = ld.getType();
373 sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'");
377 /* we promote bit, byte and short to integer types */
378 if (this.td == ReservedTypeDescriptor.BIT ||
379 this.td == ReservedTypeDescriptor.BYTE ||
380 this.td == ReservedTypeDescriptor.SHORT) {
381 this.td = ReservedTypeDescriptor.INT;
386 sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'");