6 public class DotExpr extends Expr {
12 static boolean DOMEMCHECKS=true;
13 static boolean DOTYPECHECKS=false;
14 static boolean DONULL=false;
16 public boolean isSafe() {
19 FieldDescriptor tmpfd=fd;
20 if (tmpfd instanceof ArrayDescriptor)
21 return false; // Arrays could be out of bounds
22 if (tmpfd.getPtr()) // Pointers cound be invalid
27 public void findmatch(Descriptor d, Set s) {
35 public Set freeVars() {
36 Set lset=left.freeVars();
39 iset=index.freeVars();
48 static int memoryindents = 0;
50 public static void generate_memory_endblocks(CodeWriter cr) {
51 while (memoryindents > 0) {
60 TypeDescriptor fieldtype;
63 public String name() {
64 String name=left.name()+"."+field;
66 name+="["+index.name()+"]";
70 public boolean usesDescriptor(Descriptor d) {
73 return left.usesDescriptor(d)||((intindex!=null)&&intindex.usesDescriptor(d));
76 public boolean equals(Map remap, Expr e) {
77 if (e==null||!(e instanceof DotExpr))
79 DotExpr de=(DotExpr)e;
80 if (!de.field.equals(field))
85 } else if (!index.equals(remap,de.index))
87 if (!left.equals(remap,de.left))
93 public DotExpr(Expr left, String field, Expr index) {
99 public Set getRequiredDescriptors() {
100 Set v = left.getRequiredDescriptors();
103 v.addAll(index.getRequiredDescriptors());
108 public Expr getExpr() {
112 public FieldDescriptor getField() {
116 public Expr getIndex() {
120 public void generate(CodeWriter writer, VarDescriptor dest) {
121 VarDescriptor leftd = VarDescriptor.makeNew("left");
123 writer.output("// " + leftd.getSafeSymbol() + " <-- ");
124 left.prettyPrint(writer);
125 writer.outputline("");
127 left.generate(writer, leftd);
129 writer.output("// " + leftd.getSafeSymbol() + " = ");
130 left.prettyPrint(writer);
131 writer.outputline("");
133 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
134 Expr intindex = index;
137 // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor object that is in the vector list
138 // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
139 // descriptor not the underlying field descriptor
141 /* we calculate the offset in bits */
143 offsetbits = struct.getOffsetExpr(fd);
145 FieldDescriptor fd=this.fd;
146 if (fd instanceof ArrayDescriptor)
147 fd=((ArrayDescriptor)fd).getField();
148 boolean doboundscheck=true;
149 boolean performedboundscheck=false;
151 writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol()+"=0;");
153 if (intindex != null) {
154 if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) {
155 /* short circuit for constant 0 */
157 Expr basesize = fd.getBaseSizeExpr();
159 VarDescriptor indexvd=VarDescriptor.makeNew("index");
160 indexvd.setType(ReservedTypeDescriptor.INT);
161 writer.getSymbolTable().add(indexvd);
163 writer.output("// " + indexvd.getSafeSymbol() + " <-- ");
165 intindex.prettyPrint(writer);
166 writer.outputline("");
167 intindex.generate(writer, indexvd);
168 writer.output("// " + indexvd.getSafeSymbol() + " = ");
169 intindex.prettyPrint(writer);
170 writer.outputline("");
171 Expr indexbound=((ArrayDescriptor)this.fd).getIndexBound();
172 VarDescriptor indexboundvd=VarDescriptor.makeNew("indexbound");
174 indexbound.generate(writer,indexboundvd);
176 writer.outputline("if ("+indexvd.getSafeSymbol()+">=0 &&"+indexvd.getSafeSymbol()+"<"+indexboundvd.getSafeSymbol()+")");
178 VarExpr indexve=new VarExpr(indexvd);
179 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, indexve));
181 performedboundscheck=true;
183 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
187 final SymbolTable st = writer.getSymbolTable();
188 TypeDescriptor td2 = offsetbits.typecheck(new SemanticAnalyzer() {
189 public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
190 public SymbolTable getSymbolTable() { return st; }
194 throw new IRException();
195 } else if (td2 != ReservedTypeDescriptor.INT) {
196 throw new IRException();
199 boolean dotypecheck = false;
201 VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
202 writer.output("// " + ob.getSafeSymbol() + " <-- ");
203 offsetbits.prettyPrint(writer);
204 writer.outputline("");
205 offsetbits.generate(writer, ob);
206 writer.output("// " + ob.getSafeSymbol() + " = ");
207 offsetbits.prettyPrint(writer);
208 writer.outputline("");
210 /* derive offset in bytes */
211 VarDescriptor offset = VarDescriptor.makeNew("offset");
212 writer.outputline("int " + offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
214 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
215 VarDescriptor shift = VarDescriptor.makeNew("shift");
216 writer.outputline("int " + shift.getSafeSymbol() + " = " + ob.getSafeSymbol() +
217 " - (" + offset.getSafeSymbol() + " << 3);");
218 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
220 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
221 writer.outputline("if ("+leftd.getSafeSymbol()+")");
222 writer.outputline(dest.getSafeSymbol() + " = ((*(int *)" +
223 "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " +
224 " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");
225 writer.outputline("else maybe=1;");
226 } else { /* a structure address or a ptr */
227 String ptr = fd.getPtr() ? "*(int *)" : "";
228 /* type var = [*(int *)] (base + offset) */
229 writer.outputline("if ("+leftd.getSafeSymbol()+")");
231 writer.outputline(dest.getSafeSymbol() +
232 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");
234 writer.outputline("if ("+dest.getSafeSymbol()+")");
236 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
237 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
238 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
240 } else if (DOTYPECHECKS) {
241 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
243 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
245 writer.outputline(dest.getSafeSymbol()+"=0;");
247 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")=0;");
252 writer.outputline("else maybe=1;");
254 if (performedboundscheck) {
256 writer.outputline(" else ");
258 writer.outputline(dest.getSafeSymbol()+"=0;");
259 writer.outputline("maybe=1;");
260 if (!Compiler.REPAIR)
261 writer.outputline("printf(\"Array Index Out of Bounds\");");
266 private int bitmask(int bits) {
269 for (int i = 0; i < bits; i++) {
277 public void prettyPrint(PrettyPrinter pp) {
278 left.prettyPrint(pp);
279 pp.output("." + field);
282 index.prettyPrint(pp);
287 public boolean isValue() {
288 FieldDescriptor tmpfd=fd;
289 if (tmpfd instanceof ArrayDescriptor)
290 tmpfd=((ArrayDescriptor)tmpfd).getField();
291 return (tmpfd.getPtr()||(tmpfd.getType() instanceof ReservedTypeDescriptor));
294 boolean typechecked=false;
295 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
298 else typechecked=true;
299 TypeDescriptor lefttype = left.typecheck(sa);
300 TypeDescriptor indextype = index == null ? null : index.typecheck(sa);
303 /* finished typechecking...so we can fill the fields in */
304 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
305 FieldDescriptor fd = struct.getField(field);
306 LabelDescriptor ld = struct.getLabel(field);
307 if (ld != null) { /* label */
309 fieldtype = ld.getType(); // d.s ==> Superblock, while, d.b ==> Block
312 assert intindex == null;
313 intindex = ld.getIndex();
315 fieldtype = fd.getType();
321 if ((lefttype == null) || (index != null && indextype == null)) {
325 if (indextype != null) {
326 if (indextype != ReservedTypeDescriptor.INT) {
327 sa.getErrorReporter().report(null, "Index must be of type 'int' not '" + indextype.getSymbol() + "'");
332 if (lefttype instanceof StructureTypeDescriptor) {
333 StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype;
334 FieldDescriptor fd = struct.getField(field);
335 LabelDescriptor ld = struct.getLabel(field);
337 if (fd != null) { /* field */
340 if (indextype == null && fd instanceof ArrayDescriptor) {
341 sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
343 } else if (indextype != null && !(fd instanceof ArrayDescriptor)) {
344 sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
348 this.td = fd.getType();
349 } else if (ld != null) { /* label */
353 sa.getErrorReporter().report(null, "A label cannot be accessed as an array");
357 this.td = ld.getType();
359 sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'");
363 /* we promote bit, byte and short to integer types */
364 if (this.td == ReservedTypeDescriptor.BIT ||
365 this.td == ReservedTypeDescriptor.BYTE ||
366 this.td == ReservedTypeDescriptor.SHORT) {
367 this.td = ReservedTypeDescriptor.INT;
372 sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'");