This repository was archived by the owner on Jul 12, 2023. It is now read-only.
forked from polyglot-compiler/JLang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJLangArrayAccessExt.java
114 lines (89 loc) · 3.78 KB
/
JLangArrayAccessExt.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//Copyright (C) 2018 Cornell University
package jlang.extension;
import polyglot.ast.*;
import polyglot.types.ClassType;
import polyglot.types.SemanticException;
import polyglot.util.Copy;
import polyglot.util.InternalCompilerError;
import polyglot.util.Position;
import polyglot.util.SerialVersionUID;
import java.util.Arrays;
import java.util.Collections;
import jlang.ast.JLangExt;
import jlang.visit.DesugarLocally;
import jlang.visit.LLVMTranslator;
import static org.bytedeco.javacpp.LLVM.LLVMBuildLoad;
import static org.bytedeco.javacpp.LLVM.LLVMValueRef;
public class JLangArrayAccessExt extends JLangExt {
private static final long serialVersionUID = SerialVersionUID.generate();
/** Whether this array access is already guarded by an index bounds check. */
private boolean guarded = false;
@Override
public ArrayAccess node() {
return (ArrayAccess) super.node();
}
public ArrayAccess setGuarded() {
return setGuarded(node());
}
public ArrayAccess setGuarded(ArrayAccess c) {
JLangArrayAccessExt ext = (JLangArrayAccessExt) JLangExt.ext(c);
if (ext.guarded) return c;
if (c == node) {
c = Copy.Util.copy(c);
ext = (JLangArrayAccessExt) JLangExt.ext(c);
}
ext.guarded = true;
return c;
}
@Override
public Node desugar(DesugarLocally v) {
if (!guarded)
return desugarBoundsCheck(v, node());
return super.desugar(v);
}
protected Expr desugarBoundsCheck(DesugarLocally v, ArrayAccess n) {
Position pos = n.position();
ClassType exnType;
try {
exnType = (ClassType) v.ts.typeForName("java.lang.ArrayIndexOutOfBoundsException");
} catch (SemanticException e) {
throw new InternalCompilerError(e);
}
LocalDecl arrFlat = v.tnf.TempSSA("arr", n.array());
Local arr = v.tnf.Local(pos, arrFlat);
LocalDecl lenFlat = v.tnf.TempSSA("len", v.tnf.Field(pos, copy(arr), "length"));
Local len = v.tnf.Local(pos, lenFlat);
LocalDecl idxFlat = v.tnf.TempSSA("idx", n.index());
Local idx = v.tnf.Local(pos, idxFlat);
n = n.index(copy(idx)).array(copy(arr));
// Build bounds check.
Expr zero = v.nf.IntLit(pos, IntLit.INT, 0).type(v.ts.Int());
Expr tooSmall = v.nf.Binary(pos, copy(idx), Binary.LT, zero).type(v.ts.Boolean());
Expr tooLarge = v.nf.Binary(pos, copy(idx), Binary.GE, copy(len)).type(v.ts.Boolean());
Expr check = v.nf.Binary(pos, tooSmall, Binary.COND_OR, tooLarge).type(v.ts.Boolean());
// Guard access with bounds check. Avoid duplicating side-effects.
Throw throwExn = v.tnf.Throw(pos, exnType, Collections.singletonList(copy(idx)));
Stmt guard = v.tnf.If(check, throwExn);
return v.tnf.ESeq(Arrays.asList(arrFlat, lenFlat, idxFlat, guard), setGuarded(n));
}
@Override
public Node overrideTranslateLLVM(Node parent, LLVMTranslator v) {
ArrayAccess n = node();
LLVMValueRef ptr = translateAsLValue(v); // Emits debug location.
LLVMValueRef load = LLVMBuildLoad(v.builder, ptr, "load.arr.elem");
v.addTranslation(n, load);
return n;
}
/** Return a pointer to the appropriate element in the array. */
@Override
public LLVMValueRef translateAsLValue(LLVMTranslator v) {
if (!guarded)
throw new InternalCompilerError("Unguarded array access should be desugared");
ArrayAccess n = node();
lang().visitChildren(n, v);
LLVMValueRef arr = v.getTranslation(n.array());
LLVMValueRef base = v.obj.buildArrayBaseElementPtr(arr, n.array().type().toArray());
LLVMValueRef offset = v.getTranslation(n.index());
return v.utils.buildGEP(base, offset);
}
}