1 /*
  2  * Copyright (c) 2020, 2023, 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 
 26 package java.lang.foreign;
 27 
 28 import java.lang.invoke.MethodHandle;
 29 import java.lang.invoke.MethodType;
 30 import java.util.Objects;
 31 import java.util.Optional;
 32 import java.util.List;
 33 
 34 import jdk.internal.foreign.FunctionDescriptorImpl;
 35 import jdk.internal.javac.PreviewFeature;
 36 
 37 /**
 38  * A function descriptor models the signature of a foreign function. A function descriptor is made up of zero or more
 39  * argument layouts, and zero or one return layout. A function descriptor is used to create
 40  * {@linkplain Linker#downcallHandle(MemorySegment, FunctionDescriptor, Linker.Option...) downcall method handles} and
 41  * {@linkplain Linker#upcallStub(MethodHandle, FunctionDescriptor, Arena, Linker.Option...) upcall stubs}.
 42  *
 43  * @implSpec
 44  * Implementing classes are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
 45  *
 46  * @see MemoryLayout
 47  * @since 19
 48  */
 49 @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
 50 public sealed interface FunctionDescriptor permits FunctionDescriptorImpl {
 51 
 52     /**
 53      * {@return the return layout (if any) of this function descriptor}
 54      */
 55     Optional<MemoryLayout> returnLayout();
 56 
 57     /**
 58      * {@return the argument layouts of this function descriptor (as an unmodifiable list)}.
 59      */
 60     List<MemoryLayout> argumentLayouts();
 61 
 62     /**
 63      * Returns a function descriptor with the given argument layouts appended to the argument layouts
 64      * of this function descriptor.
 65      * @param addedLayouts the argument layouts to append.
 66      * @throws IllegalArgumentException if one of the layouts in {@code addedLayouts} is a padding layout.
 67      * @return a new function descriptor, with the provided additional argument layouts.
 68      */
 69     FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts);
 70 
 71     /**
 72      * Returns a function descriptor with the given argument layouts inserted at the given index, into the argument
 73      * layout array of this function descriptor.
 74      * @param index the index at which to insert the arguments
 75      * @param addedLayouts the argument layouts to insert at given index.
 76      * @return a new function descriptor, with the provided additional argument layouts.
 77      * @throws IllegalArgumentException if one of the layouts in {@code addedLayouts} is a padding layout.
 78      * @throws IllegalArgumentException if {@code index < 0 || index > argumentLayouts().size()}.
 79      */
 80     FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts);
 81 
 82     /**
 83      * Returns a function descriptor with the provided return layout.
 84      * @param newReturn the new return layout.
 85      * @throws IllegalArgumentException if {@code newReturn} is a padding layout.
 86      * @return a new function descriptor, with the provided return layout.
 87      */
 88     FunctionDescriptor changeReturnLayout(MemoryLayout newReturn);
 89 
 90     /**
 91      * {@return a new function descriptor, with no return layout}
 92      */
 93     FunctionDescriptor dropReturnLayout();
 94 
 95     /**
 96      * Returns the method type consisting of the carrier types of the layouts in this function descriptor.
 97      * <p>
 98      * The carrier type of a layout {@code L} is determined as follows:
 99      * <ul>
100      * <li>If {@code L} is a {@link ValueLayout} the carrier type is determined through {@link ValueLayout#carrier()}.</li>
101      * <li>If {@code L} is a {@link GroupLayout} or a {@link SequenceLayout}, the carrier type is {@link MemorySegment}.</li>
102      * </ul>
103      *
104      * @apiNote A function descriptor cannot, by construction, contain any padding layouts. As such, it is not
105      * necessary to specify how padding layout should be mapped to carrier types.
106      *
107      * @return the method type consisting of the carrier types of the layouts in this function descriptor.
108      */
109     MethodType toMethodType();
110 
111     /**
112      * Creates a function descriptor with the given return and argument layouts.
113      * @param resLayout the return layout.
114      * @param argLayouts the argument layouts.
115      * @throws IllegalArgumentException if {@code resLayout} is a padding layout.
116      * @throws IllegalArgumentException if one of the layouts in {@code argLayouts} is a padding layout.
117      * @return a new function descriptor with the provided return and argument layouts.
118      */
119     static FunctionDescriptor of(MemoryLayout resLayout, MemoryLayout... argLayouts) {
120         Objects.requireNonNull(resLayout);
121         // Null checks are implicit in List.of(argLayouts)
122         return FunctionDescriptorImpl.of(resLayout, List.of(argLayouts));
123     }
124 
125     /**
126      * Creates a function descriptor with the given argument layouts and no return layout.  This is useful to model functions
127      * that return no values.
128      * @param argLayouts the argument layouts.
129      * @throws IllegalArgumentException if one of the layouts in {@code argLayouts} is a padding layout.
130      * @return a new function descriptor with the provided argument layouts.
131      */
132     static FunctionDescriptor ofVoid(MemoryLayout... argLayouts) {
133         // Null checks are implicit in List.of(argLayouts)
134         return FunctionDescriptorImpl.ofVoid(List.of(argLayouts));
135     }
136 }