< prev index next >

src/jdk.jextract/share/classes/com/sun/tools/jextract/tree/LayoutUtils.java

Print this page




  32 import java.foreign.layout.Unresolved;
  33 import java.foreign.layout.Value;
  34 import java.util.ArrayList;
  35 import java.util.List;
  36 import java.util.function.BiFunction;
  37 import java.util.stream.Collectors;
  38 import java.util.stream.Stream;
  39 import jdk.internal.clang.Cursor;
  40 import jdk.internal.clang.CursorKind;
  41 import jdk.internal.clang.SourceLocation;
  42 import jdk.internal.clang.Type;
  43 import jdk.internal.clang.TypeKind;
  44 import jdk.internal.foreign.memory.Types;
  45 
  46 /**
  47  * General Layout utility functions
  48  */
  49 public final class LayoutUtils {
  50     private LayoutUtils() {}
  51 
  52     public static String getIdentifier(Type type) {
  53         Cursor c = type.getDeclarationCursor();
  54         if (c.isInvalid()) {
  55             return type.spelling();
  56         }
  57         return getIdentifier(c);
  58     }
  59 
  60     static String getIdentifier(Cursor cursor) {





  61         // Use cursor name instead of type name, this way we don't have struct
  62         // or enum prefix
  63         String nativeName = cursor.spelling();
  64         if (nativeName.isEmpty()) {
  65             // This happens when a typedef an anonymous struct, i.e., typedef struct {} type;
  66             Type t = cursor.type();
  67             nativeName = t.spelling();
  68             if (nativeName.contains("::")) {
  69                 SourceLocation.Location loc = cursor.getSourceLocation().getFileLocation();
  70                 return "anon$"
  71                         + loc.path().getFileName().toString().replaceAll("\\.", "_")
  72                         + "$" + loc.offset();
  73             }
  74         }
  75 
  76         return nativeName;
  77     }
  78 
  79     private static boolean isFunction(Type clang_type) {
  80         switch (clang_type.kind()) {
  81             case Unexposed:
  82             case Typedef:
  83             case Elaborated:
  84                 return isFunction(clang_type.canonicalType());
  85             case FunctionProto:
  86             case FunctionNoProto:
  87                 return true;
  88             default:


 179 
 180     private static Address parsePointerInternal(Type pointeeType) {
 181         switch (pointeeType.kind()) {
 182             case Unexposed:
 183             case Typedef:
 184             case Elaborated:
 185                 return parsePointerInternal(pointeeType.canonicalType());
 186             case FunctionProto:
 187             case FunctionNoProto:
 188                 return Address.ofFunction(64, parseFunctionInternal(pointeeType));
 189             case Void:
 190                 return Address.ofVoid(64);
 191             default:
 192                 return Address.ofLayout(64, getLayout(pointeeType));
 193         }
 194     }
 195 
 196     private static Layout getRecordReferenceLayout(Type t) {
 197         //symbolic reference
 198         return Unresolved.of()
 199                 .withAnnotation(Layout.NAME, getIdentifier(t.canonicalType()));
 200     }
 201 
 202     static Layout getRecordLayout(Type t, BiFunction<Cursor, Layout, Layout> fieldMapper) {
 203         return getRecordLayoutInternal(0, t, t, fieldMapper);
 204     }
 205 
 206     private static Layout getRecordLayoutInternal(long offset, Type parent, Type t, BiFunction<Cursor, Layout, Layout> fieldMapper) {
 207         Cursor cu = t.getDeclarationCursor().getDefinition();
 208         if (cu.isInvalid()) {
 209             return getRecordReferenceLayout(t);
 210         }
 211         final boolean isUnion = cu.kind() == CursorKind.UnionDecl;
 212         Stream<Cursor> fieldTypes = cu.children()
 213                 .filter(cx -> cx.isAnonymousStruct() || cx.kind() == CursorKind.FieldDecl);
 214         List<Layout> fieldLayouts = new ArrayList<>();
 215         int pendingBitfieldStart = -1;
 216         long actualSize = 0L;
 217         for (Cursor c : fieldTypes.collect(Collectors.toList())) {
 218             boolean isBitfield = c.isBitField();
 219             if (isBitfield && c.getBitFieldWidth() == 0) continue;


 240             fieldLayouts.add(fieldLayout);
 241             long size = fieldSize(isUnion, c);
 242             if (isUnion) {
 243                 actualSize = Math.max(actualSize, size);
 244             } else {
 245                 offset += size;
 246                 actualSize += size;
 247             }
 248         }
 249         long expectedSize = t.size() * 8;
 250         if (actualSize < expectedSize) {
 251             fieldLayouts.add(Padding.of(expectedSize - actualSize));
 252         }
 253         if (pendingBitfieldStart >= 0) {
 254             //emit/replace bitfields
 255             replaceBitfields(fieldLayouts, pendingBitfieldStart);
 256         }
 257         Layout[] fields = fieldLayouts.toArray(new Layout[0]);
 258         Group g = isUnion ?
 259                 Group.union(fields) : Group.struct(fields);
 260         return g.withAnnotation(Layout.NAME, getIdentifier(cu));
 261     }
 262 
 263     private static Layout fieldLayout(boolean isUnion, Cursor c, BiFunction<Cursor, Layout, Layout> fieldMapper) {
 264         Layout layout = getLayout(c.type());
 265         if (c.isBitField()) {
 266             boolean isSigned = ((Value)layout).kind() == Value.Kind.INTEGRAL_SIGNED;
 267             Layout sublayout = isSigned ?
 268                     Value.ofSignedInt(c.getBitFieldWidth()) :
 269                     Value.ofUnsignedInt(c.getBitFieldWidth());
 270             sublayout = fieldMapper.apply(c, sublayout);
 271             return isUnion ?
 272                     bitfield((Value)layout, List.of(sublayout)) :
 273                     sublayout;
 274         } else {
 275             return fieldMapper.apply(c, layout);
 276         }
 277     }
 278 
 279     private static long fieldSize(boolean isUnion, Cursor c) {
 280         if (!c.isBitField() || isUnion) {




  32 import java.foreign.layout.Unresolved;
  33 import java.foreign.layout.Value;
  34 import java.util.ArrayList;
  35 import java.util.List;
  36 import java.util.function.BiFunction;
  37 import java.util.stream.Collectors;
  38 import java.util.stream.Stream;
  39 import jdk.internal.clang.Cursor;
  40 import jdk.internal.clang.CursorKind;
  41 import jdk.internal.clang.SourceLocation;
  42 import jdk.internal.clang.Type;
  43 import jdk.internal.clang.TypeKind;
  44 import jdk.internal.foreign.memory.Types;
  45 
  46 /**
  47  * General Layout utility functions
  48  */
  49 public final class LayoutUtils {
  50     private LayoutUtils() {}
  51 
  52     public static String getName(Type type) {
  53         Cursor c = type.getDeclarationCursor();
  54         if (c.isInvalid()) {
  55             return type.spelling();
  56         }
  57         return getName(c);
  58     }
  59 
  60     public static String getName(Tree tree) {
  61         String name = tree.name();
  62         return name.isEmpty()? getName(tree.cursor()) : name;
  63     }
  64 
  65     private static String getName(Cursor cursor) {
  66         // Use cursor name instead of type name, this way we don't have struct
  67         // or enum prefix
  68         String nativeName = cursor.spelling();
  69         if (nativeName.isEmpty()) {

  70             Type t = cursor.type();
  71             nativeName = t.spelling();
  72             if (nativeName.contains("::") || nativeName.contains(" ")) {
  73                 SourceLocation.Location loc = cursor.getSourceLocation().getFileLocation();
  74                 return "anon$"
  75                         + loc.path().getFileName().toString().replaceAll("\\.", "_")
  76                         + "$" + loc.offset();
  77             }
  78         }
  79 
  80         return nativeName;
  81     }
  82 
  83     private static boolean isFunction(Type clang_type) {
  84         switch (clang_type.kind()) {
  85             case Unexposed:
  86             case Typedef:
  87             case Elaborated:
  88                 return isFunction(clang_type.canonicalType());
  89             case FunctionProto:
  90             case FunctionNoProto:
  91                 return true;
  92             default:


 183 
 184     private static Address parsePointerInternal(Type pointeeType) {
 185         switch (pointeeType.kind()) {
 186             case Unexposed:
 187             case Typedef:
 188             case Elaborated:
 189                 return parsePointerInternal(pointeeType.canonicalType());
 190             case FunctionProto:
 191             case FunctionNoProto:
 192                 return Address.ofFunction(64, parseFunctionInternal(pointeeType));
 193             case Void:
 194                 return Address.ofVoid(64);
 195             default:
 196                 return Address.ofLayout(64, getLayout(pointeeType));
 197         }
 198     }
 199 
 200     private static Layout getRecordReferenceLayout(Type t) {
 201         //symbolic reference
 202         return Unresolved.of()
 203                 .withAnnotation(Layout.NAME, getName(t.canonicalType()));
 204     }
 205 
 206     static Layout getRecordLayout(Type t, BiFunction<Cursor, Layout, Layout> fieldMapper) {
 207         return getRecordLayoutInternal(0, t, t, fieldMapper);
 208     }
 209 
 210     private static Layout getRecordLayoutInternal(long offset, Type parent, Type t, BiFunction<Cursor, Layout, Layout> fieldMapper) {
 211         Cursor cu = t.getDeclarationCursor().getDefinition();
 212         if (cu.isInvalid()) {
 213             return getRecordReferenceLayout(t);
 214         }
 215         final boolean isUnion = cu.kind() == CursorKind.UnionDecl;
 216         Stream<Cursor> fieldTypes = cu.children()
 217                 .filter(cx -> cx.isAnonymousStruct() || cx.kind() == CursorKind.FieldDecl);
 218         List<Layout> fieldLayouts = new ArrayList<>();
 219         int pendingBitfieldStart = -1;
 220         long actualSize = 0L;
 221         for (Cursor c : fieldTypes.collect(Collectors.toList())) {
 222             boolean isBitfield = c.isBitField();
 223             if (isBitfield && c.getBitFieldWidth() == 0) continue;


 244             fieldLayouts.add(fieldLayout);
 245             long size = fieldSize(isUnion, c);
 246             if (isUnion) {
 247                 actualSize = Math.max(actualSize, size);
 248             } else {
 249                 offset += size;
 250                 actualSize += size;
 251             }
 252         }
 253         long expectedSize = t.size() * 8;
 254         if (actualSize < expectedSize) {
 255             fieldLayouts.add(Padding.of(expectedSize - actualSize));
 256         }
 257         if (pendingBitfieldStart >= 0) {
 258             //emit/replace bitfields
 259             replaceBitfields(fieldLayouts, pendingBitfieldStart);
 260         }
 261         Layout[] fields = fieldLayouts.toArray(new Layout[0]);
 262         Group g = isUnion ?
 263                 Group.union(fields) : Group.struct(fields);
 264         return g.withAnnotation(Layout.NAME, getName(cu));
 265     }
 266 
 267     private static Layout fieldLayout(boolean isUnion, Cursor c, BiFunction<Cursor, Layout, Layout> fieldMapper) {
 268         Layout layout = getLayout(c.type());
 269         if (c.isBitField()) {
 270             boolean isSigned = ((Value)layout).kind() == Value.Kind.INTEGRAL_SIGNED;
 271             Layout sublayout = isSigned ?
 272                     Value.ofSignedInt(c.getBitFieldWidth()) :
 273                     Value.ofUnsignedInt(c.getBitFieldWidth());
 274             sublayout = fieldMapper.apply(c, sublayout);
 275             return isUnion ?
 276                     bitfield((Value)layout, List.of(sublayout)) :
 277                     sublayout;
 278         } else {
 279             return fieldMapper.apply(c, layout);
 280         }
 281     }
 282 
 283     private static long fieldSize(boolean isUnion, Cursor c) {
 284         if (!c.isBitField() || isUnion) {


< prev index next >