5 public class DotExpr extends Expr {
11 static boolean DOMEMCHECKS=true;
12 static boolean DOTYPECHECKS=false;
13 static boolean DONULL=false;
15 public boolean isSafe() {
18 FieldDescriptor tmpfd=fd;
19 if (tmpfd instanceof ArrayDescriptor)
20 return false; // Arrays could be out of bounds
21 if (tmpfd.getPtr()) // Pointers cound be invalid
26 public void findmatch(Descriptor d, Set s) {
34 public Set freeVars() {
35 Set lset=left.freeVars();
38 iset=index.freeVars();
47 static int memoryindents = 0;
49 public static void generate_memory_endblocks(CodeWriter cr) {
50 while (memoryindents > 0) {
59 TypeDescriptor fieldtype;
62 public String name() {
63 String name=left.name()+"."+field;
65 name+="["+index.name()+"]";
69 public boolean usesDescriptor(Descriptor d) {
72 return left.usesDescriptor(d)||((intindex!=null)&&intindex.usesDescriptor(d));
75 public boolean equals(Map remap, Expr e) {
76 if (e==null||!(e instanceof DotExpr))
78 DotExpr de=(DotExpr)e;
79 if (!de.field.equals(field))
84 } else if (!index.equals(remap,de.index))
86 if (!left.equals(remap,de.left))
92 public DotExpr(Expr left, String field, Expr index) {
98 public Set getRequiredDescriptors() {
99 Set v = left.getRequiredDescriptors();
102 v.addAll(index.getRequiredDescriptors());
107 public Expr getExpr() {
111 public FieldDescriptor getField() {
115 public Expr getIndex() {
119 public void generate(CodeWriter writer, VarDescriptor dest) {
120 VarDescriptor leftd = VarDescriptor.makeNew("left");
122 writer.output("// " + leftd.getSafeSymbol() + " <-- ");
123 left.prettyPrint(writer);
124 writer.outputline("");
126 left.generate(writer, leftd);
128 writer.output("// " + leftd.getSafeSymbol() + " = ");
129 left.prettyPrint(writer);
130 writer.outputline("");
132 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
133 Expr intindex = index;
136 // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor object that is in the vector list
137 // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
138 // descriptor not the underlying field descriptor
140 /* we calculate the offset in bits */
142 offsetbits = struct.getOffsetExpr(fd);
144 FieldDescriptor fd=this.fd;
145 if (fd instanceof ArrayDescriptor)
146 fd=((ArrayDescriptor)fd).getField();
148 if (intindex != null) {
149 if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) {
150 /* short circuit for constant 0 */
152 Expr basesize = fd.getBaseSizeExpr();
153 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
157 final SymbolTable st = writer.getSymbolTable();
158 TypeDescriptor td2 = offsetbits.typecheck(new SemanticAnalyzer() {
159 public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
160 public SymbolTable getSymbolTable() { return st; }
164 throw new IRException();
165 } else if (td2 != ReservedTypeDescriptor.INT) {
166 throw new IRException();
169 boolean dotypecheck = false;
171 if (offsetbits instanceof IntegerLiteralExpr) {
172 int offsetinbits = ((IntegerLiteralExpr) offsetbits).getValue();
173 int offset = offsetinbits >> 3; /* offset in bytes */
175 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
176 int shift = offsetinbits - (offset << 3);
177 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
179 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
180 writer.outputline(getType().getGenerateType() + " "+dest.getSafeSymbol()+"=0;");
181 writer.outputline("if ("+leftd.getSafeSymbol()+")");
182 writer.outputline(dest.getSafeSymbol() + " = ((*(int *)" +
183 "(" + leftd.getSafeSymbol() + " + " + offset + ")) " +
184 " >> " + shift + ") & 0x" + Integer.toHexString(mask) + ";");
185 writer.outputline("else maybe=1;");
186 } else { /* a structure address or a ptr! */
187 String ptr = fd.getPtr() ? "*(int *)" : "";
188 /* type var = [*(int *)] (base + offset) */
189 writer.outputline("int " + dest.getSafeSymbol()+"=0;");
190 writer.outputline("if ("+leftd.getSafeSymbol()+")");
192 writer.outputline(dest.getSafeSymbol() +
193 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset + ");");
195 writer.outputline("if ("+dest.getSafeSymbol()+")");
197 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
198 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
199 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
201 } else if (DOTYPECHECKS) {
202 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
204 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
206 writer.outputline(dest.getSafeSymbol()+"=0;");
208 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset + ")=0;");
213 writer.outputline("else maybe=1;");
215 } else { /* offset in bits is an expression that must be generated */
216 VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
217 writer.output("// " + ob.getSafeSymbol() + " <-- ");
218 offsetbits.prettyPrint(writer);
219 writer.outputline("");
220 offsetbits.generate(writer, ob);
221 writer.output("// " + ob.getSafeSymbol() + " = ");
222 offsetbits.prettyPrint(writer);
223 writer.outputline("");
225 /* derive offset in bytes */
226 VarDescriptor offset = VarDescriptor.makeNew("offset");
227 writer.outputline("int " + offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
229 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
230 VarDescriptor shift = VarDescriptor.makeNew("shift");
231 writer.outputline("int " + shift.getSafeSymbol() + " = " + ob.getSafeSymbol() +
232 " - (" + offset.getSafeSymbol() + " << 3);");
233 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
235 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
236 writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol()+"=0;");
237 writer.outputline("if ("+leftd.getSafeSymbol()+")");
238 writer.outputline(dest.getSafeSymbol() +
240 "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " +
241 " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");
242 writer.outputline("else maybe=1;");
243 } else { /* a structure address or a ptr */
244 String ptr = fd.getPtr() ? "*(int *)" : "";
245 /* type var = [*(int *)] (base + offset) */
246 writer.outputline("int " + dest.getSafeSymbol() +"=0;");
247 writer.outputline("if ("+leftd.getSafeSymbol()+")");
249 writer.outputline(dest.getSafeSymbol() +
250 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");
252 writer.outputline("if ("+dest.getSafeSymbol()+")");
254 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
255 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
256 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
258 } else if (DOTYPECHECKS) {
259 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
261 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
263 writer.outputline(dest.getSafeSymbol()+"=0;");
265 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")=0;");
270 writer.outputline("else maybe=1;");
275 private int bitmask(int bits) {
278 for (int i = 0; i < bits; i++) {
286 public void prettyPrint(PrettyPrinter pp) {
287 left.prettyPrint(pp);
288 pp.output("." + field);
291 index.prettyPrint(pp);
296 public boolean isValue() {
297 FieldDescriptor tmpfd=fd;
298 if (tmpfd instanceof ArrayDescriptor)
299 tmpfd=((ArrayDescriptor)tmpfd).getField();
300 return (tmpfd.getPtr()||(tmpfd.getType() instanceof ReservedTypeDescriptor));
303 boolean typechecked=false;
304 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
307 else typechecked=true;
308 TypeDescriptor lefttype = left.typecheck(sa);
309 TypeDescriptor indextype = index == null ? null : index.typecheck(sa);
312 /* finished typechecking...so we can fill the fields in */
313 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
314 FieldDescriptor fd = struct.getField(field);
315 LabelDescriptor ld = struct.getLabel(field);
316 if (ld != null) { /* label */
318 fieldtype = ld.getType(); // d.s ==> Superblock, while, d.b ==> Block
321 assert intindex == null;
322 intindex = ld.getIndex();
324 fieldtype = fd.getType();
330 if ((lefttype == null) || (index != null && indextype == null)) {
334 if (indextype != null) {
335 if (indextype != ReservedTypeDescriptor.INT) {
336 sa.getErrorReporter().report(null, "Index must be of type 'int' not '" + indextype.getSymbol() + "'");
341 if (lefttype instanceof StructureTypeDescriptor) {
342 StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype;
343 FieldDescriptor fd = struct.getField(field);
344 LabelDescriptor ld = struct.getLabel(field);
346 if (fd != null) { /* field */
349 if (indextype == null && fd instanceof ArrayDescriptor) {
350 sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
352 } else if (indextype != null && !(fd instanceof ArrayDescriptor)) {
353 sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
357 this.td = fd.getType();
358 } else if (ld != null) { /* label */
362 sa.getErrorReporter().report(null, "A label cannot be accessed as an array");
366 this.td = ld.getType();
368 sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'");
372 /* we promote bit, byte and short to integer types */
373 if (this.td == ReservedTypeDescriptor.BIT ||
374 this.td == ReservedTypeDescriptor.BYTE ||
375 this.td == ReservedTypeDescriptor.SHORT) {
376 this.td = ReservedTypeDescriptor.INT;
381 sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'");