|
31 | 31 | import jdk.internal.foreign.abi.SharedUtils;
|
32 | 32 |
|
33 | 33 | import java.lang.constant.Constable;
|
34 |
| -import java.lang.constant.DynamicConstantDesc; |
35 | 34 | import java.lang.invoke.MethodHandle;
|
36 | 35 | import java.lang.invoke.MethodType;
|
37 |
| -import java.nio.ByteOrder; |
38 | 36 | import java.nio.charset.Charset;
|
39 |
| -import java.util.Map; |
40 | 37 | import java.util.Objects;
|
41 |
| -import java.util.Optional; |
42 | 38 | import java.util.function.Consumer;
|
43 | 39 |
|
44 |
| -import static java.lang.constant.ConstantDescs.BSM_GET_STATIC_FINAL; |
45 | 40 | import static jdk.internal.foreign.PlatformLayouts.*;
|
46 | 41 |
|
47 | 42 | /**
|
48 | 43 | * A foreign linker specializing for C Application Binary Interface (ABI) calling conventions.
|
49 | 44 | * Instances of this interface can be used to link foreign functions in native libraries that
|
50 | 45 | * follow the JVM's target platform C ABI.
|
51 |
| - * |
52 |
| - * <p>There are two components that go into linking a foreign function: a method type, and |
| 46 | + * <p> |
| 47 | + * There are two components that go into linking a foreign function: a method type, and |
53 | 48 | * a function descriptor. The method type, consists of a set of <em>carrier</em> types, which, together,
|
54 | 49 | * specify the Java signature which clients must adhere to when calling the underlying foreign function.
|
55 | 50 | * The function descriptor contains a set of memory layouts which, together, specify the foreign function
|
56 |
| - * signature and classification information (via custom layout attributes), so that linking can take place. |
57 |
| - * Memory layout attributes are used in the function descriptor to attach ABI classification meta-data to |
58 |
| - * memory layouts, which are required for linking. Clients of this API should build function descriptors |
59 |
| - * using the predefined memory layout constants (based on a subset of the built-in types provided by the C language), |
60 |
| - * found in this interface; a failure to do so might result in linkage errors, given that linking requires additional |
61 |
| - * classification information to determine, for instance, how arguments should be loaded into registers during a |
62 |
| - * foreign function call.</p> |
63 |
| - * |
64 |
| - * <p>Implementations of this interface support the following primitive carrier types: |
| 51 | + * signature and classification information (via a custom layout attributes, see {@link TypeKind}), so that linking can take place. |
| 52 | + * Memory layout attributes are used in the function descriptor to attach ABI classification meta-data to memory layouts, |
| 53 | + * which are required for linking. |
| 54 | + * <p> |
| 55 | + * Clients of this API can build function descriptors using the predefined memory layout constants |
| 56 | + * (based on a subset of the built-in types provided by the C language), found in this interface; alternatively, |
| 57 | + * they can also decorate existing value layouts using the required {@link TypeKind} classification attribute |
| 58 | + * (this can be done using the {@link MemoryLayout#withAttribute(String, Constable)} method). A failure to do so might |
| 59 | + * result in linkage errors, given that linking requires additional classification information to determine, for instance, |
| 60 | + * how arguments should be loaded into registers during a foreign function call. |
| 61 | + * <p> |
| 62 | + * Implementations of this interface support the following primitive carrier types: |
65 | 63 | * {@code byte}, {@code short}, {@code char}, {@code int}, {@code long}, {@code float},
|
66 | 64 | * and {@code double}, as well as {@link MemoryAddress} for passing pointers, and
|
67 | 65 | * {@link MemorySegment} for passing structs and unions. Finally, the {@link VaList}
|
68 |
| - * carrier type can be used to match the native {@code va_list} type.</p> |
69 |
| - * |
70 |
| - * <p>The function descriptor used in linking contains a memory layout to match each carrier type. |
71 |
| - * There are some restrictions on the carrier type and memory layout combinations that are allowed:</p> |
| 66 | + * carrier type can be used to match the native {@code va_list} type. |
| 67 | + * <p> |
| 68 | + * The function descriptor used in linking contains a memory layout to match each carrier type. |
| 69 | + * There are some restrictions on the carrier type and memory layout combinations that are allowed: |
72 | 70 | * <ul>
|
73 | 71 | * <li>If a primitve type is used as a carrier type, the corresponding
|
74 | 72 | * memory layout must be a {@code ValueLayout}, and the bit size of the layout must match that of the carrier type
|
|
94 | 92 | * function descriptor when linking the function. Furthermore, as memory layouts corresponding to variadic arguments in
|
95 | 93 | * a function descriptor must contain additional classification information, it is required that
|
96 | 94 | * {@link #asVarArg(MemoryLayout)} is used to create the memory layouts for each parameter corresponding to a variadic
|
97 |
| - * argument in a specialized function descriptor</p> |
| 95 | + * argument in a specialized function descriptor |
98 | 96 | *
|
99 | 97 | * @apiNote In the future, if the Java language permits, {@link MemoryLayout}
|
100 | 98 | * may become a {@code sealed} interface, which would prohibit subclassing except by
|
@@ -151,39 +149,39 @@ static CLinker getInstance() {
|
151 | 149 | /**
|
152 | 150 | * The layout for the {@code char} C type
|
153 | 151 | */
|
154 |
| - CValueLayout C_CHAR = pick(SysV.C_CHAR, Win64.C_CHAR, AArch64.C_CHAR); |
| 152 | + ValueLayout C_CHAR = pick(SysV.C_CHAR, Win64.C_CHAR, AArch64.C_CHAR); |
155 | 153 | /**
|
156 | 154 | * The layout for the {@code short} C type
|
157 | 155 | */
|
158 |
| - CValueLayout C_SHORT = pick(SysV.C_SHORT, Win64.C_SHORT, AArch64.C_SHORT); |
| 156 | + ValueLayout C_SHORT = pick(SysV.C_SHORT, Win64.C_SHORT, AArch64.C_SHORT); |
159 | 157 | /**
|
160 | 158 | * The layout for the {@code int} C type
|
161 | 159 | */
|
162 |
| - CValueLayout C_INT = pick(SysV.C_INT, Win64.C_INT, AArch64.C_INT); |
| 160 | + ValueLayout C_INT = pick(SysV.C_INT, Win64.C_INT, AArch64.C_INT); |
163 | 161 | /**
|
164 | 162 | * The layout for the {@code long} C type
|
165 | 163 | */
|
166 |
| - CValueLayout C_LONG = pick(SysV.C_LONG, Win64.C_LONG, AArch64.C_LONG); |
| 164 | + ValueLayout C_LONG = pick(SysV.C_LONG, Win64.C_LONG, AArch64.C_LONG); |
167 | 165 | /**
|
168 | 166 | * The {@code long long} native type.
|
169 | 167 | */
|
170 |
| - CValueLayout C_LONGLONG = pick(SysV.C_LONGLONG, Win64.C_LONGLONG, AArch64.C_LONGLONG); |
| 168 | + ValueLayout C_LONGLONG = pick(SysV.C_LONGLONG, Win64.C_LONGLONG, AArch64.C_LONGLONG); |
171 | 169 | /**
|
172 | 170 | * The layout for the {@code float} C type
|
173 | 171 | */
|
174 |
| - CValueLayout C_FLOAT = pick(SysV.C_FLOAT, Win64.C_FLOAT, AArch64.C_FLOAT); |
| 172 | + ValueLayout C_FLOAT = pick(SysV.C_FLOAT, Win64.C_FLOAT, AArch64.C_FLOAT); |
175 | 173 | /**
|
176 | 174 | * The layout for the {@code double} C type
|
177 | 175 | */
|
178 |
| - CValueLayout C_DOUBLE = pick(SysV.C_DOUBLE, Win64.C_DOUBLE, AArch64.C_DOUBLE); |
| 176 | + ValueLayout C_DOUBLE = pick(SysV.C_DOUBLE, Win64.C_DOUBLE, AArch64.C_DOUBLE); |
179 | 177 | /**
|
180 | 178 | * The {@code long double} native type.
|
181 | 179 | */
|
182 |
| - CValueLayout C_LONGDOUBLE = pick(SysV.C_LONGDOUBLE, Win64.C_LONGDOUBLE, AArch64.C_LONGDOUBLE); |
| 180 | + ValueLayout C_LONGDOUBLE = pick(SysV.C_LONGDOUBLE, Win64.C_LONGDOUBLE, AArch64.C_LONGDOUBLE); |
183 | 181 | /**
|
184 | 182 | * The {@code T*} native type.
|
185 | 183 | */
|
186 |
| - CValueLayout C_POINTER = pick(SysV.C_POINTER, Win64.C_POINTER, AArch64.C_POINTER); |
| 184 | + ValueLayout C_POINTER = pick(SysV.C_POINTER, Win64.C_POINTER, AArch64.C_POINTER); |
187 | 185 | /**
|
188 | 186 | * The layout for the {@code va_list} C type
|
189 | 187 | */
|
@@ -707,196 +705,90 @@ interface Builder {
|
707 | 705 | }
|
708 | 706 |
|
709 | 707 | /**
|
710 |
| - * Subclass of {@link ValueLayout} that contains information needed when linking |
711 |
| - * downcalls or upcalls. |
| 708 | + * A C type kind. Each kind corresponds to a particular C language builtin type, and can be attached to |
| 709 | + * {@link ValueLayout} instances using the {@link MemoryLayout#withAttribute(String, Constable)} in order |
| 710 | + * to obtain a layout which can be classified accordingly by {@link CLinker#downcallHandle(Addressable, MethodType, FunctionDescriptor)} |
| 711 | + * and {@link CLinker#upcallStub(MethodHandle, FunctionDescriptor)}. |
712 | 712 | */
|
713 |
| - class CValueLayout extends ValueLayout { |
| 713 | + enum TypeKind { |
714 | 714 | /**
|
715 |
| - * The kind of {@link CValueLayout}. Each kind corresponds to a particular |
716 |
| - * C language builtin type. |
| 715 | + * A kind corresponding to the C {@code char} type |
717 | 716 | */
|
718 |
| - public enum Kind { |
719 |
| - /** |
720 |
| - * A kind corresponding to the C {@code char} type |
721 |
| - */ |
722 |
| - CHAR(findBSM("C_CHAR"), true), |
723 |
| - /** |
724 |
| - * A kind corresponding to the C {@code short} type |
725 |
| - */ |
726 |
| - SHORT(findBSM("C_SHORT"), true), |
727 |
| - /** |
728 |
| - * A kind corresponding to the C {@code int} type |
729 |
| - */ |
730 |
| - INT(findBSM("C_INT"), true), |
731 |
| - /** |
732 |
| - * A kind corresponding to the C {@code long} type |
733 |
| - */ |
734 |
| - LONG(findBSM("C_LONG"), true), |
735 |
| - /** |
736 |
| - * A kind corresponding to the C {@code long long} type |
737 |
| - */ |
738 |
| - LONGLONG(findBSM("C_LONGLONG"), true), |
739 |
| - /** |
740 |
| - * A kind corresponding to the C {@code float} type |
741 |
| - */ |
742 |
| - FLOAT(findBSM("C_FLOAT"), false), |
743 |
| - /** |
744 |
| - * A kind corresponding to the C {@code double} type |
745 |
| - */ |
746 |
| - DOUBLE(findBSM("C_DOUBLE"), false), |
747 |
| - /** |
748 |
| - * A kind corresponding to the C {@code long double} type |
749 |
| - */ |
750 |
| - LONGDOUBLE(findBSM("C_LONGDOUBLE"), false), |
751 |
| - /** |
752 |
| - * A kind corresponding to the a C pointer type |
753 |
| - */ |
754 |
| - POINTER(findBSM("C_POINTER"), false); |
755 |
| - |
756 |
| - private final DynamicConstantDesc<ValueLayout> bsm; |
757 |
| - private final boolean isIntegral; |
758 |
| - |
759 |
| - Kind(DynamicConstantDesc<ValueLayout> bsm, boolean isIntegral) { |
760 |
| - this.bsm = bsm; |
761 |
| - this.isIntegral = isIntegral; |
762 |
| - } |
763 |
| - |
764 |
| - private DynamicConstantDesc<ValueLayout> bsm() { |
765 |
| - return bsm; |
766 |
| - } |
767 |
| - |
768 |
| - /** |
769 |
| - * Is this kind integral? |
770 |
| - * |
771 |
| - * @return true if this kind is integral |
772 |
| - */ |
773 |
| - public boolean isIntergral() { |
774 |
| - return isIntegral; |
775 |
| - } |
776 |
| - |
777 |
| - /** |
778 |
| - * Is this kind a floating point type? |
779 |
| - * |
780 |
| - * @return true if this kind is a floating point type |
781 |
| - */ |
782 |
| - public boolean isFloat() { |
783 |
| - return !isIntergral() && !isPointer(); |
784 |
| - } |
785 |
| - |
786 |
| - /** |
787 |
| - * Is this kind a pointer kind? |
788 |
| - * |
789 |
| - * @return true if this kind is a pointer kind |
790 |
| - */ |
791 |
| - public boolean isPointer() { |
792 |
| - return this == POINTER; |
793 |
| - } |
794 |
| - |
795 |
| - private static DynamicConstantDesc<ValueLayout> findBSM(String fieldName) { |
796 |
| - return DynamicConstantDesc.ofNamed( |
797 |
| - BSM_GET_STATIC_FINAL, |
798 |
| - fieldName, |
799 |
| - CValueLayout.class.describeConstable().orElseThrow(), |
800 |
| - CLinker.class.describeConstable().orElseThrow() |
801 |
| - ); |
802 |
| - } |
803 |
| - } |
804 |
| - |
805 |
| - private final Kind kind; |
806 |
| - |
| 717 | + CHAR(true), |
807 | 718 | /**
|
808 |
| - * CValueLayout constructor |
809 |
| - * |
810 |
| - * @param kind the kind of CValueLayout |
811 |
| - * @param order the byte order of the layout |
812 |
| - * @param bitSize the size, in bits, of the layout |
813 |
| - * @param bitAlignment the alignment, in bits, of the layout |
814 |
| - * @param attributes the attribute map of this layout |
| 719 | + * A kind corresponding to the C {@code short} type |
815 | 720 | */
|
816 |
| - public CValueLayout(Kind kind, ByteOrder order, long bitSize, long bitAlignment, |
817 |
| - Map<String, Constable> attributes) { |
818 |
| - super(order, bitSize, bitAlignment, attributes); |
819 |
| - this.kind = kind; |
820 |
| - } |
821 |
| - |
| 721 | + SHORT(true), |
822 | 722 | /**
|
823 |
| - * Accessor for the kind of this layout |
824 |
| - * |
825 |
| - * @return the kind |
| 723 | + * A kind corresponding to the C {@code int} type |
826 | 724 | */
|
827 |
| - public final Kind kind() { |
828 |
| - return kind; |
829 |
| - } |
830 |
| - |
| 725 | + INT(true), |
831 | 726 | /**
|
832 |
| - * {@inheritDoc} |
| 727 | + * A kind corresponding to the C {@code long} type |
833 | 728 | */
|
834 |
| - @Override |
835 |
| - public CValueLayout withOrder(ByteOrder order) { |
836 |
| - return new CValueLayout(kind, order, bitSize(), alignment, attributes); |
837 |
| - } |
838 |
| - |
| 729 | + LONG(true), |
839 | 730 | /**
|
840 |
| - * {@inheritDoc} |
| 731 | + * A kind corresponding to the C {@code long long} type |
841 | 732 | */
|
842 |
| - @Override |
843 |
| - public CValueLayout withName(String name) { |
844 |
| - return (CValueLayout) super.withName(name); |
845 |
| - } |
846 |
| - |
| 733 | + LONGLONG(true), |
847 | 734 | /**
|
848 |
| - * {@inheritDoc} |
| 735 | + * A kind corresponding to the C {@code float} type |
849 | 736 | */
|
850 |
| - @Override |
851 |
| - public CValueLayout withBitAlignment(long alignmentBits) { |
852 |
| - return (CValueLayout) super.withBitAlignment(alignmentBits); |
853 |
| - } |
854 |
| - |
| 737 | + FLOAT(false), |
855 | 738 | /**
|
856 |
| - * {@inheritDoc} |
| 739 | + * A kind corresponding to the C {@code double} type |
857 | 740 | */
|
858 |
| - @Override |
859 |
| - public CValueLayout withAttribute(String name, Constable value) { |
860 |
| - return (CValueLayout) super.withAttribute(name, value); |
861 |
| - } |
| 741 | + DOUBLE(false), |
| 742 | + /** |
| 743 | + * A kind corresponding to the C {@code long double} type |
| 744 | + */ |
| 745 | + LONGDOUBLE(false), |
| 746 | + /** |
| 747 | + * A kind corresponding to the a C pointer type |
| 748 | + */ |
| 749 | + POINTER(false); |
862 | 750 |
|
863 |
| - @Override |
864 |
| - CValueLayout dup(long alignment, Map<String, Constable> attributes) { |
865 |
| - return new CValueLayout(kind, order(), bitSize(), alignment, attributes); |
| 751 | + private final boolean isIntegral; |
| 752 | + |
| 753 | + TypeKind(boolean isIntegral) { |
| 754 | + this.isIntegral = isIntegral; |
866 | 755 | }
|
867 | 756 |
|
868 | 757 | /**
|
869 |
| - * {@inheritDoc} |
| 758 | + * Is this kind integral? |
| 759 | + * |
| 760 | + * @return true if this kind is integral |
870 | 761 | */
|
871 |
| - @Override |
872 |
| - public Optional<DynamicConstantDesc<ValueLayout>> describeConstable() { |
873 |
| - return Optional.of(decorateLayoutConstant(kind.bsm())); |
| 762 | + public boolean isIntergral() { |
| 763 | + return isIntegral; |
874 | 764 | }
|
875 | 765 |
|
876 | 766 | /**
|
877 |
| - * {@inheritDoc} |
| 767 | + * Is this kind a floating point type? |
| 768 | + * |
| 769 | + * @return true if this kind is a floating point type |
878 | 770 | */
|
879 |
| - @Override |
880 |
| - public boolean equals(Object other) { |
881 |
| - if (this == other) { |
882 |
| - return true; |
883 |
| - } |
884 |
| - if (other == null || getClass() != other.getClass()) { |
885 |
| - return false; |
886 |
| - } |
887 |
| - if (!super.equals(other)) { |
888 |
| - return false; |
889 |
| - } |
890 |
| - CValueLayout that = (CValueLayout) other; |
891 |
| - return kind == that.kind; |
| 771 | + public boolean isFloat() { |
| 772 | + return !isIntergral() && !isPointer(); |
892 | 773 | }
|
893 | 774 |
|
894 | 775 | /**
|
895 |
| - * {@inheritDoc} |
| 776 | + * Is this kind a pointer kind? |
| 777 | + * |
| 778 | + * @return true if this kind is a pointer kind |
896 | 779 | */
|
897 |
| - @Override |
898 |
| - public int hashCode() { |
899 |
| - return Objects.hash(super.hashCode(), kind); |
| 780 | + public boolean isPointer() { |
| 781 | + return this == POINTER; |
900 | 782 | }
|
| 783 | + |
| 784 | + /** |
| 785 | + * The layout attribute name associated with this classification kind. Clients can retrieve the type kind |
| 786 | + * of a layout using the following code: |
| 787 | + * <blockquote><pre>{@code |
| 788 | + ValueLayout layout = ... |
| 789 | + TypeKind = layout.attribute(TypeKind.ATTR_NAME).orElse(null); |
| 790 | + * }</pre></blockquote> |
| 791 | + */ |
| 792 | + public final static String ATTR_NAME = "abi/kind"; |
901 | 793 | }
|
902 | 794 | }
|
0 commit comments