Skip to content
This repository has been archived by the owner on Jul 6, 2023. It is now read-only.

Commit

Permalink
Fix multiple field access bug due to non initializable fields
Browse files Browse the repository at this point in the history
  • Loading branch information
anmolkabra committed May 16, 2019
1 parent cb88491 commit 44caff8
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 68 deletions.
164 changes: 102 additions & 62 deletions src/main/java/kc875/ast/visit/IRTranslationVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ public class IRTranslationVisitor implements ASTVisitor<IRNode> {
// ordered layouts of dispatch vectors for each class
private Map<String, List<String>> dispatchVectorLayouts;

// maps class names to all stmt decls accessible by the class
private Map<String, List<StmtDecl>> classAllStmtDecls;

private String newLabel() {
return String.format("_mir_l%d", (labelcounter++));
}
Expand Down Expand Up @@ -106,6 +109,7 @@ public IRTranslationVisitor(boolean optimCF,
this.classAllFields = new HashMap<>();
this.furthestParents = new HashMap<>();
this.closestInterfaceParents = new HashMap<>();
this.classAllStmtDecls = new HashMap<>();
for (String className : classHierarchyTraversal) {
// skip the top parent node
if (className.equals(CLASS_SUPER_PARENT)) {
Expand All @@ -117,6 +121,7 @@ public IRTranslationVisitor(boolean optimCF,
List<String> dvLayout = new ArrayList<>();
Map<String, String> methodMap = new HashMap<>();
List<String> allFields = new ArrayList<>();
List<StmtDecl> allStmtDecls = new ArrayList<>();
// build on the parent's dispatch vector and method map, if a parent exists
try {
// get the parent class, if it exists
Expand All @@ -137,6 +142,11 @@ public IRTranslationVisitor(boolean optimCF,
this.classAllFields.get(parent)
);

// inherit the parent's stmtdecls
allStmtDecls.addAll(
this.classAllStmtDecls.get(parent)
);

// if the class is an interface, its closes interface parent is itself
// otherwise, its closest interface parent is its parent's closest interface parent
if (classes.get(className) instanceof ClassDecl) {
Expand Down Expand Up @@ -172,11 +182,13 @@ public IRTranslationVisitor(boolean optimCF,

for (StmtDecl field : clazz.getFields()) {
allFields.addAll(field.varsOf());
allStmtDecls.add(field);
}

this.dispatchVectorLayouts.put(className, dvLayout);
this.classMethodDefinitions.put(className, methodMap);
this.classAllFields.put(className, allFields);
this.classAllStmtDecls.put(className, allStmtDecls);
}
}
}
Expand Down Expand Up @@ -779,6 +791,29 @@ public IRExpr visit(ExprFunctionCall node) {
new IRTemp(returnValueName(0)));
}

private IRMem getFieldOffset(IRExpr obj,
String className,
String fieldName,
List<IRStmt> seq) {
String t = newTemp();
seq.add(new IRMove(new IRTemp(t), obj));

int idxField = this.classAllFields.get(className).indexOf(fieldName);
Maybe<String> cWithSizeNotAvail = this.closestInterfaceParents.get(className);

IRExpr offsetObjLayoutAccess = cWithSizeNotAvail.to(
interfaceName -> (IRExpr) new IRName(classSizeLoc(interfaceName))
).otherwise(new IRConst(8));

seq.add(new IRMove(new IRTemp(t), new IRBinOp(
OpType.ADD, new IRTemp(t), offsetObjLayoutAccess
)));

return new IRMem(new IRBinOp(OpType.ADD,
new IRTemp(t), new IRConst(idxField * 8)
));
}

@Override
public IRExpr visit(ExprId node) {
if (global_names.contains(node.getName())) {
Expand All @@ -787,38 +822,11 @@ public IRExpr visit(ExprId node) {
} else if (inClass && currentClass.getFieldNames().contains(node.getName())) {
//treat like a field access for "this"
List<IRStmt> seq = new ArrayList<>();
String fieldName = node.getName();
String className = currentClass.getName();
while (!classFields.get(className).contains(fieldName)){
try {
className = classHierarchy.get(className).get();
} catch (Maybe.NoMaybeValueException e) {
break;
}
}
String classSize = classSizeLoc(className);
String t = newTemp(); //move this into temp t
seq.add(new IRMove(new IRTemp(t), new IRTemp("this")));
//t is the location of obj

//get n-th to last field by adding size and then subtracting field idx from back
seq.add(new IRMove(
new IRTemp(t),
new IRBinOp(OpType.ADD,
new IRTemp(t),
new IRMem(new IRName(classSize))
)
));
seq.add(new IRMove(
new IRTemp(t),
new IRBinOp(OpType.ADD,
new IRTemp(t),
new IRConst(classFieldOffsetFromBack(className, fieldName) -8)
)
));
//t is now the location of the field data
//eval to a mem because we want this to be compatible with IRMoves
return new IRESeq(new IRSeq(seq), new IRMem(new IRTemp(t)));
IRMem fieldLoc = getFieldOffset(
new IRTemp("this"), currentClass.getName(),
node.getName(), seq
);
return new IRESeq(new IRSeq(seq), fieldLoc);
}
return new IRTemp(node.getName());
}
Expand Down Expand Up @@ -891,10 +899,52 @@ public IRExpr visit(ExprNew node) {
new IRName(dispatchVectorLoc(className))
);

return new IRESeq(
new IRSeq(baseAllocAddress, storeDV),
new IRTemp(objectBaseAddress)
);
List<IRStmt> stmts = new ArrayList<>();
stmts.add(baseAllocAddress);
stmts.add(storeDV);

// Initialize the fields
for (StmtDecl field : this.classAllStmtDecls.get(className)) {
String fieldName;
TypeTTau fieldType;

if (field instanceof StmtDeclSingle) {
StmtDeclSingle s = (StmtDeclSingle) field;
fieldName = s.getName();
stmts.add(this.visit(s));
// Calculate offset for fieldName
IRMem fieldLoc = getFieldOffset(
new IRTemp(objectBaseAddress), className, fieldName, stmts
);
stmts.add(new IRMove(fieldLoc, new IRTemp(fieldName)));
} else if (field instanceof StmtDeclAssign) {
StmtDeclAssign s = (StmtDeclAssign) field;
stmts.add(this.visit(s));
List<String> names = s.getNames();
for (int i = 0; i < names.size(); i++) {
fieldName = names.get(i);
TypeT t = s.getDecls().get(i).typeOf();
if (t instanceof TypeTTau) {
IRMem fieldLoc = getFieldOffset(
new IRTemp(objectBaseAddress), className, fieldName, stmts
);
stmts.add(new IRMove(fieldLoc, new IRTemp(fieldName)));
}
}
} else if (field instanceof StmtDeclMulti) {
List<String> names = (field).varsOf();
for (String name : names) {
fieldName = name;
fieldType = ((StmtDeclMulti) field).getType();
stmts.add(initDecl(fieldName, fieldType));
IRMem fieldLoc = getFieldOffset(
new IRTemp(objectBaseAddress), className, fieldName, stmts
);
stmts.add(new IRMove(fieldLoc, new IRTemp(fieldName)));
}
}
}
return new IRESeq(new IRSeq(stmts), new IRTemp(objectBaseAddress));
}

@Override
Expand Down Expand Up @@ -1314,37 +1364,27 @@ public IRExpr visit(ExprFieldAccess node) {
Expr obj = node.getObj();
String fieldName = node.getField().getName();
String className = ((TypeTTauClass) obj.getTypeCheckType()).getName();
while (!classFields.get(className).contains(fieldName)){
try {
className = classHierarchy.get(className).get();
} catch (Maybe.NoMaybeValueException e) {
break;
}
}
String classSize = classSizeLoc(className);

String t = newTemp();
IRExpr objExpr = (IRExpr) obj.accept(this);
seq.add(new IRMove(new IRTemp(t), objExpr));
//t is the location of obj

//get n-th to last field by adding size and then subtracting field idx from back
seq.add(new IRMove(
new IRTemp(t),
new IRBinOp(OpType.ADD,
new IRTemp(t),
new IRMem(new IRName(classSize))
)
));
seq.add(new IRMove(
new IRTemp(t),
new IRBinOp(OpType.ADD,
new IRTemp(t),
new IRConst(classFieldOffsetFromBack(className, fieldName) -8)
)
int idxField = this.classAllFields.get(className).indexOf(fieldName);
Maybe<String> cWithSizeNotAvail = this.closestInterfaceParents.get(className);

IRExpr offsetObjLayoutAccess = cWithSizeNotAvail.to(
interfaceName -> (IRExpr) new IRName(classSizeLoc(interfaceName))
).otherwise(new IRConst(8));

seq.add(new IRMove(new IRTemp(t), new IRBinOp(
OpType.ADD, new IRTemp(t), offsetObjLayoutAccess
)));

IRMem fieldLoc = new IRMem(new IRBinOp(OpType.ADD,
new IRTemp(t), new IRConst(idxField * 8)
));
//t is now the location of the field data
//eval to a mem because we want this to be compatible with IRMoves
return new IRESeq(new IRSeq(seq), new IRMem(new IRTemp(t)));

return new IRESeq(new IRSeq(seq), fieldLoc);
}

@Override
Expand Down
9 changes: 8 additions & 1 deletion tests/pa7-tests/class_multiple_field_method_access.ssol.nml
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
Valid Xi Program
97
11
11
22
22
0
1
2
4 changes: 2 additions & 2 deletions tests/pa7-tests/class_multiple_field_method_access.xi
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ class C {
class B extends A {
afield: A
b: int
cs: C[b]
cs: C[3]
fb(): int { return 'b' }
initB(a_: int, afield_: A, b_: int): B {
_ = initA(a_)
afield = afield_
b = b_

i: int = 0
while (i < b) {
while (i < 3) {
cs[i] = new C.initC(i)
i = i + 1
}
Expand Down
26 changes: 26 additions & 0 deletions tests/pa7-tests/coloredpoint.xi
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use io
use conv
use point

class Color {
r, g, b: int
}

class ColoredPoint extends Point {
col: Color
color(): Color { return col }

initColoredPoint(x0: int, y0: int, c: Color): ColoredPoint {
col = c
_ = initPoint(x0, y0)
return this
}
}

main(args:int[][]) {
c:Color = new Color
c.r = 1; c.g = 2; c.b = 3;

p:Point = new ColoredPoint
_ = p.initPoint(1, 2)
}
25 changes: 25 additions & 0 deletions tests/pa7-tests/point.xi
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Point{ // a mutable point
x, y: int

move(dx: int, dy: int) {
x = x + dx
y = y + dy
}
coords(): int, int {
return x, y
}
add(p: Point): Point {
return createPoint(x + p.x, y + p.y)
}
initPoint(x0: int, y0: int): Point {
x = x0
y = y0
return this
}
clone(): Point { return createPoint(x, y) }
}

createPoint(x: int, y:int): Point {
return new Point.initPoint(x, y)
}

Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ class C {
class B extends A {
afield: A
b: int
cs: C[b]
cs: C[3]
fb(): int { return 'b' }
initB(a_: int, afield_: A, b_: int): B {
_ = initA(a_)
afield = afield_
b = b_

i: int = 0
while (i < b) {
while (i < 3) {
cs[i] = new C.initC(i)
i = i + 1
}
Expand All @@ -40,7 +40,7 @@ class B extends A {
}
}

f() {
main(args:int[][]) {
aobj_inB: A = new A.initA(1)
bobj: B = new B.initB(0, aobj_inB, 2)

Expand Down

0 comments on commit 44caff8

Please sign in to comment.