5 public class DotExpr extends Expr {
11 static boolean DOMEMCHECKS=true;
12 static boolean DOTYPECHECKS=false;
13 static boolean DONULL=false;
15 public void findmatch(Descriptor d, Set s) {
23 public Set freeVars() {
24 Set lset=left.freeVars();
27 iset=index.freeVars();
36 static int memoryindents = 0;
38 public static void generate_memory_endblocks(CodeWriter cr) {
39 while (memoryindents > 0) {
48 TypeDescriptor fieldtype;
51 public String name() {
52 String name=left.name()+"."+field;
54 name+="["+index.name()+"]";
58 public boolean usesDescriptor(Descriptor d) {
61 return left.usesDescriptor(d)||((intindex!=null)&&intindex.usesDescriptor(d));
64 public boolean equals(Map remap, Expr e) {
65 if (e==null||!(e instanceof DotExpr))
67 DotExpr de=(DotExpr)e;
68 if (!de.field.equals(field))
73 } else if (!index.equals(remap,de.index))
75 if (!left.equals(remap,de.left))
81 public DotExpr(Expr left, String field, Expr index) {
87 public Set getRequiredDescriptors() {
88 Set v = left.getRequiredDescriptors();
91 v.addAll(index.getRequiredDescriptors());
96 public Expr getExpr() {
100 public FieldDescriptor getField() {
104 public Expr getIndex() {
108 public void generate(CodeWriter writer, VarDescriptor dest) {
109 VarDescriptor leftd = VarDescriptor.makeNew("left");
111 writer.output("// " + leftd.getSafeSymbol() + " <-- ");
112 left.prettyPrint(writer);
113 writer.outputline("");
115 left.generate(writer, leftd);
117 writer.output("// " + leftd.getSafeSymbol() + " = ");
118 left.prettyPrint(writer);
119 writer.outputline("");
121 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
122 Expr intindex = index;
125 // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor object that is in the vector list
126 // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
127 // descriptor not the underlying field descriptor
129 /* we calculate the offset in bits */
131 offsetbits = struct.getOffsetExpr(fd);
133 FieldDescriptor fd=this.fd;
134 if (fd instanceof ArrayDescriptor)
135 fd=((ArrayDescriptor)fd).getField();
137 if (intindex != null) {
138 if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) {
139 /* short circuit for constant 0 */
141 Expr basesize = fd.getBaseSizeExpr();
142 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
146 final SymbolTable st = writer.getSymbolTable();
147 TypeDescriptor td2 = offsetbits.typecheck(new SemanticAnalyzer() {
148 public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
149 public SymbolTable getSymbolTable() { return st; }
153 throw new IRException();
154 } else if (td2 != ReservedTypeDescriptor.INT) {
155 throw new IRException();
158 boolean dotypecheck = false;
160 if (offsetbits instanceof IntegerLiteralExpr) {
161 int offsetinbits = ((IntegerLiteralExpr) offsetbits).getValue();
162 int offset = offsetinbits >> 3; /* offset in bytes */
164 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
165 int shift = offsetinbits - (offset << 3);
166 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
168 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
169 writer.outputline(getType().getGenerateType() + " "+dest.getSafeSymbol()+"=0;");
170 writer.outputline("if ("+leftd.getSafeSymbol()+")");
171 writer.outputline(dest.getSafeSymbol() + " = ((*(int *)" +
172 "(" + leftd.getSafeSymbol() + " + " + offset + ")) " +
173 " >> " + shift + ") & 0x" + Integer.toHexString(mask) + ";");
174 writer.outputline("else maybe=1;");
175 } else { /* a structure address or a ptr! */
176 String ptr = fd.getPtr() ? "*(int *)" : "";
177 /* type var = [*(int *)] (base + offset) */
178 writer.outputline("int " + dest.getSafeSymbol()+"=0;");
179 writer.outputline("if ("+leftd.getSafeSymbol()+")");
181 writer.outputline(dest.getSafeSymbol() +
182 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset + ");");
184 writer.outputline("if ("+dest.getSafeSymbol()+")");
186 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
187 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
188 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
190 } else if (DOTYPECHECKS) {
191 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
193 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
195 writer.outputline(dest.getSafeSymbol()+"=0;");
197 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset + ")=0;");
202 writer.outputline("else maybe=1;");
204 } else { /* offset in bits is an expression that must be generated */
205 VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
206 writer.output("// " + ob.getSafeSymbol() + " <-- ");
207 offsetbits.prettyPrint(writer);
208 writer.outputline("");
209 offsetbits.generate(writer, ob);
210 writer.output("// " + ob.getSafeSymbol() + " = ");
211 offsetbits.prettyPrint(writer);
212 writer.outputline("");
214 /* derive offset in bytes */
215 VarDescriptor offset = VarDescriptor.makeNew("offset");
216 writer.outputline("int " + offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
218 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
219 VarDescriptor shift = VarDescriptor.makeNew("shift");
220 writer.outputline("int " + shift.getSafeSymbol() + " = " + ob.getSafeSymbol() +
221 " - (" + offset.getSafeSymbol() + " << 3);");
222 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
224 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
225 writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol()+"=0;");
226 writer.outputline("if ("+leftd.getSafeSymbol()+")");
227 writer.outputline(dest.getSafeSymbol() +
229 "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " +
230 " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");
231 writer.outputline("else maybe=1;");
232 } else { /* a structure address or a ptr */
233 String ptr = fd.getPtr() ? "*(int *)" : "";
234 /* type var = [*(int *)] (base + offset) */
235 writer.outputline("int " + dest.getSafeSymbol() +"=0;");
236 writer.outputline("if ("+leftd.getSafeSymbol()+")");
238 writer.outputline(dest.getSafeSymbol() +
239 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");
241 writer.outputline("if ("+dest.getSafeSymbol()+")");
243 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
244 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
245 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
247 } else if (DOTYPECHECKS) {
248 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
250 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
252 writer.outputline(dest.getSafeSymbol()+"=0;");
254 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")=0;");
259 writer.outputline("else maybe=1;");
264 private int bitmask(int bits) {
267 for (int i = 0; i < bits; i++) {
275 public void prettyPrint(PrettyPrinter pp) {
276 left.prettyPrint(pp);
277 pp.output("." + field);
280 index.prettyPrint(pp);
285 public boolean isValue() {
286 FieldDescriptor tmpfd=fd;
287 if (tmpfd instanceof ArrayDescriptor)
288 tmpfd=((ArrayDescriptor)tmpfd).getField();
289 return (tmpfd.getPtr()||(tmpfd.getType() instanceof ReservedTypeDescriptor));
292 boolean typechecked=false;
293 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
296 else typechecked=true;
297 TypeDescriptor lefttype = left.typecheck(sa);
298 TypeDescriptor indextype = index == null ? null : index.typecheck(sa);
301 /* finished typechecking...so we can fill the fields in */
302 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
303 FieldDescriptor fd = struct.getField(field);
304 LabelDescriptor ld = struct.getLabel(field);
305 if (ld != null) { /* label */
307 fieldtype = ld.getType(); // d.s ==> Superblock, while, d.b ==> Block
310 assert intindex == null;
311 intindex = ld.getIndex();
313 fieldtype = fd.getType();
319 if ((lefttype == null) || (index != null && indextype == null)) {
323 if (indextype != null) {
324 if (indextype != ReservedTypeDescriptor.INT) {
325 sa.getErrorReporter().report(null, "Index must be of type 'int' not '" + indextype.getSymbol() + "'");
330 if (lefttype instanceof StructureTypeDescriptor) {
331 StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype;
332 FieldDescriptor fd = struct.getField(field);
333 LabelDescriptor ld = struct.getLabel(field);
335 if (fd != null) { /* field */
338 if (indextype == null && fd instanceof ArrayDescriptor) {
339 sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
341 } else if (indextype != null && !(fd instanceof ArrayDescriptor)) {
342 sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
346 this.td = fd.getType();
347 } else if (ld != null) { /* label */
351 sa.getErrorReporter().report(null, "A label cannot be accessed as an array");
355 this.td = ld.getType();
357 sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'");
361 /* we promote bit, byte and short to integer types */
362 if (this.td == ReservedTypeDescriptor.BIT ||
363 this.td == ReservedTypeDescriptor.BYTE ||
364 this.td == ReservedTypeDescriptor.SHORT) {
365 this.td = ReservedTypeDescriptor.INT;
370 sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'");