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