< prev index next >

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

Print this page




  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     }
  70 







  71     private void annotateC(ClassVisitor cw, Cursor dcl) {
  72         AnnotationVisitor av = cw.visitAnnotation(
  73                 "Ljava/nicl/metadata/C;", true);
  74         SourceLocation src = dcl.getSourceLocation();
  75         SourceLocation.Location loc = src.getFileLocation();
  76         Path p = loc.path();
  77         av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
  78         av.visit("line", loc.line());
  79         av.visit("column", loc.column());
  80         av.visit("USR", dcl.USR());
  81         av.visitEnd();
  82     }
  83 
  84     private void writeClassFile(final ClassWriter cw, String clsName)
  85             throws IOException {
  86         cw.visitEnd();
  87         byte[] bytecodes = cw.toByteArray();
  88         types.put(clsName, bytecodes);
  89     }
  90 


 186                 "java/lang/Object", new String[] {"java/nicl/types/Reference"});
 187         annotateC(cw, cursor);
 188         AnnotationVisitor av = cw.visitAnnotation(
 189                 "Ljava/nicl/metadata/NativeType;", true);
 190         av.visit("layout", Utils.getLayout(t));
 191         av.visit("ctype", t.spelling());
 192         av.visit("size", t.size());
 193         av.visit("isRecordType", true);
 194         av.visitEnd();
 195         cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
 196 
 197         // fields
 198         Printer dbg = new Printer();
 199         cursor.stream()
 200                 .filter(cx -> cx.kind() == CursorKind.FieldDecl)
 201                 .forEachOrdered(cx -> addField(cw, cx, cursor.type()));
 202         // Write class
 203         try {
 204             writeClassFile(cw, owner.clsName + "$" + intf);
 205         } catch (IOException ex) {
 206             ex.printStackTrace(System.err);
 207         }
 208     }
 209 
 210     private void createEnum(Cursor cursor) {
 211         String nativeName = Utils.getIdentifier(cursor);
 212         logger.fine(() -> "create enum: " + nativeName);
 213 
 214         String intf = Utils.toClassName(nativeName);
 215         String name = internal_name + "$" + intf;
 216 
 217         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 218         global_cw.visitInnerClass(name, internal_name, intf,
 219                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 220         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 221         String[] superAnno = { "java/lang/annotation/Annotation" };
 222         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION,
 223                 name, null, "java/lang/Object", superAnno);
 224         annotateC(cw, cursor);
 225         AnnotationVisitor av = cw.visitAnnotation(
 226                 "Ljava/nicl/metadata/NativeType;", true);


 229         av.visit("ctype", t.spelling());
 230         av.visit("size", t.size());
 231         av.visitEnd();
 232 
 233         av = cw.visitAnnotation("Ljava/lang/annotation/Target;", true);
 234         av.visitEnum("value", "Ljava/lang/annotation/ElementType;", "TYPE_USE");
 235         av.visitEnd();
 236         av = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
 237         av.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
 238         av.visitEnd();
 239         cw.visitInnerClass(name, internal_name, intf,
 240                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 241         // constants
 242         cursor.stream()
 243                 .filter(cx -> cx.kind() == CursorKind.EnumConstantDecl)
 244                 .forEachOrdered(cx -> addConstant(cw, cx));
 245         // Write class
 246         try {
 247             writeClassFile(cw, owner.clsName + "$" + intf);
 248         } catch (IOException ex) {
 249             ex.printStackTrace(System.err);
 250         }
 251     }
 252 
 253     private void createAnnotationCls(Cursor dcl) {
 254         String nativeName = Utils.getIdentifier(dcl);
 255         logger.fine(() -> "Create annotation for: " + nativeName);
 256 
 257         String intf = Utils.toClassName(nativeName);
 258         String name = internal_name + "$" + intf;
 259 
 260         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 261         global_cw.visitInnerClass(name, internal_name, intf,
 262                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 263         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 264         String[] superAnno = { "java/lang/annotation/Annotation" };
 265         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION,
 266                 name, null, "java/lang/Object", superAnno);
 267         annotateC(cw, dcl);
 268         Type t = dcl.type().canonicalType();
 269         AnnotationVisitor av = cw.visitAnnotation(
 270                 "Ljava/nicl/metadata/NativeType;", true);
 271         av.visit("layout", Utils.getLayout(t));
 272         av.visit("ctype", t.spelling());
 273         av.visit("size", t.size());
 274         av.visitEnd();
 275 
 276         av = cw.visitAnnotation("Ljava/lang/annotation/Target;", true);
 277         av.visitEnum("value", "Ljava/lang/annotation/ElementType;", "TYPE_USE");
 278         av.visitEnd();
 279         av = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
 280         av.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
 281         av.visitEnd();
 282         cw.visitInnerClass(name, internal_name, intf,
 283                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 284         // Write class
 285         try {
 286             writeClassFile(cw, owner.clsName + "$" + intf);
 287         } catch (IOException ex) {
 288             ex.printStackTrace(System.err);
 289         }
 290     }
 291 
 292     private void createFunctionalInterface(JType2 jt2) {
 293         JType.FnIf fnif = (JType.FnIf) jt2.getDelegate();
 294         JType.Function fn = fnif.getFunction();
 295         String intf = ((JType.InnerType) fnif.type).getName();
 296         logger.fine(() -> "Create FunctionalInterface " + intf);
 297         String nDesc = jt2.getNativeDescriptor();
 298 
 299         final String name = internal_name + "$" + intf;
 300 
 301         logger.fine(() -> "Define class " + name + " for anonymous function " + nDesc);
 302         global_cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
 303         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 304         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE,
 305                 name, null, "java/lang/Object", null);
 306         AnnotationVisitor av = cw.visitAnnotation(
 307                 "Ljava/lang/FunctionalInterface;", true);
 308         av.visitEnd();


 311         // add the method
 312         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "fn",
 313                 fn.getDescriptor(), fn.getSignature(), null);
 314         av = mv.visitAnnotation(
 315                 "Ljava/nicl/metadata/NativeType;", true);
 316         av.visit("layout", nDesc);
 317         av.visit("ctype", "N/A");
 318         av.visit("size", -1);
 319         av.visitEnd();
 320         // FIXME: We need calling convention
 321         av = mv.visitAnnotation(
 322                 "Ljava/nicl/metadata/CallingConvention;", true);
 323         av.visit("value", jt2.getCallingConvention());
 324         av.visitEnd();
 325 
 326         mv.visitEnd();
 327         // Write class
 328         try {
 329             writeClassFile(cw, owner.clsName + "$" + intf);
 330         } catch (IOException ex) {
 331             ex.printStackTrace(System.err);
 332         }
 333     }
 334 
 335     private void createFunctionalInterface(Cursor dcl, JType.FnIf fnif) {
 336         JType.Function fn = fnif.getFunction();
 337         String intf;
 338         String nativeName;
 339         if (dcl == null) {
 340             intf = ((JType.InnerType) fnif.type).getName();
 341             nativeName = "N/A";
 342         } else {
 343             nativeName = Utils.getIdentifier(dcl);
 344             intf = Utils.toClassName(nativeName);
 345         }
 346         logger.fine(() -> "Create FunctionalInterface " + intf);
 347 
 348         final String name = internal_name + "$" + intf;
 349 
 350         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 351         global_cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);


 364         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "fn",
 365                 fn.getDescriptor(), fn.getSignature(), null);
 366         if (dcl != null) {
 367             av = mv.visitAnnotation(
 368                     "Ljava/nicl/metadata/NativeType;", true);
 369             Type t = dcl.type().canonicalType();
 370             av.visit("layout", Utils.getLayout(t));
 371             av.visit("ctype", t.spelling());
 372             av.visit("size", t.size());
 373             av.visitEnd();
 374             av = mv.visitAnnotation(
 375                     "Ljava/nicl/metadata/CallingConvention;", true);
 376             av.visit("value", t.getCallingConvention().value());
 377             av.visitEnd();
 378         }
 379         mv.visitEnd();
 380         // Write class
 381         try {
 382             writeClassFile(cw, owner.clsName + "$" + intf);
 383         } catch (IOException ex) {
 384             ex.printStackTrace(System.err);
 385         }
 386     }
 387 
 388     private void defineType(Cursor dcl, TypeAlias alias) {
 389         if (alias.getAnnotationDescriptor() != null) {
 390             createAnnotationCls(dcl);
 391         } else {
 392             JType real = alias.canonicalType();
 393             if (real instanceof JType.FnIf) {
 394                 createFunctionalInterface(dcl, (JType.FnIf) real);
 395             }
 396             // Otherwise, type alias is a same named stuct
 397         }
 398     }
 399 
 400     private void addMethod(Cursor dcl, JType.Function fn) {
 401         logger.fine(() -> "Add method: " + fn.getSignature());
 402         int flags = ACC_PUBLIC | ACC_ABSTRACT;
 403         if (fn.isVarArgs) {
 404             flags |= ACC_VARARGS;


 455             TypeAlias alias = (TypeAlias) fn.returnType;
 456             logger.finest(() -> "  return type is an alias " + alias);
 457             if (alias.getAnnotationDescriptor() != null) {
 458                 mv.visitTypeAnnotation(
 459                         TypeReference.newTypeReference(TypeReference.METHOD_RETURN).getValue(),
 460                         null, alias.getAnnotationDescriptor(), true)
 461                   .visitEnd();
 462             }
 463         }
 464         mv.visitEnd();
 465     }
 466 
 467     @Override
 468     protected CodeFactory addType(JType jt, Cursor cursor) {
 469         JType2 jt2 = null;
 470         if (jt instanceof JType2) {
 471             jt2 = (JType2) jt;
 472             jt = jt2.getDelegate();
 473         } else {
 474             logger.warning(() -> "Should have JType2 in addType");

 475             new Throwable().printStackTrace(System.err);
 476         }

 477         if (cursor == null) {
 478             assert (jt2 != null);
 479             if (jt instanceof JType.FnIf) {
 480                 createFunctionalInterface(jt2);
 481             }
 482             return this;
 483         }
 484 
 485         try {
 486             logger.fine(() -> "Process cursor " + cursor.spelling());
 487             switch (cursor.kind()) {
 488                 case StructDecl:
 489                     createStruct(cursor);
 490                     break;
 491                 case FunctionDecl:
 492                     assert (jt instanceof JType.Function);
 493                     addMethod(cursor, (JType.Function) jt);
 494                     break;
 495                 case EnumDecl:
 496                     createEnum(cursor);
 497                     break;
 498                 case TypedefDecl:
 499                     // anonymous typedef struct {} xxx will not get TypeAlias
 500                     if (jt instanceof TypeAlias) {
 501                         defineType(cursor, (TypeAlias) jt);
 502                     }
 503                     break;
 504                 case VarDecl:
 505                     addField(global_cw, cursor, null);
 506                     break;
 507                 default:
 508                     logger.warning(() -> "Unsupported declaration Cursor:");
 509                     logger.fine(() -> Printer.Stringifier(p -> p.dumpCursor(cursor, true)));
 510                     break;
 511             }
 512         } catch (Exception ex) {
 513             ex.printStackTrace(System.err);
 514             logger.warning("Cursor causing above exception is: " + cursor.spelling());
 515             logger.fine(() -> Printer.Stringifier(p -> p.dumpCursor(cursor, true)));
 516         }
 517         return this;
 518     }
 519 
 520     private static class Literal {
 521         private enum Type {
 522             INT(int.class),
 523             LONG(long.class),
 524             STRING(String.class);
 525 
 526             private Class<?> c;
 527 
 528             Type(Class<?> c) {
 529                 this.c = c;
 530             }
 531 
 532             Class<?> getTypeClass() {
 533                 return c;


 677             case LONG:
 678                 mv.visitInsn(LRETURN);
 679                 break;
 680             case STRING:
 681                 mv.visitInsn(ARETURN);
 682                 break;
 683         }
 684         mv.visitMaxs(0, 0);
 685         mv.visitEnd();
 686 
 687         handledMacros.add(macroName);
 688 
 689         return this;
 690     }
 691 
 692     @Override
 693     protected void produce() {
 694         try {
 695             writeClassFile(global_cw, owner.clsName);
 696         } catch (IOException ex) {
 697             ex.printStackTrace(System.err);
 698         }
 699     }
 700 
 701     @Override
 702     protected Map<String, byte[]> collect() {
 703         // Ensure classes are produced
 704         produce();
 705         HashMap<String, byte[]> rv = new HashMap<>();
 706         // Not copying byte[] for efficiency, perhaps not a safe idea though
 707         if (owner.pkgName.isEmpty()) {
 708             types.forEach((clsName, bytecodes) -> {
 709                 rv.put(clsName, bytecodes);
 710             });
 711         } else {
 712             types.forEach((clsName, bytecodes) -> {
 713                 rv.put(owner.pkgName + "." + clsName, bytecodes);
 714             });
 715         }
 716         return Collections.unmodifiableMap(rv);
 717     }


  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     }
  70 
  71     private void handleException(Exception ex) {
  72         System.err.println(Main.format("cannot.write.class.file", owner.pkgName + "." + owner.clsName, ex));
  73         if (Main.DEBUG) {
  74             ex.printStackTrace(System.err);
  75         }
  76     }
  77 
  78     private void annotateC(ClassVisitor cw, Cursor dcl) {
  79         AnnotationVisitor av = cw.visitAnnotation(
  80                 "Ljava/nicl/metadata/C;", true);
  81         SourceLocation src = dcl.getSourceLocation();
  82         SourceLocation.Location loc = src.getFileLocation();
  83         Path p = loc.path();
  84         av.visit("file", p == null ? "builtin" : p.toAbsolutePath().toString());
  85         av.visit("line", loc.line());
  86         av.visit("column", loc.column());
  87         av.visit("USR", dcl.USR());
  88         av.visitEnd();
  89     }
  90 
  91     private void writeClassFile(final ClassWriter cw, String clsName)
  92             throws IOException {
  93         cw.visitEnd();
  94         byte[] bytecodes = cw.toByteArray();
  95         types.put(clsName, bytecodes);
  96     }
  97 


 193                 "java/lang/Object", new String[] {"java/nicl/types/Reference"});
 194         annotateC(cw, cursor);
 195         AnnotationVisitor av = cw.visitAnnotation(
 196                 "Ljava/nicl/metadata/NativeType;", true);
 197         av.visit("layout", Utils.getLayout(t));
 198         av.visit("ctype", t.spelling());
 199         av.visit("size", t.size());
 200         av.visit("isRecordType", true);
 201         av.visitEnd();
 202         cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
 203 
 204         // fields
 205         Printer dbg = new Printer();
 206         cursor.stream()
 207                 .filter(cx -> cx.kind() == CursorKind.FieldDecl)
 208                 .forEachOrdered(cx -> addField(cw, cx, cursor.type()));
 209         // Write class
 210         try {
 211             writeClassFile(cw, owner.clsName + "$" + intf);
 212         } catch (IOException ex) {
 213             handleException(ex);
 214         }
 215     }
 216 
 217     private void createEnum(Cursor cursor) {
 218         String nativeName = Utils.getIdentifier(cursor);
 219         logger.fine(() -> "create enum: " + nativeName);
 220 
 221         String intf = Utils.toClassName(nativeName);
 222         String name = internal_name + "$" + intf;
 223 
 224         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 225         global_cw.visitInnerClass(name, internal_name, intf,
 226                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 227         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 228         String[] superAnno = { "java/lang/annotation/Annotation" };
 229         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION,
 230                 name, null, "java/lang/Object", superAnno);
 231         annotateC(cw, cursor);
 232         AnnotationVisitor av = cw.visitAnnotation(
 233                 "Ljava/nicl/metadata/NativeType;", true);


 236         av.visit("ctype", t.spelling());
 237         av.visit("size", t.size());
 238         av.visitEnd();
 239 
 240         av = cw.visitAnnotation("Ljava/lang/annotation/Target;", true);
 241         av.visitEnum("value", "Ljava/lang/annotation/ElementType;", "TYPE_USE");
 242         av.visitEnd();
 243         av = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
 244         av.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
 245         av.visitEnd();
 246         cw.visitInnerClass(name, internal_name, intf,
 247                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 248         // constants
 249         cursor.stream()
 250                 .filter(cx -> cx.kind() == CursorKind.EnumConstantDecl)
 251                 .forEachOrdered(cx -> addConstant(cw, cx));
 252         // Write class
 253         try {
 254             writeClassFile(cw, owner.clsName + "$" + intf);
 255         } catch (IOException ex) {
 256             handleException(ex);
 257         }
 258     }
 259 
 260     private void createAnnotationCls(Cursor dcl) {
 261         String nativeName = Utils.getIdentifier(dcl);
 262         logger.fine(() -> "Create annotation for: " + nativeName);
 263 
 264         String intf = Utils.toClassName(nativeName);
 265         String name = internal_name + "$" + intf;
 266 
 267         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 268         global_cw.visitInnerClass(name, internal_name, intf,
 269                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 270         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 271         String[] superAnno = { "java/lang/annotation/Annotation" };
 272         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION,
 273                 name, null, "java/lang/Object", superAnno);
 274         annotateC(cw, dcl);
 275         Type t = dcl.type().canonicalType();
 276         AnnotationVisitor av = cw.visitAnnotation(
 277                 "Ljava/nicl/metadata/NativeType;", true);
 278         av.visit("layout", Utils.getLayout(t));
 279         av.visit("ctype", t.spelling());
 280         av.visit("size", t.size());
 281         av.visitEnd();
 282 
 283         av = cw.visitAnnotation("Ljava/lang/annotation/Target;", true);
 284         av.visitEnum("value", "Ljava/lang/annotation/ElementType;", "TYPE_USE");
 285         av.visitEnd();
 286         av = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
 287         av.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
 288         av.visitEnd();
 289         cw.visitInnerClass(name, internal_name, intf,
 290                 ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_ANNOTATION);
 291         // Write class
 292         try {
 293             writeClassFile(cw, owner.clsName + "$" + intf);
 294         } catch (IOException ex) {
 295             handleException(ex);
 296         }
 297     }
 298 
 299     private void createFunctionalInterface(JType2 jt2) {
 300         JType.FnIf fnif = (JType.FnIf) jt2.getDelegate();
 301         JType.Function fn = fnif.getFunction();
 302         String intf = ((JType.InnerType) fnif.type).getName();
 303         logger.fine(() -> "Create FunctionalInterface " + intf);
 304         String nDesc = jt2.getNativeDescriptor();
 305 
 306         final String name = internal_name + "$" + intf;
 307 
 308         logger.fine(() -> "Define class " + name + " for anonymous function " + nDesc);
 309         global_cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
 310         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
 311         cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE,
 312                 name, null, "java/lang/Object", null);
 313         AnnotationVisitor av = cw.visitAnnotation(
 314                 "Ljava/lang/FunctionalInterface;", true);
 315         av.visitEnd();


 318         // add the method
 319         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "fn",
 320                 fn.getDescriptor(), fn.getSignature(), null);
 321         av = mv.visitAnnotation(
 322                 "Ljava/nicl/metadata/NativeType;", true);
 323         av.visit("layout", nDesc);
 324         av.visit("ctype", "N/A");
 325         av.visit("size", -1);
 326         av.visitEnd();
 327         // FIXME: We need calling convention
 328         av = mv.visitAnnotation(
 329                 "Ljava/nicl/metadata/CallingConvention;", true);
 330         av.visit("value", jt2.getCallingConvention());
 331         av.visitEnd();
 332 
 333         mv.visitEnd();
 334         // Write class
 335         try {
 336             writeClassFile(cw, owner.clsName + "$" + intf);
 337         } catch (IOException ex) {
 338             handleException(ex);
 339         }
 340     }
 341 
 342     private void createFunctionalInterface(Cursor dcl, JType.FnIf fnif) {
 343         JType.Function fn = fnif.getFunction();
 344         String intf;
 345         String nativeName;
 346         if (dcl == null) {
 347             intf = ((JType.InnerType) fnif.type).getName();
 348             nativeName = "N/A";
 349         } else {
 350             nativeName = Utils.getIdentifier(dcl);
 351             intf = Utils.toClassName(nativeName);
 352         }
 353         logger.fine(() -> "Create FunctionalInterface " + intf);
 354 
 355         final String name = internal_name + "$" + intf;
 356 
 357         logger.fine(() -> "Define class " + name + " for native type " + nativeName);
 358         global_cw.visitInnerClass(name, internal_name, intf, ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);


 371         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, "fn",
 372                 fn.getDescriptor(), fn.getSignature(), null);
 373         if (dcl != null) {
 374             av = mv.visitAnnotation(
 375                     "Ljava/nicl/metadata/NativeType;", true);
 376             Type t = dcl.type().canonicalType();
 377             av.visit("layout", Utils.getLayout(t));
 378             av.visit("ctype", t.spelling());
 379             av.visit("size", t.size());
 380             av.visitEnd();
 381             av = mv.visitAnnotation(
 382                     "Ljava/nicl/metadata/CallingConvention;", true);
 383             av.visit("value", t.getCallingConvention().value());
 384             av.visitEnd();
 385         }
 386         mv.visitEnd();
 387         // Write class
 388         try {
 389             writeClassFile(cw, owner.clsName + "$" + intf);
 390         } catch (IOException ex) {
 391             handleException(ex);
 392         }
 393     }
 394 
 395     private void defineType(Cursor dcl, TypeAlias alias) {
 396         if (alias.getAnnotationDescriptor() != null) {
 397             createAnnotationCls(dcl);
 398         } else {
 399             JType real = alias.canonicalType();
 400             if (real instanceof JType.FnIf) {
 401                 createFunctionalInterface(dcl, (JType.FnIf) real);
 402             }
 403             // Otherwise, type alias is a same named stuct
 404         }
 405     }
 406 
 407     private void addMethod(Cursor dcl, JType.Function fn) {
 408         logger.fine(() -> "Add method: " + fn.getSignature());
 409         int flags = ACC_PUBLIC | ACC_ABSTRACT;
 410         if (fn.isVarArgs) {
 411             flags |= ACC_VARARGS;


 462             TypeAlias alias = (TypeAlias) fn.returnType;
 463             logger.finest(() -> "  return type is an alias " + alias);
 464             if (alias.getAnnotationDescriptor() != null) {
 465                 mv.visitTypeAnnotation(
 466                         TypeReference.newTypeReference(TypeReference.METHOD_RETURN).getValue(),
 467                         null, alias.getAnnotationDescriptor(), true)
 468                   .visitEnd();
 469             }
 470         }
 471         mv.visitEnd();
 472     }
 473 
 474     @Override
 475     protected CodeFactory addType(JType jt, Cursor cursor) {
 476         JType2 jt2 = null;
 477         if (jt instanceof JType2) {
 478             jt2 = (JType2) jt;
 479             jt = jt2.getDelegate();
 480         } else {
 481             logger.warning(() -> "Should have JType2 in addType");
 482             if (Main.DEBUG) {
 483                 new Throwable().printStackTrace(System.err);
 484             }
 485         }
 486         if (cursor == null) {
 487             assert (jt2 != null);
 488             if (jt instanceof JType.FnIf) {
 489                 createFunctionalInterface(jt2);
 490             }
 491             return this;
 492         }
 493 
 494         try {
 495             logger.fine(() -> "Process cursor " + cursor.spelling());
 496             switch (cursor.kind()) {
 497                 case StructDecl:
 498                     createStruct(cursor);
 499                     break;
 500                 case FunctionDecl:
 501                     assert (jt instanceof JType.Function);
 502                     addMethod(cursor, (JType.Function) jt);
 503                     break;
 504                 case EnumDecl:
 505                     createEnum(cursor);
 506                     break;
 507                 case TypedefDecl:
 508                     // anonymous typedef struct {} xxx will not get TypeAlias
 509                     if (jt instanceof TypeAlias) {
 510                         defineType(cursor, (TypeAlias) jt);
 511                     }
 512                     break;
 513                 case VarDecl:
 514                     addField(global_cw, cursor, null);
 515                     break;
 516                 default:
 517                     logger.warning(() -> "Unsupported declaration Cursor:");
 518                     logger.fine(() -> Printer.Stringifier(p -> p.dumpCursor(cursor, true)));
 519                     break;
 520             }
 521         } catch (Exception ex) {
 522             handleException(ex);
 523             logger.warning("Cursor causing above exception is: " + cursor.spelling());
 524             logger.fine(() -> Printer.Stringifier(p -> p.dumpCursor(cursor, true)));
 525         }
 526         return this;
 527     }
 528 
 529     private static class Literal {
 530         private enum Type {
 531             INT(int.class),
 532             LONG(long.class),
 533             STRING(String.class);
 534 
 535             private Class<?> c;
 536 
 537             Type(Class<?> c) {
 538                 this.c = c;
 539             }
 540 
 541             Class<?> getTypeClass() {
 542                 return c;


 686             case LONG:
 687                 mv.visitInsn(LRETURN);
 688                 break;
 689             case STRING:
 690                 mv.visitInsn(ARETURN);
 691                 break;
 692         }
 693         mv.visitMaxs(0, 0);
 694         mv.visitEnd();
 695 
 696         handledMacros.add(macroName);
 697 
 698         return this;
 699     }
 700 
 701     @Override
 702     protected void produce() {
 703         try {
 704             writeClassFile(global_cw, owner.clsName);
 705         } catch (IOException ex) {
 706             handleException(ex);
 707         }
 708     }
 709 
 710     @Override
 711     protected Map<String, byte[]> collect() {
 712         // Ensure classes are produced
 713         produce();
 714         HashMap<String, byte[]> rv = new HashMap<>();
 715         // Not copying byte[] for efficiency, perhaps not a safe idea though
 716         if (owner.pkgName.isEmpty()) {
 717             types.forEach((clsName, bytecodes) -> {
 718                 rv.put(clsName, bytecodes);
 719             });
 720         } else {
 721             types.forEach((clsName, bytecodes) -> {
 722                 rv.put(owner.pkgName + "." + clsName, bytecodes);
 723             });
 724         }
 725         return Collections.unmodifiableMap(rv);
 726     }
< prev index next >