144 AnnotationVisitor globals = av.visitArray("globals");
145 global_layouts.stream().map(Layout::toString).forEach(s -> globals.visit(null, s));
146 globals.visitEnd();
147 av.visitEnd();
148 global_cw.visitEnd();
149 addClassIfNeeded(headerClassName, global_cw.toByteArray());
150 return Collections.unmodifiableMap(types);
151 }
152
153 private void handleException(Exception ex) {
154 log.printError("cannot.write.class.file", headerFile.pkgName + "." + headerFile.headerClsName, ex);
155 log.printStackTrace(ex);
156 }
157
158 private void annotateNativeLocation(ClassVisitor cw, Tree tree) {
159 if (! noNativeLocations) {
160 AnnotationVisitor av = cw.visitAnnotation(NATIVE_LOCATION, true);
161 SourceLocation src = tree.location();
162 SourceLocation.Location loc = src.getFileLocation();
163 Path p = loc.path();
164 av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
165 av.visit("line", loc.line());
166 av.visit("column", loc.column());
167 av.visitEnd();
168 }
169 }
170
171 private void addClassIfNeeded(String clsName, byte[] bytes) {
172 if (null != types.put(clsName, bytes)) {
173 log.printWarning("warn.class.overwritten", clsName);
174 }
175 }
176
177 private static boolean isBitField(Tree tree) {
178 return tree instanceof FieldTree && ((FieldTree)tree).isBitField();
179 }
180
181 /**
182 *
183 * @param cw ClassWriter for the struct
184 * @param tree The Tree
185 * @param parentType The struct type
186 */
187 private boolean addField(ClassVisitor cw, Tree tree, Type parentType) {
188 String fieldName = tree.name();
189 assert !fieldName.isEmpty();
190 Type type = tree.type();
191 JType jt = headerFile.dictionary().lookup(type);
192 assert (jt != null);
193 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, fieldName + "$get",
194 "()" + jt.getDescriptor(), "()" + jt.getSignature(false), null);
195 jt.visitInner(cw);
196
197 if (! noNativeLocations) {
198 AnnotationVisitor av = mv.visitAnnotation(NATIVE_LOCATION, true);
199 SourceLocation src = tree.location();
200 SourceLocation.Location loc = src.getFileLocation();
201 Path p = loc.path();
202 av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
203 av.visit("line", loc.line());
204 av.visit("column", loc.column());
205 av.visitEnd();
206 }
207
208 AnnotationVisitor av = mv.visitAnnotation(NATIVE_GETTER, true);
209 av.visit("value", fieldName);
210 av.visitEnd();
211
212 mv.visitEnd();
213 mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, fieldName + "$set",
214 "(" + jt.getDescriptor() + ")V",
215 "(" + jt.getSignature(true) + ")V", null);
216 jt.visitInner(cw);
217 av = mv.visitAnnotation(NATIVE_SETTER, true);
218 av.visit("value", fieldName);
219 av.visitEnd();
220 mv.visitEnd();
221
222 if (tree instanceof VarTree || !isBitField(tree)) {
232
233 return true;
234 }
235
236 @Override
237 public Boolean visitVar(VarTree varTree, JType jt) {
238 global_layouts.add(varTree.layout().withAnnotation(Layout.NAME, varTree.name()));
239 return addField(global_cw, varTree, null);
240 }
241
242 private void addConstant(ClassWriter cw, SourceLocation src, String name, JType type, Object value) {
243 String desc = "()" + type.getDescriptor();
244 String sig = "()" + type.getSignature(false);
245 MethodVisitor mv = global_cw.visitMethod(ACC_ABSTRACT | ACC_PUBLIC, name, desc, sig, null);
246 type.visitInner(cw);
247
248 if (! noNativeLocations) {
249 AnnotationVisitor av = mv.visitAnnotation(NATIVE_LOCATION, true);
250 SourceLocation.Location loc = src.getFileLocation();
251 Path p = loc.path();
252 av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
253 av.visit("line", loc.line());
254 av.visit("column", loc.column());
255 av.visitEnd();
256 }
257
258 if (value instanceof String) {
259 AnnotationVisitor av = mv.visitAnnotation(NATIVE_STR_CONST, true);
260 av.visit("value", value);
261 av.visitEnd();
262 } else {
263 //numeric (int, long or double)
264 final long longValue;
265 if (value instanceof Integer) {
266 longValue = (Integer)value;
267 } else if (value instanceof Long) {
268 longValue = (Long)value;
269 } else if (value instanceof Double) {
270 longValue = Double.doubleToRawLongBits((Double)value);
271 } else {
272 throw new IllegalStateException("Unexpected constant: " + value);
427 int flags = ACC_PUBLIC | ACC_ABSTRACT;
428 if (fn.isVarArgs) {
429 flags |= ACC_VARARGS;
430 }
431 MethodVisitor mv = global_cw.visitMethod(flags,
432 funcTree.name(), fn.getDescriptor(), fn.getSignature(false), null);
433 jt.visitInner(global_cw);
434 final int arg_cnt = funcTree.numParams();
435 for (int i = 0; i < arg_cnt; i++) {
436 String name = funcTree.paramName(i);
437 final int tmp = i;
438 log.print(Level.FINER, () -> " arg " + tmp + ": " + name);
439 mv.visitParameter(name, 0);
440 }
441
442 if (! noNativeLocations) {
443 AnnotationVisitor av = mv.visitAnnotation(NATIVE_LOCATION, true);
444 SourceLocation src = funcTree.location();
445 SourceLocation.Location loc = src.getFileLocation();
446 Path p = loc.path();
447 av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
448 av.visit("line", loc.line());
449 av.visit("column", loc.column());
450 av.visitEnd();
451 }
452
453 Type type = funcTree.type();
454 final String descStr = Utils.getFunction(type).toString();
455
456 AnnotationVisitor av = mv.visitAnnotation(NATIVE_FUNCTION, true);
457 av.visit("value", descStr);
458 av.visitEnd();
459
460 mv.visitEnd();
461 return true;
462 }
463
464 private AsmCodeFactory generateDecl(Tree tree) {
465 try {
466 log.print(Level.FINE, () -> "Process tree " + tree.name());
467 tree.accept(this, tree.isPreprocessing() ? null : headerFile.dictionary().lookup(tree.type()));
|
144 AnnotationVisitor globals = av.visitArray("globals");
145 global_layouts.stream().map(Layout::toString).forEach(s -> globals.visit(null, s));
146 globals.visitEnd();
147 av.visitEnd();
148 global_cw.visitEnd();
149 addClassIfNeeded(headerClassName, global_cw.toByteArray());
150 return Collections.unmodifiableMap(types);
151 }
152
153 private void handleException(Exception ex) {
154 log.printError("cannot.write.class.file", headerFile.pkgName + "." + headerFile.headerClsName, ex);
155 log.printStackTrace(ex);
156 }
157
158 private void annotateNativeLocation(ClassVisitor cw, Tree tree) {
159 if (! noNativeLocations) {
160 AnnotationVisitor av = cw.visitAnnotation(NATIVE_LOCATION, true);
161 SourceLocation src = tree.location();
162 SourceLocation.Location loc = src.getFileLocation();
163 Path p = loc.path();
164 av.visit("file", p == null ? "<builtin>" : p.toAbsolutePath().toString());
165 av.visit("line", loc.line());
166 av.visit("column", loc.column());
167 av.visitEnd();
168 }
169 }
170
171 private void addClassIfNeeded(String clsName, byte[] bytes) {
172 if (null != types.put(clsName, bytes)) {
173 log.printWarning("warn.class.overwritten", clsName);
174 }
175 }
176
177 private static boolean isBitField(Tree tree) {
178 return tree instanceof FieldTree && ((FieldTree)tree).isBitField();
179 }
180
181 /**
182 *
183 * @param cw ClassWriter for the struct
184 * @param tree The Tree
185 * @param parentType The struct type
186 */
187 private boolean addField(ClassVisitor cw, Tree tree, Type parentType) {
188 String fieldName = tree.name();
189 assert !fieldName.isEmpty();
190 Type type = tree.type();
191 JType jt = headerFile.dictionary().lookup(type);
192 assert (jt != null);
193 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, fieldName + "$get",
194 "()" + jt.getDescriptor(), "()" + jt.getSignature(false), null);
195 jt.visitInner(cw);
196
197 if (! noNativeLocations) {
198 AnnotationVisitor av = mv.visitAnnotation(NATIVE_LOCATION, true);
199 SourceLocation src = tree.location();
200 SourceLocation.Location loc = src.getFileLocation();
201 Path p = loc.path();
202 av.visit("file", p == null ? "<builtin>" : p.toAbsolutePath().toString());
203 av.visit("line", loc.line());
204 av.visit("column", loc.column());
205 av.visitEnd();
206 }
207
208 AnnotationVisitor av = mv.visitAnnotation(NATIVE_GETTER, true);
209 av.visit("value", fieldName);
210 av.visitEnd();
211
212 mv.visitEnd();
213 mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, fieldName + "$set",
214 "(" + jt.getDescriptor() + ")V",
215 "(" + jt.getSignature(true) + ")V", null);
216 jt.visitInner(cw);
217 av = mv.visitAnnotation(NATIVE_SETTER, true);
218 av.visit("value", fieldName);
219 av.visitEnd();
220 mv.visitEnd();
221
222 if (tree instanceof VarTree || !isBitField(tree)) {
232
233 return true;
234 }
235
236 @Override
237 public Boolean visitVar(VarTree varTree, JType jt) {
238 global_layouts.add(varTree.layout().withAnnotation(Layout.NAME, varTree.name()));
239 return addField(global_cw, varTree, null);
240 }
241
242 private void addConstant(ClassWriter cw, SourceLocation src, String name, JType type, Object value) {
243 String desc = "()" + type.getDescriptor();
244 String sig = "()" + type.getSignature(false);
245 MethodVisitor mv = global_cw.visitMethod(ACC_ABSTRACT | ACC_PUBLIC, name, desc, sig, null);
246 type.visitInner(cw);
247
248 if (! noNativeLocations) {
249 AnnotationVisitor av = mv.visitAnnotation(NATIVE_LOCATION, true);
250 SourceLocation.Location loc = src.getFileLocation();
251 Path p = loc.path();
252 av.visit("file", p == null ? "<builtin>" : p.toAbsolutePath().toString());
253 av.visit("line", loc.line());
254 av.visit("column", loc.column());
255 av.visitEnd();
256 }
257
258 if (value instanceof String) {
259 AnnotationVisitor av = mv.visitAnnotation(NATIVE_STR_CONST, true);
260 av.visit("value", value);
261 av.visitEnd();
262 } else {
263 //numeric (int, long or double)
264 final long longValue;
265 if (value instanceof Integer) {
266 longValue = (Integer)value;
267 } else if (value instanceof Long) {
268 longValue = (Long)value;
269 } else if (value instanceof Double) {
270 longValue = Double.doubleToRawLongBits((Double)value);
271 } else {
272 throw new IllegalStateException("Unexpected constant: " + value);
427 int flags = ACC_PUBLIC | ACC_ABSTRACT;
428 if (fn.isVarArgs) {
429 flags |= ACC_VARARGS;
430 }
431 MethodVisitor mv = global_cw.visitMethod(flags,
432 funcTree.name(), fn.getDescriptor(), fn.getSignature(false), null);
433 jt.visitInner(global_cw);
434 final int arg_cnt = funcTree.numParams();
435 for (int i = 0; i < arg_cnt; i++) {
436 String name = funcTree.paramName(i);
437 final int tmp = i;
438 log.print(Level.FINER, () -> " arg " + tmp + ": " + name);
439 mv.visitParameter(name, 0);
440 }
441
442 if (! noNativeLocations) {
443 AnnotationVisitor av = mv.visitAnnotation(NATIVE_LOCATION, true);
444 SourceLocation src = funcTree.location();
445 SourceLocation.Location loc = src.getFileLocation();
446 Path p = loc.path();
447 av.visit("file", p == null ? "<builtin>" : p.toAbsolutePath().toString());
448 av.visit("line", loc.line());
449 av.visit("column", loc.column());
450 av.visitEnd();
451 }
452
453 Type type = funcTree.type();
454 final String descStr = Utils.getFunction(type).toString();
455
456 AnnotationVisitor av = mv.visitAnnotation(NATIVE_FUNCTION, true);
457 av.visit("value", descStr);
458 av.visitEnd();
459
460 mv.visitEnd();
461 return true;
462 }
463
464 private AsmCodeFactory generateDecl(Tree tree) {
465 try {
466 log.print(Level.FINE, () -> "Process tree " + tree.name());
467 tree.accept(this, tree.isPreprocessing() ? null : headerFile.dictionary().lookup(tree.type()));
|