5 public class DotExpr extends Expr {
11 static boolean DOMEMCHECKS=true;
12 static boolean DOTYPECHECKS=false;
13 static boolean DONULL=false;
15 public Set freeVars() {
16 Set lset=left.freeVars();
19 iset=index.freeVars();
28 static int memoryindents = 0;
30 public static void generate_memory_endblocks(CodeWriter cr) {
31 while (memoryindents > 0) {
40 TypeDescriptor fieldtype;
43 public String name() {
44 String name=left.name()+"."+field;
46 name+="["+index.name()+"]";
50 public boolean usesDescriptor(Descriptor d) {
53 return left.usesDescriptor(d)||((intindex!=null)&&intindex.usesDescriptor(d));
56 public boolean equals(Map remap, Expr e) {
57 if (e==null||!(e instanceof DotExpr))
59 DotExpr de=(DotExpr)e;
60 if (!de.field.equals(field))
65 } else if (!index.equals(remap,de.index))
67 if (!left.equals(remap,de.left))
73 public DotExpr(Expr left, String field, Expr index) {
79 public Set getRequiredDescriptors() {
80 Set v = left.getRequiredDescriptors();
83 v.addAll(index.getRequiredDescriptors());
88 public Expr getExpr() {
92 public FieldDescriptor getField() {
96 public Expr getIndex() {
100 public void generate(CodeWriter writer, VarDescriptor dest) {
101 VarDescriptor leftd = VarDescriptor.makeNew("left");
103 writer.output("// " + leftd.getSafeSymbol() + " <-- ");
104 left.prettyPrint(writer);
105 writer.outputline("");
107 left.generate(writer, leftd);
109 writer.output("// " + leftd.getSafeSymbol() + " = ");
110 left.prettyPrint(writer);
111 writer.outputline("");
113 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
114 Expr intindex = index;
117 // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor obect that is in teh vector list
118 // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array
119 // descriptor not the underlying field descriptor
121 /* we calculate the offset in bits */
122 offsetbits = struct.getOffsetExpr(fd);
124 if (fd instanceof ArrayDescriptor) {
125 fd = ((ArrayDescriptor) fd).getField();
128 if (intindex != null) {
129 if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) {
130 /* short circuit for constant 0 */
132 Expr basesize = fd.getBaseSizeExpr();
133 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
137 final SymbolTable st = writer.getSymbolTable();
138 TypeDescriptor td = offsetbits.typecheck(new SemanticAnalyzer() {
139 public IRErrorReporter getErrorReporter() { throw new IRException("badness"); }
140 public SymbolTable getSymbolTable() { return st; }
144 throw new IRException();
145 } else if (td != ReservedTypeDescriptor.INT) {
146 throw new IRException();
149 boolean dotypecheck = false;
151 if (offsetbits instanceof IntegerLiteralExpr) {
152 int offsetinbits = ((IntegerLiteralExpr) offsetbits).getValue();
153 int offset = offsetinbits >> 3; /* offset in bytes */
155 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
156 int shift = offsetinbits - (offset << 3);
157 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
159 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
160 writer.outputline(getType().getGenerateType() + " "+dest.getSafeSymbol()+"=0;");
161 writer.outputline("if ("+leftd.getSafeSymbol()+")");
162 writer.outputline(dest.getSafeSymbol() + " = ((*(int *)" +
163 "(" + leftd.getSafeSymbol() + " + " + offset + ")) " +
164 " >> " + shift + ") & 0x" + Integer.toHexString(mask) + ";");
165 writer.outputline("else maybe=1;");
166 } else { /* a structure address or a ptr! */
167 String ptr = fd.getPtr() ? "*(int *)" : "";
168 /* type var = [*(int *)] (base + offset) */
169 writer.outputline("int " + dest.getSafeSymbol()+"=0;");
170 writer.outputline("if ("+leftd.getSafeSymbol()+")");
172 writer.outputline(dest.getSafeSymbol() +
173 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset + ");");
175 writer.outputline("if ("+dest.getSafeSymbol()+")");
177 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
178 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
179 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
181 } else if (DOTYPECHECKS) {
182 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
184 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
186 writer.outputline(dest.getSafeSymbol()+"=0;");
188 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset + ")=0;");
193 writer.outputline("else maybe=1;");
195 } else { /* offset in bits is an expression that must be generated */
196 VarDescriptor ob = VarDescriptor.makeNew("offsetinbits");
197 writer.output("// " + ob.getSafeSymbol() + " <-- ");
198 offsetbits.prettyPrint(writer);
199 writer.outputline("");
200 offsetbits.generate(writer, ob);
201 writer.output("// " + ob.getSafeSymbol() + " = ");
202 offsetbits.prettyPrint(writer);
203 writer.outputline("");
205 /* derive offset in bytes */
206 VarDescriptor offset = VarDescriptor.makeNew("offset");
207 writer.outputline("int " + offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;");
209 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
210 VarDescriptor shift = VarDescriptor.makeNew("shift");
211 writer.outputline("int " + shift.getSafeSymbol() + " = " + ob.getSafeSymbol() +
212 " - (" + offset.getSafeSymbol() + " << 3);");
213 int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue());
215 /* type var = ((*(int *) (base + offset)) >> shift) & mask */
216 writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol()+"=0;");
217 writer.outputline("if ("+leftd.getSafeSymbol()+")");
218 writer.outputline(dest.getSafeSymbol() +
220 "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " +
221 " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";");
222 writer.outputline("else maybe=1;");
223 } else { /* a structure address or a ptr */
224 String ptr = fd.getPtr() ? "*(int *)" : "";
225 /* type var = [*(int *)] (base + offset) */
226 writer.outputline("int " + dest.getSafeSymbol() +"=0;");
227 writer.outputline("if ("+leftd.getSafeSymbol()+")");
229 writer.outputline(dest.getSafeSymbol() +
230 " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");");
232 writer.outputline("if ("+dest.getSafeSymbol()+")");
234 VarDescriptor typevar=VarDescriptor.makeNew("typechecks");
235 if (DOMEMCHECKS&&(!DOTYPECHECKS)) {
236 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
238 } else if (DOTYPECHECKS) {
239 writer.outputline("bool "+typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");");
241 writer.outputline("if (!"+typevar.getSafeSymbol()+")");
243 writer.outputline(dest.getSafeSymbol()+"=0;");
245 writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")=0;");
250 writer.outputline("else maybe=1;");
255 private int bitmask(int bits) {
258 for (int i = 0; i < bits; i++) {
266 public void prettyPrint(PrettyPrinter pp) {
267 left.prettyPrint(pp);
268 pp.output("." + field);
271 index.prettyPrint(pp);
276 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
277 TypeDescriptor lefttype = left.typecheck(sa);
278 TypeDescriptor indextype = index == null ? null : index.typecheck(sa);
281 /* finished typechecking...so we can fill the fields in */
282 StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType();
283 FieldDescriptor fd = struct.getField(field);
284 LabelDescriptor ld = struct.getLabel(field);
285 if (ld != null) { /* label */
287 fieldtype = ld.getType(); // d.s ==> Superblock, while, d.b ==> Block
290 assert intindex == null;
291 intindex = ld.getIndex();
293 fieldtype = fd.getType();
299 if ((lefttype == null) || (index != null && indextype == null)) {
303 if (indextype != null) {
304 if (indextype != ReservedTypeDescriptor.INT) {
305 sa.getErrorReporter().report(null, "Index must be of type 'int' not '" + indextype.getSymbol() + "'");
310 if (lefttype instanceof StructureTypeDescriptor) {
311 StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype;
312 FieldDescriptor fd = struct.getField(field);
313 LabelDescriptor ld = struct.getLabel(field);
315 if (fd != null) { /* field */
318 if (indextype == null && fd instanceof ArrayDescriptor) {
319 sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
321 } else if (indextype != null && !(fd instanceof ArrayDescriptor)) {
322 sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'");
326 this.td = fd.getType();
327 } else if (ld != null) { /* label */
331 sa.getErrorReporter().report(null, "A label cannot be accessed as an array");
335 this.td = ld.getType();
337 sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'");
341 /* we promote bit, byte and short to integer types */
342 if (this.td == ReservedTypeDescriptor.BIT ||
343 this.td == ReservedTypeDescriptor.BYTE ||
344 this.td == ReservedTypeDescriptor.SHORT) {
345 this.td = ReservedTypeDescriptor.INT;
350 sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'");