< prev index next >

src/jdk.jextract/share/classes/com/sun/tools/jextract/AsmCodeFactory.java

Print this page




 149             throws IOException {
 150         cw.visitEnd();
 151         byte[] bytecodes = cw.toByteArray();
 152         if (null != types.put(clsName, bytecodes)) {
 153             logger.warning("Class " + clsName + " definition is overwritten");
 154         }
 155     }
 156 
 157     private static boolean isBitField(Tree tree) {
 158         return tree instanceof FieldTree && ((FieldTree)tree).isBitField();
 159     }
 160 
 161     /**
 162      *
 163      * @param cw ClassWriter for the struct
 164      * @param tree The Tree
 165      * @param parentType The struct type
 166      */
 167     private void addField(ClassVisitor cw, Tree tree, Type parentType) {
 168         String fieldName = tree.name();
 169         if (fieldName.isEmpty()) {
 170             //skip anon fields
 171             return;
 172         }
 173         Type type = tree.type();
 174         JType jt = owner.globalLookup(type);
 175         assert (jt != null);
 176         if (cw == global_cw) {
 177             String uniqueName = fieldName + "." + jt.getDescriptor();
 178             if (! global_fields.add(uniqueName)) {
 179                 return; // added already
 180             }
 181         }
 182         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, fieldName + "$get",
 183                 "()" + jt.getDescriptor(), "()" + jt.getSignature(), null);
 184 
 185         AnnotationVisitor av = mv.visitAnnotation(NATIVE_LOCATION, true);
 186         SourceLocation src = tree.location();
 187         SourceLocation.Location loc = src.getFileLocation();
 188         Path p = loc.path();
 189         av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
 190         av.visit("line", loc.line());
 191         av.visit("column", loc.column());
 192         av.visit("USR", tree.USR());


 217     }
 218 
 219     private void addConstant(ClassVisitor cw, FieldTree fieldTree) {
 220         assert (fieldTree.isEnumConstant());
 221         String name = fieldTree.name();
 222         String desc = owner.globalLookup(fieldTree.type()).getDescriptor();
 223         Object value = null;
 224         switch (desc) {
 225             case "J":
 226                 value = fieldTree.enumConstant().get();
 227                 break;
 228             case "I":
 229                 value = fieldTree.enumConstant().get().intValue();
 230                 break;
 231         }
 232         cw.visitField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC, name, desc, null, value);
 233     }
 234 
 235     @Override
 236     public Void visitStruct(StructTree structTree, JType jt) {
 237         String nativeName = structTree.identifier();
 238         Type type = structTree.type();
 239         logger.fine(() -> "Create struct: " + nativeName);
 240 
 241         String intf = Utils.toClassName(nativeName);
 242         String name = internal_name + "$" + intf;
 243 
 244         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 245         /* FIXME: Member interface is implicit static, also ASM.CheckClassAdapter is not
 246          * taking static as a valid flag, so comment this out during development.
 247          */
 248         global_cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
 249         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 250         cw.visit(V1_8, ACC_PUBLIC /*| ACC_STATIC*/ | ACC_INTERFACE | ACC_ABSTRACT,
 251                 name, "Ljava/lang/Object;Ljava/foreign/memory/Struct<L" + name + ";>;",
 252                 "java/lang/Object", new String[] {"java/foreign/memory/Struct"});
 253         annotateNativeLocation(cw, structTree);
 254 
 255         AnnotationVisitor av = cw.visitAnnotation(NATIVE_STRUCT, true);
 256         Layout structLayout = structTree.layout(this::decorateAsAccessor);
 257         av.visit("value", structLayout.toString());


 288         }
 289         return layout;
 290     }
 291 
 292     @Override
 293     public Void visitEnum(EnumTree enumTree, JType jt) {
 294         // define enum constants in global_cw
 295         enumTree.constants().forEach(constant -> addConstant(global_cw, constant));
 296 
 297         if (enumTree.name().isEmpty()) {
 298             // We are done with anonymous enum
 299             return null;
 300         }
 301 
 302         // generate annotation class for named enum
 303         createAnnotationCls(enumTree);
 304         return null;
 305     }
 306 
 307     private void createAnnotationCls(Tree tree) {
 308         String nativeName = tree.identifier();
 309         logger.fine(() -> "Create annotation for: " + nativeName);
 310 
 311         String intf = Utils.toClassName(nativeName);
 312         String name = internal_name + "$" + intf;
 313 
 314         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 315         global_cw.visitInnerClass(name, internal_name, intf,
 316                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 317         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 318         String[] superAnno = { "java/lang/annotation/Annotation" };
 319         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION,
 320                 name, null, "java/lang/Object", superAnno);
 321         annotateNativeLocation(cw, tree);
 322         Type type = tree.type().canonicalType();
 323         AnnotationVisitor av = cw.visitAnnotation("Ljava/lang/annotation/Target;", true);
 324         av.visitEnum("value", "Ljava/lang/annotation/ElementType;", "TYPE_USE");
 325         av.visitEnd();
 326         av = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
 327         av.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
 328         av.visitEnd();
 329         cw.visitInnerClass(name, internal_name, intf,
 330                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 331         // Write class
 332         try {
 333             writeClassFile(cw, owner.clsName + "$" + intf);
 334         } catch (IOException ex) {
 335             handleException(ex);
 336         }
 337     }
 338 
 339     private void createFunctionalInterface(Tree tree, JType.FnIf fnif) {
 340         JType.Function fn = fnif.getFunction();
 341         String intf;
 342         String nativeName;
 343         String nDesc = fnif.getFunction().getNativeDescriptor();
 344         if (tree == null) {
 345             intf = ((JType.InnerType) fnif.type).getName();
 346             nativeName = "anonymous function";
 347         } else {
 348             nativeName = tree.identifier();
 349             intf = Utils.toClassName(nativeName);
 350         }
 351         logger.fine(() -> "Create FunctionalInterface " + intf);
 352 
 353         final String name = internal_name + "$" + intf;
 354 
 355         logger.fine(() -> "Define class " + name + " for native type " + nativeName + nDesc);
 356         global_cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
 357         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 358         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE,
 359                 name, "Ljava/lang/Object;",
 360                 "java/lang/Object", new String[0]);
 361         if (tree != null) {
 362             annotateNativeLocation(cw, tree);
 363         }
 364         AnnotationVisitor av = cw.visitAnnotation(
 365                 "Ljava/lang/FunctionalInterface;", true);
 366         av.visitEnd();
 367         av = cw.visitAnnotation(NATIVE_CALLBACK, true);
 368         av.visit("value", nDesc);


 371 
 372         // add the method
 373 
 374         int flags = ACC_PUBLIC | ACC_ABSTRACT;
 375         if (fn.isVarArgs) {
 376             flags |= ACC_VARARGS;
 377         }
 378         MethodVisitor mv = cw.visitMethod(flags, "fn",
 379                 fn.getDescriptor(), fn.getSignature(), null);
 380         mv.visitEnd();
 381         // Write class
 382         try {
 383             writeClassFile(cw, owner.clsName + "$" + intf);
 384         } catch (IOException ex) {
 385             handleException(ex);
 386         }
 387     }
 388 
 389     @Override
 390     public Void visitTypedef(TypedefTree typedefTree, JType jt) {
 391         Type t = typedefTree.type();
 392         if (t.canonicalType().kind() == TypeKind.Enum &&
 393             t.spelling().equals(t.canonicalType().getDeclarationCursor().spelling())) {
 394             logger.fine("Skip redundant typedef " + t.spelling());
 395             return null;
 396         }
 397 
 398         // anonymous typedef struct {} xxx will not get TypeAlias
 399         if (jt instanceof TypeAlias) {
 400             TypeAlias alias = (TypeAlias) jt;
 401             if (alias.getAnnotationDescriptor() != null) {
 402                 createAnnotationCls(typedefTree);
 403             } else {
 404                 JType real = alias.canonicalType();
 405                 if (real instanceof JType.FnIf) {
 406                     createFunctionalInterface(typedefTree, (JType.FnIf) real);
 407                 }
 408                 // Otherwise, type alias is a same named stuct
 409             }
 410         }
 411         return null;
 412     }
 413 
 414     @Override
 415     public Void visitTree(Tree tree, JType jt) {
 416         logger.warning(() -> "Unsupported declaration tree:");
 417         logger.warning(() -> tree.toString());




 149             throws IOException {
 150         cw.visitEnd();
 151         byte[] bytecodes = cw.toByteArray();
 152         if (null != types.put(clsName, bytecodes)) {
 153             logger.warning("Class " + clsName + " definition is overwritten");
 154         }
 155     }
 156 
 157     private static boolean isBitField(Tree tree) {
 158         return tree instanceof FieldTree && ((FieldTree)tree).isBitField();
 159     }
 160 
 161     /**
 162      *
 163      * @param cw ClassWriter for the struct
 164      * @param tree The Tree
 165      * @param parentType The struct type
 166      */
 167     private void addField(ClassVisitor cw, Tree tree, Type parentType) {
 168         String fieldName = tree.name();
 169         assert !fieldName.isEmpty();



 170         Type type = tree.type();
 171         JType jt = owner.globalLookup(type);
 172         assert (jt != null);
 173         if (cw == global_cw) {
 174             String uniqueName = fieldName + "." + jt.getDescriptor();
 175             if (! global_fields.add(uniqueName)) {
 176                 return; // added already
 177             }
 178         }
 179         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, fieldName + "$get",
 180                 "()" + jt.getDescriptor(), "()" + jt.getSignature(), null);
 181 
 182         AnnotationVisitor av = mv.visitAnnotation(NATIVE_LOCATION, true);
 183         SourceLocation src = tree.location();
 184         SourceLocation.Location loc = src.getFileLocation();
 185         Path p = loc.path();
 186         av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
 187         av.visit("line", loc.line());
 188         av.visit("column", loc.column());
 189         av.visit("USR", tree.USR());


 214     }
 215 
 216     private void addConstant(ClassVisitor cw, FieldTree fieldTree) {
 217         assert (fieldTree.isEnumConstant());
 218         String name = fieldTree.name();
 219         String desc = owner.globalLookup(fieldTree.type()).getDescriptor();
 220         Object value = null;
 221         switch (desc) {
 222             case "J":
 223                 value = fieldTree.enumConstant().get();
 224                 break;
 225             case "I":
 226                 value = fieldTree.enumConstant().get().intValue();
 227                 break;
 228         }
 229         cw.visitField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC, name, desc, null, value);
 230     }
 231 
 232     @Override
 233     public Void visitStruct(StructTree structTree, JType jt) {
 234         String nativeName = structTree.name();
 235         Type type = structTree.type();
 236         logger.fine(() -> "Create struct: " + nativeName);
 237 
 238         String intf = Utils.toClassName(nativeName);
 239         String name = internal_name + "$" + intf;
 240 
 241         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 242         /* FIXME: Member interface is implicit static, also ASM.CheckClassAdapter is not
 243          * taking static as a valid flag, so comment this out during development.
 244          */
 245         global_cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
 246         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 247         cw.visit(V1_8, ACC_PUBLIC /*| ACC_STATIC*/ | ACC_INTERFACE | ACC_ABSTRACT,
 248                 name, "Ljava/lang/Object;Ljava/foreign/memory/Struct<L" + name + ";>;",
 249                 "java/lang/Object", new String[] {"java/foreign/memory/Struct"});
 250         annotateNativeLocation(cw, structTree);
 251 
 252         AnnotationVisitor av = cw.visitAnnotation(NATIVE_STRUCT, true);
 253         Layout structLayout = structTree.layout(this::decorateAsAccessor);
 254         av.visit("value", structLayout.toString());


 285         }
 286         return layout;
 287     }
 288 
 289     @Override
 290     public Void visitEnum(EnumTree enumTree, JType jt) {
 291         // define enum constants in global_cw
 292         enumTree.constants().forEach(constant -> addConstant(global_cw, constant));
 293 
 294         if (enumTree.name().isEmpty()) {
 295             // We are done with anonymous enum
 296             return null;
 297         }
 298 
 299         // generate annotation class for named enum
 300         createAnnotationCls(enumTree);
 301         return null;
 302     }
 303 
 304     private void createAnnotationCls(Tree tree) {
 305         String nativeName = tree.name();
 306         logger.fine(() -> "Create annotation for: " + nativeName);
 307 
 308         String intf = Utils.toClassName(nativeName);
 309         String name = internal_name + "$" + intf;
 310 
 311         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 312         global_cw.visitInnerClass(name, internal_name, intf,
 313                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 314         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 315         String[] superAnno = { "java/lang/annotation/Annotation" };
 316         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION,
 317                 name, null, "java/lang/Object", superAnno);
 318         annotateNativeLocation(cw, tree);
 319         Type type = tree.type().canonicalType();
 320         AnnotationVisitor av = cw.visitAnnotation("Ljava/lang/annotation/Target;", true);
 321         av.visitEnum("value", "Ljava/lang/annotation/ElementType;", "TYPE_USE");
 322         av.visitEnd();
 323         av = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
 324         av.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
 325         av.visitEnd();
 326         cw.visitInnerClass(name, internal_name, intf,
 327                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 328         // Write class
 329         try {
 330             writeClassFile(cw, owner.clsName + "$" + intf);
 331         } catch (IOException ex) {
 332             handleException(ex);
 333         }
 334     }
 335 
 336     private void createFunctionalInterface(Tree tree, JType.FnIf fnif) {
 337         JType.Function fn = fnif.getFunction();
 338         String intf;
 339         String nativeName;
 340         String nDesc = fnif.getFunction().getNativeDescriptor();
 341         if (tree == null) {
 342             intf = ((JType.InnerType) fnif.type).getName();
 343             nativeName = "anonymous function";
 344         } else {
 345             nativeName = tree.name();
 346             intf = Utils.toClassName(nativeName);
 347         }
 348         logger.fine(() -> "Create FunctionalInterface " + intf);
 349 
 350         final String name = internal_name + "$" + intf;
 351 
 352         logger.fine(() -> "Define class " + name + " for native type " + nativeName + nDesc);
 353         global_cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
 354         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 355         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE,
 356                 name, "Ljava/lang/Object;",
 357                 "java/lang/Object", new String[0]);
 358         if (tree != null) {
 359             annotateNativeLocation(cw, tree);
 360         }
 361         AnnotationVisitor av = cw.visitAnnotation(
 362                 "Ljava/lang/FunctionalInterface;", true);
 363         av.visitEnd();
 364         av = cw.visitAnnotation(NATIVE_CALLBACK, true);
 365         av.visit("value", nDesc);


 368 
 369         // add the method
 370 
 371         int flags = ACC_PUBLIC | ACC_ABSTRACT;
 372         if (fn.isVarArgs) {
 373             flags |= ACC_VARARGS;
 374         }
 375         MethodVisitor mv = cw.visitMethod(flags, "fn",
 376                 fn.getDescriptor(), fn.getSignature(), null);
 377         mv.visitEnd();
 378         // Write class
 379         try {
 380             writeClassFile(cw, owner.clsName + "$" + intf);
 381         } catch (IOException ex) {
 382             handleException(ex);
 383         }
 384     }
 385 
 386     @Override
 387     public Void visitTypedef(TypedefTree typedefTree, JType jt) {







 388         // anonymous typedef struct {} xxx will not get TypeAlias
 389         if (jt instanceof TypeAlias) {
 390             TypeAlias alias = (TypeAlias) jt;
 391             if (alias.getAnnotationDescriptor() != null) {
 392                 createAnnotationCls(typedefTree);
 393             } else {
 394                 JType real = alias.canonicalType();
 395                 if (real instanceof JType.FnIf) {
 396                     createFunctionalInterface(typedefTree, (JType.FnIf) real);
 397                 }
 398                 // Otherwise, type alias is a same named stuct
 399             }
 400         }
 401         return null;
 402     }
 403 
 404     @Override
 405     public Void visitTree(Tree tree, JType jt) {
 406         logger.warning(() -> "Unsupported declaration tree:");
 407         logger.warning(() -> tree.toString());


< prev index next >