1 /*
  2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package jdk.internal.jextract.impl;
 26 
 27 import jdk.incubator.foreign.MemoryLayout;
 28 import jdk.incubator.foreign.ValueLayout;
 29 import jdk.incubator.jextract.Declaration;
 30 import jdk.incubator.jextract.Type;
 31 
 32 import java.nio.ByteOrder;
 33 
 34 /*
 35  * Layouts for the primitive types not supported by ABI implementations.
 36  */
 37 public final class UnsupportedLayouts {
 38     private UnsupportedLayouts() {}
 39 
 40     public static final MemoryLayout __INT128 = makeUnsupportedLayout(128, "__int128");
 41 
 42     public static final MemoryLayout LONG_DOUBLE = makeUnsupportedLayout(128, "long double");
 43 
 44     public static final MemoryLayout _FLOAT128 = makeUnsupportedLayout(128, "_float128");
 45 
 46     public static final MemoryLayout __FP16 = makeUnsupportedLayout(16, "__fp16");
 47 
 48     public static final MemoryLayout CHAR16 = makeUnsupportedLayout(16, "char16");
 49 
 50     public static final MemoryLayout WCHAR_T = makeUnsupportedLayout(16, "wchar_t");
 51 
 52     static String firstUnsupportedType(Type type) {
 53         return type.accept(unsupportedVisitor, null);
 54     }
 55 
 56     private static MemoryLayout makeUnsupportedLayout(long size, String name) {
 57         return MemoryLayout.paddingLayout(size).withBitAlignment(size).withName(name);
 58     }
 59 
 60     static Type.Visitor<String, Void> unsupportedVisitor = new Type.Visitor<>() {
 61         @Override
 62         public String visitPrimitive(Type.Primitive t, Void unused) {
 63             MemoryLayout layout = t.kind().layout().orElse(MemoryLayout.paddingLayout(64));
 64             if (layout.equals(__INT128) || layout.equals(LONG_DOUBLE) || layout.equals(_FLOAT128) || layout.equals(__FP16)) {
 65                 return layout.name().get();
 66             } else {
 67                 return null;
 68             }
 69         }
 70 
 71         @Override
 72         public String visitFunction(Type.Function t, Void unused) {
 73             for (Type arg : t.argumentTypes()) {
 74                 String unsupported = firstUnsupportedType(arg);
 75                 if (unsupported != null) {
 76                     return unsupported;
 77                 }
 78             }
 79             String unsupported = firstUnsupportedType(t.returnType());
 80             if (unsupported != null) {
 81                 return unsupported;
 82             }
 83             return null;
 84         }
 85 
 86         @Override
 87         public String visitDeclared(Type.Declared t, Void unused) {
 88             for (Declaration d : t.tree().members()) {
 89                 if (d instanceof Declaration.Variable) {
 90                     String unsupported = firstUnsupportedType(((Declaration.Variable) d).type());
 91                     if (unsupported != null) {
 92                         return unsupported;
 93                     }
 94                 }
 95             }
 96             return null;
 97         }
 98 
 99         @Override
100         public String visitDelegated(Type.Delegated t, Void unused) {
101             return t.kind() == Type.Delegated.Kind.TYPEDEF ?
102                     firstUnsupportedType(t.type()) :
103                     null;
104             //in principle we should always do this:
105             // return firstUnsupportedType(t.type());
106             // but if we do that, we might end up with infinite recursion. Old code did not have that issue
107             // as it was layout-based, but doing so it also missed unsupported pointer types (e.g. *long double)
108         }
109 
110         @Override
111         public String visitArray(Type.Array t, Void unused) {
112             return firstUnsupportedType(t.elementType());
113         }
114 
115         @Override
116         public String visitType(Type t, Void unused) {
117             return null;
118         }
119     };
120 }