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 }