11
11
import com .sun .tools .javac .tree .TreeInfo ;
12
12
import com .sun .tools .javac .tree .TreeMaker ;
13
13
import com .sun .tools .javac .util .*;
14
+ import com .sun .tools .javac .util .List ;
14
15
import jdk .incubator .code .*;
15
16
import jdk .incubator .code .op .CoreOp ;
16
17
import jdk .incubator .code .type .*;
17
18
18
- import java .util .HashMap ;
19
- import java .util .Map ;
19
+ import java .util .*;
20
20
21
21
import static com .sun .tools .javac .code .Flags .*;
22
22
@@ -30,9 +30,13 @@ public class CodeModelToAST {
30
30
private final Types types ;
31
31
private final Symbol .ClassSymbol currClassSym ;
32
32
private final CodeReflectionSymbols crSym ;
33
- private final Map <Value , Symbol .VarSymbol > valueToVarSym = new HashMap <>();
34
33
private Symbol .MethodSymbol ms ;
35
34
private int localVarCount = 0 ; // used to name variables we introduce in the AST
35
+ private final Map <Value , JCTree > valueToTree = new HashMap <>();
36
+ private static final MethodRef M_BLOCK_BUILDER_OP = MethodRef .method (Block .Builder .class , "op" ,
37
+ Op .Result .class , Op .class );
38
+ private static final MethodRef M_BLOCK_BUILDER_PARAM = MethodRef .method (Block .Builder .class , "parameter" ,
39
+ Block .Parameter .class , TypeElement .class );
36
40
37
41
public CodeModelToAST (TreeMaker treeMaker , Names names , Symtab syms , Resolve resolve ,
38
42
Types types , Env <AttrContext > attrEnv , CodeReflectionSymbols crSym ) {
@@ -66,6 +70,14 @@ private Type typeElementToType(TypeElement jt) {
66
70
};
67
71
}
68
72
73
+ private JCExpression toExpr (JCTree t ) {
74
+ return switch (t ) {
75
+ case JCExpression e -> e ;
76
+ case JCTree .JCVariableDecl vd -> treeMaker .Ident (vd );
77
+ case null , default -> throw new IllegalArgumentException ();
78
+ };
79
+ }
80
+
69
81
private JCTree invokeOpToJCMethodInvocation (CoreOp .InvokeOp invokeOp ) {
70
82
Value receiver = (invokeOp .invokeKind () == CoreOp .InvokeOp .InvokeKind .INSTANCE ) ?
71
83
invokeOp .operands ().get (0 ) : null ;
@@ -75,10 +87,10 @@ private JCTree invokeOpToJCMethodInvocation(CoreOp.InvokeOp invokeOp) {
75
87
var methodSym = methodDescriptorToSymbol (invokeOp .invokeDescriptor ());
76
88
var meth = (receiver == null ) ?
77
89
treeMaker .Ident (methodSym ) :
78
- treeMaker .Select (exprTree ( receiver ), methodSym );
90
+ treeMaker .Select (toExpr ( opToTree ( receiver ) ), methodSym );
79
91
var args = new ListBuffer <JCTree .JCExpression >();
80
92
for (Value operand : arguments ) {
81
- args .add (exprTree ( operand ));
93
+ args .add (toExpr ( opToTree ( operand ) ));
82
94
}
83
95
var methodInvocation = treeMaker .App (meth , args .toList ());
84
96
if (invokeOp .isVarArgs ()) {
@@ -96,7 +108,48 @@ void setVarargs(JCExpression tree, FunctionType type) {
96
108
}
97
109
}
98
110
99
- private JCTree opToTree (Op op ) {
111
+ public JCTree .JCMethodDecl transformFuncOpToAST (CoreOp .FuncOp funcOp , Name methodName ) {
112
+ Assert .check (funcOp .body ().blocks ().size () == 1 );
113
+
114
+ var paramTypes = List .of (crSym .opFactoryType , crSym .typeElementFactoryType );
115
+ var mt = new Type .MethodType (paramTypes , crSym .opType , List .nil (), syms .methodClass );
116
+ ms = new Symbol .MethodSymbol (PUBLIC | STATIC | SYNTHETIC , methodName , mt , currClassSym );
117
+ currClassSym .members ().enter (ms );
118
+
119
+ for (int i = 0 ; i < funcOp .parameters ().size (); i ++) {
120
+ valueToTree .put (funcOp .parameters ().get (i ), treeMaker .Ident (ms .params ().get (i )));
121
+ }
122
+
123
+ java .util .List <Value > rootValues = funcOp .traverse (new ArrayList <>(), (l , ce ) -> {
124
+ if (ce instanceof Op op && op .result () != null && op .result ().uses ().size () != 1 ) {
125
+ l .add (op .result ());
126
+ } else if (ce instanceof CoreOp .InvokeOp invokeOp && (invokeOp .invokeDescriptor ().equals (M_BLOCK_BUILDER_OP )
127
+ || invokeOp .invokeDescriptor ().equals (M_BLOCK_BUILDER_PARAM ))) {
128
+ l .add (invokeOp .result ());
129
+ }
130
+ return l ;
131
+ });
132
+
133
+ var stats = new ListBuffer <JCTree .JCStatement >();
134
+ for (Value root : rootValues ) {
135
+ JCTree tree = opToTree (root );
136
+ if (tree instanceof JCExpression e ) {
137
+ var vs = new Symbol .VarSymbol (LocalVarFlags | SYNTHETIC , names .fromString ("_$" + localVarCount ++), tree .type , ms );
138
+ tree = treeMaker .VarDef (vs , e );
139
+ valueToTree .put (root , tree );
140
+ }
141
+ stats .add ((JCTree .JCStatement ) tree );
142
+ }
143
+ var mb = treeMaker .Block (0 , stats .toList ());
144
+
145
+ return treeMaker .MethodDef (ms , mb );
146
+ }
147
+
148
+ private JCTree opToTree (Value v ) {
149
+ if (valueToTree .containsKey (v )) {
150
+ return valueToTree .get (v );
151
+ }
152
+ Op op = ((Op .Result ) v ).op ();
100
153
JCTree tree = switch (op ) {
101
154
case CoreOp .ConstantOp constantOp when constantOp .value () == null ->
102
155
treeMaker .Literal (TypeTag .BOT , null ).setType (syms .botType );
@@ -106,7 +159,7 @@ private JCTree opToTree(Op op) {
106
159
var elemType = treeMaker .Ident (typeElementToType (at .componentType ()).tsym );
107
160
var dims = new ListBuffer <JCTree .JCExpression >();
108
161
for (int d = 0 ; d < at .dimensions (); d ++) {
109
- dims .add (exprTree ( newOp .operands ().get (d )));
162
+ dims .add (toExpr ( opToTree ( newOp .operands ().get (d ) )));
110
163
}
111
164
var na = treeMaker .NewArray (elemType , dims .toList (), null );
112
165
na .type = typeElementToType (at );
@@ -117,7 +170,7 @@ private JCTree opToTree(Op op) {
117
170
var clazz = treeMaker .Ident (ownerType .tsym );
118
171
var args = new ListBuffer <JCTree .JCExpression >();
119
172
for (Value operand : newOp .operands ()) {
120
- args .add (exprTree ( operand ));
173
+ args .add (toExpr ( opToTree ( operand ) ));
121
174
}
122
175
var nc = treeMaker .NewClass (null , null , clazz , args .toList (), null );
123
176
if (newOp .isVarargs ()) {
@@ -129,7 +182,7 @@ private JCTree opToTree(Op op) {
129
182
yield nc ;
130
183
}
131
184
case CoreOp .ReturnOp returnOp ->
132
- treeMaker .Return (exprTree ( returnOp .returnValue ()));
185
+ treeMaker .Return (toExpr ( opToTree ( returnOp .returnValue () )));
133
186
case CoreOp .FieldAccessOp .FieldLoadOp fieldLoadOp -> {
134
187
var sym = fieldDescriptorToSymbol (fieldLoadOp .fieldDescriptor ());
135
188
Assert .check (sym .isStatic ());
@@ -140,63 +193,16 @@ private JCTree opToTree(Op op) {
140
193
var val = arrayStoreOp .operands ().get (1 );
141
194
var index = arrayStoreOp .operands ().get (2 );
142
195
var as = treeMaker .Assign (
143
- treeMaker .Indexed (exprTree (array ), exprTree (index )), exprTree (val )
196
+ treeMaker .Indexed (
197
+ toExpr (opToTree (array )), toExpr (opToTree (index ))), toExpr (opToTree (val ))
144
198
);
145
199
as .type = typeElementToType (((ArrayType ) array .type ()).componentType ());
146
200
yield as ;
147
201
}
148
202
default -> throw new IllegalStateException ("Op -> JCTree not supported for :" + op .getClass ().getName ());
149
203
};
150
- if (tree instanceof JCTree .JCExpression expr ) {
151
- // introduce a local variable to hold the expr, to make sure an op's tree is inserted right away
152
- // for some operations this is essential, e.g. to ensure the correct order of operations
153
- Type type ;
154
- if (op instanceof CoreOp .ConstantOp cop && cop .value () == null ) {
155
- // if ConstantOp value is null, tree.type will be null_type
156
- // if null_type is used to create a VarSymbol, an exception will be thrown
157
- type = typeElementToType (cop .resultType ());
158
- } else {
159
- type = tree .type ;
160
- }
161
- var vs = new Symbol .VarSymbol (LocalVarFlags , names .fromString ("_$" + localVarCount ++), type , ms );
162
- var varDef = treeMaker .VarDef (vs , expr );
163
- map (op .result (), vs );
164
- return varDef ;
165
- } else {
166
- return tree ;
167
- }
168
- }
169
-
170
- private JCTree .JCExpression exprTree (Value v ) {
171
- return treeMaker .Ident (valueToVarSym .get (v ));
172
- }
173
-
174
- private void map (Value v , Symbol .VarSymbol vs ) {
175
- valueToVarSym .put (v , vs );
176
- }
177
-
178
- public JCTree .JCMethodDecl transformFuncOpToAST (CoreOp .FuncOp funcOp , Name methodName ) {
179
- Assert .check (funcOp .body ().blocks ().size () == 1 );
180
-
181
- var paramTypes = List .of (crSym .opFactoryType , crSym .typeElementFactoryType );
182
- var mt = new Type .MethodType (paramTypes , crSym .opType , List .nil (), syms .methodClass );
183
- ms = new Symbol .MethodSymbol (PUBLIC | STATIC | SYNTHETIC , methodName , mt , currClassSym );
184
- currClassSym .members ().enter (ms );
185
-
186
- for (int i = 0 ; i < funcOp .parameters ().size (); i ++) {
187
- map (funcOp .parameters ().get (i ), ms .params ().get (i ));
188
- }
189
-
190
- var stats = new ListBuffer <JCTree .JCStatement >();
191
- for (Op op : funcOp .body ().entryBlock ().ops ()) {
192
- var tree = opToTree (op );
193
- if (tree instanceof JCTree .JCStatement stat ) {
194
- stats .add (stat );
195
- }
196
- }
197
- var mb = treeMaker .Block (0 , stats .toList ());
198
-
199
- return treeMaker .MethodDef (ms , mb );
204
+ valueToTree .put (v , tree );
205
+ return tree ;
200
206
}
201
207
202
208
VarSymbol fieldDescriptorToSymbol (FieldRef fieldRef ) {
0 commit comments