< prev index next >

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

Print this page




  24 
  25 import jdk.internal.clang.*;
  26 import jdk.internal.clang.Type;
  27 import jdk.internal.org.objectweb.asm.*;
  28 
  29 import java.io.IOException;
  30 import java.nio.file.Path;
  31 import java.nio.file.Paths;
  32 import java.util.Collections;
  33 import java.util.HashMap;
  34 import java.util.HashSet;
  35 import java.util.Map;
  36 import java.util.logging.Logger;
  37 
  38 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  39 
  40 /**
  41  * Scan a header file and generate classes for entities defined in that header
  42  * file.
  43  */
  44 public class AsmCodeFactory extends CodeFactory {
  45     final ClassWriter global_cw;
  46     final String internal_name;
  47     final HeaderFile owner;
  48     final Map<String, byte[]> types;
  49     final HashSet<String> handledMacros = new HashSet<>();
  50     final Logger logger = Logger.getLogger(getClass().getPackage().getName());

  51 
  52     public AsmCodeFactory(HeaderFile header) {

  53         logger.info(() -> "Instantiate AsmCodeFactory for " + header.path);
  54         owner = header;
  55         internal_name = Utils.toInternalName(owner.pkgName, owner.clsName);
  56         global_cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
  57         types = new HashMap<>();
  58         init();
  59     }
  60 
  61     private void init() {
  62         global_cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE,
  63                 internal_name,
  64                 null, "java/lang/Object", null);
  65         AnnotationVisitor av = global_cw.visitAnnotation(
  66                 "Ljava/nicl/metadata/Header;", true);
  67         av.visit("path", owner.path.toAbsolutePath().toString());
  68         av.visitEnd();
  69         if (owner.libraries != null && !owner.libraries.isEmpty()) {
  70             AnnotationVisitor deps = global_cw.visitAnnotation(
  71                 "Ljava/nicl/metadata/LibraryDependencies;", true);
  72             AnnotationVisitor libNames = deps.visitArray("names");
  73             for (String name : owner.libraries) {
  74                 libNames.visit(null, name);
  75             }
  76             libNames.visitEnd();
  77             if (owner.libraryPaths != null && !owner.libraryPaths.isEmpty()) {
  78                 AnnotationVisitor libPaths = deps.visitArray("paths");
  79                 for (String path : owner.libraryPaths) {
  80                     libPaths.visit(null, path);
  81                 }
  82                 libPaths.visitEnd();
  83             }
  84             deps.visitEnd();
  85         }
  86     }
  87 
  88     private void handleException(Exception ex) {
  89         Context.getInstance().err.println(Main.format("cannot.write.class.file", owner.pkgName + "." + owner.clsName, ex));
  90         if (Main.DEBUG) {
  91             ex.printStackTrace(Context.getInstance().err);
  92         }
  93     }
  94 
  95     private void annotateC(ClassVisitor cw, Cursor dcl) {
  96         AnnotationVisitor av = cw.visitAnnotation(
  97                 "Ljava/nicl/metadata/C;", true);
  98         SourceLocation src = dcl.getSourceLocation();
  99         SourceLocation.Location loc = src.getFileLocation();
 100         Path p = loc.path();
 101         av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
 102         av.visit("line", loc.line());
 103         av.visit("column", loc.column());
 104         av.visit("USR", dcl.USR());
 105         av.visitEnd();
 106     }
 107 
 108     private void writeClassFile(final ClassWriter cw, String clsName)
 109             throws IOException {
 110         cw.visitEnd();
 111         byte[] bytecodes = cw.toByteArray();


 480             logger.finest(() -> "  return type is an alias " + alias);
 481             if (alias.getAnnotationDescriptor() != null) {
 482                 mv.visitTypeAnnotation(
 483                         TypeReference.newTypeReference(TypeReference.METHOD_RETURN).getValue(),
 484                         null, alias.getAnnotationDescriptor(), true)
 485                   .visitEnd();
 486             }
 487         }
 488         mv.visitEnd();
 489     }
 490 
 491     @Override
 492     protected CodeFactory addType(JType jt, Cursor cursor) {
 493         JType2 jt2 = null;
 494         if (jt instanceof JType2) {
 495             jt2 = (JType2) jt;
 496             jt = jt2.getDelegate();
 497         } else {
 498             logger.warning(() -> "Should have JType2 in addType");
 499             if (Main.DEBUG) {
 500                 new Throwable().printStackTrace(Context.getInstance().err);
 501             }
 502         }
 503         if (cursor == null) {
 504             assert (jt2 != null);
 505             if (jt instanceof JType.FnIf) {
 506                 createFunctionalInterface(jt2);
 507             }
 508             return this;
 509         }
 510 
 511         try {
 512             logger.fine(() -> "Process cursor " + cursor.spelling());
 513             switch (cursor.kind()) {
 514                 case StructDecl:
 515                     createStruct(cursor);
 516                     break;
 517                 case FunctionDecl:
 518                     assert (jt instanceof JType.Function);
 519                     addMethod(cursor, (JType.Function) jt);
 520                     break;


 728     protected Map<String, byte[]> collect() {
 729         // Ensure classes are produced
 730         produce();
 731         HashMap<String, byte[]> rv = new HashMap<>();
 732         // Not copying byte[] for efficiency, perhaps not a safe idea though
 733         if (owner.pkgName.isEmpty()) {
 734             types.forEach((clsName, bytecodes) -> {
 735                 rv.put(clsName, bytecodes);
 736             });
 737         } else {
 738             types.forEach((clsName, bytecodes) -> {
 739                 rv.put(owner.pkgName + "." + clsName, bytecodes);
 740             });
 741         }
 742         return Collections.unmodifiableMap(rv);
 743     }
 744 
 745     public static void main(String[] args) throws IOException {
 746         final Path file = Paths.get(args[1]);
 747         final String pkg = args[0];
 748         Context ctx = Context.getInstance();
 749         ctx.usePackageForFolder(file, pkg);
 750         ctx.usePackageForFolder(Paths.get("/usr/include"), "system");
 751         ctx.sources.add(file);
 752         ctx.parse(AsmCodeFactory::new);
 753         ctx.collectJarFile(Paths.get(args[2]), pkg);
 754     }
 755 
 756 }


  24 
  25 import jdk.internal.clang.*;
  26 import jdk.internal.clang.Type;
  27 import jdk.internal.org.objectweb.asm.*;
  28 
  29 import java.io.IOException;
  30 import java.nio.file.Path;
  31 import java.nio.file.Paths;
  32 import java.util.Collections;
  33 import java.util.HashMap;
  34 import java.util.HashSet;
  35 import java.util.Map;
  36 import java.util.logging.Logger;
  37 
  38 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  39 
  40 /**
  41  * Scan a header file and generate classes for entities defined in that header
  42  * file.
  43  */
  44 final class AsmCodeFactory extends CodeFactory {
  45     private final Context ctx;
  46     private final ClassWriter global_cw;
  47     private final String internal_name;
  48     private final HeaderFile owner;
  49     private final Map<String, byte[]> types;
  50     private final HashSet<String> handledMacros = new HashSet<>();
  51     private final Logger logger = Logger.getLogger(getClass().getPackage().getName());
  52 
  53     AsmCodeFactory(Context ctx, HeaderFile header) {
  54         this.ctx = ctx;
  55         logger.info(() -> "Instantiate AsmCodeFactory for " + header.path);
  56         this.owner = header;
  57         this.internal_name = Utils.toInternalName(owner.pkgName, owner.clsName);
  58         this.global_cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
  59         this.types = new HashMap<>();
  60         init();
  61     }
  62 
  63     private void init() {
  64         global_cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE,
  65                 internal_name,
  66                 null, "java/lang/Object", null);
  67         AnnotationVisitor av = global_cw.visitAnnotation(
  68                 "Ljava/nicl/metadata/Header;", true);
  69         av.visit("path", owner.path.toAbsolutePath().toString());
  70         av.visitEnd();
  71         if (owner.libraries != null && !owner.libraries.isEmpty()) {
  72             AnnotationVisitor deps = global_cw.visitAnnotation(
  73                 "Ljava/nicl/metadata/LibraryDependencies;", true);
  74             AnnotationVisitor libNames = deps.visitArray("names");
  75             for (String name : owner.libraries) {
  76                 libNames.visit(null, name);
  77             }
  78             libNames.visitEnd();
  79             if (owner.libraryPaths != null && !owner.libraryPaths.isEmpty()) {
  80                 AnnotationVisitor libPaths = deps.visitArray("paths");
  81                 for (String path : owner.libraryPaths) {
  82                     libPaths.visit(null, path);
  83                 }
  84                 libPaths.visitEnd();
  85             }
  86             deps.visitEnd();
  87         }
  88     }
  89 
  90     private void handleException(Exception ex) {
  91         ctx.err.println(Main.format("cannot.write.class.file", owner.pkgName + "." + owner.clsName, ex));
  92         if (Main.DEBUG) {
  93             ex.printStackTrace(ctx.err);
  94         }
  95     }
  96 
  97     private void annotateC(ClassVisitor cw, Cursor dcl) {
  98         AnnotationVisitor av = cw.visitAnnotation(
  99                 "Ljava/nicl/metadata/C;", true);
 100         SourceLocation src = dcl.getSourceLocation();
 101         SourceLocation.Location loc = src.getFileLocation();
 102         Path p = loc.path();
 103         av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
 104         av.visit("line", loc.line());
 105         av.visit("column", loc.column());
 106         av.visit("USR", dcl.USR());
 107         av.visitEnd();
 108     }
 109 
 110     private void writeClassFile(final ClassWriter cw, String clsName)
 111             throws IOException {
 112         cw.visitEnd();
 113         byte[] bytecodes = cw.toByteArray();


 482             logger.finest(() -> "  return type is an alias " + alias);
 483             if (alias.getAnnotationDescriptor() != null) {
 484                 mv.visitTypeAnnotation(
 485                         TypeReference.newTypeReference(TypeReference.METHOD_RETURN).getValue(),
 486                         null, alias.getAnnotationDescriptor(), true)
 487                   .visitEnd();
 488             }
 489         }
 490         mv.visitEnd();
 491     }
 492 
 493     @Override
 494     protected CodeFactory addType(JType jt, Cursor cursor) {
 495         JType2 jt2 = null;
 496         if (jt instanceof JType2) {
 497             jt2 = (JType2) jt;
 498             jt = jt2.getDelegate();
 499         } else {
 500             logger.warning(() -> "Should have JType2 in addType");
 501             if (Main.DEBUG) {
 502                 new Throwable().printStackTrace(ctx.err);
 503             }
 504         }
 505         if (cursor == null) {
 506             assert (jt2 != null);
 507             if (jt instanceof JType.FnIf) {
 508                 createFunctionalInterface(jt2);
 509             }
 510             return this;
 511         }
 512 
 513         try {
 514             logger.fine(() -> "Process cursor " + cursor.spelling());
 515             switch (cursor.kind()) {
 516                 case StructDecl:
 517                     createStruct(cursor);
 518                     break;
 519                 case FunctionDecl:
 520                     assert (jt instanceof JType.Function);
 521                     addMethod(cursor, (JType.Function) jt);
 522                     break;


 730     protected Map<String, byte[]> collect() {
 731         // Ensure classes are produced
 732         produce();
 733         HashMap<String, byte[]> rv = new HashMap<>();
 734         // Not copying byte[] for efficiency, perhaps not a safe idea though
 735         if (owner.pkgName.isEmpty()) {
 736             types.forEach((clsName, bytecodes) -> {
 737                 rv.put(clsName, bytecodes);
 738             });
 739         } else {
 740             types.forEach((clsName, bytecodes) -> {
 741                 rv.put(owner.pkgName + "." + clsName, bytecodes);
 742             });
 743         }
 744         return Collections.unmodifiableMap(rv);
 745     }
 746 
 747     public static void main(String[] args) throws IOException {
 748         final Path file = Paths.get(args[1]);
 749         final String pkg = args[0];
 750         Context ctx = new Context();
 751         ctx.usePackageForFolder(file, pkg);
 752         ctx.usePackageForFolder(Paths.get("/usr/include"), "system");
 753         ctx.addSource(file);
 754         ctx.parse();
 755         ctx.collectJarFile(Paths.get(args[2]), pkg);
 756     }

 757 }
< prev index next >