diff --git a/runtime/tests/clinkerffi/CMakeLists.txt b/runtime/tests/clinkerffi/CMakeLists.txt index 4f4978b6d7b..6a203680743 100644 --- a/runtime/tests/clinkerffi/CMakeLists.txt +++ b/runtime/tests/clinkerffi/CMakeLists.txt @@ -23,6 +23,8 @@ set(OMR_ENHANCED_WARNINGS OFF) j9vm_add_library(clinkerffitests SHARED downcall.c + upcall.c + valist.c ) target_link_libraries(clinkerffitests PRIVATE @@ -42,9 +44,6 @@ omr_add_exports(clinkerffitests add2Longs add2Floats add2Doubles - addIntsFromVaList - addLongsFromVaList - addDoublesFromVaList addIntAndIntFromPointer addBoolAndBoolFromPointerWithOr createNewCharFromCharAndCharFromPointer @@ -165,6 +164,245 @@ omr_add_exports(clinkerffitests add2DoubleStructs_returnStruct add2DoubleStructs_returnStructPointer add3DoubleStructs_returnStruct + add2BoolsWithOrByUpcallMH + addBoolAndBoolFromPointerWithOrByUpcallMH + addBoolAndBoolFromNativePtrWithOrByUpcallMH + addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH + createNewCharFrom2CharsByUpcallMH + createNewCharFromCharAndCharFromPointerByUpcallMH + createNewCharFromCharAndCharFromNativePtrByUpcallMH + createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH + add2BytesByUpcallMH + addByteAndByteFromPointerByUpcallMH + addByteAndByteFromNativePtrByUpcallMH + addByteAndByteFromPtr_RetPtr_ByUpcallMH + add2ShortsByUpcallMH + addShortAndShortFromPointerByUpcallMH + addShortAndShortFromNativePtrByUpcallMH + addShortAndShortFromPtr_RetPtr_ByUpcallMH + add2IntsByUpcallMH + addIntAndIntFromPointerByUpcallMH + addIntAndIntFromNativePtrByUpcallMH + addIntAndIntFromPtr_RetPtr_ByUpcallMH + add3IntsByUpcallMH + addIntAndCharByUpcallMH + add2IntsReturnVoidByUpcallMH + add2LongsByUpcallMH + addLongAndLongFromPointerByUpcallMH + addLongAndLongFromNativePtrByUpcallMH + addLongAndLongFromPtr_RetPtr_ByUpcallMH + add2FloatsByUpcallMH + addFloatAndFloatFromPointerByUpcallMH + addFloatAndFloatFromNativePtrByUpcallMH + addFloatAndFloatFromPtr_RetPtr_ByUpcallMH + add2DoublesByUpcallMH + addDoubleAndDoubleFromPointerByUpcallMH + addDoubleAndDoubleFromNativePtrByUpcallMH + addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH + addBoolAndBoolsFromStructWithXorByUpcallMH + addBoolAnd20BoolsFromStructWithXorByUpcallMH + addBoolFromPointerAndBoolsFromStructWithXorByUpcallMH + addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointerByUpcallMH + addBoolAndBoolsFromStructPointerWithXorByUpcallMH + addBoolAndBoolsFromNestedStructWithXorByUpcallMH + addBoolAndBoolsFromNestedStructWithXor_reverseOrderByUpcallMH + addBoolAndBoolsFromStructWithNestedBoolArrayByUpcallMH + addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrderByUpcallMH + addBoolAndBoolsFromStructWithNestedStructArrayByUpcallMH + addBoolAndBoolsFromStructWithNestedStructArray_reverseOrderByUpcallMH + add2BoolStructsWithXor_returnStructByUpcallMH + add2BoolStructsWithXor_returnStructPointerByUpcallMH + add3BoolStructsWithXor_returnStructByUpcallMH + addByteAndBytesFromStructByUpcallMH + addByteAnd20BytesFromStructByUpcallMH + addByteFromPointerAndBytesFromStructByUpcallMH + addByteFromPointerAndBytesFromStruct_returnBytePointerByUpcallMH + addByteAndBytesFromStructPointerByUpcallMH + addByteAndBytesFromNestedStructByUpcallMH + addByteAndBytesFromNestedStruct_reverseOrderByUpcallMH + addByteAndBytesFromStructWithNestedByteArrayByUpcallMH + addByteAndBytesFromStructWithNestedByteArray_reverseOrderByUpcallMH + addByteAndBytesFromStructWithNestedStructArrayByUpcallMH + addByteAndBytesFromStructWithNestedStructArray_reverseOrderByUpcallMH + add1ByteStructs_returnStructByUpcallMH + add2ByteStructs_returnStructByUpcallMH + add2ByteStructs_returnStructPointerByUpcallMH + add3ByteStructs_returnStructByUpcallMH + addCharAndCharsFromStructByUpcallMH + addCharFromPointerAndCharsFromStructByUpcallMH + addCharFromPointerAndCharsFromStruct_returnCharPointerByUpcallMH + addCharAndCharsFromStructPointerByUpcallMH + addCharAndCharsFromNestedStructByUpcallMH + addCharAnd10CharsFromStructByUpcallMH + addCharAndCharsFromNestedStruct_reverseOrderByUpcallMH + addCharAndCharsFromStructWithNestedCharArrayByUpcallMH + addCharAndCharsFromStructWithNestedCharArray_reverseOrderByUpcallMH + addCharAndCharsFromStructWithNestedStructArrayByUpcallMH + addCharAndCharsFromStructWithNestedStructArray_reverseOrderByUpcallMH + add2CharStructs_returnStructByUpcallMH + add2CharStructs_returnStructPointerByUpcallMH + add3CharStructs_returnStructByUpcallMH + addShortAndShortsFromStructByUpcallMH + addShortAnd10ShortsFromStructByUpcallMH + addShortFromPointerAndShortsFromStructByUpcallMH + addShortFromPointerAndShortsFromStruct_returnShortPointerByUpcallMH + addShortAndShortsFromStructPointerByUpcallMH + addShortAndShortsFromNestedStructByUpcallMH + addShortAndShortsFromNestedStruct_reverseOrderByUpcallMH + addShortAndShortsFromStructWithNestedShortArrayByUpcallMH + addShortAndShortsFromStructWithNestedShortArray_reverseOrderByUpcallMH + addShortAndShortsFromStructWithNestedStructArrayByUpcallMH + addShortAndShortsFromStructWithNestedStructArray_reverseOrderByUpcallMH + add2ShortStructs_returnStructByUpcallMH + add2ShortStructs_returnStructPointerByUpcallMH + add3ShortStructs_returnStructByUpcallMH + addIntAndIntsFromStructByUpcallMH + addIntAnd5IntsFromStructByUpcallMH + addIntFromPointerAndIntsFromStructByUpcallMH + addIntFromPointerAndIntsFromStruct_returnIntPointerByUpcallMH + addIntAndIntsFromStructPointerByUpcallMH + addIntAndIntsFromNestedStructByUpcallMH + addIntAndIntsFromNestedStruct_reverseOrderByUpcallMH + addIntAndIntsFromStructWithNestedIntArrayByUpcallMH + addIntAndIntsFromStructWithNestedIntArray_reverseOrderByUpcallMH + addIntAndIntsFromStructWithNestedStructArrayByUpcallMH + addIntAndIntsFromStructWithNestedStructArray_reverseOrderByUpcallMH + add2IntStructs_returnStructByUpcallMH + add2IntStructs_returnStructPointerByUpcallMH + add3IntStructs_returnStructByUpcallMH + addLongAndLongsFromStructByUpcallMH + addLongFromPointerAndLongsFromStructByUpcallMH + addLongFromPointerAndLongsFromStruct_returnLongPointerByUpcallMH + addLongAndLongsFromStructPointerByUpcallMH + addLongAndLongsFromNestedStructByUpcallMH + addLongAndLongsFromNestedStruct_reverseOrderByUpcallMH + addLongAndLongsFromStructWithNestedLongArrayByUpcallMH + addLongAndLongsFromStructWithNestedLongArray_reverseOrderByUpcallMH + addLongAndLongsFromStructWithNestedStructArrayByUpcallMH + addLongAndLongsFromStructWithNestedStructArray_reverseOrderByUpcallMH + add2LongStructs_returnStructByUpcallMH + add2LongStructs_returnStructPointerByUpcallMH + add3LongStructs_returnStructByUpcallMH + addFloatAndFloatsFromStructByUpcallMH + addFloatAnd5FloatsFromStructByUpcallMH + addFloatFromPointerAndFloatsFromStructByUpcallMH + addFloatFromPointerAndFloatsFromStruct_returnFloatPointerByUpcallMH + addFloatAndFloatsFromStructPointerByUpcallMH + addFloatAndFloatsFromNestedStructByUpcallMH + addFloatAndFloatsFromNestedStruct_reverseOrderByUpcallMH + addFloatAndFloatsFromStructWithNestedFloatArrayByUpcallMH + addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrderByUpcallMH + addFloatAndFloatsFromStructWithNestedStructArrayByUpcallMH + addFloatAndFloatsFromStructWithNestedStructArray_reverseOrderByUpcallMH + add2FloatStructs_returnStructByUpcallMH + add2FloatStructs_returnStructPointerByUpcallMH + add3FloatStructs_returnStructByUpcallMH + addDoubleAndDoublesFromStructByUpcallMH + addDoubleFromPointerAndDoublesFromStructByUpcallMH + addDoubleFromPointerAndDoublesFromStruct_returnDoublePointerByUpcallMH + addDoubleAndDoublesFromStructPointerByUpcallMH + addDoubleAndDoublesFromNestedStructByUpcallMH + addDoubleAndDoublesFromNestedStruct_reverseOrderByUpcallMH + addDoubleAndDoublesFromStructWithNestedDoubleArrayByUpcallMH + addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrderByUpcallMH + addDoubleAndDoublesFromStructWithNestedStructArrayByUpcallMH + addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrderByUpcallMH + add2DoubleStructs_returnStructByUpcallMH + add2DoubleStructs_returnStructPointerByUpcallMH + add3DoubleStructs_returnStructByUpcallMH + addIntAndIntShortFromStructByUpcallMH + addIntAndShortIntFromStructByUpcallMH + addIntAndIntLongFromStructByUpcallMH + addIntAndLongIntFromStructByUpcallMH + addDoubleAndDoubleIntFromStructByUpcallMH + addDoubleAndIntDoubleFromStructByUpcallMH + addDoubleAndFloatDoubleFromStructByUpcallMH + addDoubleAndDoubleFloatFromStructByUpcallMH + addDoubleAnd2FloatsDoubleFromStructByUpcallMH + addDoubleAndDouble2FloatsFromStructByUpcallMH + addFloatAndInt2FloatsFromStructByUpcallMH + addFloatAndFloatIntFloatFromStructByUpcallMH + addDoubleAndIntFloatDoubleFromStructByUpcallMH + addDoubleAndFloatIntDoubleFromStructByUpcallMH + addDoubleAndLongDoubleFromStructByUpcallMH + addFloatAndInt3FloatsFromStructByUpcallMH + addLongAndLong2FloatsFromStructByUpcallMH + addFloatAnd3FloatsIntFromStructByUpcallMH + addLongAndFloatLongFromStructByUpcallMH + addDoubleAndDoubleFloatIntFromStructByUpcallMH + addDoubleAndDoubleLongFromStructByUpcallMH + addLongAnd2FloatsLongFromStructByUpcallMH + addShortAnd3ShortsCharFromStructByUpcallMH + addFloatAndIntFloatIntFloatFromStructByUpcallMH + addDoubleAndIntDoubleFloatFromStructByUpcallMH + addDoubleAndFloatDoubleIntFromStructByUpcallMH + addDoubleAndIntDoubleIntFromStructByUpcallMH + addDoubleAndFloatDoubleFloatFromStructByUpcallMH + addDoubleAndIntDoubleLongFromStructByUpcallMH + return254BytesFromStructByUpcallMH + return4KBytesFromStructByUpcallMH + addIntsFromVaList + addLongsFromVaList + addDoublesFromVaList + addMixedArgsFromVaList + addMoreMixedArgsFromVaList + addIntsByPtrFromVaList + addLongsByPtrFromVaList + addDoublesByPtrFromVaList + add1ByteOfStructsFromVaList + add2BytesOfStructsFromVaList + add3BytesOfStructsFromVaList + add5BytesOfStructsFromVaList + add7BytesOfStructsFromVaList + add1ShortOfStructsFromVaList + add2ShortsOfStructsFromVaList + add3ShortsOfStructsFromVaList + add1IntOfStructsFromVaList + add2IntsOfStructsFromVaList + add3IntsOfStructsFromVaList + add2LongsOfStructsFromVaList + add1FloatOfStructsFromVaList + add2FloatsOfStructsFromVaList + add3FloatsOfStructsFromVaList + add1DoubleOfStructsFromVaList + add2DoublesOfStructsFromVaList + addIntShortOfStructsFromVaList + addShortIntOfStructsFromVaList + addIntLongOfStructsFromVaList + addLongIntOfStructsFromVaList + addFloatDoubleOfStructsFromVaList + addDoubleFloatOfStructsFromVaList + addIntsFromVaListByUpcallMH + addLongsFromVaListByUpcallMH + addDoublesFromVaListByUpcallMH + addMixedArgsFromVaListByUpcallMH + addMoreMixedArgsFromVaListByUpcallMH + addIntsByPtrFromVaListByUpcallMH + addLongsByPtrFromVaListByUpcallMH + addDoublesByPtrFromVaListByUpcallMH + add1ByteOfStructsFromVaListByUpcallMH + add2BytesOfStructsFromVaListByUpcallMH + add3BytesOfStructsFromVaListByUpcallMH + add5BytesOfStructsFromVaListByUpcallMH + add7BytesOfStructsFromVaListByUpcallMH + add1ShortOfStructsFromVaListByUpcallMH + add2ShortsOfStructsFromVaListByUpcallMH + add3ShortsOfStructsFromVaListByUpcallMH + add1IntOfStructsFromVaListByUpcallMH + add2IntsOfStructsFromVaListByUpcallMH + add3IntsOfStructsFromVaListByUpcallMH + add2LongsOfStructsFromVaListByUpcallMH + add1FloatOfStructsFromVaListByUpcallMH + add2FloatsOfStructsFromVaListByUpcallMH + add3FloatsOfStructsFromVaListByUpcallMH + add1DoubleOfStructsFromVaListByUpcallMH + add2DoublesOfStructsFromVaListByUpcallMH + addIntShortOfStructsFromVaListByUpcallMH + addShortIntOfStructsFromVaListByUpcallMH + addIntLongOfStructsFromVaListByUpcallMH + addLongIntOfStructsFromVaListByUpcallMH + addFloatDoubleOfStructsFromVaListByUpcallMH + addDoubleFloatOfStructsFromVaListByUpcallMH ) install( diff --git a/runtime/tests/clinkerffi/downcall.c b/runtime/tests/clinkerffi/downcall.c index 8fee504cc32..65131f1f741 100644 --- a/runtime/tests/clinkerffi/downcall.c +++ b/runtime/tests/clinkerffi/downcall.c @@ -21,8 +21,11 @@ *******************************************************************************/ /** - * This file contains the native code used by the test cases in - * org.openj9.test.jep389.downcall via a Clinker FFI DownCall. + * This file contains the native code used by the test cases via a Clinker FFI DownCall in java, + * which come from: + * org.openj9.test.jep389.downcall (JDK16/17) + * org.openj9.test.jep419.downcall (JDK18) + * org.openj9.test.jep424.downcall (JDK19+) * * Created by jincheng@ca.ibm.com */ @@ -72,24 +75,6 @@ add3Ints(int intArg1, int intArg2, int intArg3) return intSum; } -/** - * Add integers from the va_list with the specified count - * - * @param intCount the count of the integers - * @param intArgList the integer va_list - * @return the sum of integers from the va_list - */ -int -addIntsFromVaList(int intCount, va_list intVaList) -{ - int intSum = 0; - while (intCount > 0) { - intSum += va_arg(intVaList, int); - intCount--; - } - return intSum; -} - /** * Add an integer and a character. * @@ -267,24 +252,6 @@ addLongAndLongFromPointer(LONG *longArg1, LONG longArg2) return longSum; } -/** - * Add long integers from the va_list with the specified count - * - * @param longCount the count of the long integers - * @param longArgList the long va_list - * @return the sum of long integers from the va_list - */ -LONG -addLongsFromVaList(int longCount, va_list longVaList) -{ - LONG longSum = 0; - while (longCount > 0) { - longSum += va_arg(longVaList, LONG); - longCount--; - } - return longSum; -} - /** * Add two floats. * @@ -341,24 +308,6 @@ addDoubleAndDoubleFromPointer(double *doubleArg1, double doubleArg2) return doubleSum; } -/** - * Add doubles from the va_list with the specified count - * - * @param doubleCount the count of the double arguments - * @param doubleArgList the double va_list - * @return the sum of doubles from the va_list - */ -double -addDoublesFromVaList(int doubleCount, va_list doubleVaList) -{ - double doubleSum = 0; - while (doubleCount > 0) { - doubleSum += va_arg(doubleVaList, double); - doubleCount--; - } - return doubleSum; -} - /** * Add a boolean and all boolean elements of a struct with the XOR (^) operator. * @@ -1255,7 +1204,7 @@ addIntAndIntsFromNestedStruct(int arg1, stru_NestedStruct_Int arg2) * * @param arg1 an integer * @param arg2 a struct with an integer and a nested struct - * @return the sum of these ints + * @return the sum of these integers */ int addIntAndIntsFromNestedStruct_reverseOrder(int arg1, stru_Int_NestedStruct arg2) diff --git a/runtime/tests/clinkerffi/downcall.h b/runtime/tests/clinkerffi/downcall.h index eff640631b3..6dc94d8038f 100644 --- a/runtime/tests/clinkerffi/downcall.h +++ b/runtime/tests/clinkerffi/downcall.h @@ -21,8 +21,11 @@ *******************************************************************************/ /** - * This file contains the structs required in the native code used by org.openj9.test.jep389.downcall.StructTests - * via a Clinker FFI DownCall. + * This file contains the structs required in the native code via a Clinker FFI DownCall & Upcall in java, + * which come from: + * org.openj9.test.jep389.downcall/upcall (JDK16/17) + * org.openj9.test.jep419.downcall/upcall (JDK18) + * org.openj9.test.jep424.downcall/upcall (JDK19+) * * Created by jincheng@ca.ibm.com */ @@ -48,6 +51,29 @@ typedef struct stru_Bool_Bool_Bool { bool elem3; } stru_Bool_Bool_Bool; +typedef struct stru_20_Bools { + bool elem1; + bool elem2; + bool elem3; + bool elem4; + bool elem5; + bool elem6; + bool elem7; + bool elem8; + bool elem9; + bool elem10; + bool elem11; + bool elem12; + bool elem13; + bool elem14; + bool elem15; + bool elem16; + bool elem17; + bool elem18; + bool elem19; + bool elem20; +} stru_20_Bools; + typedef struct stru_NestedStruct_Bool { stru_Bool_Bool elem1; bool elem2; @@ -78,6 +104,10 @@ typedef struct stru_Bool_NestedStruArray { stru_Bool_Bool elem2[2]; } stru_Bool_NestedStruArray; +typedef struct stru_Byte { + char elem1; +} stru_Byte; + typedef struct stru_Byte_Byte { char elem1; char elem2; @@ -89,6 +119,55 @@ typedef struct stru_Byte_Byte_Byte { char elem3; } stru_Byte_Byte_Byte; +typedef struct stru_5_Bytes { + char elem1; + char elem2; + char elem3; + char elem4; + char elem5; +} stru_5_Bytes; + +typedef struct stru_7_Bytes { + char elem1; + char elem2; + char elem3; + char elem4; + char elem5; + char elem6; + char elem7; +} stru_7_Bytes; + +typedef struct stru_20_Bytes { + char elem1; + char elem2; + char elem3; + char elem4; + char elem5; + char elem6; + char elem7; + char elem8; + char elem9; + char elem10; + char elem11; + char elem12; + char elem13; + char elem14; + char elem15; + char elem16; + char elem17; + char elem18; + char elem19; + char elem20; +} stru_20_Bytes; + +typedef struct stru_254_Bytes { + char elem[254]; +} stru_254_Bytes; + +typedef struct stru_4K_Bytes { + char elem[4096]; +} stru_4K_Bytes; + typedef struct stru_NestedStruct_Byte { stru_Byte_Byte elem1; char elem2; @@ -130,6 +209,19 @@ typedef struct stru_Char_Char_Char { short elem3; } stru_Char_Char_Char; +typedef struct stru_10_Chars { + short elem1; + short elem2; + short elem3; + short elem4; + short elem5; + short elem6; + short elem7; + short elem8; + short elem9; + short elem10; +} stru_10_Chars; + typedef struct stru_NestedStruct_Char { stru_Char_Char elem1; short elem2; @@ -160,6 +252,10 @@ typedef struct stru_Char_NestedStruArray { stru_Char_Char elem2[2]; } stru_Char_NestedStruArray; +typedef struct stru_Short { + short elem1; +} stru_Short; + typedef struct stru_Short_Short { short elem1; short elem2; @@ -171,6 +267,19 @@ typedef struct stru_Short_Short_Short { short elem3; } stru_Short_Short_Short; +typedef struct stru_10_Shorts { + short elem1; + short elem2; + short elem3; + short elem4; + short elem5; + short elem6; + short elem7; + short elem8; + short elem9; + short elem10; +} stru_10_Shorts; + typedef struct stru_NestedStruct_Short { stru_Short_Short elem1; short elem2; @@ -201,6 +310,10 @@ typedef struct stru_Short_NestedStruArray { stru_Short_Short elem2[2]; } stru_Short_NestedStruArray; +typedef struct stru_Int { + int elem1; +} stru_Int; + typedef struct stru_Int_Int { int elem1; int elem2; @@ -212,15 +325,13 @@ typedef struct stru_Int_Int_Int { int elem3; } stru_Int_Int_Int; -typedef struct stru_Int_Short { +typedef struct stru_5_Ints { int elem1; - short elem2; -} stru_Int_Short; - -typedef struct stru_Short_Int { - short elem1; int elem2; -} stru_Short_Int; + int elem3; + int elem4; + int elem5; +} stru_5_Ints; typedef struct stru_NestedStruct_Int { stru_Int_Int elem1; @@ -263,16 +374,6 @@ typedef struct stru_Long_Long_Long { LONG elem3; } stru_Long_Long_Long; -typedef struct stru_Int_Long { - int elem1; - LONG elem2; -} stru_Int_Long; - -typedef struct stru_Long_Int { - LONG elem1; - int elem2; -} stru_Long_Int; - typedef struct stru_NestedStruct_Long { stru_Long_Long elem1; LONG elem2; @@ -303,6 +404,10 @@ typedef struct stru_Long_NestedStruArray { stru_Long_Long elem2[2]; } stru_Long_NestedStruArray; +typedef struct stru_Float { + float elem1; +} stru_Float; + typedef struct stru_Float_Float { float elem1; float elem2; @@ -314,6 +419,14 @@ typedef struct stru_Float_Float_Float { float elem3; } stru_Float_Float_Float; +typedef struct stru_5_Floats { + float elem1; + float elem2; + float elem3; + float elem4; + float elem5; +} stru_5_Floats; + typedef struct stru_NestedStruct_Float { stru_Float_Float elem1; float elem2; @@ -344,6 +457,10 @@ typedef struct stru_Float_NestedStruArray { stru_Float_Float elem2[2]; } stru_Float_NestedStruArray; +typedef struct stru_Double { + double elem1; +} stru_Double; + typedef struct stru_Double_Double { double elem1; double elem2; @@ -355,26 +472,6 @@ typedef struct stru_Double_Double_Double { double elem3; } stru_Double_Double_Double; -typedef struct stru_Float_Double { - float elem1; - double elem2; -} stru_Float_Double; - -typedef struct stru_Int_Double { - int elem1; - double elem2; -} stru_Int_Double; - -typedef struct stru_Double_Float { - double elem1; - float elem2; -} stru_Double_Float; - -typedef struct stru_Double_Int { - double elem1; - int elem2; -} stru_Double_Int; - typedef struct stru_NestedStruct_Double { stru_Double_Double elem1; double elem2; @@ -405,4 +502,169 @@ typedef struct stru_Double_NestedStruArray { stru_Double_Double elem2[2]; } stru_Double_NestedStruArray; +typedef struct stru_Int_Short { + int elem1; + short elem2; +} stru_Int_Short; + +typedef struct stru_Short_Int { + short elem1; + int elem2; +} stru_Short_Int; + +typedef struct stru_Int_Long { + int elem1; + LONG elem2; +} stru_Int_Long; + +typedef struct stru_Long_Int { + LONG elem1; + int elem2; +} stru_Long_Int; + +typedef struct stru_Int_Double { + int elem1; + double elem2; +} stru_Int_Double; + +typedef struct stru_Double_Int { + double elem1; + int elem2; +} stru_Double_Int; + +typedef struct stru_Float_Double { + float elem1; + double elem2; +} stru_Float_Double; + +typedef struct stru_Double_Float { + double elem1; + float elem2; +} stru_Double_Float; + +typedef struct stru_Float_Float_Double { + float elem1; + float elem2; + double elem3; +} stru_Float_Float_Double; + +typedef struct stru_Double_Float_Float { + double elem1; + float elem2; + float elem3; +} stru_Double_Float_Float; + +typedef struct stru_Int_Float_Float { + int elem1; + float elem2; + float elem3; +} stru_Int_Float_Float; + +typedef struct stru_Float_Int_Float { + float elem1; + int elem2; + float elem3; +} stru_Float_Int_Float; + +typedef struct stru_Int_Float_Double { + int elem1; + float elem2; + double elem3; +} stru_Int_Float_Double; + +typedef struct stru_Float_Int_Double { + float elem1; + int elem2; + double elem3; +} stru_Float_Int_Double; + +typedef struct stru_Long_Double { + LONG elem1; + double elem2; +} stru_Long_Double; + +typedef struct stru_Int_3_Floats { + int elem1; + float elem2; + float elem3; + float elem4; +} stru_Int_3_Floats; + +typedef struct stru_Long_2_Floats { + LONG elem1; + float elem2; + float elem3; +} stru_Long_2_Floats; + +typedef struct stru_3_Floats_Int { + float elem1; + float elem2; + float elem3; + int elem4; +} stru_3_Floats_Int; + +typedef struct stru_Float_Long { + float elem1; + LONG elem2; +} stru_Float_Long; + +typedef struct stru_Double_Float_Int { + double elem1; + float elem2; + int elem3; +} stru_Double_Float_Int; + +typedef struct stru_Double_Long { + double elem1; + LONG elem2; +} stru_Double_Long; + +typedef struct stru_Float_Float_Long { + float elem1; + float elem2; + LONG elem3; +} stru_Float_Float_Long; + +typedef struct stru_3_Shorts_Char { + short elem1[3]; + short elem2; // intended for the char type in java +} stru_3_Shorts_Char; + +typedef struct stru_Int_Float_Int_Float { + int elem1; + float elem2; + int elem3; + float elem4; +} stru_Int_Float_Int_Float; + +typedef struct stru_Int_Double_Float { + int elem1; + double elem2; + float elem3; +} stru_Int_Double_Float; + +typedef struct stru_Float_Double_Int { + float elem1; + double elem2; + int elem3; +} stru_Float_Double_Int; + +typedef struct stru_Int_Double_Int { + int elem1; + double elem2; + int elem3; +} stru_Int_Double_Int; + +typedef struct stru_Float_Double_Float { + float elem1; + double elem2; + float elem3; +} stru_Float_Double_Float; + +typedef struct stru_Int_Double_Long { + int elem1; + double elem2; + LONG elem3; +} stru_Int_Double_Long; + #endif /* DOWNCALL_H */ diff --git a/runtime/tests/clinkerffi/module.xml b/runtime/tests/clinkerffi/module.xml index 9c355104980..c641cfd1e5a 100644 --- a/runtime/tests/clinkerffi/module.xml +++ b/runtime/tests/clinkerffi/module.xml @@ -35,9 +35,6 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti - - - @@ -158,6 +155,245 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-excepti + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/runtime/tests/clinkerffi/upcall.c b/runtime/tests/clinkerffi/upcall.c new file mode 100644 index 00000000000..2c6bb939b15 --- /dev/null +++ b/runtime/tests/clinkerffi/upcall.c @@ -0,0 +1,2849 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + +/** + * This file contains the native code used by the test cases via a Clinker FFI Upcall in java, + * which come from: + * org.openj9.test.jep389.upcall (JDK16/17) + * org.openj9.test.jep419.upcall (JDK18) + * org.openj9.test.jep424.upcall (JDK19+) + * + * Created by jincheng@ca.ibm.com + */ + +#include +#include +#include +#include "downcall.h" + +/** + * Add two booleans with the OR (||) operator by invoking an upcall method. + * + * @param boolArg1 the 1st boolean + * @param boolArg2 the 2nd boolean + * @param upcallMH the function pointer to the upcall method + * @return the result value + */ +bool +add2BoolsWithOrByUpcallMH(bool boolArg1, bool boolArg2, bool (*upcallMH)(bool, bool)) +{ + bool result = (*upcallMH)(boolArg1, boolArg2); + return result; +} + +/** + * Add two booleans with the OR (||) operator (the 2nd one is dereferenced from a pointer) + * by invoking an upcall method. + * + * @param boolArg1 a boolean + * @param boolArg2 a pointer to boolean + * @param upcallMH the function pointer to the upcall method + * @return the result value + */ +bool +addBoolAndBoolFromPointerWithOrByUpcallMH(bool boolArg1, bool *boolArg2, bool (*upcallMH)(bool, bool *)) +{ + bool result = (*upcallMH)(boolArg1, boolArg2); + return result; +} + +/** + * Add two booleans (the 2nd one assigned in native) with + * the OR (||) operator by invoking an upcall method. + * + * @param boolArg1 the 1st boolean + * @param upcallMH the function pointer to the upcall method + * @return the result value + */ +bool +addBoolAndBoolFromNativePtrWithOrByUpcallMH(bool boolArg1, bool (*upcallMH)(bool, bool *)) +{ + bool boolArg2 = 1; + bool result = (*upcallMH)(boolArg1, &boolArg2); + return result; +} + +/** + * Add two booleans with the OR (||) operator (the 2nd one is dereferenced from a pointer) + * by invoking an upcall method and return a pointer to the XOR result of booleans. + * + * @param boolArg1 the 1st boolean + * @param boolArg2 a pointer to the 2nd boolean + * @param upcallMH the function pointer to the upcall method + * @return the resulting pointer to boolean + */ +bool * +addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH(bool boolArg1, bool *boolArg2, bool *(*upcallMH)(bool, bool *)) +{ + bool *resultPtr = (*upcallMH)(boolArg1, boolArg2); + return resultPtr; +} + +/** + * Add two bytes by invoking an upcall method. + * Note: + * the passed-in arguments are byte given the byte size + * in Java is the same size as the char in C code. + * + * @param byteArg1 the 1st byte + * @param byteArg2 the 2nd byte + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +add2BytesByUpcallMH(char byteArg1, char byteArg2, char (*upcallMH)(char, char)) +{ + char byteSum = (*upcallMH)(byteArg1, byteArg2); + return byteSum; +} + +/** + * Add two bytes (the 2nd one is dereferenced from a pointer) + * by invoking an upcall method. + * Note: + * the passed-in arguments are byte given the byte size + * in Java is the same size as the char in C code. + * + * @param byteArg1 the 1st byte + * @param byteArg2 a pointer to the 2nd byte in char size + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndByteFromPointerByUpcallMH(char byteArg1, char *byteArg2, char (*upcallMH)(char, char *)) +{ + char byteSum = (*upcallMH)(byteArg1, byteArg2); + return byteSum; +} + +/** + * Add two bytes (the 2nd one assigned in native) by invoking an upcall method. + * Note: the passed-in arguments are byte given the byte size + * in Java is the same size as the char in C code. + * + * @param byteArg1 the 1st byte + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndByteFromNativePtrByUpcallMH(char byteArg1, char (*upcallMH)(char, char *)) +{ + char byteArg2 = 55; + char byteSum = (*upcallMH)(byteArg1, &byteArg2); + return byteSum; +} + +/** + * Add two bytes (the 2nd one is dereferenced from a pointer) by invoking an upcall method + * and return a pointer to the sum. + * Note: + * the passed-in arguments are byte given the byte size + * in Java is the same size as the char in C code. + * + * @param byteArg1 the 1st byte + * @param byteArg2 a pointer to the 2nd byte in char size + * @param upcallMH the function pointer to the upcall method + * @return the pointer to the sum + */ +char * +addByteAndByteFromPtr_RetPtr_ByUpcallMH(char byteArg1, char *byteArg2, char *(*upcallMH)(char, char *)) +{ + char *byteSum = (*upcallMH)(byteArg1, byteArg2); + return byteSum; +} + +/** + * Generate a new char by manipulating two chars by invoking an upcall method. + * + * @param charArg1 the 1st char + * @param charArg2 the 2nd char + * @param upcallMH the function pointer to the upcall method + * @return the resulting char + */ +short +createNewCharFrom2CharsByUpcallMH(short charArg1, short charArg2, short (*upcallMH)(short, short)) +{ + short result = (*upcallMH)(charArg1, charArg2); + return result; +} + +/** + * Generate a new char by manipulating two chars (the 1st one dereferenced from a pointer) + * by invoking an upcall method. + * + * @param charArg1 a pointer to the 1st char + * @param charArg2 the 2nd char + * @param upcallMH the function pointer to the upcall method + * @return the resulting char + */ +short +createNewCharFromCharAndCharFromPointerByUpcallMH(short *charArg1, short charArg2, short (*upcallMH)(short *, short)) +{ + short result = (*upcallMH)(charArg1, charArg2); + return result; +} + +/** + * Generate a new char by manipulating two chars (the 1st one is assigned in native) + * via invoking an upcall method. + * + * @param charArg2 the 2nd char + * @param upcallMH the function pointer to the upcall method + * @return the resulting char + */ +short +createNewCharFromCharAndCharFromNativePtrByUpcallMH(short charArg2, short (*upcallMH)(short *, short)) +{ + short charArg1 = 'B'; + short result = (*upcallMH)(&charArg1, charArg2); + return result; +} + +/** + * Generate a new char by manipulating two chars (the 1st one dereferenced from a pointer) + * by invoking an upcall method and return a pointer to a new char. + * + * @param charArg1 a pointer to the 1st char + * @param charArg2 the 2nd char + * @param upcallMH the function pointer to the upcall method + * @return the resulting pointer to a new char + */ +short * +createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH(short *charArg1, short charArg2, short *(*upcallMH)(short *, short)) +{ + short *resultPtr = (*upcallMH)(charArg1, charArg2); + return resultPtr; +} + +/** + * Add two shorts by invoking an upcall method. + * + * @param shortArg1 the 1st short + * @param shortArg2 the 2nd short + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +add2ShortsByUpcallMH(short shortArg1, short shortArg2, short (*upcallMH)(short, short)) +{ + short shortSum = (*upcallMH)(shortArg1, shortArg2); + return shortSum; +} + +/** + * Add two shorts (the 1st one dereferenced from a pointer) + * by invoking an upcall method. + * + * @param shortArg1 a pointer to the 1st short + * @param shortArg2 the 2nd short + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortFromPointerByUpcallMH(short *shortArg1, short shortArg2, short (*upcallMH)(short *, short)) +{ + short shortSum = (*upcallMH)(shortArg1, shortArg2); + return shortSum; +} + +/** + * Add two shorts (the 1st one is assigned in native) by invoking an upcall method. + * + * @param shortArg2 the 2nd short + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortFromNativePtrByUpcallMH(short shortArg2, short (*upcallMH)(short *, short)) +{ + short shortArg1 = 456; + short shortSum = (*upcallMH)(&shortArg1, shortArg2); + return shortSum; +} + +/** + * Add two shorts (the 1st one dereferenced from a pointer) by invoking an upcall method + * and return a pointer to the sum. + * + * @param shortArg1 a pointer to the 1st short + * @param shortArg2 the 2nd short + * @param upcallMH the function pointer to the upcall method + * @return the pointer to the sum + */ +short * +addShortAndShortFromPtr_RetPtr_ByUpcallMH(short *shortArg1, short shortArg2, short *(*upcallMH)(short *, short)) +{ + short *shortSum = (*upcallMH)(shortArg1, shortArg2); + return shortSum; +} + +/** + * Add two ints by invoking an upcall method. + * + * @param intArg1 the 1st int + * @param intArg2 the 2nd int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +add2IntsByUpcallMH(int intArg1, int intArg2, int (*upcallMH)(int, int)) +{ + int intSum = (*upcallMH)(intArg1, intArg2); + return intSum; +} + +/** + * Add two ints (the 2nd one is dereferenced from a pointer) + * by invoking an upcall method. + * + * @param intArg1 the 1st int + * @param intArg2 a pointer to the 2nd int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntFromPointerByUpcallMH(int intArg1, int *intArg2, int (*upcallMH)(int, int *)) +{ + int intSum = (*upcallMH)(intArg1, intArg2); + return intSum; +} + +/** + * Add two ints (the 2nd one is assigned in native) by invoking an upcall method. + * + * @param intArg1 the 1st int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntFromNativePtrByUpcallMH(int intArg1, int (*upcallMH)(int, int *)) +{ + int intArg2 = 444444; + int intSum = (*upcallMH)(intArg1, &intArg2); + return intSum; +} + +/** + * Add two ints (the 1st one is dereferenced from a pointer) by invoking an upcall method + * and return a pointer to the sum. + * + * @param intArg1 the 1st int + * @param intArg2 a pointer to the 2nd int + * @param upcallMH the function pointer to the upcall method + * @return the pointer to the sum + */ +int * +addIntAndIntFromPtr_RetPtr_ByUpcallMH(int intArg1, int *intArg2, int *(*upcallMH)(int, int *)) +{ + int *intSum = (*upcallMH)(intArg1, intArg2); + return intSum; +} + +/** + * Add three ints by invoking an upcall method. + * + * @param intArg1 the 1st int + * @param intArg2 the 2nd int + * @param intArg3 the 3rd int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +add3IntsByUpcallMH(int intArg1, int intArg2, int intArg3, int (*upcallMH)(int, int, int)) +{ + int intSum = (*upcallMH)(intArg1, intArg2, intArg3); + return intSum; +} + +/** + * Add an int and a char by invoking an upcall method. + * + * @param intArg an int + * @param charArg a char + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndCharByUpcallMH(int intArg, char charArg, int (*upcallMH)(int, char)) +{ + int sum = (*upcallMH)(intArg, charArg); + return sum; +} + +/** + * Add two ints without return value by invoking an upcall method. + * + * @param intArg1 the 1st int + * @param intArg2 the 2nd int + * @param upcallMH the function pointer to the upcall method + * @return void + */ +void +add2IntsReturnVoidByUpcallMH(int intArg1, int intArg2, int (*upcallMH)(int, int)) +{ + (*upcallMH)(intArg1, intArg2); +} + +/** + * Add two longs by invoking an upcall method. + * + * @param longArg1 the 1st long + * @param longArg2 the 2nd long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +add2LongsByUpcallMH(LONG longArg1, LONG longArg2, LONG (*upcallMH)(LONG, LONG)) +{ + LONG longSum = (*upcallMH)(longArg1, longArg2); + return longSum; +} + +/** + * Add two longs (the 1st one dereferenced from a pointer) + * by invoking an upcall method. + * + * @param longArg1 a pointer to the 1stlong + * @param longArg2 the 2nd long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongFromPointerByUpcallMH(LONG *longArg1, LONG longArg2, LONG (*upcallMH)(LONG *, LONG)) +{ + LONG longSum = (*upcallMH)(longArg1, longArg2); + return longSum; +} + +/** + * Add two longs (the 1st one is assigned in native) by invoking an upcall method. + * + * @param longArg2 the 2nd long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongFromNativePtrByUpcallMH(LONG longArg2, LONG (*upcallMH)(LONG *, LONG)) +{ + LONG longArg1 = 3333333333; + LONG longSum = (*upcallMH)(&longArg1, longArg2); + return longSum; +} + +/** + * Add two longs (the 1st one dereferenced from a pointer) by invoking an upcall method + * and return a pointer to the sum. + * + * @param longArg1 a pointer to the 1st long + * @param longArg2 the 2nd long + * @param upcallMH the function pointer to the upcall method + * @return the pointer to the sum + */ +LONG * +addLongAndLongFromPtr_RetPtr_ByUpcallMH(LONG *longArg1, LONG longArg2, LONG *(*upcallMH)(LONG *, LONG)) +{ + LONG *longSum = (*upcallMH)(longArg1, longArg2); + return longSum; +} + +/** + * Add two floats by invoking an upcall method. + * + * @param floatArg1 the 1st float + * @param floatArg2 the 2nd float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +add2FloatsByUpcallMH(float floatArg1, float floatArg2, float (*upcallMH)(float, float)) +{ + float floatSum = (*upcallMH)(floatArg1, floatArg2); + return floatSum; +} + +/** + * Add two floats (the 2nd one is dereferenced from a pointer) + * by invoking an upcall method. + * + * @param floatArg1 the 1st float + * @param floatArg2 a pointer to the 2nd float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatFromPointerByUpcallMH(float floatArg1, float *floatArg2, float (*upcallMH)(float, float *)) +{ + float floatSum = (*upcallMH)(floatArg1, floatArg2); + return floatSum; +} + +/** + * Add two floats (the 2nd one is assigned in native) by invoking an upcall method. + * + * @param floatArg1 the 1st float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatFromNativePtrByUpcallMH(float floatArg1, float (*upcallMH)(float, float *)) +{ + float floatArg2 = 6.79F; + float floatSum = (*upcallMH)(floatArg1, &floatArg2); + return floatSum; +} + +/** + * Add two floats (the 2nd one is dereferenced from a pointer) by invoking an upcall method + * and return a pointer to the sum. + * + * @param floatArg1 the 1st float + * @param floatArg2 a pointer to the 2nd float + * @param upcallMH the function pointer to the upcall method + * @return the pointer to the sum + */ +float * +addFloatAndFloatFromPtr_RetPtr_ByUpcallMH(float floatArg1, float *floatArg2, float *(*upcallMH)(float, float *)) +{ + float *floatSum = (*upcallMH)(floatArg1, floatArg2); + return floatSum; +} + +/** + * Add two doubles by invoking an upcall method. + * + * @param doubleArg1 the 1st double + * @param doubleArg2 the 2nd double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +add2DoublesByUpcallMH(double doubleArg1, double doubleArg2, double (*upcallMH)(double, double)) +{ + double doubleSum = (*upcallMH)(doubleArg1, doubleArg2); + return doubleSum; +} + +/** + * Add two doubles (the 1st one dereferenced from a pointer) + * by invoking an upcall method. + * + * @param doubleArg1 a pointer to the 1st double + * @param doubleArg2 the 2nd double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoubleFromPointerByUpcallMH(double *doubleArg1, double doubleArg2, double (*upcallMH)(double *, double)) +{ + double doubleSum = (*upcallMH)(doubleArg1, doubleArg2); + return doubleSum; +} + +/** + * Add two doubles (the 1st one is assigned in native) by invoking an upcall method. + * + * @param doubleArg2 the 2nd double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoubleFromNativePtrByUpcallMH(double doubleArg2, double (*upcallMH)(double *, double)) +{ + double doubleArg1 = 1159.748; + double doubleSum = (*upcallMH)(&doubleArg1, doubleArg2); + return doubleSum; +} + +/** + * Add two doubles (the 1st one dereferenced from a pointer) by invoking an upcall method + * and return a pointer to the sum. + * + * @param doubleArg1 a pointer to the 1st double + * @param doubleArg2 the 2nd double + * @param upcallMH the function pointer to the upcall method + * @return the pointer to the sum + */ +double * +addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH(double *doubleArg1, double doubleArg2, double *(*upcallMH)(double *, double)) +{ + double *doubleSum = (*upcallMH)(doubleArg1, doubleArg2); + return doubleSum; +} + +/** + * Add a boolean and two booleans of a struct with the XOR (^) operator + * by invoking an upcall method. + * + * @param arg1 a boolean + * @param arg2 a struct with two booleans + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolAndBoolsFromStructWithXorByUpcallMH(bool arg1, stru_Bool_Bool arg2, bool (*upcallMH)(bool, stru_Bool_Bool)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Add a boolean and 20 booleans of a struct with the XOR (^) operator + * by invoking an upcall method. + * + * @param arg1 a boolean + * @param arg2 a struct with 20 booleans + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolAnd20BoolsFromStructWithXorByUpcallMH(bool arg1, stru_20_Bools arg2, bool (*upcallMH)(bool, stru_20_Bools)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Add a boolean (dereferenced from a pointer) and all booleans of + * a struct with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a pointer to boolean + * @param arg2 a struct with two booleans + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolFromPointerAndBoolsFromStructWithXorByUpcallMH(bool *arg1, stru_Bool_Bool arg2, bool (*upcallMH)(bool *, stru_Bool_Bool)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Get a pointer to boolean by adding a boolean (dereferenced from a pointer) and all booleans + * of a struct with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a pointer to boolean + * @param arg2 a struct with two booleans + * @param upcallMH the function pointer to the upcall method + * @return a pointer to the XOR result of booleans + */ +bool * +addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointerByUpcallMH(bool *arg1, stru_Bool_Bool arg2, bool * (*upcallMH)(bool *, stru_Bool_Bool)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Add a boolean and two booleans of a struct (dereferenced from a pointer) + * with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a boolean + * @param arg2 a pointer to struct with two booleans + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolAndBoolsFromStructPointerWithXorByUpcallMH(bool arg1, stru_Bool_Bool *arg2, bool (*upcallMH)(bool, stru_Bool_Bool *)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Add a boolean and all booleans of a struct with a nested struct and a boolean + * with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a boolean + * @param arg2 a struct with a nested struct and a boolean + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolAndBoolsFromNestedStructWithXorByUpcallMH(bool arg1, stru_NestedStruct_Bool arg2, bool (*upcallMH)(bool, stru_NestedStruct_Bool)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Add a boolean and all booleans of a struct with a boolean and a nested struct (in reverse order) + * with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a boolean + * @param arg2 a struct with a boolean and a nested struct + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolAndBoolsFromNestedStructWithXor_reverseOrderByUpcallMH(bool arg1, stru_Bool_NestedStruct arg2, bool (*upcallMH)(bool, stru_Bool_NestedStruct)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Add a boolean and all booleans of a struct with a nested array and a boolean + * with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a boolean + * @param arg2 a struct with a nested array and a boolean + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolAndBoolsFromStructWithNestedBoolArrayByUpcallMH(bool arg1, stru_NestedBoolArray_Bool arg2, bool (*upcallMH)(bool, stru_NestedBoolArray_Bool)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Add a boolean and all booleans of a struct with a boolean and a nested array (in reverse order) + * with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a boolean + * @param arg2 a struct with a boolean and a nested array + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrderByUpcallMH(bool arg1, stru_Bool_NestedBoolArray arg2, bool (*upcallMH)(bool, stru_Bool_NestedBoolArray)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Add a boolean and all booleans of a struct with a nested struct array and a boolean + * with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a boolean + * @param arg2 a struct with a nested struct array and a boolean + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolAndBoolsFromStructWithNestedStructArrayByUpcallMH(bool arg1, stru_NestedStruArray_Bool arg2, bool (*upcallMH)(bool, stru_NestedStruArray_Bool)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Add a boolean and all booleans of a struct with a boolean and a nested struct array + * (in reverse order) with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a boolean + * @param arg2 a struct with a boolean and a nested struct array + * @param upcallMH the function pointer to the upcall method + * @return the XOR result of booleans + */ +bool +addBoolAndBoolsFromStructWithNestedStructArray_reverseOrderByUpcallMH(bool arg1, stru_Bool_NestedStruArray arg2, bool (*upcallMH)(bool, stru_Bool_NestedStruArray)) +{ + bool boolSum = (*upcallMH)(arg1, arg2); + return boolSum; +} + +/** + * Get a new struct by adding each boolean of two structs + * with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 the 1st struct with two booleans + * @param arg2 the 2nd struct with two booleans + * @param upcallMH the function pointer to the upcall method + * @return a struct with two booleans + */ +stru_Bool_Bool +add2BoolStructsWithXor_returnStructByUpcallMH(stru_Bool_Bool arg1, stru_Bool_Bool arg2, stru_Bool_Bool (*upcallMH)(stru_Bool_Bool, stru_Bool_Bool)) +{ + stru_Bool_Bool boolStruct = (*upcallMH)(arg1, arg2); + return boolStruct; +} + +/** + * Get a pointer to struct by adding each boolean of two structs + * with the XOR (^) operator by invoking an upcall method. + * + * @param arg1 a pointer to the 1st struct with two booleans + * @param arg2 the 2nd struct with two booleans + * @param upcallMH the function pointer to the upcall method + * @return a pointer to struct with two booleans + */ +stru_Bool_Bool * +add2BoolStructsWithXor_returnStructPointerByUpcallMH(stru_Bool_Bool *arg1, stru_Bool_Bool arg2, stru_Bool_Bool * (*upcallMH)(stru_Bool_Bool *, stru_Bool_Bool)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Get a new struct by adding each boolean of two structs with + * three booleans by invoking an upcall method. + * + * @param arg1 the 1st struct with three booleans + * @param arg2 the 2nd struct with three booleans + * @param upcallMH the function pointer to the upcall method + * @return a struct with three booleans + */ +stru_Bool_Bool_Bool +add3BoolStructsWithXor_returnStructByUpcallMH(stru_Bool_Bool_Bool arg1, stru_Bool_Bool_Bool arg2, stru_Bool_Bool_Bool (*upcallMH)(stru_Bool_Bool_Bool, stru_Bool_Bool_Bool)) +{ + stru_Bool_Bool_Bool boolStruct = (*upcallMH)(arg1, arg2); + return boolStruct; +} + +/** + * Add a byte and two bytes of a struct by invoking an upcall method. + * + * @param arg1 a byte + * @param arg2 a struct with two bytes + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndBytesFromStructByUpcallMH(char arg1, stru_Byte_Byte arg2, char (*upcallMH)(char, stru_Byte_Byte)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Add a byte and 20 bytes of a struct by invoking an upcall method. + * + * @param arg1 a byte + * @param arg2 a struct with 20 bytes + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAnd20BytesFromStructByUpcallMH(char arg1, stru_20_Bytes arg2, char (*upcallMH)(char, stru_20_Bytes)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Add a byte (dereferenced from a pointer) and two bytes + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to byte + * @param arg2 a struct with two bytes + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteFromPointerAndBytesFromStructByUpcallMH(char *arg1, stru_Byte_Byte arg2, char (*upcallMH)(char *, stru_Byte_Byte)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Get a pointer to byte by adding a byte (dereferenced from a pointer) + * and two bytes of a struct by invoking an upcall method. + * + * @param arg1 a pointer to byte + * @param arg2 a struct with two bytes + * @param upcallMH the function pointer to the upcall method + * @return a pointer to the sum + */ +char * +addByteFromPointerAndBytesFromStruct_returnBytePointerByUpcallMH(char *arg1, stru_Byte_Byte arg2, char * (*upcallMH)(char *, stru_Byte_Byte)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Add a byte and two bytes of a struct (dereferenced from a pointer) + * by invoking an upcall method. + * + * @param arg1 a byte + * @param arg2 a pointer to struct with two bytes + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndBytesFromStructPointerByUpcallMH(char arg1, stru_Byte_Byte *arg2, char (*upcallMH)(char, stru_Byte_Byte *)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Add a byte and all bytes of a struct with a nested struct + * and a byte by invoking an upcall method. + * + * @param arg1 a byte + * @param arg2 a struct with a nested struct and a byte + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndBytesFromNestedStructByUpcallMH(char arg1, stru_NestedStruct_Byte arg2, char (*upcallMH)(char, stru_NestedStruct_Byte)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Add a byte and all bytes of a struct with a byte and a nested struct + * (in reverse order) by invoking an upcall method. + * + * @param arg1 a byte + * @param arg2 a struct with a byte and a nested struct + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndBytesFromNestedStruct_reverseOrderByUpcallMH(char arg1, stru_Byte_NestedStruct arg2, char (*upcallMH)(char, stru_Byte_NestedStruct)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Add a byte and all byte elements of a struct with a nested byte array + * and a byte by invoking an upcall method. + * + * @param arg1 a byte + * @param arg2 a struct with a nested byte array and a byte + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndBytesFromStructWithNestedByteArrayByUpcallMH(char arg1, stru_NestedByteArray_Byte arg2, char (*upcallMH)(char, stru_NestedByteArray_Byte)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Add a byte and all byte elements of a struct with a byte and a nested byte array + * (in reverse order) by invoking an upcall method. + * + * @param arg1 a byte + * @param arg2 a struct with a byte and a nested byte array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndBytesFromStructWithNestedByteArray_reverseOrderByUpcallMH(char arg1, stru_Byte_NestedByteArray arg2, char (*upcallMH)(char, stru_Byte_NestedByteArray)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Add a byte and all byte elements of a struct with a nested struct array + * and a byte by invoking an upcall method. + * + * @param arg1 a byte + * @param arg2 a struct with a nested struct array and a byte + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndBytesFromStructWithNestedStructArrayByUpcallMH(char arg1, stru_NestedStruArray_Byte arg2, char (*upcallMH)(char, stru_NestedStruArray_Byte)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Add a byte and all byte elements of a struct with a byte and a nested + * struct array (in reverse order) by invoking an upcall method. + * + * @param arg1 a byte + * @param arg2 a struct with a byte and a nested byte array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +addByteAndBytesFromStructWithNestedStructArray_reverseOrderByUpcallMH(char arg1, stru_Byte_NestedStruArray arg2, char (*upcallMH)(char, stru_Byte_NestedStruArray)) +{ + char byteSum = (*upcallMH)(arg1, arg2); + return byteSum; +} + +/** + * Get a new struct by adding each byte element of two structs with + * two byte elements by invoking an upcall method. + * + * @param arg1 the 1st struct with one byte + * @param arg2 the 2nd struct with one byte + * @param upcallMH the function pointer to the upcall method + * @return a struct with one byte + */ +stru_Byte +add1ByteStructs_returnStructByUpcallMH(stru_Byte arg1, stru_Byte arg2, stru_Byte (*upcallMH)(stru_Byte, stru_Byte)) +{ + stru_Byte byteStruct = (*upcallMH)(arg1, arg2); + return byteStruct; +} + +/** + * Get a new struct by adding each byte element of two structs with + * two byte elements by invoking an upcall method. + * + * @param arg1 the 1st struct with two bytes + * @param arg2 the 2nd struct with two bytes + * @param upcallMH the function pointer to the upcall method + * @return a struct with two bytes + */ +stru_Byte_Byte +add2ByteStructs_returnStructByUpcallMH(stru_Byte_Byte arg1, stru_Byte_Byte arg2, stru_Byte_Byte (*upcallMH)(stru_Byte_Byte, stru_Byte_Byte)) +{ + stru_Byte_Byte byteStruct = (*upcallMH)(arg1, arg2); + return byteStruct; +} + +/** + * Get a pointer to struct by adding each byte element of two structs + * with two byte elements by invoking an upcall method. + * + * @param arg1 a pointer to the 1st struct with two bytes + * @param arg2 the 2nd struct with two bytes + * @param upcallMH the function pointer to the upcall method + * @return a pointer to struct with two bytes + */ +stru_Byte_Byte * +add2ByteStructs_returnStructPointerByUpcallMH(stru_Byte_Byte *arg1, stru_Byte_Byte arg2, stru_Byte_Byte * (*upcallMH)(stru_Byte_Byte *, stru_Byte_Byte)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Get a new struct by adding each byte element of two structs with + * three byte elements by invoking an upcall method. + * + * @param arg1 the 1st struct with three bytes + * @param arg2 the 2nd struct with three bytes + * @param upcallMH the function pointer to the upcall method + * @return a struct with three bytes + */ +stru_Byte_Byte_Byte +add3ByteStructs_returnStructByUpcallMH(stru_Byte_Byte_Byte arg1, stru_Byte_Byte_Byte arg2, stru_Byte_Byte_Byte (*upcallMH)(stru_Byte_Byte_Byte, stru_Byte_Byte_Byte)) +{ + stru_Byte_Byte_Byte byteStruct = (*upcallMH)(arg1, arg2); + return byteStruct; +} + +/** + * Generate a new char by adding a char and two chars of a struct + * by invoking an upcall method. + * + * @param arg1 a char + * @param arg2 a struct with two chars + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharAndCharsFromStructByUpcallMH(short arg1, stru_Char_Char arg2, short (*upcallMH)(short, stru_Char_Char)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + +/** + * Generate a new char by adding a char and 10 chars of a struct + * by invoking an upcall method. + * + * @param arg1 a char + * @param arg2 a struct with 10 chars + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharAnd10CharsFromStructByUpcallMH(short arg1, stru_10_Chars arg2, short (*upcallMH)(short, stru_10_Chars)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + + +/** + * Generate a new char by adding a char (dereferenced from a pointer) + * and two chars of a struct by invoking an upcall method. + * + * @param arg1 a pointer to char + * @param arg2 a struct with two chars + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharFromPointerAndCharsFromStructByUpcallMH(short *arg1, stru_Char_Char arg2, short (*upcallMH)(short *, stru_Char_Char)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + +/** + * Get a pointer to char by adding a char (dereferenced from a pointer) + * and two chars of a struct by invoking an upcall method. + * + * @param arg1 a pointer to char + * @param arg2 a struct with two chars + * @param upcallMH the function pointer to the upcall method + * @return a pointer to a new char + */ +short * +addCharFromPointerAndCharsFromStruct_returnCharPointerByUpcallMH(short *arg1, stru_Char_Char arg2, short * (*upcallMH)(short *, stru_Char_Char)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Generate a new char by adding a char and two chars of struct (dereferenced from a pointer) + * by invoking an upcall method. + * + * @param arg1 a char + * @param arg2 a pointer to struct with two chars + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharAndCharsFromStructPointerByUpcallMH(short arg1, stru_Char_Char *arg2, short (*upcallMH)(short, stru_Char_Char *)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + +/** + * Generate a new char by adding a char and all char elements of a struct + * with a nested struct and a char by invoking an upcall method. + * + * @param arg1 a char + * @param arg2 a struct with a nested struct + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharAndCharsFromNestedStructByUpcallMH(short arg1, stru_NestedStruct_Char arg2, short (*upcallMH)(short, stru_NestedStruct_Char)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + +/** + * Generate a new char by adding a char and all char elements of a struct with a char + * and a nested struct (in reverse order) by invoking an upcall method. + * + * @param arg1 a char + * @param arg2 a struct with a char and a nested struct + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharAndCharsFromNestedStruct_reverseOrderByUpcallMH(short arg1, stru_Char_NestedStruct arg2, short (*upcallMH)(short, stru_Char_NestedStruct)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + +/** + * Generate a new char by adding a char and all char elements of a struct with + * a nested char array and a char by invoking an upcall method. + * + * @param arg1 a char + * @param arg2 a struct with a nested char array and a char + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharAndCharsFromStructWithNestedCharArrayByUpcallMH(short arg1, stru_NestedCharArray_Char arg2, short (*upcallMH)(short, stru_NestedCharArray_Char)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + +/** + * Generate a new char by adding a char and all char elements of a struct with a char + * and a nested char array (in reverse order) by invoking an upcall method. + * + * @param arg1 a char + * @param arg2 a struct with a char and a nested char array + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharAndCharsFromStructWithNestedCharArray_reverseOrderByUpcallMH(short arg1, stru_Char_NestedCharArray arg2, short (*upcallMH)(short, stru_Char_NestedCharArray)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + +/** + * Generate a new char by adding a char and all char elements of a struct with + * a nested struct array and a char by invoking an upcall method. + * + * @param arg1 a char + * @param arg2 a struct with a nested char array and a char + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharAndCharsFromStructWithNestedStructArrayByUpcallMH(short arg1, stru_NestedStruArray_Char arg2, short (*upcallMH)(short, stru_NestedStruArray_Char)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + +/** + * Generate a new char by adding a char and all char elements of a struct with a char + * and a nested struct array (in reverse order) by invoking an upcall method. + * + * @param arg1 a char + * @param arg2 a struct with a char and a nested char array + * @param upcallMH the function pointer to the upcall method + * @return a new char + */ +short +addCharAndCharsFromStructWithNestedStructArray_reverseOrderByUpcallMH(short arg1, stru_Char_NestedStruArray arg2, short (*upcallMH)(short, stru_Char_NestedStruArray)) +{ + short result = (*upcallMH)(arg1, arg2); + return result; +} + +/** + * Create a new struct by adding each char element of two structs + * by invoking an upcall method. + * + * @param arg1 the 1st struct with two chars + * @param arg2 the 2nd struct with two chars + * @param upcallMH the function pointer to the upcall method + * @return a new struct of with two chars + */ +stru_Char_Char +add2CharStructs_returnStructByUpcallMH(stru_Char_Char arg1, stru_Char_Char arg2, stru_Char_Char (*upcallMH)(stru_Char_Char, stru_Char_Char)) +{ + stru_Char_Char charStruct = (*upcallMH)(arg1, arg2); + return charStruct; +} + +/** + * Get a pointer to a struct by adding each element of two structs + * by invoking an upcall method. + * + * @param arg1 a pointer to the 1st struct with two chars + * @param arg2 the 2nd struct with two chars + * @param upcallMH the function pointer to the upcall method + * @return a pointer to a struct of with two chars + */ +stru_Char_Char * +add2CharStructs_returnStructPointerByUpcallMH(stru_Char_Char *arg1, stru_Char_Char arg2, stru_Char_Char * (*upcallMH)(stru_Char_Char *, stru_Char_Char)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Create a new struct by adding each char element of two structs + * with three chars by invoking an upcall method. + * + * @param arg1 the 1st struct with three chars + * @param arg2 the 2nd struct with three chars + * @param upcallMH the function pointer to the upcall method + * @return a new struct of with three chars + */ +stru_Char_Char_Char +add3CharStructs_returnStructByUpcallMH(stru_Char_Char_Char arg1, stru_Char_Char_Char arg2, stru_Char_Char_Char (*upcallMH)(stru_Char_Char_Char, stru_Char_Char_Char)) +{ + stru_Char_Char_Char charStruct = (*upcallMH)(arg1, arg2); + return charStruct; +} + +/** + * Add a short and two shorts of a struct by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a struct with two shorts + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortsFromStructByUpcallMH(short arg1, stru_Short_Short arg2, short (*upcallMH)(short, stru_Short_Short)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a short and 10 shorts of a struct by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a struct with 10 shorts + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAnd10ShortsFromStructByUpcallMH(short arg1, stru_10_Shorts arg2, short (*upcallMH)(short, stru_10_Shorts)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a short (dereferenced from a pointer) and two shorts of + * a struct by invoking an upcall method. + * + * @param arg1 a pointer to short + * @param arg2 a struct with two shorts + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortFromPointerAndShortsFromStructByUpcallMH(short *arg1, stru_Short_Short arg2, short (*upcallMH)(short *, stru_Short_Short)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a short (dereferenced from a pointer) and two shorts + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to short + * @param arg2 a struct with two shorts + * @param upcallMH the function pointer to the upcall method + * @return a pointer to the sum + */ +short * +addShortFromPointerAndShortsFromStruct_returnShortPointerByUpcallMH(short *arg1, stru_Short_Short arg2, short * (*upcallMH)(short *, stru_Short_Short)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Add a short and two shorts of a struct (dereferenced from a pointer) + * by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a pointer to struct with two shorts + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortsFromStructPointerByUpcallMH(short arg1, stru_Short_Short *arg2, short (*upcallMH)(short, stru_Short_Short *)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a short and all short elements of a struct with a nested struct + * and a short by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a struct with a nested struct and a short + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortsFromNestedStructByUpcallMH(short arg1, stru_NestedStruct_Short arg2, short (*upcallMH)(short, stru_NestedStruct_Short)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a short and all short elements of a struct with a short and a nested struct + * (in reverse order) by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a struct with a short and a nested struct + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortsFromNestedStruct_reverseOrderByUpcallMH(short arg1, stru_Short_NestedStruct arg2, short (*upcallMH)(short, stru_Short_NestedStruct)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a short and all short elements of a struct with a nested short array + * and a short by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a struct with a nested short array and a short + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortsFromStructWithNestedShortArrayByUpcallMH(short arg1, stru_NestedShortArray_Short arg2, short (*upcallMH)(short, stru_NestedShortArray_Short)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a short and all short elements of a struct with a short and a nested + * short array (in reverse order) by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a struct with a short and a nested short array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortsFromStructWithNestedShortArray_reverseOrderByUpcallMH(short arg1, stru_Short_NestedShortArray arg2, short (*upcallMH)(short, stru_Short_NestedShortArray)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a short and all short elements of a struct with a nested struct + * array and a short by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a struct with a nested short array and a short + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortsFromStructWithNestedStructArrayByUpcallMH(short arg1, stru_NestedStruArray_Short arg2, short (*upcallMH)(short, stru_NestedStruArray_Short)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a short and all short elements of a struct with a short and a nested + * struct array (in reverse order) by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a struct with a short and a nested short array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAndShortsFromStructWithNestedStructArray_reverseOrderByUpcallMH(short arg1, stru_Short_NestedStruArray arg2, short (*upcallMH)(short, stru_Short_NestedStruArray)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Get a new struct by adding each short element of two structs + * with two short elements by invoking an upcall method. + * + * @param arg1 the 1st struct with two shorts + * @param arg2 the 2nd struct with two shorts + * @param upcallMH the function pointer to the upcall method + * @return a struct with two shorts + */ +stru_Short_Short +add2ShortStructs_returnStructByUpcallMH(stru_Short_Short arg1, stru_Short_Short arg2, stru_Short_Short (*upcallMH)(stru_Short_Short, stru_Short_Short)) +{ + stru_Short_Short shortStruct = (*upcallMH)(arg1, arg2); + return shortStruct; +} + +/** + * Get a pointer to struct by adding each short element of two structs + * with two short elements by invoking an upcall method. + * + * @param arg1 a pointer to the 1st struct with two shorts + * @param arg2 the 2nd struct with two shorts + * @param upcallMH the function pointer to the upcall method + * @return a pointer to struct with two shorts + */ +stru_Short_Short * +add2ShortStructs_returnStructPointerByUpcallMH(stru_Short_Short *arg1, stru_Short_Short arg2, stru_Short_Short * (*upcallMH)(stru_Short_Short *, stru_Short_Short)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Get a new struct by adding each short element of two structs with + * three short elements by invoking an upcall method. + * + * @param arg1 the 1st struct with three shorts + * @param arg2 the 2nd struct with three shorts + * @param upcallMH the function pointer to the upcall method + * @return a struct with three shorts + */ +stru_Short_Short_Short +add3ShortStructs_returnStructByUpcallMH(stru_Short_Short_Short arg1, stru_Short_Short_Short arg2, stru_Short_Short_Short (*upcallMH)(stru_Short_Short_Short, stru_Short_Short_Short)) +{ + stru_Short_Short_Short shortStruct = (*upcallMH)(arg1, arg2); + return shortStruct; +} + +/** + * Add an int and two ints of a struct + * by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with two ints + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntsFromStructByUpcallMH(int arg1, stru_Int_Int arg2, int (*upcallMH)(int, stru_Int_Int)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int and 5 ints of a struct + * by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with 5 ints + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAnd5IntsFromStructByUpcallMH(int arg1, stru_5_Ints arg2, int (*upcallMH)(int, stru_5_Ints)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int (dereferenced from a pointer) and two ints + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to int + * @param arg2 a struct with two ints + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntFromPointerAndIntsFromStructByUpcallMH(int *arg1, stru_Int_Int arg2, int (*upcallMH)(int *, stru_Int_Int)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int (dereferenced from a pointer) and two ints + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to int + * @param arg2 a struct with two ints + * @param upcallMH the function pointer to the upcall method + * @return a pointer to the sum + */ +int * +addIntFromPointerAndIntsFromStruct_returnIntPointerByUpcallMH(int *arg1, stru_Int_Int arg2, int *(*upcallMH)(int *, stru_Int_Int)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Add an int and two ints of a struct (dereferenced from a pointer) + * by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a pointer to struct with two ints + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntsFromStructPointerByUpcallMH(int arg1, stru_Int_Int *arg2, int (*upcallMH)(int, stru_Int_Int *)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int and all int elements of a struct with a nested struct + * and an int by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with a nested struct and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntsFromNestedStructByUpcallMH(int arg1, stru_NestedStruct_Int arg2, int (*upcallMH)(int, stru_NestedStruct_Int)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int and all int elements of a struct with an int and + * a nested struct (in reverse order) by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with an int and a nested struct + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntsFromNestedStruct_reverseOrderByUpcallMH(int arg1, stru_Int_NestedStruct arg2, int (*upcallMH)(int, stru_Int_NestedStruct)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int and all int elements of a struct with a nested int array + * and an int by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with a nested int array and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntsFromStructWithNestedIntArrayByUpcallMH(int arg1, stru_NestedIntArray_Int arg2, int (*upcallMH)(int, stru_NestedIntArray_Int)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int and all int elements of a struct with an int and a + * nested int array (in reverse order) by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with an int and a nested int array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntsFromStructWithNestedIntArray_reverseOrderByUpcallMH(int arg1, stru_Int_NestedIntArray arg2, int (*upcallMH)(int, stru_Int_NestedIntArray)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int and all int elements of a struct with a nested struct array + * and an int by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with a nested int array and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntsFromStructWithNestedStructArrayByUpcallMH(int arg1, stru_NestedStruArray_Int arg2, int (*upcallMH)(int, stru_NestedStruArray_Int)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int and all int elements of a struct with an int and a nested + * struct array (in reverse order) by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with an int and a nested int array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntsFromStructWithNestedStructArray_reverseOrderByUpcallMH(int arg1, stru_Int_NestedStruArray arg2, int (*upcallMH)(int, stru_Int_NestedStruArray)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Get a new struct by adding each int element of two structs + * by invoking an upcall method. + * + * @param arg1 the 1st struct with two ints + * @param arg2 the 2nd struct with two ints + * @param upcallMH the function pointer to the upcall method + * @return a struct with two ints + */ +stru_Int_Int +add2IntStructs_returnStructByUpcallMH(stru_Int_Int arg1, stru_Int_Int arg2, stru_Int_Int (*upcallMH)(stru_Int_Int, stru_Int_Int)) +{ + stru_Int_Int intStruct = (*upcallMH)(arg1, arg2); + return intStruct; +} + +/** + * Get a pointer to struct by adding each int element of two structs + * by invoking an upcall method. + * + * @param arg1 a pointer to the 1st struct with two ints + * @param arg2 the 2nd struct with two ints + * @param upcallMH the function pointer to the upcall method + * @return a pointer to struct with two ints + */ +stru_Int_Int * +add2IntStructs_returnStructPointerByUpcallMH(stru_Int_Int *arg1, stru_Int_Int arg2, stru_Int_Int * (*upcallMH)(stru_Int_Int *, stru_Int_Int)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Get a new struct by adding each int element of two structs + * by invoking an upcall method. + * + * @param arg1 the 1st struct with three ints + * @param arg2 the 2nd struct with three ints + * @param upcallMH the function pointer to the upcall method + * @return a struct with three ints + */ +stru_Int_Int_Int +add3IntStructs_returnStructByUpcallMH(stru_Int_Int_Int arg1, stru_Int_Int_Int arg2, stru_Int_Int_Int (*upcallMH)(stru_Int_Int_Int, stru_Int_Int_Int)) +{ + stru_Int_Int_Int intStruct = (*upcallMH)(arg1, arg2); + return intStruct; +} + +/** + * Add a long and two longs of a struct by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with two longs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongsFromStructByUpcallMH(LONG arg1, stru_Long_Long arg2, LONG (*upcallMH)(LONG, stru_Long_Long)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a long (dereferenced from a pointer) and two longs + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to long + * @param arg2 a struct with two longs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongFromPointerAndLongsFromStructByUpcallMH(LONG *arg1, stru_Long_Long arg2, LONG (*upcallMH)(LONG *, stru_Long_Long)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a long (dereferenced from a pointer) and two longs + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to long + * @param arg2 a struct with two longs + * @param upcallMH the function pointer to the upcall method + * @return a pointer to the sum + */ +LONG * +addLongFromPointerAndLongsFromStruct_returnLongPointerByUpcallMH(LONG *arg1, stru_Long_Long arg2, LONG * (*upcallMH)(LONG *, stru_Long_Long)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Add a long and two longs of a struct (dereferenced from a pointer) + * by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a pointer to struct with two longs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongsFromStructPointerByUpcallMH(LONG arg1, stru_Long_Long *arg2, LONG (*upcallMH)(LONG, stru_Long_Long *)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a long and all long elements of a struct with a nested struct + * and a long by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with a nested struct and long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongsFromNestedStructByUpcallMH(LONG arg1, stru_NestedStruct_Long arg2, LONG (*upcallMH)(LONG, stru_NestedStruct_Long)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a long and all long elements of a struct with a long and a nested + * struct (in reverse order) by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with a long and a nested struct + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongsFromNestedStruct_reverseOrderByUpcallMH(LONG arg1, stru_Long_NestedStruct arg2, LONG (*upcallMH)(LONG, stru_Long_NestedStruct)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a long and all long elements of a struct with a nested long + * array and a long by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with a nested long array and a long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongsFromStructWithNestedLongArrayByUpcallMH(LONG arg1, stru_NestedLongArray_Long arg2, LONG (*upcallMH)(LONG, stru_NestedLongArray_Long)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a long and all long elements of a struct with a long and a nested + * long array (in reverse order) by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with a long and a nested long array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongsFromStructWithNestedLongArray_reverseOrderByUpcallMH(LONG arg1, stru_Long_NestedLongArray arg2, LONG (*upcallMH)(LONG, stru_Long_NestedLongArray)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a long and all long elements of a struct with a nested struct + * array and a long by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with a nested long array and a long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongsFromStructWithNestedStructArrayByUpcallMH(LONG arg1, stru_NestedStruArray_Long arg2, LONG (*upcallMH)(LONG, stru_NestedStruArray_Long)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a long and all long elements of a struct with a long and a nested + * struct array (in reverse order) by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with a long and a nested long array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLongsFromStructWithNestedStructArray_reverseOrderByUpcallMH(LONG arg1, stru_Long_NestedStruArray arg2, LONG (*upcallMH)(LONG, stru_Long_NestedStruArray)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Get a new struct by adding each long element of two structs + * by invoking an upcall method. + * + * @param arg1 the 1st struct with two longs + * @param arg2 the 2nd struct with two longs + * @param upcallMH the function pointer to the upcall method + * @return a struct with two longs + */ +stru_Long_Long +add2LongStructs_returnStructByUpcallMH(stru_Long_Long arg1, stru_Long_Long arg2, stru_Long_Long (*upcallMH)(stru_Long_Long, stru_Long_Long)) +{ + stru_Long_Long longStruct = (*upcallMH)(arg1, arg2); + return longStruct; +} + +/** + * Get a pointer to struct by adding each long element of two structs + * by invoking an upcall method. + * + * @param arg1 a pointer to the 1st struct with two longs + * @param arg2 the 2nd struct with two longs + * @param upcallMH the function pointer to the upcall method + * @return a pointer to struct with two longs + */ +stru_Long_Long * +add2LongStructs_returnStructPointerByUpcallMH(stru_Long_Long *arg1, stru_Long_Long arg2, stru_Long_Long * (*upcallMH)(stru_Long_Long *, stru_Long_Long)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Get a new struct by adding each long element of two structs + * by invoking an upcall method. + * + * @param arg1 the 1st struct with three longs + * @param arg2 the 2nd struct with three longs + * @param upcallMH the function pointer to the upcall method + * @return a struct with three longs + */ +stru_Long_Long_Long +add3LongStructs_returnStructByUpcallMH(stru_Long_Long_Long arg1, stru_Long_Long_Long arg2, stru_Long_Long_Long (*upcallMH)(stru_Long_Long_Long, stru_Long_Long_Long)) +{ + stru_Long_Long_Long longStruct = (*upcallMH)(arg1, arg2); + return longStruct; +} + +/** + * Add a float and two floats of a struct by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with two floats + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatsFromStructByUpcallMH(float arg1, stru_Float_Float arg2, float (*upcallMH)(float, stru_Float_Float)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float and 5 floats of a struct by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with 5 floats + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAnd5FloatsFromStructByUpcallMH(float arg1, stru_5_Floats arg2, float (*upcallMH)(float, stru_5_Floats)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float (dereferenced from a pointer) and two floats + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to float + * @param arg2 a struct with two floats + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatFromPointerAndFloatsFromStructByUpcallMH(float *arg1, stru_Float_Float arg2, float (*upcallMH)(float *, stru_Float_Float)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float (dereferenced from a pointer) and two floats + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to float + * @param arg2 a struct with two floats + * @param upcallMH the function pointer to the upcall method + * @return a pointer to the sum + */ +float * +addFloatFromPointerAndFloatsFromStruct_returnFloatPointerByUpcallMH(float *arg1, stru_Float_Float arg2, float * (*upcallMH)(float *, stru_Float_Float)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Add a float and two floats of a struct (dereferenced from a pointer) + * by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a pointer to struct with two floats + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatsFromStructPointerByUpcallMH(float arg1, stru_Float_Float *arg2, float (*upcallMH)(float, stru_Float_Float *)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float and all float elements of a struct with a nested + * struct and a float by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with a nested struct and a float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatsFromNestedStructByUpcallMH(float arg1, stru_NestedStruct_Float arg2, float (*upcallMH)(float, stru_NestedStruct_Float)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float and all float elements of a struct with a float and a nested struct + * (in reverse order) by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with a float and a nested struct + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatsFromNestedStruct_reverseOrderByUpcallMH(float arg1, stru_Float_NestedStruct arg2, float (*upcallMH)(float, stru_Float_NestedStruct)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float and all float elements of a struct with a nested + * float array and a float by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with a nested float array and a float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatsFromStructWithNestedFloatArrayByUpcallMH(float arg1, stru_NestedFloatArray_Float arg2, float (*upcallMH)(float, stru_NestedFloatArray_Float)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float and all float elements of a struct with a float and a nested + * float array (in reverse order) by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with a float and a nested float array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrderByUpcallMH(float arg1, stru_Float_NestedFloatArray arg2, float (*upcallMH)(float, stru_Float_NestedFloatArray)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float and all float elements of a struct with a nested + * struct array and a float by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with a nested float array and a float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatsFromStructWithNestedStructArrayByUpcallMH(float arg1, stru_NestedStruArray_Float arg2, float (*upcallMH)(float, stru_NestedStruArray_Float)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float and all float elements of a struct with a float and a nested + * struct array (in reverse order) by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with a float and a nested float array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatsFromStructWithNestedStructArray_reverseOrderByUpcallMH(float arg1, stru_Float_NestedStruArray arg2, float (*upcallMH)(float, stru_Float_NestedStruArray)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Create a new struct by adding each float element of two structs + * by invoking an upcall method. + * + * @param arg1 the 1st struct with two floats + * @param arg2 the 2nd struct with two floats + * @param upcallMH the function pointer to the upcall method + * @return a struct with two floats + */ +stru_Float_Float +add2FloatStructs_returnStructByUpcallMH(stru_Float_Float arg1, stru_Float_Float arg2, stru_Float_Float (*upcallMH)(stru_Float_Float, stru_Float_Float)) +{ + stru_Float_Float floatStruct = (*upcallMH)(arg1, arg2); + return floatStruct; +} + +/** + * Get a pointer to struct by adding each float element of two structs + * by invoking an upcall method. + * + * @param arg1 a pointer to the 1st struct with two floats + * @param arg2 the 2nd struct with two floats + * @param upcallMH the function pointer to the upcall method + * @return a pointer to struct with two floats + */ +stru_Float_Float * +add2FloatStructs_returnStructPointerByUpcallMH(stru_Float_Float *arg1, stru_Float_Float arg2, stru_Float_Float * (*upcallMH)(stru_Float_Float *, stru_Float_Float)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Create a new struct by adding each float element of two structs + * by invoking an upcall method. + * + * @param arg1 the 1st struct with three floats + * @param arg2 the 2nd struct with three floats + * @param upcallMH the function pointer to the upcall method + * @return a struct with three floats + */ +stru_Float_Float_Float +add3FloatStructs_returnStructByUpcallMH(stru_Float_Float_Float arg1, stru_Float_Float_Float arg2, stru_Float_Float_Float (*upcallMH)(stru_Float_Float_Float, stru_Float_Float_Float)) +{ + stru_Float_Float_Float floatStruct = (*upcallMH)(arg1, arg2); + return floatStruct; +} + +/** + * Add a double and two doubles of a struct by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with two doubles + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoublesFromStructByUpcallMH(double arg1, stru_Double_Double arg2, double (*upcallMH)(double, stru_Double_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double (dereferenced from a pointer) and two doubles + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to double + * @param arg2 a struct with two doubles + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleFromPointerAndDoublesFromStructByUpcallMH(double *arg1, stru_Double_Double arg2, double (*upcallMH)(double *, stru_Double_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double (dereferenced from a pointer) and two doubles + * of a struct by invoking an upcall method. + * + * @param arg1 a pointer to double + * @param arg2 a struct with two doubles + * @param upcallMH the function pointer to the upcall method + * @return a pointer to the sum + */ +double * +addDoubleFromPointerAndDoublesFromStruct_returnDoublePointerByUpcallMH(double *arg1, stru_Double_Double arg2, double * (*upcallMH)(double *, stru_Double_Double)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Add a double and two doubles of a struct (dereferenced from a pointer) + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a pointer to struct with two doubles + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoublesFromStructPointerByUpcallMH(double arg1, stru_Double_Double *arg2, double (*upcallMH)(double, stru_Double_Double *)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all doubles of a struct with a nested struct + * and a double by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a nested struct and a double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoublesFromNestedStructByUpcallMH(double arg1, stru_NestedStruct_Double arg2, double (*upcallMH)(double, stru_NestedStruct_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all doubles of a struct with a double and a nested struct + * (in reverse order) by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a double a nested struct + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoublesFromNestedStruct_reverseOrderByUpcallMH(double arg1, stru_Double_NestedStruct arg2, double (*upcallMH)(double, stru_Double_NestedStruct)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all double elements of a struct with a nested + * double array and a double by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a nested double array and a double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoublesFromStructWithNestedDoubleArrayByUpcallMH(double arg1, stru_NestedDoubleArray_Double arg2, double (*upcallMH)(double, stru_NestedDoubleArray_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all double elements of a struct with a double and a nested + * double array (in reverse order) by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a double and a nested double array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrderByUpcallMH(double arg1, stru_Double_NestedDoubleArray arg2, double (*upcallMH)(double, stru_Double_NestedDoubleArray)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all double elements of a struct with a nested struct array + * and a double by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a nested double array and a double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoublesFromStructWithNestedStructArrayByUpcallMH(double arg1, stru_NestedStruArray_Double arg2, double (*upcallMH)(double, stru_NestedStruArray_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all double elements of a struct with a double and a nested + * struct array (in reverse order) by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a double and a nested double array + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrderByUpcallMH(double arg1, stru_Double_NestedStruArray arg2, double (*upcallMH)(double, stru_Double_NestedStruArray)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Create a new struct by adding each double element of two structs + * by invoking an upcall method. + * + * @param arg1 the 1st struct with two doubles + * @param arg2 the 2nd struct with two doubles + * @param upcallMH the function pointer to the upcall method + * @return a struct with two doubles + */ +stru_Double_Double +add2DoubleStructs_returnStructByUpcallMH(stru_Double_Double arg1, stru_Double_Double arg2, stru_Double_Double (*upcallMH)(stru_Double_Double, stru_Double_Double)) +{ + stru_Double_Double doubleStruct = (*upcallMH)(arg1, arg2); + return doubleStruct; +} + +/** + * Get a pointer to struct by adding each double element of two structs + * by invoking an upcall method. + * + * @param arg1 a pointer to the 1st struct with two doubles + * @param arg2 the 2nd struct with two doubles + * @param upcallMH the function pointer to the upcall method + * @return a pointer to struct with two doubles + */ +stru_Double_Double * +add2DoubleStructs_returnStructPointerByUpcallMH(stru_Double_Double *arg1, stru_Double_Double arg2, stru_Double_Double * (*upcallMH)(stru_Double_Double *, stru_Double_Double)) +{ + arg1 = (*upcallMH)(arg1, arg2); + return arg1; +} + +/** + * Create a new struct by adding each double element of two structs + * by invoking an upcall method. + * + * @param arg1 the 1st struct with three doubles + * @param arg2 the 2nd struct with three doubles + * @param upcallMH the function pointer to the upcall method + * @return a struct with three doubles + */ +stru_Double_Double_Double +add3DoubleStructs_returnStructByUpcallMH(stru_Double_Double_Double arg1, stru_Double_Double_Double arg2, stru_Double_Double_Double (*upcallMH)(stru_Double_Double_Double, stru_Double_Double_Double)) +{ + stru_Double_Double_Double doubleStruct = (*upcallMH)(arg1, arg2); + return doubleStruct; +} + +/** + * Add an int and all elements (int & short) of a struct + * by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with an int and a short + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndIntShortFromStructByUpcallMH(int arg1, stru_Int_Short arg2, int (*upcallMH)(int, stru_Int_Short)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int and all elements (short & int) of a struct + * by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with a short and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntAndShortIntFromStructByUpcallMH(int arg1, stru_Short_Int arg2, int (*upcallMH)(int, stru_Short_Int)) +{ + int intSum = (*upcallMH)(arg1, arg2); + return intSum; +} + +/** + * Add an int and all elements (int & long) of a struct + * by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with an int and a long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addIntAndIntLongFromStructByUpcallMH(int arg1, stru_Int_Long arg2, LONG (*upcallMH)(int, stru_Int_Long)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add an int and all elements (long & int) of a struct + * by invoking an upcall method. + * + * @param arg1 an int + * @param arg2 a struct with a long and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addIntAndLongIntFromStructByUpcallMH(int arg1, stru_Long_Int arg2, LONG (*upcallMH)(int, stru_Long_Int)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a double and all elements (double & int) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a double and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoubleIntFromStructByUpcallMH(double arg1, stru_Double_Int arg2, double (*upcallMH)(double, stru_Double_Int)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (int & double) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with an int and a double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndIntDoubleFromStructByUpcallMH(double arg1, stru_Int_Double arg2, double (*upcallMH)(double, stru_Int_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (float & double) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a float and a double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndFloatDoubleFromStructByUpcallMH(double arg1, stru_Float_Double arg2, double (*upcallMH)(double, stru_Float_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (double & float) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a double and a float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoubleFloatFromStructByUpcallMH(double arg1, stru_Double_Float arg2, double (*upcallMH)(double, stru_Double_Float)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (2 floats & a double) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with 2 floats and a double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAnd2FloatsDoubleFromStructByUpcallMH(double arg1, stru_Float_Float_Double arg2, double (*upcallMH)(double, stru_Float_Float_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (a double & 2 floats) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a double and 2 floats + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDouble2FloatsFromStructByUpcallMH(double arg1, stru_Double_Float_Float arg2, double (*upcallMH)(double, stru_Double_Float_Float)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a float and all elements (int & 2 floats) of a struct + * by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with an int and 2 floats + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndInt2FloatsFromStructByUpcallMH(float arg1, stru_Int_Float_Float arg2, float (*upcallMH)(float, stru_Int_Float_Float)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a float and all elements (float, int and float) of a struct + * by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with a float, an int and a float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndFloatIntFloatFromStructByUpcallMH(float arg1, stru_Float_Int_Float arg2, float (*upcallMH)(float, stru_Float_Int_Float)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a double and all elements (int, float & double) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with an int, a float and a double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndIntFloatDoubleFromStructByUpcallMH(double arg1, stru_Int_Float_Double arg2, double (*upcallMH)(double, stru_Int_Float_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (float, int & double) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a float, an int and a double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndFloatIntDoubleFromStructByUpcallMH(double arg1, stru_Float_Int_Double arg2, double (*upcallMH)(double, stru_Float_Int_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (long & double) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a long and a double + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndLongDoubleFromStructByUpcallMH(double arg1, stru_Long_Double arg2, double (*upcallMH)(double, stru_Long_Double)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a float and all elements (int & 3 floats) of a struct + * by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with an int and 3 floats + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndInt3FloatsFromStructByUpcallMH(float arg1, stru_Int_3_Floats arg2, float (*upcallMH)(float, stru_Int_3_Floats)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a long and all elements (long & 2 floats) of a struct + * by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with a long and 2 floats + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndLong2FloatsFromStructByUpcallMH(LONG arg1, stru_Long_2_Floats arg2, LONG (*upcallMH)(LONG, stru_Long_2_Floats)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a float and all elements (3 floats & int) of a struct + * by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with 3 floats and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAnd3FloatsIntFromStructByUpcallMH(float arg1, stru_3_Floats_Int arg2, float (*upcallMH)(float, stru_3_Floats_Int)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a long and all elements (float & long) of a struct + * by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with a float and a long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAndFloatLongFromStructByUpcallMH(LONG arg1, stru_Float_Long arg2, LONG (*upcallMH)(LONG, stru_Float_Long)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a double and all elements (double, float & int) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a double, a float and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoubleFloatIntFromStructByUpcallMH(double arg1, stru_Double_Float_Int arg2, double (*upcallMH)(double, stru_Double_Float_Int)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (double & long) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a double and a long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndDoubleLongFromStructByUpcallMH(double arg1, stru_Double_Long arg2, double (*upcallMH)(double, stru_Double_Long)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a long and all elements (2 floats & a long) of a struct + * by invoking an upcall method. + * + * @param arg1 a long + * @param arg2 a struct with 2 floats and a long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongAnd2FloatsLongFromStructByUpcallMH(LONG arg1, stru_Float_Float_Long arg2, LONG (*upcallMH)(LONG, stru_Float_Float_Long)) +{ + LONG longSum = (*upcallMH)(arg1, arg2); + return longSum; +} + +/** + * Add a short and all elements (an array of 3 shorts & a char) of a struct + * by invoking an upcall method. + * + * @param arg1 a short + * @param arg2 a struct with an array of 3 shorts & a char + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +addShortAnd3ShortsCharFromStructByUpcallMH(short arg1, stru_3_Shorts_Char arg2, short (*upcallMH)(short, stru_3_Shorts_Char)) +{ + short shortSum = (*upcallMH)(arg1, arg2); + return shortSum; +} + +/** + * Add a float and all elements (int, float, int & float) of a struct + * by invoking an upcall method. + * + * @param arg1 a float + * @param arg2 a struct with an int, a float, an int and a float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +addFloatAndIntFloatIntFloatFromStructByUpcallMH(float arg1, stru_Int_Float_Int_Float arg2, float (*upcallMH)(float, stru_Int_Float_Int_Float)) +{ + float floatSum = (*upcallMH)(arg1, arg2); + return floatSum; +} + +/** + * Add a double and all elements (int, double, float) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with an int, a double and a float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndIntDoubleFloatFromStructByUpcallMH(double arg1, stru_Int_Double_Float arg2, double (*upcallMH)(double, stru_Int_Double_Float)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (float, double, int) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a float, a double and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndFloatDoubleIntFromStructByUpcallMH(double arg1, stru_Float_Double_Int arg2, double (*upcallMH)(double, stru_Float_Double_Int)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (int, double, int) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with an int, a double and an int + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndIntDoubleIntFromStructByUpcallMH(double arg1, stru_Int_Double_Int arg2, double (*upcallMH)(double, stru_Int_Double_Int)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (float, double, float) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with a float, a double and a float + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndFloatDoubleFloatFromStructByUpcallMH(double arg1, stru_Float_Double_Float arg2, double (*upcallMH)(double, stru_Float_Double_Float)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Add a double and all elements (int, double and long) of a struct + * by invoking an upcall method. + * + * @param arg1 a double + * @param arg2 a struct with an int, a double and a long + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoubleAndIntDoubleLongFromStructByUpcallMH(double arg1, stru_Int_Double_Long arg2, double (*upcallMH)(double, stru_Int_Double_Long)) +{ + double doubleSum = (*upcallMH)(arg1, arg2); + return doubleSum; +} + +/** + * Return a struct with 254 bytes by invoking an upcall method. + * + * @param arg a struct with 254 bytes + * @param upcallMH the function pointer to the upcall method + * @return the struct + */ +stru_254_Bytes +return254BytesFromStructByUpcallMH(stru_254_Bytes (*upcallMH)()) +{ + return (*upcallMH)(); +} + +/** + * Return a struct with 4K bytes by invoking an upcall method. + * + * @param arg a struct with 4K bytes + * @param upcallMH the function pointer to the upcall method + * @return the struct + */ +stru_4K_Bytes +return4KBytesFromStructByUpcallMH(stru_4K_Bytes (*upcallMH)()) +{ + return (*upcallMH)(); +} diff --git a/runtime/tests/clinkerffi/valist.c b/runtime/tests/clinkerffi/valist.c new file mode 100644 index 00000000000..f8f08f9214a --- /dev/null +++ b/runtime/tests/clinkerffi/valist.c @@ -0,0 +1,1109 @@ +/******************************************************************************* + * Copyright (c) 2022, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ + +/** + * This file contains the native code used by the VaList specific test cases + * via a Clinker FFI Downcall & Upcall in java, which come from: + * org.openj9.test.jep389.valist (JDK16/17) + * org.openj9.test.jep419.valist (JDK18) + * org.openj9.test.jep424.valist (JDK19+) + * + * Created by jincheng@ca.ibm.com + */ + +#include +#include +#include +#include "downcall.h" + +/** + * Add ints from the va_list with the specified count + * + * @param argCount the count of the ints + * @param intArgList the integer va_list + * @return the sum of ints from the va_list + */ +int +addIntsFromVaList(int argCount, va_list intVaList) +{ + int intSum = 0; + while (argCount > 0) { + intSum += va_arg(intVaList, int); + argCount--; + } + return intSum; +} + +/** + * Add longs from the va_list with the specified count + * + * @param argCount the count of longs + * @param longArgList the long va_list + * @return the sum of longs from the va_list + */ +LONG +addLongsFromVaList(int argCount, va_list longVaList) +{ + LONG longSum = 0; + while (argCount > 0) { + longSum += va_arg(longVaList, LONG); + argCount--; + } + return longSum; +} + +/** + * Add doubles from the va_list with the specified count + * + * @param argCount the count of the doubles + * @param doubleArgList the double va_list + * @return the sum of doubles from the va_list + */ +double +addDoublesFromVaList(int argCount, va_list doubleVaList) +{ + double doubleSum = 0; + while (argCount > 0) { + doubleSum += va_arg(doubleVaList, double); + argCount--; + } + return doubleSum; +} + +/** + * Add arguments with different types from the va_list + * + * @param argVaList the va_list with mixed arguments + * @return the sum of arguments from the va_list + */ +double +addMixedArgsFromVaList(va_list argVaList) +{ + double argSum = va_arg(argVaList, int) + va_arg(argVaList, long) + va_arg(argVaList, double); + return argSum; +} + +/** + * Add more arguments with different types from the va_list + * + * @param argVaList the va_list with mixed arguments + * @return the sum of arguments from the va_list + */ +double +addMoreMixedArgsFromVaList(va_list argVaList) +{ + double argSum = va_arg(argVaList, int) + va_arg(argVaList, long) + va_arg(argVaList, int) + + va_arg(argVaList, long) + va_arg(argVaList, int) + va_arg(argVaList, long) + + va_arg(argVaList, int) + va_arg(argVaList, double) + va_arg(argVaList, int) + + va_arg(argVaList, double) + va_arg(argVaList, int) + va_arg(argVaList, double) + + va_arg(argVaList, int) + va_arg(argVaList, double) + va_arg(argVaList, int) + + va_arg(argVaList, double); + return argSum; +} + +/** + * Add ints (accessed by pointers) from the va_list + * + * @param argCount the count of integer pointers in the va_list + * @param ptrVaList the passed-in va_list containing the integer pointers + * @return the sum of ints + */ +int +addIntsByPtrFromVaList(int argCount, va_list ptrVaList) +{ + int intSum = 0; + while (argCount > 0) { + intSum += *va_arg(ptrVaList, int *); + argCount--; + } + return intSum; +} + +/** + * Add longs (accessed by pointers) from the va_list + * + * @param argCount the count of long pointers in the va_list + * @param ptrVaList the passed-in va_list containing the long pointers + * @return the sum of longs + */ +LONG +addLongsByPtrFromVaList(int argCount, va_list ptrVaList) +{ + LONG longSum = 0; + while (argCount > 0) { + longSum += *va_arg(ptrVaList, LONG *); + argCount--; + } + return longSum; +} + +/** + * Add doubles (accessed by pointers) from the va_list + * + * @param argCount the count of double pointers in the va_list + * @param ptrVaList the passed-in va_list containing the double pointers + * @return the sum of doubles + */ +double +addDoublesByPtrFromVaList(int argCount, va_list ptrVaList) +{ + double doubleSum = 0; + while (argCount > 0) { + doubleSum += *va_arg(ptrVaList, double *); + argCount--; + } + return doubleSum; +} + +/** + * Add the only one element(byte) of structs from the va_list + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +char +add1ByteOfStructsFromVaList(int argCount, va_list struVaList) +{ + char byteSum = 0; + while (argCount > 0) { + stru_Byte struArg = va_arg(struVaList, stru_Byte); + byteSum += struArg.elem1; + argCount--; + } + return byteSum; +} + +/** + * Add bytes of structs with two elements from the va_list + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +char +add2BytesOfStructsFromVaList(int argCount, va_list struVaList) +{ + char byteSum = 0; + while (argCount > 0) { + stru_Byte_Byte struArg = va_arg(struVaList, stru_Byte_Byte); + byteSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return byteSum; +} + +/** + * Add bytes of structs with three elements from the va_list + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +char +add3BytesOfStructsFromVaList(int argCount, va_list struVaList) +{ + char byteSum = 0; + while (argCount > 0) { + stru_Byte_Byte_Byte struArg = va_arg(struVaList, stru_Byte_Byte_Byte); + byteSum += struArg.elem1 + struArg.elem2 + struArg.elem3; + argCount--; + } + return byteSum; +} + +/** + * Add bytes of structs with five elements from the va_list + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +char +add5BytesOfStructsFromVaList(int argCount, va_list struVaList) +{ + char byteSum = 0; + while (argCount > 0) { + stru_5_Bytes struArg = va_arg(struVaList, stru_5_Bytes); + byteSum += struArg.elem1 + struArg.elem2 + struArg.elem3 + struArg.elem4 + struArg.elem5; + argCount--; + } + return byteSum; +} + +/** + * Add bytes of structs with seven elements from the va_list + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +char +add7BytesOfStructsFromVaList(int argCount, va_list struVaList) +{ + char byteSum = 0; + while (argCount > 0) { + stru_7_Bytes struArg = va_arg(struVaList, stru_7_Bytes); + byteSum += struArg.elem1 + struArg.elem2 + struArg.elem3 + + struArg.elem4 + struArg.elem5 + struArg.elem6 + struArg.elem7; + argCount--; + } + return byteSum; +} + +/** + * Add the only one element(short) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +short +add1ShortOfStructsFromVaList(int argCount, va_list struVaList) +{ + short shortSum = 0; + while (argCount > 0) { + stru_Short struArg = va_arg(struVaList, stru_Short); + shortSum += struArg.elem1; + argCount--; + } + return shortSum; +} + +/** + * Add shorts of structs with two elements from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +short +add2ShortsOfStructsFromVaList(int argCount, va_list struVaList) +{ + short shortSum = 0; + while (argCount > 0) { + stru_Short_Short struArg = va_arg(struVaList, stru_Short_Short); + shortSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return shortSum; +} + +/** + * Add shorts of structs with three elements from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +short +add3ShortsOfStructsFromVaList(int argCount, va_list struVaList) +{ + short shortSum = 0; + while (argCount > 0) { + stru_Short_Short_Short struArg = va_arg(struVaList, stru_Short_Short_Short); + shortSum += struArg.elem1 + struArg.elem2 + struArg.elem3; + argCount--; + } + return shortSum; +} + +/** + * Add the only one element(int) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +int +add1IntOfStructsFromVaList(int argCount, va_list struVaList) +{ + int intSum = 0; + while (argCount > 0) { + stru_Int struArg = va_arg(struVaList, stru_Int); + intSum += struArg.elem1; + argCount--; + } + return intSum; +} + +/** + * Add ints of structs with two elements from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum of ints + */ +int +add2IntsOfStructsFromVaList(int argCount, va_list struVaList) +{ + int intSum = 0; + while (argCount > 0) { + stru_Int_Int struArg = va_arg(struVaList, stru_Int_Int); + intSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return intSum; +} + +/** + * Add ints of structs with three elements from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum of ints + */ +int +add3IntsOfStructsFromVaList(int argCount, va_list struVaList) +{ + int intSum = 0; + while (argCount > 0) { + stru_Int_Int_Int struArg = va_arg(struVaList, stru_Int_Int_Int); + intSum += struArg.elem1 + struArg.elem2 + struArg.elem3; + argCount--; + } + return intSum; +} + +/** + * Add longs of structs with two elements from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum of longs + */ +LONG +add2LongsOfStructsFromVaList(int argCount, va_list struVaList) +{ + LONG longSum = 0; + while (argCount > 0) { + stru_Long_Long struArg = va_arg(struVaList, stru_Long_Long); + longSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return longSum; +} + +/** + * Add the only one element(float) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +float +add1FloatOfStructsFromVaList(int argCount, va_list struVaList) +{ + float floatSum = 0; + while (argCount > 0) { + stru_Float struArg = va_arg(struVaList, stru_Float); + floatSum += struArg.elem1; + argCount--; + } + return floatSum; +} + +/** + * Add floats of structs with two elements from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum of floats + */ +float +add2FloatsOfStructsFromVaList(int argCount, va_list struVaList) +{ + float floatSum = 0; + while (argCount > 0) { + stru_Float_Float struArg = va_arg(struVaList, stru_Float_Float); + floatSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return floatSum; +} + +/** + * Add floats of structs with three elements from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum of floats + */ +float +add3FloatsOfStructsFromVaList(int argCount, va_list struVaList) +{ + float floatSum = 0; + while (argCount > 0) { + stru_Float_Float_Float struArg = va_arg(struVaList, stru_Float_Float_Float); + floatSum += struArg.elem1 + struArg.elem2 + struArg.elem3; + argCount--; + } + return floatSum; +} + +/** + * Add the only one element(double) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +double +add1DoubleOfStructsFromVaList(int argCount, va_list struVaList) +{ + double doubleSum = 0; + while (argCount > 0) { + stru_Double struArg = va_arg(struVaList, stru_Double); + doubleSum += struArg.elem1; + argCount--; + } + return doubleSum; +} + +/** + * Add doubles of structs with two elements from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum of doubles + */ +double +add2DoublesOfStructsFromVaList(int argCount, va_list struVaList) +{ + double doubleSum = 0; + while (argCount > 0) { + stru_Double_Double struArg = va_arg(struVaList, stru_Double_Double); + doubleSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return doubleSum; +} + +/** + * Add the elements(int & short) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +int +addIntShortOfStructsFromVaList(int argCount, va_list struVaList) +{ + int intSum = 0; + while (argCount > 0) { + stru_Int_Short struArg = va_arg(struVaList, stru_Int_Short); + intSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return intSum; +} + +/** + * Add the elements(short & int) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +int +addShortIntOfStructsFromVaList(int argCount, va_list struVaList) +{ + int intSum = 0; + while (argCount > 0) { + stru_Short_Int struArg = va_arg(struVaList, stru_Short_Int); + intSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return intSum; +} + +/** + * Add the elements(int & long) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +LONG +addIntLongOfStructsFromVaList(int argCount, va_list struVaList) +{ + LONG longSum = 0; + while (argCount > 0) { + stru_Int_Long struArg = va_arg(struVaList, stru_Int_Long); + longSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return longSum; +} + +/** + * Add the elements(long & int) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +LONG +addLongIntOfStructsFromVaList(int argCount, va_list struVaList) +{ + LONG longSum = 0; + while (argCount > 0) { + stru_Long_Int struArg = va_arg(struVaList, stru_Long_Int); + longSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return longSum; +} + +/** + * Add the elements(float & double) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +double +addFloatDoubleOfStructsFromVaList(int argCount, va_list struVaList) +{ + double doubleSum = 0; + while (argCount > 0) { + stru_Float_Double struArg = va_arg(struVaList, stru_Float_Double); + doubleSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return doubleSum; +} + +/** + * Add the elements(double & float) of structs from the va_list + * + * @param argCount the count of structs in the va_list + * @param struVaList the passed-in va_list containing structs + * @return the sum + */ +double +addDoubleFloatOfStructsFromVaList(int argCount, va_list struVaList) +{ + double doubleSum = 0; + while (argCount > 0) { + stru_Double_Float struArg = va_arg(struVaList, stru_Double_Float); + doubleSum += struArg.elem1 + struArg.elem2; + argCount--; + } + return doubleSum; +} + +/** + * Add ints from the va_list with the specified count + * by invoking an upcall method. + * + * @param argCount the count of the ints + * @param intArgList the int va_list + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntsFromVaListByUpcallMH(int argCount, va_list intVaList, int (*upcallMH)(int, va_list)) +{ + int arg1 = va_arg(intVaList, int); + int intSum = arg1 + (*upcallMH)(argCount - 1, intVaList); + return intSum; +} + +/** + * Add longs from the va_list with the specified count + * by invoking an upcall method. + * + * @param argCount the count of the longs + * @param longArgList the long va_list + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongsFromVaListByUpcallMH(int argCount, va_list longVaList, LONG (*upcallMH)(int, va_list)) +{ + LONG longSum = (*upcallMH)(argCount, longVaList); + return longSum; +} + +/** + * Add doubles from the va_list with the specified count + * by invoking an upcall method. + * + * @param argCount the count of the double arguments + * @param doubleArgList the double va_list + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoublesFromVaListByUpcallMH(int argCount, va_list doubleVaList, double (*upcallMH)(int, va_list)) +{ + double arg1 = va_arg(doubleVaList, double); + double doubleSum = arg1 + (*upcallMH)(argCount - 1, doubleVaList); + return doubleSum; +} + +/** + * Add arguments with different types from the va_list + * by invoking an upcall method. + * + * @param argVaList the va_list with mixed arguments + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addMixedArgsFromVaListByUpcallMH(va_list argVaList, double (*upcallMH)(va_list)) +{ + double argSum = (*upcallMH)(argVaList); + return argSum; +} + +/** + * Add more arguments with different types from the va_list + * by invoking an upcall method. + * + * @param argVaList the va_list with mixed arguments + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addMoreMixedArgsFromVaListByUpcallMH(va_list argVaList, double (*upcallMH)(va_list)) +{ + double argSum = (*upcallMH)(argVaList); + return argSum; +} + +/** + * Add ints (accessed via MemoryAddress in java) from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of integer pointers in the va_list + * @param ptrVaList the passed-in va_list containing the int pointers + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntsByPtrFromVaListByUpcallMH(int argCount, va_list ptrVaList, int (*upcallMH)(int, va_list)) +{ + int intSum = (*upcallMH)(argCount, ptrVaList); + return intSum; +} + +/** + * Add longs (accessed via MemoryAddress in java) from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of integer pointers in the va_list + * @param ptrVaList the passed-in va_list containing the long pointers + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongsByPtrFromVaListByUpcallMH(int argCount, va_list ptrVaList, LONG (*upcallMH)(int, va_list)) +{ + LONG longSum = (*upcallMH)(argCount, ptrVaList); + return longSum; +} + +/** + * Add doubles (accessed via MemoryAddress in java) from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of integer pointers in the va_list + * @param ptrVaList the passed-in va_list containing the double pointers + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +addDoublesByPtrFromVaListByUpcallMH(int argCount, va_list ptrVaList, double (*upcallMH)(int, va_list)) +{ + double doubleSum = (*upcallMH)(argCount, ptrVaList); + return doubleSum; +} + +/** + * Add the only one element(byte) of structs with the specified count + * by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +add1ByteOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, char (*upcallMH)(int, va_list)) +{ + char byteSum = (*upcallMH)(argCount, struVaList); + return byteSum; +} + +/** + * Add bytes of structs with two elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +add2BytesOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, char (*upcallMH)(int, va_list)) +{ + char byteSum = (*upcallMH)(argCount, struVaList); + return byteSum; +} + +/** + * Add bytes of structs with three elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +add3BytesOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, char (*upcallMH)(int, va_list)) +{ + char byteSum = (*upcallMH)(argCount, struVaList); + return byteSum; +} + +/** + * Add bytes of structs with five elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +add5BytesOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, char (*upcallMH)(int, va_list)) +{ + char byteSum = (*upcallMH)(argCount, struVaList); + return byteSum; +} + +/** + * Add bytes of structs with seven elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +char +add7BytesOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, char (*upcallMH)(int, va_list)) +{ + char byteSum = (*upcallMH)(argCount, struVaList); + return byteSum; +} + +/** + * Add the only one element(short) of structs with the specified count + * by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +add1ShortOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, short (*upcallMH)(int, va_list)) +{ + short shortSum = (*upcallMH)(argCount, struVaList); + return shortSum; +} + +/** + * Add shorts of structs with two elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +add2ShortsOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, short (*upcallMH)(int, va_list)) +{ + short shortSum = (*upcallMH)(argCount, struVaList); + return shortSum; +} + +/** + * Add shorts of structs with three elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +short +add3ShortsOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, short (*upcallMH)(int, va_list)) +{ + short shortSum = (*upcallMH)(argCount, struVaList); + return shortSum; +} + +/** + * Add the only one element(int) of structs with the specified count + * by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +add1IntOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, int (*upcallMH)(int, va_list)) +{ + int intSum = (*upcallMH)(argCount, struVaList); + return intSum; +} + +/** + * Add ints of structs with two elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +add2IntsOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, int (*upcallMH)(int, va_list)) +{ + int intSum = (*upcallMH)(argCount, struVaList); + return intSum; +} + +/** + * Add ints of structs with three elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +add3IntsOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, int (*upcallMH)(int, va_list)) +{ + int intSum = (*upcallMH)(argCount, struVaList); + return intSum; +} + +/** + * Add longs of structs with two elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +add2LongsOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, LONG (*upcallMH)(int, va_list)) +{ + LONG longSum = (*upcallMH)(argCount, struVaList); + return longSum; +} + +/** + * Add the only one element(float) of structs with the specified count + * by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +add1FloatOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, float (*upcallMH)(int, va_list)) +{ + float floatSum = (*upcallMH)(argCount, struVaList); + return floatSum; +} + +/** + * Add floats of structs with two elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +add2FloatsOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, float (*upcallMH)(int, va_list)) +{ + float floatSum = (*upcallMH)(argCount, struVaList); + return floatSum; +} + +/** + * Add floats of structs with three elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +float +add3FloatsOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, float (*upcallMH)(int, va_list)) +{ + float floatSum = (*upcallMH)(argCount, struVaList); + return floatSum; +} + +/** + * Add the only one element(double) of structs with the specified count + * by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +add1DoubleOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, double (*upcallMH)(int, va_list)) +{ + double doubleSum = (*upcallMH)(argCount, struVaList); + return doubleSum; +} + +/** + * Add doubles of structs with two elements from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +double +add2DoublesOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, double (*upcallMH)(int, va_list)) +{ + double doubleSum = (*upcallMH)(argCount, struVaList); + return doubleSum; +} + +/** + * Add the elements(int & short) of structs from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addIntShortOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, int (*upcallMH)(int, va_list)) +{ + int intSum = (*upcallMH)(argCount, struVaList); + return intSum; +} + +/** + * Add the elements(short & int) of structs from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +int +addShortIntOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, int (*upcallMH)(int, va_list)) +{ + int intSum = (*upcallMH)(argCount, struVaList); + return intSum; +} + +/** + * Add the elements(int & long) of structs from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addIntLongOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, LONG (*upcallMH)(int, va_list)) +{ + LONG longSum = (*upcallMH)(argCount, struVaList); + return longSum; +} + +/** + * Add the elements(long & int) of structs from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pointer to the upcall method + * @return the sum + */ +LONG +addLongIntOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, LONG (*upcallMH)(int, va_list)) +{ + LONG longSum = (*upcallMH)(argCount, struVaList); + return longSum; +} + +/** + * Add the elements(float & double) of structs from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pofloater to the upcall method + * @return the sum + */ +double +addFloatDoubleOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, double (*upcallMH)(int, va_list)) +{ + double doubleSum = (*upcallMH)(argCount, struVaList); + return doubleSum; +} + +/** + * Add the elements(double & float) of structs from the va_list + * with the specified count by invoking an upcall method. + * + * @param argCount the count of struct in the va_list + * @param struVaList the passed-in va_list containing structs + * @param upcallMH the function pofloater to the upcall method + * @return the sum + */ +double +addDoubleFloatOfStructsFromVaListByUpcallMH(int argCount, va_list struVaList, double (*upcallMH)(int, va_list)) +{ + double doubleSum = (*upcallMH)(argCount, struVaList); + return doubleSum; +} diff --git a/test/functional/Java17andUp/playlist.xml b/test/functional/Java17andUp/playlist.xml index 8fd3519cb7d..977b3c3d5e0 100644 --- a/test/functional/Java17andUp/playlist.xml +++ b/test/functional/Java17andUp/playlist.xml @@ -43,7 +43,7 @@ -excludegroups $(DEFAULT_EXCLUDE); \ $(TEST_STATUS) - bits.64,^arch.x86,^arch.aarch64,^arch.ppc,^arch.390,^arch.arm,^arch.riscv,^os.zos,^os.sunos + bits.64,^arch.x86,^arch.arm,^arch.riscv,^os.zos,^os.sunos sanity @@ -57,6 +57,37 @@ 17 + + + Jep389Tests_testClinkerFfi_UpCall + + --enable-preview + + $(ADD_JVM_LIB_DIR_TO_LIBPATH) $(JAVA_COMMAND) $(JVM_OPTIONS) \ + --add-modules jdk.incubator.foreign \ + --enable-native-access=ALL-UNNAMED \ + -Dforeign.restricted=permit \ + -cp $(Q)$(LIB_DIR)$(D)asm.jar$(P)$(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(TEST_RESROOT)$(D)GeneralTest.jar$(Q) \ + org.testng.TestNG -d $(REPORTDIR) $(Q)$(TEST_RESROOT)$(D)testng_170.xml$(Q) -testnames Jep389Tests_testClinkerFfi_UpCall \ + -groups $(TEST_GROUP) \ + -excludegroups $(DEFAULT_EXCLUDE); \ + $(TEST_STATUS) + + bits.64,^arch.x86,^arch.arm,^arch.riscv,^os.zos,^os.sunos + + sanity + + + functional + + + openj9 + + + 17 + + + Jep389Tests_testClinkerFfi_VaList diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/InvalidDownCallTests.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/InvalidDownCallTests.java index c37ec8166f5..16bd73dbad2 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/InvalidDownCallTests.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/InvalidDownCallTests.java @@ -57,7 +57,7 @@ public class InvalidDownCallTests { System.loadLibrary("clinkerffitests"); } private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); - private static final SymbolLookup defaultLibLookup = (!isAixOS) ? CLinker.systemLookup() : null; + private static final SymbolLookup defaultLibLookup = CLinker.systemLookup(); @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "The return type must be .*") public void test_invalidBooleanTypeOnReturn() throws Throwable { @@ -358,19 +358,11 @@ public void test_invalidMemoryLayoutForIntType() throws Throwable { @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "ValueLayout is expected.*") public void test_invalidMemoryLayoutForMemoryAddress() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (isAixOS) { - throw new IllegalArgumentException("ValueLayout is expected"); - } else { - Addressable functionSymbol = defaultLibLookup.lookup("strlen").get(); - MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); - FunctionDescriptor fd = FunctionDescriptor.of(longLayout, MemoryLayout.paddingLayout(64)); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - fail("Failed to throw out IllegalArgumentException in the case of the invalid MemoryLayout"); - } + Addressable functionSymbol = defaultLibLookup.lookup("strlen").get(); + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, MemoryLayout.paddingLayout(64)); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + fail("Failed to throw out IllegalArgumentException in the case of the invalid MemoryLayout"); } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Mismatched size .*") @@ -384,19 +376,11 @@ public void test_mismatchedLayoutSizeForIntType() throws Throwable { @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Mismatched size .*") public void test_mismatchedLayoutSizeForMemoryAddress() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (isAixOS) { - throw new IllegalArgumentException("Mismatched size "); - } else { - Addressable functionSymbol = defaultLibLookup.lookup("strlen").get(); - MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); - FunctionDescriptor fd = FunctionDescriptor.of(longLayout, MemoryLayouts.BITS_16_LE); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - fail("Failed to throw out IllegalArgumentException in the case of the mismatched layout size"); - } + Addressable functionSymbol = defaultLibLookup.lookup("strlen").get(); + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, MemoryLayouts.BITS_16_LE); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + fail("Failed to throw out IllegalArgumentException in the case of the mismatched layout size"); } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".* neither primitive nor .*") diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests1.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests1.java index 167b2c3c179..140791cf7b8 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests1.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests1.java @@ -31,12 +31,16 @@ import jdk.incubator.foreign.CLinker; import static jdk.incubator.foreign.CLinker.*; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.SymbolLookup; /** * Test cases for JEP 389: Foreign Linker API (Incubator) for primitive types in downcall, - * which verifies the downcalls with the same layout & argument and return types in multithreading. + * which verifies the downcalls with the same downcall handlder (cached as soft reference in OpenJDK) + * in multithreading. */ @Test(groups = { "level.sanity" }) public class MultiThreadingTests1 implements Thread.UncaughtExceptionHandler { @@ -55,44 +59,57 @@ public void uncaughtException(Thread thr, Throwable t) { } @Test - public void test_twoThreadsWithSameFuncDescriptor() throws Throwable { + public void test_twoThreadsWithSameFuncDesc_SameDowncallHandler() throws Throwable { Thread thr1 = new Thread(){ public void run() { try { - MethodType mt = MethodType.methodType(int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); - Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - int result = (int)mh.invokeExact(112, 123); - Assert.assertEquals(result, 235); + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MethodType mt = MethodType.methodType(int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointer").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + MemorySegment intSegmt = MemorySegment.allocateNative(C_INT, scope); + MemoryAccess.setInt(intSegmt, 215); + int result = (int)mh.invokeExact(321, intSegmt.address()); + Assert.assertEquals(result, 536); + } } catch (Throwable t) { throw new RuntimeException(t); } } }; - thr1.setUncaughtExceptionHandler(this); - thr1.start(); Thread thr2 = new Thread(){ public void run() { try { - MethodType mt = MethodType.methodType(int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); - Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - int result = (int)mh.invokeExact(235, 439); - Assert.assertEquals(result, 674); + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MethodType mt = MethodType.methodType(int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointer").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + MemorySegment intSegmt = MemorySegment.allocateNative(C_INT, scope); + MemoryAccess.setInt(intSegmt, 215); + int result = (int)mh.invokeExact(322, intSegmt.address()); + Assert.assertEquals(result, 537); + } } catch (Throwable t) { throw new RuntimeException(t); } } }; + + thr1.setUncaughtExceptionHandler(this); thr2.setUncaughtExceptionHandler(this); + + thr1.start(); thr2.start(); thr1.join(); thr2.join(); + if (initException != null){ throw new RuntimeException(initException); } diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests2.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests2.java index b7a3ea24789..9fded4ad86b 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests2.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests2.java @@ -24,29 +24,41 @@ import org.testng.annotations.Test; import org.testng.Assert; import org.testng.AssertJUnit; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.CLinker; import static jdk.incubator.foreign.CLinker.*; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; /** * Test cases for JEP 389: Foreign Linker API (Incubator) for primitive types in downcall, - * which verifies the downcalls with the diffrent layouts and arguments/return types in multithreading. + * which verifies the downcalls with the shared downcall handlder (cached as soft reference in OpenJDK) + * in multithreading. */ @Test(groups = { "level.sanity" }) public class MultiThreadingTests2 implements Thread.UncaughtExceptionHandler { private volatile Throwable initException; - private static CLinker clinker = CLinker.getInstance(); static { System.loadLibrary("clinkerffitests"); } - private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + private static final GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + private static final MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class); + private static final FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + private static final Addressable functionSymbol = SymbolLookup.loaderLookup().lookup("add2IntStructs_returnStruct").get(); + private static final MethodHandle mh = CLinker.getInstance().downcallHandle(mt, fd); @Test(enabled=false) @Override @@ -55,16 +67,26 @@ public void uncaughtException(Thread thr, Throwable t) { } @Test - public void test_twoThreadsWithDiffFuncDescriptor() throws Throwable { + public void test_twoThreadsWithSameFuncDesc_SharedDowncallHandler() throws Throwable { Thread thr1 = new Thread(){ public void run() { try { - MethodType mt = MethodType.methodType(int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); - Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - int result = (int)mh.invokeExact(112, 123); - Assert.assertEquals(result, 235); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224466); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113354); + } } catch (Throwable t) { throw new RuntimeException(t); } @@ -74,12 +96,22 @@ public void run() { Thread thr2 = new Thread(){ public void run() { try { - MethodType mt = MethodType.methodType(int.class, int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_INT); - Addressable functionSymbol = nativeLibLookup.lookup("add3Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - int result = (int)mh.invokeExact(112, 123, 235); - Assert.assertEquals(result, 470); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001123); + intHandle2.set(structSegmt2, 33445567); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224467); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113355); + } } catch (Throwable t) { throw new RuntimeException(t); } diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests3.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests3.java index 84baab16283..f89dfc7b55a 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests3.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests3.java @@ -36,7 +36,7 @@ /** * Test cases for JEP 389: Foreign Linker API (Incubator) for primitive types in downcall, - * which verifies the downcalls with the diffrent return types in multithreading. + * which verifies the downcalls with the diffrent layouts and arguments/return types in multithreading. */ @Test(groups = { "level.sanity" }) public class MultiThreadingTests3 implements Thread.UncaughtExceptionHandler { @@ -55,7 +55,7 @@ public void uncaughtException(Thread thr, Throwable t) { } @Test - public void test_twoThreadsWithDiffReturnType() throws Throwable { + public void test_twoThreadsWithDiffFuncDescriptor() throws Throwable { Thread thr1 = new Thread(){ public void run() { try { @@ -74,11 +74,12 @@ public void run() { Thread thr2 = new Thread(){ public void run() { try { - MethodType mt = MethodType.methodType(void.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT); - Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoid").get(); + MethodType mt = MethodType.methodType(int.class, int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add3Ints").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - mh.invokeExact(454, 398); + int result = (int)mh.invokeExact(112, 123, 235); + Assert.assertEquals(result, 470); } catch (Throwable t) { throw new RuntimeException(t); } diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests4.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests4.java index f2736dec7be..d6e83835cf6 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests4.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests4.java @@ -36,7 +36,7 @@ /** * Test cases for JEP 389: Foreign Linker API (Incubator) for primitive types in downcall, - * which verifies multiple downcalls combined with the diffrent layouts/arguments/return types in multithreading. + * which verifies the downcalls with the diffrent return types in multithreading. */ @Test(groups = { "level.sanity" }) public class MultiThreadingTests4 implements Thread.UncaughtExceptionHandler { @@ -55,7 +55,7 @@ public void uncaughtException(Thread thr, Throwable t) { } @Test - public void test_multiThreadsWithMixedFuncDescriptors() throws Throwable { + public void test_twoThreadsWithDiffReturnType() throws Throwable { Thread thr1 = new Thread(){ public void run() { try { @@ -63,8 +63,8 @@ public void run() { FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - int result = (int)mh.invokeExact(128, 246); - Assert.assertEquals(result, 374); + int result = (int)mh.invokeExact(112, 123); + Assert.assertEquals(result, 235); } catch (Throwable t) { throw new RuntimeException(t); } @@ -74,72 +74,11 @@ public void run() { Thread thr2 = new Thread(){ public void run() { try { - MethodType mt = MethodType.methodType(int.class, int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_INT); - Addressable functionSymbol = nativeLibLookup.lookup("add3Ints").get(); + MethodType mt = MethodType.methodType(void.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoid").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - int result = (int)mh.invokeExact(112, 642, 971); - Assert.assertEquals(result, 1725); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - }; - - Thread thr3 = new Thread(){ - public void run() { - try { - MethodType mt = MethodType.methodType(boolean.class, boolean.class, boolean.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR); - Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - boolean result = (boolean)mh.invokeExact(true, false); - Assert.assertEquals(result, true); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - }; - - Thread thr4 = new Thread(){ - public void run() { - try { - MethodType mt = MethodType.methodType(int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); - Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - int result = (int)mh.invokeExact(416, 728); - Assert.assertEquals(result, 1144); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - }; - - Thread thr5 = new Thread(){ - public void run() { - try { - MethodType mt = MethodType.methodType(int.class, int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_INT); - Addressable functionSymbol = nativeLibLookup.lookup("add3Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - int result = (int)mh.invokeExact(1012, 1023, 2035); - Assert.assertEquals(result, 4070); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - }; - - Thread thr6 = new Thread(){ - public void run() { - try { - MethodType mt = MethodType.methodType(boolean.class, boolean.class, boolean.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR); - Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - boolean result = (boolean)mh.invokeExact(false, false); - Assert.assertEquals(result, false); + mh.invokeExact(454, 398); } catch (Throwable t) { throw new RuntimeException(t); } @@ -148,24 +87,12 @@ public void run() { thr1.setUncaughtExceptionHandler(this); thr2.setUncaughtExceptionHandler(this); - thr3.setUncaughtExceptionHandler(this); - thr4.setUncaughtExceptionHandler(this); - thr5.setUncaughtExceptionHandler(this); - thr6.setUncaughtExceptionHandler(this); thr1.start(); thr2.start(); - thr3.start(); - thr4.start(); - thr5.start(); - thr6.start(); - thr6.join(); - thr5.join(); - thr4.join(); - thr3.join(); - thr2.join(); thr1.join(); + thr2.join(); if (initException != null){ throw new RuntimeException(initException); diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests5.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests5.java new file mode 100644 index 00000000000..9b6d64dff95 --- /dev/null +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/MultiThreadingTests5.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep389.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import static jdk.incubator.foreign.CLinker.*; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SymbolLookup; + +/** + * Test cases for JEP 389: Foreign Linker API (Incubator) for primitive types in downcall, + * which verifies multiple downcalls combined with the diffrent layouts/arguments/return types in multithreading. + */ +@Test(groups = { "level.sanity" }) +public class MultiThreadingTests5 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static CLinker clinker = CLinker.getInstance(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_multiThreadsWithMixedFuncDescriptors() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + int result = (int)mh.invokeExact(128, 246); + Assert.assertEquals(result, 374); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr2 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add3Ints").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + int result = (int)mh.invokeExact(112, 642, 971); + Assert.assertEquals(result, 1725); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr3 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(boolean.class, boolean.class, boolean.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + boolean result = (boolean)mh.invokeExact(true, false); + Assert.assertEquals(result, true); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr4 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + int result = (int)mh.invokeExact(416, 728); + Assert.assertEquals(result, 1144); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr5 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add3Ints").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + int result = (int)mh.invokeExact(1012, 1023, 2035); + Assert.assertEquals(result, 4070); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr6 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(boolean.class, boolean.class, boolean.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + boolean result = (boolean)mh.invokeExact(false, false); + Assert.assertEquals(result, false); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + thr1.setUncaughtExceptionHandler(this); + thr2.setUncaughtExceptionHandler(this); + thr3.setUncaughtExceptionHandler(this); + thr4.setUncaughtExceptionHandler(this); + thr5.setUncaughtExceptionHandler(this); + thr6.setUncaughtExceptionHandler(this); + + thr1.start(); + thr2.start(); + thr3.start(); + thr4.start(); + thr5.start(); + thr6.start(); + + thr6.join(); + thr5.join(); + thr4.join(); + thr3.join(); + thr2.join(); + thr1.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests1.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests1.java index 4fd78a19205..7a8de880ea0 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests1.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests1.java @@ -61,7 +61,7 @@ public class PrimitiveTypeTests1 { System.loadLibrary("clinkerffitests"); } private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); - private static final SymbolLookup defaultLibLookup = (!isAixOS) ? CLinker.systemLookup() : null; + private static final SymbolLookup defaultLibLookup = CLinker.systemLookup(); @Test public void test_addTwoBoolsWithOr_1() throws Throwable { @@ -407,134 +407,92 @@ public void test_addTwoDoubles_fromMemAddr_1() throws Throwable { @Test public void test_strlenFromDefaultLibWithMemAddr_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); - MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); - FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); - MethodHandle mh = clinker.downcallHandle(strlenSymbol, mt, fd); - MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); - long strLength = (long)mh.invokeExact(funcMemSegment.address()); - Assert.assertEquals(strLength, 27); - } + Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); + MethodHandle mh = clinker.downcallHandle(strlenSymbol, mt, fd); + MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); + long strLength = (long)mh.invokeExact(funcMemSegment.address()); + Assert.assertEquals(strLength, 27); } @Test public void test_strlenFromDefaultLibWithMemAddr_fromMemAddr_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); - MemoryAddress memAddr = strlenSymbol.address(); - MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); - FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); - MethodHandle mh = clinker.downcallHandle(memAddr, mt, fd); - MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); - long strLength = (long)mh.invokeExact(funcMemSegment.address()); - Assert.assertEquals(strLength, 27); - } + Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); + MemoryAddress memAddr = strlenSymbol.address(); + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); + MethodHandle mh = clinker.downcallHandle(memAddr, mt, fd); + MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); + long strLength = (long)mh.invokeExact(funcMemSegment.address()); + Assert.assertEquals(strLength, 27); } @Test public void test_memoryAllocFreeFromDefaultLib_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); - MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); - FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); - MethodHandle allocHandle = clinker.downcallHandle(allocSymbol, allocMethodType, allocFuncDesc); - MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); - MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); - MemoryAccess.setIntAtOffset(memSeg, 0, 15); - Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); - - Addressable freeSymbol = defaultLibLookup.lookup("free").get(); - MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); - FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); - MethodHandle freeHandle = clinker.downcallHandle(freeSymbol, freeMethodType, freeFuncDesc); - freeHandle.invokeExact(allocMemAddr); - } + Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); + MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); + MethodHandle allocHandle = clinker.downcallHandle(allocSymbol, allocMethodType, allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); + MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); + MemoryAccess.setIntAtOffset(memSeg, 0, 15); + Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); + + Addressable freeSymbol = defaultLibLookup.lookup("free").get(); + MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); + MethodHandle freeHandle = clinker.downcallHandle(freeSymbol, freeMethodType, freeFuncDesc); + freeHandle.invokeExact(allocMemAddr); } @Test public void test_memoryAllocFreeFromDefaultLib_fromMemAddr_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); - MemoryAddress allocMemAddrFromSymbol = allocSymbol.address(); - MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); - FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); - MethodHandle allocHandle = clinker.downcallHandle(allocMemAddrFromSymbol, allocMethodType, allocFuncDesc); - MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); - MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); - MemoryAccess.setIntAtOffset(memSeg, 0, 15); - Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); - - Addressable freeSymbol = defaultLibLookup.lookup("free").get(); - MemoryAddress freeMemAddr = freeSymbol.address(); - MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); - FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); - MethodHandle freeHandle = clinker.downcallHandle(freeMemAddr, freeMethodType, freeFuncDesc); - freeHandle.invokeExact(allocMemAddr); - } + Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); + MemoryAddress allocMemAddrFromSymbol = allocSymbol.address(); + MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); + MethodHandle allocHandle = clinker.downcallHandle(allocMemAddrFromSymbol, allocMethodType, allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); + MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); + MemoryAccess.setIntAtOffset(memSeg, 0, 15); + Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); + + Addressable freeSymbol = defaultLibLookup.lookup("free").get(); + MemoryAddress freeMemAddr = freeSymbol.address(); + MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); + MethodHandle freeHandle = clinker.downcallHandle(freeMemAddr, freeMethodType, freeFuncDesc); + freeHandle.invokeExact(allocMemAddr); } @Test public void test_memoryAllocFreeFromCLinkerMethod_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - MemoryAddress allocMemAddr = CLinker.allocateMemory(10L); - MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); - MemoryAccess.setIntAtOffset(memSeg, 0, 49); - Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 49); - CLinker.freeMemory(allocMemAddr); - } + MemoryAddress allocMemAddr = CLinker.allocateMemory(10L); + MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); + MemoryAccess.setIntAtOffset(memSeg, 0, 49); + Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 49); + CLinker.freeMemory(allocMemAddr); } @Test public void test_printfFromDefaultLibWithMemAddr_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); - mh.invoke(formatMemSegment.address(), 15, 27, 42); - } + Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); + MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); + mh.invoke(formatMemSegment.address(), 15, 27, 42); } @Test public void test_printfFromDefaultLibWithMemAddr_fromMemAddr_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); - MemoryAddress memAddr = functionSymbol.address(); - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); - MethodHandle mh = clinker.downcallHandle(memAddr, mt, fd); - MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); - mh.invoke(formatMemSegment.address(), 15, 27, 42); - } + Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); + MemoryAddress memAddr = functionSymbol.address(); + MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); + MethodHandle mh = clinker.downcallHandle(memAddr, mt, fd); + MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); + mh.invoke(formatMemSegment.address(), 15, 27, 42); } } diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests2.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests2.java index 35542535f4d..8c40c30ad3e 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests2.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests2.java @@ -62,7 +62,7 @@ public class PrimitiveTypeTests2 { System.loadLibrary("clinkerffitests"); } private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); - private static final SymbolLookup defaultLibLookup = (!isAixOS) ? CLinker.systemLookup() : null; + private static final SymbolLookup defaultLibLookup = CLinker.systemLookup(); @Test public void test_addTwoBoolsWithOr_2() throws Throwable { @@ -408,134 +408,92 @@ public void test_addTwoDoubles_fromMemAddr_2() throws Throwable { @Test public void test_strlenFromDefaultLibWithMemAddr_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); - MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); - FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); - MethodHandle mh = clinker.downcallHandle(strlenSymbol, allocator, mt, fd); - MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); - long strLength = (long)mh.invokeExact(funcMemSegment.address()); - Assert.assertEquals(strLength, 27); - } + Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); + MethodHandle mh = clinker.downcallHandle(strlenSymbol, allocator, mt, fd); + MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); + long strLength = (long)mh.invokeExact(funcMemSegment.address()); + Assert.assertEquals(strLength, 27); } @Test public void test_strlenFromDefaultLibWithMemAddr_fromMemAddr_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); - MemoryAddress memAddr = strlenSymbol.address(); - MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); - FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); - MethodHandle mh = clinker.downcallHandle(memAddr, allocator, mt, fd); - MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); - long strLength = (long)mh.invokeExact(funcMemSegment.address()); - Assert.assertEquals(strLength, 27); - } + Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); + MemoryAddress memAddr = strlenSymbol.address(); + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); + MethodHandle mh = clinker.downcallHandle(memAddr, allocator, mt, fd); + MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); + long strLength = (long)mh.invokeExact(funcMemSegment.address()); + Assert.assertEquals(strLength, 27); } @Test public void test_memoryAllocFreeFromDefaultLib_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); - MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); - FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); - MethodHandle allocHandle = clinker.downcallHandle(allocSymbol, allocator, allocMethodType, allocFuncDesc); - MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); - MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); - MemoryAccess.setIntAtOffset(memSeg, 0, 15); - Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); - - Addressable freeSymbol = defaultLibLookup.lookup("free").get(); - MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); - FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); - MethodHandle freeHandle = clinker.downcallHandle(freeSymbol, allocator, freeMethodType, freeFuncDesc); - freeHandle.invokeExact(allocMemAddr); - } + Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); + MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); + MethodHandle allocHandle = clinker.downcallHandle(allocSymbol, allocator, allocMethodType, allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); + MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); + MemoryAccess.setIntAtOffset(memSeg, 0, 15); + Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); + + Addressable freeSymbol = defaultLibLookup.lookup("free").get(); + MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); + MethodHandle freeHandle = clinker.downcallHandle(freeSymbol, allocator, freeMethodType, freeFuncDesc); + freeHandle.invokeExact(allocMemAddr); } @Test public void test_memoryAllocFreeFromDefaultLib_fromMemAddr_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); - MemoryAddress allocMemAddrFromSymbol = allocSymbol.address(); - MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); - FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); - MethodHandle allocHandle = clinker.downcallHandle(allocMemAddrFromSymbol, allocator, allocMethodType, allocFuncDesc); - MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); - MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); - MemoryAccess.setIntAtOffset(memSeg, 0, 15); - Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); - - Addressable freeSymbol = defaultLibLookup.lookup("free").get(); - MemoryAddress freeMemAddr = freeSymbol.address(); - MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); - FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); - MethodHandle freeHandle = clinker.downcallHandle(freeMemAddr, allocator, freeMethodType, freeFuncDesc); - freeHandle.invokeExact(allocMemAddr); - } + Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); + MemoryAddress allocMemAddrFromSymbol = allocSymbol.address(); + MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); + MethodHandle allocHandle = clinker.downcallHandle(allocMemAddrFromSymbol, allocator, allocMethodType, allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); + MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); + MemoryAccess.setIntAtOffset(memSeg, 0, 15); + Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); + + Addressable freeSymbol = defaultLibLookup.lookup("free").get(); + MemoryAddress freeMemAddr = freeSymbol.address(); + MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); + MethodHandle freeHandle = clinker.downcallHandle(freeMemAddr, allocator, freeMethodType, freeFuncDesc); + freeHandle.invokeExact(allocMemAddr); } @Test public void test_memoryAllocFreeFromCLinkerMethod_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - MemoryAddress allocMemAddr = CLinker.allocateMemory(10L); - MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); - MemoryAccess.setIntAtOffset(memSeg, 0, 49); - Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 49); - CLinker.freeMemory(allocMemAddr); - } + MemoryAddress allocMemAddr = CLinker.allocateMemory(10L); + MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); + MemoryAccess.setIntAtOffset(memSeg, 0, 49); + Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 49); + CLinker.freeMemory(allocMemAddr); } @Test public void test_printfFromDefaultLibWithMemAddr_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); - MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); - MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); - mh.invoke(formatMemSegment.address(), 15, 27, 42); - } + Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); + MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); + mh.invoke(formatMemSegment.address(), 15, 27, 42); } @Test public void test_printfFromDefaultLibWithMemAddr_fromMemAddr_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); - MemoryAddress memAddr = functionSymbol.address(); - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); - MethodHandle mh = clinker.downcallHandle(memAddr, allocator, mt, fd); - MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); - mh.invoke(formatMemSegment.address(), 15, 27, 42); - } + Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); + MemoryAddress memAddr = functionSymbol.address(); + MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); + MethodHandle mh = clinker.downcallHandle(memAddr, allocator, mt, fd); + MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); + mh.invoke(formatMemSegment.address(), 15, 27, 42); } } diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests3.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests3.java index 9a3e62007ed..352be9b3e66 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests3.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/PrimitiveTypeTests3.java @@ -62,7 +62,7 @@ public class PrimitiveTypeTests3 { System.loadLibrary("clinkerffitests"); } private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); - private static final SymbolLookup defaultLibLookup = (!isAixOS) ? CLinker.systemLookup() : null; + private static final SymbolLookup defaultLibLookup = CLinker.systemLookup(); @Test public void test_addTwoBoolsWithOr_3() throws Throwable { @@ -398,132 +398,90 @@ public void test_addTwoDoubles_fromMemAddr_3() throws Throwable { @Test public void test_strlenFromDefaultLibWithMemAddr_3() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); - MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); - FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); - MethodHandle mh = clinker.downcallHandle(mt, fd); - MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); - long strLength = (long)mh.invokeExact(strlenSymbol, funcMemSegment.address()); - Assert.assertEquals(strLength, 27); - } + Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); + MethodHandle mh = clinker.downcallHandle(mt, fd); + MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); + long strLength = (long)mh.invokeExact(strlenSymbol, funcMemSegment.address()); + Assert.assertEquals(strLength, 27); } @Test public void test_strlenFromDefaultLibWithMemAddr_fromMemAddr_3() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); - MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); - FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); - MethodHandle mh = clinker.downcallHandle(mt, fd); - MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); - long strLength = (long)mh.invokeExact(strlenSymbol, funcMemSegment.address()); - Assert.assertEquals(strLength, 27); - } + Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER); + MethodHandle mh = clinker.downcallHandle(mt, fd); + MemorySegment funcMemSegment = CLinker.toCString("JEP389 DOWNCALL TEST SUITES", resourceScope); + long strLength = (long)mh.invokeExact(strlenSymbol, funcMemSegment.address()); + Assert.assertEquals(strLength, 27); } @Test public void test_memoryAllocFreeFromDefaultLib_3() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); - MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); - FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); - MethodHandle allocHandle = clinker.downcallHandle(allocMethodType, allocFuncDesc); - MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(allocSymbol, 10L); - MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); - MemoryAccess.setIntAtOffset(memSeg, 0, 15); - Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); - - Addressable freeSymbol = defaultLibLookup.lookup("free").get(); - MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); - FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); - MethodHandle freeHandle = clinker.downcallHandle(freeMethodType, freeFuncDesc); - freeHandle.invokeExact(freeSymbol, allocMemAddr); - } + Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); + MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); + MethodHandle allocHandle = clinker.downcallHandle(allocMethodType, allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(allocSymbol, 10L); + MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); + MemoryAccess.setIntAtOffset(memSeg, 0, 15); + Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); + + Addressable freeSymbol = defaultLibLookup.lookup("free").get(); + MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); + MethodHandle freeHandle = clinker.downcallHandle(freeMethodType, freeFuncDesc); + freeHandle.invokeExact(freeSymbol, allocMemAddr); } @Test public void test_memoryAllocFreeFromDefaultLib_fromMemAddr_3() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); - MemoryAddress allocMemAddrFromSymbol = allocSymbol.address(); - MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); - FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); - MethodHandle allocHandle = clinker.downcallHandle(allocMethodType, allocFuncDesc); - MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(allocSymbol, 10L); - MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); - MemoryAccess.setIntAtOffset(memSeg, 0, 15); - Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); - - Addressable freeSymbol = defaultLibLookup.lookup("free").get(); - MemoryAddress freeMemAddr = freeSymbol.address(); - MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); - FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); - MethodHandle freeHandle = clinker.downcallHandle(freeMethodType, freeFuncDesc); - freeHandle.invokeExact(freeSymbol, allocMemAddr); - } + Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); + MemoryAddress allocMemAddrFromSymbol = allocSymbol.address(); + MethodType allocMethodType = MethodType.methodType(MemoryAddress.class, long.class); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(C_POINTER, longLayout); + MethodHandle allocHandle = clinker.downcallHandle(allocMethodType, allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(allocSymbol, 10L); + MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); + MemoryAccess.setIntAtOffset(memSeg, 0, 15); + Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 15); + + Addressable freeSymbol = defaultLibLookup.lookup("free").get(); + MemoryAddress freeMemAddr = freeSymbol.address(); + MethodType freeMethodType = MethodType.methodType(void.class, MemoryAddress.class); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(C_POINTER); + MethodHandle freeHandle = clinker.downcallHandle(freeMethodType, freeFuncDesc); + freeHandle.invokeExact(freeSymbol, allocMemAddr); } @Test public void test_memoryAllocFreeFromCLinkerMethod_3() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - MemoryAddress allocMemAddr = CLinker.allocateMemory(10L); - MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); - MemoryAccess.setIntAtOffset(memSeg, 0, 49); - Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 49); - CLinker.freeMemory(allocMemAddr); - } + MemoryAddress allocMemAddr = CLinker.allocateMemory(10L); + MemorySegment memSeg = allocMemAddr.asSegment(10L, resourceScope); + MemoryAccess.setIntAtOffset(memSeg, 0, 49); + Assert.assertEquals(MemoryAccess.getIntAtOffset(memSeg, 0), 49); + CLinker.freeMemory(allocMemAddr); } @Test public void test_printfFromDefaultLibWithMemAddr_3() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); - MethodHandle mh = clinker.downcallHandle(mt, fd); - MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); - mh.invoke(functionSymbol, formatMemSegment.address(), 15, 27, 42); - } + Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); + MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); + MethodHandle mh = clinker.downcallHandle(mt, fd); + MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); + mh.invoke(functionSymbol, formatMemSegment.address(), 15, 27, 42); } @Test public void test_printfFromDefaultLibWithMemAddr_fromMemAddr_3() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); - MethodHandle mh = clinker.downcallHandle(mt, fd); - MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); - mh.invoke(functionSymbol, formatMemSegment.address(), 15, 27, 42); - } + Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); + MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, int.class, int.class, int.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_INT, C_INT); + MethodHandle mh = clinker.downcallHandle(mt, fd); + MemorySegment formatMemSegment = CLinker.toCString("\n%d + %d = %d\n", resourceScope); + mh.invoke(functionSymbol, formatMemSegment.address(), 15, 27, 42); } } diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/StructTests1.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/StructTests1.java index bd10a3d2920..6f985c54c52 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/StructTests1.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/StructTests1.java @@ -170,7 +170,8 @@ public void test_addBoolAndBoolsFromStructPointerWithXor_1() throws Throwable { @Test public void test_addBoolAndBoolsFromNestedStructWithXor_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); @@ -213,7 +214,8 @@ public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrder_1() throws @Test public void test_addBoolAndBoolsFromNestedStructWithXor_withoutLayoutName_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR, C_CHAR); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); @@ -278,7 +280,8 @@ public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder_1() t @Test public void test_addBoolAndBoolsFromStructWithNestedBoolArray_withoutLayoutName_1() throws Throwable { SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, C_CHAR); - GroupLayout structLayout = MemoryLayout.structLayout(boolArray, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); @@ -350,7 +353,8 @@ public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder_1() public void test_addBoolAndBoolsFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { GroupLayout boolStruct = MemoryLayout.structLayout(C_CHAR, C_CHAR); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); @@ -555,7 +559,8 @@ public void test_addByteAndBytesFromStructPointer_1() throws Throwable { @Test public void test_addByteAndBytesFromNestedStruct_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); @@ -598,7 +603,8 @@ public void test_addByteAndBytesFromNestedStruct_reverseOrder_1() throws Throwab @Test public void test_addByteAndBytesFromNestedStruct_withoutLayoutName_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR, C_CHAR); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); @@ -663,7 +669,8 @@ public void test_addByteAndBytesFromStructWithNestedByteArray_reverseOrder_1() t @Test public void test_addByteAndBytesFromStructWithNestedByteArray_withoutLayoutName_1() throws Throwable { SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, C_CHAR); - GroupLayout structLayout = MemoryLayout.structLayout(byteArray, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray").get(); @@ -735,7 +742,8 @@ public void test_addByteAndBytesFromStructWithNestedStructArray_reverseOrder_1() public void test_addByteAndBytesFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { GroupLayout byteStruct = MemoryLayout.structLayout(C_CHAR, C_CHAR); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray").get(); @@ -940,7 +948,8 @@ public void test_addCharAndCharsFromStructPointer_1() throws Throwable { @Test public void test_addCharAndCharsFromNestedStruct_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(C_SHORT.bitSize())); MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct").get(); @@ -1174,7 +1183,8 @@ public void test_add2CharStructs_returnStructPointer_1() throws Throwable { @Test public void test_add3CharStructs_returnStruct_1() throws Throwable { - GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), C_SHORT.withName("elem3")); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3"), MemoryLayout.paddingLayout(C_SHORT.bitSize())); VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); VarHandle charHandle3 = structLayout.varHandle(char.class, PathElement.groupElement("elem3")); @@ -1345,7 +1355,8 @@ public void test_addShortAndShortsFromNestedStruct_reverseOrder_1() throws Throw @Test public void test_addShortAndShortsFromNestedStruct_withoutLayoutName_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT, C_SHORT); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_SHORT, + MemoryLayout.paddingLayout(C_SHORT.bitSize())); MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct").get(); @@ -2839,34 +2850,25 @@ public void test_addDoubleAndDoublesFromStruct_1() throws Throwable { @Test public void test_addDoubleAndFloatDoubleFromStruct_1() throws Throwable { - GroupLayout structLayout = null; - MemorySegment structSegmt = null; + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(C_FLOAT.bitSize()), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.ofScope(scope); - - /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default - * while the same struct is 16 bytes with padding on other platforms. - */ - if (isAixOS) { - structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_DOUBLE.withName("elem2")); - structSegmt = allocator.allocate(structLayout); - MemoryAccess.setFloatAtOffset(structSegmt, 0, 18.444F); - MemoryAccess.setDoubleAtOffset(structSegmt, 4, 619.777D); - } else { - structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), - MemoryLayout.paddingLayout(C_FLOAT.bitSize()), C_DOUBLE.withName("elem2")); - VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); - VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); - structSegmt = allocator.allocate(structLayout); - elemHandle1.set(structSegmt, 18.444F); - elemHandle2.set(structSegmt, 619.777D); - } - - MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout); - Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18.444F); + elemHandle2.set(structSegmt, 619.777D); double result = (double)mh.invokeExact(113.567D, structSegmt); Assert.assertEquals(result, 751.788D, 0.001D); @@ -2875,34 +2877,25 @@ public void test_addDoubleAndFloatDoubleFromStruct_1() throws Throwable { @Test public void test_addDoubleAndIntDoubleFromStruct_1() throws Throwable { - GroupLayout structLayout = null; - MemorySegment structSegmt = null; + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(C_INT.withName("elem1"), + MemoryLayout.paddingLayout(C_INT.bitSize()), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.ofScope(scope); - - /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default - * while the same struct is 16 bytes with padding on other platforms. - */ - if (isAixOS) { - structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_DOUBLE.withName("elem2")); - structSegmt = allocator.allocate(structLayout); - MemoryAccess.setIntAtOffset(structSegmt, 0, 18); - MemoryAccess.setDoubleAtOffset(structSegmt, 4, 619.777D); - } else { - structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), - MemoryLayout.paddingLayout(C_INT.bitSize()), C_DOUBLE.withName("elem2")); - VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); - VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); - structSegmt = allocator.allocate(structLayout); - elemHandle1.set(structSegmt, 18); - elemHandle2.set(structSegmt, 619.777D); - } - - MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout); - Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18); + elemHandle2.set(structSegmt, 619.777D); double result = (double)mh.invokeExact(113.567D, structSegmt); Assert.assertEquals(result, 751.344D, 0.001D); diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/StructTests2.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/StructTests2.java index d921575c52f..93114de729b 100644 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/StructTests2.java +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/downcall/StructTests2.java @@ -168,7 +168,8 @@ public void test_addBoolAndBoolsFromStructPointerWithXor_2() throws Throwable { @Test public void test_addBoolAndBoolsFromNestedStructWithXor_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); @@ -211,7 +212,8 @@ public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrder_2() throws @Test public void test_addBoolAndBoolsFromNestedStructWithXor_withoutLayoutName_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR, C_CHAR); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); @@ -276,7 +278,7 @@ public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder_2() t @Test public void test_addBoolAndBoolsFromStructWithNestedBoolArray_withoutLayoutName_2() throws Throwable { SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, C_CHAR); - GroupLayout structLayout = MemoryLayout.structLayout(boolArray, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray, C_CHAR, MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); @@ -348,7 +350,8 @@ public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder_2() public void test_addBoolAndBoolsFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { GroupLayout boolStruct = MemoryLayout.structLayout(C_CHAR, C_CHAR); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); @@ -553,7 +556,8 @@ public void test_addByteAndBytesFromStructPointer_2() throws Throwable { @Test public void test_addByteAndBytesFromNestedStruct_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); @@ -596,7 +600,8 @@ public void test_addByteAndBytesFromNestedStruct_reverseOrder_2() throws Throwab @Test public void test_addByteAndBytesFromNestedStruct_withoutLayoutName_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR, C_CHAR); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); @@ -661,7 +666,8 @@ public void test_addByteAndBytesFromStructWithNestedByteArray_reverseOrder_2() t @Test public void test_addByteAndBytesFromStructWithNestedByteArray_withoutLayoutName_2() throws Throwable { SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, C_CHAR); - GroupLayout structLayout = MemoryLayout.structLayout(byteArray, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize())); MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray").get(); @@ -733,7 +739,8 @@ public void test_addByteAndBytesFromStructWithNestedStructArray_reverseOrder_2() public void test_addByteAndBytesFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { GroupLayout byteStruct = MemoryLayout.structLayout(C_CHAR, C_CHAR); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, C_CHAR, + MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray").get(); @@ -938,7 +945,8 @@ public void test_addCharAndCharsFromStructPointer_2() throws Throwable { @Test public void test_addCharAndCharsFromNestedStruct_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(C_SHORT.bitSize())); MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct").get(); @@ -1172,7 +1180,8 @@ public void test_add2CharStructs_returnStructPointer_2() throws Throwable { @Test public void test_add3CharStructs_returnStruct_2() throws Throwable { - GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), C_SHORT.withName("elem3")); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3"), MemoryLayout.paddingLayout(C_SHORT.bitSize())); VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); VarHandle charHandle3 = structLayout.varHandle(char.class, PathElement.groupElement("elem3")); @@ -1343,7 +1352,8 @@ public void test_addShortAndShortsFromNestedStruct_reverseOrder_2() throws Throw @Test public void test_addShortAndShortsFromNestedStruct_withoutLayoutName_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT, C_SHORT); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, C_SHORT, + MemoryLayout.paddingLayout(C_SHORT.bitSize())); MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout); Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct").get(); @@ -2837,34 +2847,25 @@ public void test_addDoubleAndDoublesFromStruct_2() throws Throwable { @Test public void test_addDoubleAndFloatDoubleFromStruct_2() throws Throwable { - GroupLayout structLayout = null; - MemorySegment structSegmt = null; + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(C_FLOAT.bitSize()), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); + MethodHandle mh = clinker.downcallHandle(mt, fd); try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.ofScope(scope); - - /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default - * while the same struct is 16 bytes with padding on other platforms. - */ - if (isAixOS) { - structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_DOUBLE.withName("elem2")); - structSegmt = allocator.allocate(structLayout); - MemoryAccess.setFloatAtOffset(structSegmt, 0, 18.444F); - MemoryAccess.setDoubleAtOffset(structSegmt, 4, 619.777D); - } else { - structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), - MemoryLayout.paddingLayout(C_FLOAT.bitSize()), C_DOUBLE.withName("elem2")); - VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); - VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); - structSegmt = allocator.allocate(structLayout); - elemHandle1.set(structSegmt, 18.444F); - elemHandle2.set(structSegmt, 619.777D); - } - - MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout); - Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); - MethodHandle mh = clinker.downcallHandle(mt, fd); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18.444F); + elemHandle2.set(structSegmt, 619.777D); double result = (double)mh.invokeExact(functionSymbol, 113.567D, structSegmt); Assert.assertEquals(result, 751.788D, 0.001D); @@ -2873,34 +2874,25 @@ public void test_addDoubleAndFloatDoubleFromStruct_2() throws Throwable { @Test public void test_addDoubleAndIntDoubleFromStruct_2() throws Throwable { - GroupLayout structLayout = null; - MemorySegment structSegmt = null; + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(C_INT.withName("elem1"), + MemoryLayout.paddingLayout(C_INT.bitSize()), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); + MethodHandle mh = clinker.downcallHandle(mt, fd); try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.ofScope(scope); - - /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default - * while the same struct is 16 bytes with padding on other platforms. - */ - if (isAixOS) { - structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_DOUBLE.withName("elem2")); - structSegmt = allocator.allocate(structLayout); - MemoryAccess.setIntAtOffset(structSegmt, 0, 18); - MemoryAccess.setDoubleAtOffset(structSegmt, 4, 619.777D); - } else { - structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), - MemoryLayout.paddingLayout(C_INT.bitSize()), C_DOUBLE.withName("elem2")); - VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); - VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); - structSegmt = allocator.allocate(structLayout); - elemHandle1.set(structSegmt, 18); - elemHandle2.set(structSegmt, 619.777D); - } - - MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout); - Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); - MethodHandle mh = clinker.downcallHandle(mt, fd); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18); + elemHandle2.set(structSegmt, 619.777D); double result = (double)mh.invokeExact(functionSymbol, 113.567D, structSegmt); Assert.assertEquals(result, 751.344D, 0.001D); diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/MultiUpcallMHTests.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/MultiUpcallMHTests.java new file mode 100644 index 00000000000..56be08e532e --- /dev/null +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/MultiUpcallMHTests.java @@ -0,0 +1,606 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep389.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import static jdk.incubator.foreign.CLinker.*; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; + +/** + * Test cases for JEP 389: Foreign Linker API (Incubator) in upcall intended for + * the situations when the multiple primitive specific upcalls happen within + * the same resource scope or from different resource scopes. + */ +@Test(groups = { "level.sanity" }) +public class MultiUpcallMHTests { + private static String osName = System.getProperty("os.name").toLowerCase(); + private static boolean isAixOS = osName.contains("aix"); + private static boolean isWinOS = osName.contains("win"); + /* long long is 64 bits on AIX/ppc64, which is the same as Windows */ + private static ValueLayout longLayout = (isWinOS || isAixOS) ? C_LONG_LONG : C_LONG; + private static CLinker clinker = CLinker.getInstance(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addTwoBoolsWithOrByUpcallMH_SameScope() throws Throwable { + MethodType mt = MethodType.methodType(boolean.class, boolean.class, boolean.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR), scope); + boolean result = (boolean)mh.invokeExact(true, false, upcallFuncAddr1); + Assert.assertEquals(result, true); + + MemoryAddress upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR), scope); + result = (boolean)mh.invokeExact(true, false, upcallFuncAddr2); + Assert.assertEquals(result, true); + + MemoryAddress upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR), scope); + result = (boolean)mh.invokeExact(true, false, upcallFuncAddr3); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addTwoBoolsWithOrByUpcallMH_DiffScope() throws Throwable { + MethodType mt = MethodType.methodType(boolean.class, boolean.class, boolean.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR), scope); + boolean result = (boolean)mh.invokeExact(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR), scope); + boolean result = (boolean)mh.invokeExact(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR), scope); + boolean result = (boolean)mh.invokeExact(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPointerByUpcallMH_SameScope() throws Throwable { + MethodType mt = MethodType.methodType(char.class, MemoryAddress.class, char.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setChar(shortSegmt, 'B'); + char result = (char)mh.invokeExact(shortSegmt.address(), 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + + MemoryAddress upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + result = (char)mh.invokeExact(shortSegmt.address(), 'D', upcallFuncAddr2); + Assert.assertEquals(result, 'C'); + + MemoryAddress upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + result = (char)mh.invokeExact(shortSegmt.address(), 'D', upcallFuncAddr3); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPointerByUpcallMH_DiffScope() throws Throwable { + MethodType mt = MethodType.methodType(char.class, MemoryAddress.class, char.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setChar(shortSegmt, 'B'); + char result = (char)mh.invokeExact(shortSegmt.address(), 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setChar(shortSegmt, 'B'); + char result = (char)mh.invokeExact(shortSegmt.address(), 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setChar(shortSegmt, 'B'); + char result = (char)mh.invokeExact(shortSegmt.address(), 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_addByteAndByteFromNativePtrByUpcallMH_SameScope() throws Throwable { + MethodType mt = MethodType.methodType(byte.class, byte.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + byte result = (byte)mh.invokeExact((byte)33, upcallFuncAddr1); + Assert.assertEquals(result, (byte)88); + + MemoryAddress upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + result = (byte)mh.invokeExact((byte)33, upcallFuncAddr2); + Assert.assertEquals(result, (byte)88); + + MemoryAddress upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + result = (byte)mh.invokeExact((byte)33, upcallFuncAddr3); + Assert.assertEquals(result, (byte)88); + } + } + + @Test + public void test_addByteAndByteFromNativePtrByUpcallMH_DiffScope() throws Throwable { + MethodType mt = MethodType.methodType(byte.class, byte.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + byte result = (byte)mh.invokeExact((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + byte result = (byte)mh.invokeExact((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + byte result = (byte)mh.invokeExact((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetPtr_ByUpcallMH_SameScope() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, short.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setShort(shortSegmt, (short)444); + MemoryAddress resultAddr1 = (MemoryAddress)mh.invokeExact(shortSegmt.address(), (short)555, upcallFuncAddr1); + short result = MemoryAccess.getShort(resultAddr1.asSegment(C_SHORT.byteSize(), resultAddr1.scope())); + Assert.assertEquals(result, (short)999); + + MemoryAddress upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + MemoryAddress resultAddr2 = (MemoryAddress)mh.invokeExact(shortSegmt.address(), (short)555, upcallFuncAddr2); + result = MemoryAccess.getShort(resultAddr2.asSegment(C_SHORT.byteSize(), resultAddr2.scope())); + Assert.assertEquals(result, (short)999); + + MemoryAddress upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + MemoryAddress resultAddr3 = (MemoryAddress)mh.invokeExact(shortSegmt.address(), (short)555, upcallFuncAddr3); + result = MemoryAccess.getShort(resultAddr3.asSegment(C_SHORT.byteSize(), resultAddr3.scope())); + Assert.assertEquals(result, (short)999); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetPtr_ByUpcallMH_DiffScope() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, short.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setShort(shortSegmt, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(shortSegmt.address(), (short)555, upcallFuncAddr); + short result = MemoryAccess.getShort(resultAddr.asSegment(C_SHORT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, (short)999); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setShort(shortSegmt, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(shortSegmt.address(), (short)555, upcallFuncAddr); + short result = MemoryAccess.getShort(resultAddr.asSegment(C_SHORT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, (short)999); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setShort(shortSegmt, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(shortSegmt.address(), (short)555, upcallFuncAddr); + short result = MemoryAccess.getShort(resultAddr.asSegment(C_SHORT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, (short)999); + } + } + + @Test + public void test_addTwoIntsByUpcallMH_SameScope() throws Throwable { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + int result = (int)mh.invokeExact(111112, 111123, upcallFuncAddr1); + Assert.assertEquals(result, 222235); + + MemoryAddress upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + result = (int)mh.invokeExact(111112, 111123, upcallFuncAddr2); + Assert.assertEquals(result, 222235); + + MemoryAddress upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + result = (int)mh.invokeExact(111112, 111123, upcallFuncAddr3); + Assert.assertEquals(result, 222235); + } + } + + @Test + public void test_addTwoIntsByUpcallMH_DiffScope() throws Throwable { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + int result = (int)mh.invokeExact(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + int result = (int)mh.invokeExact(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + int result = (int)mh.invokeExact(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + } + + @Test + public void test_addTwoIntsReturnVoidByUpcallMH_SameScope() throws Throwable { + MethodType mt = MethodType.methodType(void.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoidByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(C_INT, C_INT), scope); + mh.invokeExact(111454, 111398, upcallFuncAddr1); + + MemoryAddress upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(C_INT, C_INT), scope); + mh.invokeExact(111454, 111398, upcallFuncAddr2); + + MemoryAddress upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(C_INT, C_INT), scope); + mh.invokeExact(111454, 111398, upcallFuncAddr3); + } + } + + @Test + public void test_addTwoIntsReturnVoidByUpcallMH_DiffScope() throws Throwable { + MethodType mt = MethodType.methodType(void.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoidByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(C_INT, C_INT), scope); + mh.invokeExact(111454, 111398, upcallFuncAddr); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(C_INT, C_INT), scope); + mh.invokeExact(111454, 111398, upcallFuncAddr); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(C_INT, C_INT), scope); + mh.invokeExact(111454, 111398, upcallFuncAddr); + } + } + + @Test + public void test_addLongAndLongFromPointerByUpcallMH_SameScope() throws Throwable { + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class, long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER, longLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(longLayout, C_POINTER, longLayout), scope); + MemorySegment longSegmt = allocator.allocate(longLayout); + MemoryAccess.setLong(longSegmt, 5742457424L); + long result = (long)mh.invokeExact(longSegmt.address(), 6666698235L, upcallFuncAddr1); + Assert.assertEquals(result, 12409155659L); + + MemoryAddress upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(longLayout, C_POINTER, longLayout), scope); + result = (long)mh.invokeExact(longSegmt.address(), 6666698235L, upcallFuncAddr2); + Assert.assertEquals(result, 12409155659L); + + MemoryAddress upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(longLayout, C_POINTER, longLayout), scope); + result = (long)mh.invokeExact(longSegmt.address(), 6666698235L, upcallFuncAddr3); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addLongAndLongFromPointerByUpcallMH_DiffScope() throws Throwable { + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class, long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER, longLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(longLayout, C_POINTER, longLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment longSegmt = allocator.allocate(longLayout); + MemoryAccess.setLong(longSegmt, 5742457424L); + long result = (long)mh.invokeExact(longSegmt.address(), 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(longLayout, C_POINTER, longLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment longSegmt = allocator.allocate(longLayout); + MemoryAccess.setLong(longSegmt, 5742457424L); + long result = (long)mh.invokeExact(longSegmt.address(), 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(longLayout, C_POINTER, longLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment longSegmt = allocator.allocate(longLayout); + MemoryAccess.setLong(longSegmt, 5742457424L); + long result = (long)mh.invokeExact(longSegmt.address(), 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addFloatAndFloatFromNativePtrByUpcallMH_SameScope() throws Throwable { + MethodType mt = MethodType.methodType(float.class, float.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER), scope); + float result = (float)mh.invokeExact(5.74F, upcallFuncAddr1); + Assert.assertEquals(result, 12.53F, 0.01F); + + MemoryAddress upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER), scope); + result = (float)mh.invokeExact(5.74F, upcallFuncAddr2); + Assert.assertEquals(result, 12.53F, 0.01F); + + MemoryAddress upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER), scope); + result = (float)mh.invokeExact(5.74F, upcallFuncAddr3); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromNativePtrByUpcallMH_DiffScope() throws Throwable { + MethodType mt = MethodType.methodType(float.class, float.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER), scope); + float result = (float)mh.invokeExact(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER), scope); + float result = (float)mh.invokeExact(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER), scope); + float result = (float)mh.invokeExact(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH_SameScope() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, double.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + + MemoryAddress upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE), scope); + MemorySegment doubleSegmt = allocator.allocate(C_DOUBLE); + MemoryAccess.setDouble(doubleSegmt, 1159.748d); + MemoryAddress resultAddr1 = (MemoryAddress)mh.invokeExact(doubleSegmt.address(), 1262.795d, upcallFuncAddr1); + double result = MemoryAccess.getDouble(resultAddr1.asSegment(C_DOUBLE.byteSize(), resultAddr1.scope())); + Assert.assertEquals(result, 2422.543d, 0.001d); + + MemoryAddress upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE), scope); + MemoryAddress resultAddr2 = (MemoryAddress)mh.invokeExact(doubleSegmt.address(), 1262.795d, upcallFuncAddr2); + result = MemoryAccess.getDouble(resultAddr2.asSegment(C_DOUBLE.byteSize(), resultAddr2.scope())); + Assert.assertEquals(result, 2422.543d, 0.001d); + + MemoryAddress upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE), scope); + MemoryAddress resultAddr3 = (MemoryAddress)mh.invokeExact(doubleSegmt.address(), 1262.795d, upcallFuncAddr3); + result = MemoryAccess.getDouble(resultAddr3.asSegment(C_DOUBLE.byteSize(), resultAddr3.scope())); + Assert.assertEquals(result, 2422.543d, 0.001d); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH_DiffScope() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, double.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment doubleSegmt = allocator.allocate(C_DOUBLE); + MemoryAccess.setDouble(doubleSegmt, 1159.748d); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(doubleSegmt.address(), 1262.795d, upcallFuncAddr); + double result = MemoryAccess.getDouble(resultAddr.asSegment(C_DOUBLE.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 2422.543d, 0.001d); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment doubleSegmt = allocator.allocate(C_DOUBLE); + MemoryAccess.setDouble(doubleSegmt, 1159.748d); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(doubleSegmt.address(), 1262.795d, upcallFuncAddr); + double result = MemoryAccess.getDouble(resultAddr.asSegment(C_DOUBLE.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 2422.543d, 0.001d); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment doubleSegmt = allocator.allocate(C_DOUBLE); + MemoryAccess.setDouble(doubleSegmt, 1159.748d); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(doubleSegmt.address(), 1262.795d, upcallFuncAddr); + double result = MemoryAccess.getDouble(resultAddr.asSegment(C_DOUBLE.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 2422.543d, 0.001d); + } + } +} diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/MultiUpcallThrdsMHTests1.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/MultiUpcallThrdsMHTests1.java new file mode 100644 index 00000000000..9147800ab80 --- /dev/null +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/MultiUpcallThrdsMHTests1.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep389.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import static jdk.incubator.foreign.CLinker.*; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; + +/** + * Test cases for JEP 389: Foreign Linker API (Incubator) intended for + * the situation when the multi-threading specific upcalls happen to the same + * upcall method handle within different resource scopes, in which case the upcall + * metadata and the generated thunk are allocated separately. + */ +@Test(groups = { "level.sanity" }) +public class MultiUpcallThrdsMHTests1 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static CLinker clinker = CLinker.getInstance(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_multiUpcallThrdsWithDiffScopes() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + int result = (int)mh.invokeExact(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr1.setUncaughtExceptionHandler(this); + thr1.start(); + + Thread thr2 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + int result = (int)mh.invokeExact(111113, 111124, upcallFuncAddr); + Assert.assertEquals(result, 222237); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr2.setUncaughtExceptionHandler(this); + thr2.start(); + + Thread thr3 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + int result = (int)mh.invokeExact(111114, 111125, upcallFuncAddr); + Assert.assertEquals(result, 222239); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr3.setUncaughtExceptionHandler(this); + thr3.start(); + + thr1.join(); + thr2.join(); + thr3.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/MultiUpcallThrdsMHTests2.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/MultiUpcallThrdsMHTests2.java new file mode 100644 index 00000000000..ceaea1ca751 --- /dev/null +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/MultiUpcallThrdsMHTests2.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep389.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import static jdk.incubator.foreign.CLinker.*; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; + +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; + +/** + * Test cases for JEP 389: Foreign Linker API (Incubator) intended for + * the situation when the multi-threading specific upcalls happen to the same + * upcall method handle within the same resource scope, in which case the upcall + * metadata and the generated thunk are only allocated once and shared among + * these threads. + */ +@Test(groups = { "level.sanity" }) +public class MultiUpcallThrdsMHTests2 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static CLinker clinker = CLinker.getInstance(); + private static ResourceScope resourceScope = ResourceScope.newImplicitScope(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_multiUpcallThrdsWithSameScope() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), resourceScope); + int result = (int)mh.invokeExact(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr1.setUncaughtExceptionHandler(this); + thr1.start(); + + Thread thr2 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), resourceScope); + int result = (int)mh.invokeExact(111113, 111124, upcallFuncAddr); + Assert.assertEquals(result, 222237); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr2.setUncaughtExceptionHandler(this); + thr2.start(); + + Thread thr3 = new Thread(){ + public void run() { + try { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), resourceScope); + int result = (int)mh.invokeExact(111114, 111125, upcallFuncAddr); + Assert.assertEquals(result, 222239); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr3.setUncaughtExceptionHandler(this); + thr3.start(); + + thr1.join(); + thr2.join(); + thr3.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMHWithMixedSigStruTests.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMHWithMixedSigStruTests.java new file mode 100644 index 00000000000..eb3c2c36d7b --- /dev/null +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMHWithMixedSigStruTests.java @@ -0,0 +1,934 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep389.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.nio.ByteOrder; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import static jdk.incubator.foreign.CLinker.*; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryHandles; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; + +/** + * Test cases for JEP 389: Foreign Linker API (Incubator) for the mixed native signatures + * in argument/return struct in upcall. + * + * Note: the padding elements in the struct are only required by RI or VarHandle (accessing the + * data address) while they are totally ignored in OpenJ9 given the padding/alignment are + * computed by libffi automatically in native. + */ +@Test(groups = { "level.sanity" }) +public class UpcallMHWithMixedSigStruTests { + private static String osName = System.getProperty("os.name").toLowerCase(); + private static boolean isAixOS = osName.contains("aix"); + private static boolean isWinOS = osName.contains("win"); + /* long long is 64 bits on AIX/ppc64, which is the same as Windows */ + private static ValueLayout longLayout = (isWinOS || isAixOS) ? C_LONG_LONG : C_LONG; + private static CLinker clinker = CLinker.getInstance(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addIntAndIntShortFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntShortFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntShortFromStruct, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, (short)32766); + + int result = (int)mh.invokeExact(22334455, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 33590565); + } + } + + @Test + public void test_addIntAndShortIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), + MemoryLayout.paddingLayout(16), C_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndShortIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndShortIntFromStruct, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, (short)32766); + elemHandle2.set(structSegmt, 22446688); + + int result = (int)mh.invokeExact(11335577, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 33815031); + } + } + + @Test + public void test_addIntAndIntLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), longLayout.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(long.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntLongFromStruct, + FunctionDescriptor.of(longLayout, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, 667788990011L); + + long result = (long)mh.invokeExact(22446688, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 667822660043L); + } + } + + @Test + public void test_addIntAndLongIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), + C_INT.withName("elem2"), MemoryLayout.paddingLayout(32)); + VarHandle elemHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(long.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndLongIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndLongIntFromStruct, + FunctionDescriptor.of(longLayout, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 667788990011L); + elemHandle2.set(structSegmt, 11223344); + + long result = (long)mh.invokeExact(1234567, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 667801447922L); + } + } + + @Test + public void test_addDoubleAndIntDoubleFromStructByUpcallMH() throws Throwable { + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(C_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111111); + elemHandle2.set(structSegmt, 619.777D); + + double result = (double)mh.invokeExact(113.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111844.344D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleIntFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 111111111); + + double result = (double)mh.invokeExact(216.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111546.221D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleFromStructByUpcallMH() throws Throwable { + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatDoubleFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18.444F); + elemHandle2.set(structSegmt, 619.777D); + + double result = (double)mh.invokeExact(113.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 751.788D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFloatFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19.22F); + + double result = (double)mh.invokeExact(216.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 454.441D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFloatPlusPaddingFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), + C_FLOAT.withName("elem2"), MemoryLayout.paddingLayout(32)); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFloatFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19.22F); + + double result = (double)mh.invokeExact(216.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 454.441D, 0.001D); + } + } + + @Test + public void test_addDoubleAnd2FloatsDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_FLOAT.withName("elem2"), C_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(double.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAnd2FloatsDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAnd2FloatsDoubleFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.22F); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 333.444D); + + double result = (double)mh.invokeExact(111.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 478.105D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDouble2FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDouble2FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDouble2FloatsFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 333.444D); + elemHandle2.set(structSegmt, 11.22F); + elemHandle3.set(structSegmt, 22.33F); + + double result = (double)mh.invokeExact(111.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 478.105D, 0.001D); + } + } + + @Test + public void test_addFloatAndInt2FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndInt2FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndInt2FloatsFromStruct, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111); + elemHandle2.set(structSegmt, 11.22F); + elemHandle3.set(structSegmt, 22.33F); + + float result = (float)mh.invokeExact(55.567F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111200.12F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatIntFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_INT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatIntFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatIntFloatFromStruct, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.22F); + elemHandle2.set(structSegmt, 111111); + elemHandle3.set(structSegmt, 22.33F); + + float result = (float)mh.invokeExact(55.567F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111200.12F, 0.01F); + } + } + + @Test + public void test_addDoubleAndIntFloatDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_FLOAT.withName("elem2"), C_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(double.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntFloatDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntFloatDoubleFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111111); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 333.444D); + + double result = (double)mh.invokeExact(555.55D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111112022.324D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatIntDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_INT.withName("elem2"), C_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(double.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatIntDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatIntDoubleFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 22.33F); + elemHandle2.set(structSegmt, 111111111); + elemHandle3.set(structSegmt, 333.444D); + + double result = (double)mh.invokeExact(555.55D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111112022.324D, 0.001D); + } + } + + @Test + public void test_addDoubleAndLongDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndLongDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndLongDoubleFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 22222222222222L); + elemHandle2.set(structSegmt, 33333.444D); + + double result = (double)mh.invokeExact(55555.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 22222222311110.555D, 0.001D); + } + } + + @Test + public void test_addFloatAndInt3FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3"), C_FLOAT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(float.class, PathElement.groupElement("elem4")); + + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndInt3FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndInt3FloatsFromStruct, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 77777777); + elemHandle2.set(structSegmt, 11.22F); + elemHandle3.set(structSegmt, 22.33F); + elemHandle4.set(structSegmt, 44.55F); + + float result = (float)mh.invokeExact(66.678F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 77777921.778F, 0.001F); + } + } + + @Test + public void test_addLongAndLong2FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLong2FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLong2FloatsFromStruct, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 777777777777L); + elemHandle2.set(structSegmt, 11.25F); + elemHandle3.set(structSegmt, 22.75F); + + long result = (long)mh.invokeExact(555555555555L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1333333333365L); + } + } + + @Test + public void test_addFloatAnd3FloatsIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3"), C_INT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(int.class, PathElement.groupElement("elem4")); + + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAnd3FloatsIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAnd3FloatsIntFromStruct, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.22F); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 44.55F); + elemHandle4.set(structSegmt, 77777777); + + float result = (float)mh.invokeExact(66.456F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 77777921.556F, 0.001F); + } + } + + @Test + public void test_addLongAndFloatLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), longLayout.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndFloatLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndFloatLongFromStruct, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 55.11F); + elemHandle2.set(structSegmt, 150000000000L); + + long result = (long)mh.invokeExact(5555555555L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 155555555610L); + } + } + + @Test + public void test_addDoubleAndDoubleFloatIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), + C_FLOAT.withName("elem2"), C_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFloatIntFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 333.444D); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 111111111); + + double result = (double)mh.invokeExact(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111112022.341D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), longLayout.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleLongFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 33333.444D); + elemHandle2.set(structSegmt, 222222222222L); + + double result = (double)mh.invokeExact(55555.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 222222311110.555D, 0.001D); + } + } + + @Test + public void test_addLongAnd2FloatsLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_FLOAT.withName("elem2"), longLayout.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(long.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAnd2FloatsLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAnd2FloatsLongFromStruct, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.11F); + elemHandle2.set(structSegmt, 22.11F); + elemHandle3.set(structSegmt, 4444444444L); + + long result = (long)mh.invokeExact(11111111111L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 15555555588L); + } + } + + @Test + public void test_addShortAnd3ShortsCharFromStructByUpcallMH() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(3, C_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(shortArray, C_SHORT); + + MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAnd3ShortsCharFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAnd3ShortsCharFromStruct, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setShortAtOffset(structSegmt, 0, (short)1000); + MemoryAccess.setShortAtOffset(structSegmt, 2, (short)2000); + MemoryAccess.setShortAtOffset(structSegmt, 4, (short)3000); + MemoryAccess.setCharAtOffset(structSegmt, 6, 'A'); + + short result = (short)mh.invokeExact((short)4000, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 10065); + } + } + + @Test + public void test_addFloatAndIntFloatIntFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_FLOAT.withName("elem2"), C_INT.withName("elem3"), C_FLOAT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(float.class, PathElement.groupElement("elem4")); + + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndIntFloatIntFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndIntFloatIntFloatFromStruct, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 555555555); + elemHandle2.set(structSegmt, 11.222F); + elemHandle3.set(structSegmt, 666666666); + elemHandle4.set(structSegmt, 33.444F); + + float result = (float)mh.invokeExact(77.456F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1222222343.122F, 0.001F); + } + } + + @Test + public void test_addDoubleAndIntDoubleFloatFromStructByUpcallMH() throws Throwable { + /* The size of [int, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2"), C_FLOAT.withName("elem3")) + : MemoryLayout.structLayout(C_INT.withName("elem1"), MemoryLayout.paddingLayout(32), + C_DOUBLE.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleFloatFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 7777); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 33.444F); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 8584.566D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleIntFromStructByUpcallMH() throws Throwable { + /* The size of [float, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_DOUBLE.withName("elem2"), C_INT.withName("elem3")) + : MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), C_DOUBLE.withName("elem2"), + C_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatDoubleIntFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 33.444F); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 7777); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 8584.566D, 0.001D); + } + } + + @Test + public void test_addDoubleAndIntDoubleIntFromStructByUpcallMH() throws Throwable { + /* The size of [int, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2"), C_INT.withName("elem3")) + : MemoryLayout.structLayout(C_INT.withName("elem1"), MemoryLayout.paddingLayout(32), + C_DOUBLE.withName("elem2"), C_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleIntFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 6666); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 7777); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 15217.122D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleFloatFromStructByUpcallMH() throws Throwable { + /* The size of [float, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_DOUBLE.withName("elem2"), C_FLOAT.withName("elem3")) + : MemoryLayout.structLayout(C_FLOAT.withName("elem1"), MemoryLayout.paddingLayout(32), + C_DOUBLE.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatDoubleFloatFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.222F); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 33.444F); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 818.788D, 0.001D); + } + } + + @Test + public void test_addDoubleAndIntDoubleLongFromStructByUpcallMH() throws Throwable { + /* The size of [int, double, long] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 24 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2"), longLayout.withName("elem3")) : MemoryLayout.structLayout(C_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), C_DOUBLE.withName("elem2"), longLayout.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(long.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleLongFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111111); + elemHandle2.set(structSegmt, 619.777D); + elemHandle3.set(structSegmt, 888888888888L); + + double result = (double)mh.invoke(113.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 889000000732.344D, 0.001D); + } + } + + @Test + public void test_return254BytesFromStructByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(254, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("return254BytesFromStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_return254BytesFromStruct, + FunctionDescriptor.of(structLayout), scope); + + MemorySegment byteArrStruSegment = (MemorySegment)mh.invoke(upcallFuncAddr); + for (int i = 0; i < 254; i++) { + Assert.assertEquals(MemoryAccess.getByteAtOffset(byteArrStruSegment, i), (byte)i); + } + } + } + + @Test + public void test_return4KBytesFromStructByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(4096, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("return4KBytesFromStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_return4KBytesFromStruct, + FunctionDescriptor.of(structLayout), scope); + + MemorySegment byteArrStruSegment = (MemorySegment)mh.invoke(upcallFuncAddr); + for (int i = 0; i < 4096; i++) { + Assert.assertEquals(MemoryAccess.getByteAtOffset(byteArrStruSegment, i), (byte)i); + } + } + } +} diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMHWithPrimTests.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMHWithPrimTests.java new file mode 100644 index 00000000000..9499a515712 --- /dev/null +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMHWithPrimTests.java @@ -0,0 +1,821 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep389.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import static jdk.incubator.foreign.CLinker.*; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; + +/** + * Test cases for JEP 389: Foreign Linker API (Incubator) for primitive types in upcall. + */ +@Test(groups = { "level.sanity" }) +public class UpcallMHWithPrimTests { + private static String osName = System.getProperty("os.name").toLowerCase(); + private static boolean isAixOS = osName.contains("aix"); + private static boolean isWinOS = osName.contains("win"); + /* long long is 64 bits on AIX/ppc64, which is the same as Windows */ + private static ValueLayout longLayout = (isWinOS || isAixOS) ? C_LONG_LONG : C_LONG; + private static CLinker clinker = CLinker.getInstance(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + private static final SymbolLookup defaultLibLookup = CLinker.systemLookup(); + + @Test(enabled=false) + public static boolean byteToBool(byte value) { + return (value != 0); + } + + @Test + public void test_addTwoBoolsWithOrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(boolean.class, boolean.class, boolean.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR), scope); + boolean result = (boolean)mh.invokeExact(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolFromPointerWithOrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPointerWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPointerWithOr, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment boolSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(boolSegmt, (byte)1); + boolean result = (boolean)mh.invokeExact(false, boolSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolFromNativePtrWithOrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromNativePtrWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPointerWithOr, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + boolean result = (boolean)mh.invokeExact(false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, boolean.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_CHAR, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPtrWithOr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_CHAR, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment boolSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(boolSegmt, (byte)1); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(false, boolSegmt.address(), upcallFuncAddr); + byte result = MemoryAccess.getByte(resultAddr.asSegment(C_CHAR.byteSize(), resultAddr.scope())); + Assert.assertEquals(byteToBool(result), true); + } + } + + @Test + public void test_addBoolAndBoolFromPtrWithOr_RetArgPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, boolean.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_CHAR, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPtrWithOr_RetArgPtr, + FunctionDescriptor.of(C_POINTER, C_CHAR, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment boolSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(boolSegmt, (byte)1); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(false, boolSegmt.address(), upcallFuncAddr); + byte result = MemoryAccess.getByte(resultAddr.asSegment(C_CHAR.byteSize(), resultAddr.scope())); + Assert.assertEquals(byteToBool(result), true); + } + } + + @Test + public void test_addTwoBytesByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(byte.class, byte.class, byte.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2BytesByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Bytes, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_CHAR), scope); + byte result = (byte)mh.invokeExact((byte)6, (byte)3, upcallFuncAddr); + Assert.assertEquals(result, (byte)9); + } + } + + @Test + public void test_addByteAndByteFromPointerByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(byte.class, byte.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment charSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(charSegmt, (byte)7); + byte result = (byte)mh.invokeExact((byte)8, charSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, (byte)15); + } + } + + @Test + public void test_addByteAndByteFromNativePtrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(byte.class, byte.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + byte result = (byte)mh.invokeExact((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + } + + @Test + public void test_addByteAndByteFromPtr_RetPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, byte.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_CHAR, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_CHAR, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment charSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(charSegmt, (byte)35); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact((byte)47, charSegmt.address(), upcallFuncAddr); + byte result = MemoryAccess.getByte(resultAddr.asSegment(C_CHAR.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, (byte)82); + } + } + + @Test + public void test_addByteAndByteFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, byte.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_CHAR, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPtr_RetArgPtr, + FunctionDescriptor.of(C_POINTER, C_CHAR, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment charSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(charSegmt, (byte)35); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact((byte)47, charSegmt.address(), upcallFuncAddr); + byte result = MemoryAccess.getByte(resultAddr.asSegment(C_CHAR.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, (byte)82); + } + } + + @Test + public void test_createNewCharFrom2CharsByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(char.class, char.class, char.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFrom2CharsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFrom2Chars, + FunctionDescriptor.of(C_SHORT, C_SHORT, C_SHORT), scope); + char result = (char)mh.invokeExact('B', 'D', upcallFuncAddr); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPointerByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(char.class, MemoryAddress.class, char.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setChar(shortSegmt, 'B'); + char result = (char)mh.invokeExact(shortSegmt.address(), 'D', upcallFuncAddr); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromNativePtrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(char.class, char.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + char result = (char)mh.invokeExact('D', upcallFuncAddr); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, char.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setChar(shortSegmt, 'B'); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(shortSegmt.address(), 'D', upcallFuncAddr); + char result = MemoryAccess.getChar(resultAddr.asSegment(C_SHORT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, char.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPtr_RetArgPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setChar(shortSegmt, 'B'); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(shortSegmt.address(), 'D', upcallFuncAddr); + char result = MemoryAccess.getChar(resultAddr.asSegment(C_SHORT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_addTwoShortsByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(short.class, short.class, short.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Shorts, + FunctionDescriptor.of(C_SHORT, C_SHORT, C_SHORT), scope); + short result = (short)mh.invokeExact((short)1111, (short)2222, upcallFuncAddr); + Assert.assertEquals(result, (short)3333); + } + } + + @Test + public void test_addShortAndShortFromPointerByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(short.class, MemoryAddress.class, short.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setShort(shortSegmt, (short)2222); + short result = (short)mh.invokeExact(shortSegmt.address(), (short)3333, upcallFuncAddr); + Assert.assertEquals(result, (short)5555); + } + } + + @Test + public void test_addShortAndShortFromNativePtrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(short.class, short.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPointer, + FunctionDescriptor.of(C_SHORT, C_POINTER, C_SHORT), scope); + short result = (short)mh.invokeExact((short)789, upcallFuncAddr); + Assert.assertEquals(result, (short)1245); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, short.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setShort(shortSegmt, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(shortSegmt.address(), (short)555, upcallFuncAddr); + short result = MemoryAccess.getShort(resultAddr.asSegment(C_SHORT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, (short)999); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, short.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetArgPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setShort(shortSegmt, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(shortSegmt.address(), (short)555, upcallFuncAddr); + short result = MemoryAccess.getShort(resultAddr.asSegment(C_SHORT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, (short)999); + } + } + + @Test + public void test_addTwoIntsByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT), scope); + int result = (int)mh.invokeExact(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + } + + @Test + public void test_addIntAndIntFromPointerByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(int.class, int.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPointer, + FunctionDescriptor.of(C_INT, C_INT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment intSegmt = allocator.allocate(C_INT); + MemoryAccess.setInt(intSegmt, 222215); + int result = (int)mh.invokeExact(333321, intSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, 555536); + } + } + + @Test + public void test_addIntAndIntFromNativePtrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPointer, + FunctionDescriptor.of(C_INT, C_INT, C_POINTER), scope); + int result = (int)mh.invokeExact(222222, upcallFuncAddr); + Assert.assertEquals(result, 666666); + } + } + + @Test + public void test_addIntAndIntFromPtr_RetPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, int.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_INT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_INT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment intSegmt = allocator.allocate(C_INT); + MemoryAccess.setInt(intSegmt, 222215); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(333321, intSegmt.address(), upcallFuncAddr); + int result = MemoryAccess.getInt(resultAddr.asSegment(C_INT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 555536); + } + } + + @Test + public void test_addIntAndIntFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, int.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_INT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPtr_RetArgPtr, + FunctionDescriptor.of(C_POINTER, C_INT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment intSegmt = allocator.allocate(C_INT); + MemoryAccess.setInt(intSegmt, 222215); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(333321, intSegmt.address(), upcallFuncAddr); + int result = MemoryAccess.getInt(resultAddr.asSegment(C_INT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 555536); + } + } + + @Test + public void test_add3IntsByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(int.class, int.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add3IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3Ints, + FunctionDescriptor.of(C_INT, C_INT, C_INT, C_INT), scope); + int result = (int)mh.invokeExact(111112, 111123, 111124, upcallFuncAddr); + Assert.assertEquals(result, 333359); + } + } + + @Test + public void test_addIntAndCharByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(int.class, int.class, char.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_SHORT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndCharByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndChar, + FunctionDescriptor.of(C_INT, C_INT, C_SHORT), scope); + int result = (int)mh.invokeExact(555558, 'A', upcallFuncAddr); + Assert.assertEquals(result, 555623); + } + } + + @Test + public void test_addTwoIntsReturnVoidByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(void.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoidByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(C_INT, C_INT), scope); + mh.invokeExact(44454, 333398, upcallFuncAddr); + } + } + + @Test + public void test_addTwoLongsByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(long.class, long.class, long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, longLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Longs, + FunctionDescriptor.of(longLayout, longLayout, longLayout), scope); + long result = (long)mh.invokeExact(333333222222L, 111111555555L, upcallFuncAddr); + Assert.assertEquals(result, 444444777777L); + } + } + + @Test + public void test_addLongAndLongFromPointerByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class, long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER, longLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(longLayout, C_POINTER, longLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment longSegmt = allocator.allocate(longLayout); + MemoryAccess.setLong(longSegmt, 5742457424L); + long result = (long)mh.invokeExact(longSegmt.address(), 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addLongAndLongFromNativePtrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(long.class, long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(longLayout, C_POINTER, longLayout), scope); + long result = (long)mh.invokeExact(5555555555L, upcallFuncAddr); + Assert.assertEquals(result, 8888888888L); + } + } + + @Test + public void test_addLongAndLongFromPtr_RetPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, longLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, longLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment longSegmt = allocator.allocate(longLayout); + MemoryAccess.setLong(longSegmt, 5742457424L); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(longSegmt.address(), 6666698235L, upcallFuncAddr); + long result = MemoryAccess.getLong(resultAddr.asSegment(longLayout.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addLongAndLongFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, long.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, longLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPtr_RetArgPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, longLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment longSegmt = allocator.allocate(longLayout); + MemoryAccess.setLong(longSegmt, 5742457424L); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(longSegmt.address(), 6666698235L, upcallFuncAddr); + long result = MemoryAccess.getLong(resultAddr.asSegment(longLayout.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addTwoFloatsByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(float.class, float.class, float.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_FLOAT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Floats, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_FLOAT), scope); + float result = (float)mh.invokeExact(15.74F, 16.79F, upcallFuncAddr); + Assert.assertEquals(result, 32.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromPointerByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(float.class, float.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment floatSegmt = allocator.allocate(C_FLOAT); + MemoryAccess.setFloat(floatSegmt, 6.79F); + float result = (float)mh.invokeExact(5.74F, floatSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromNativePtrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(float.class, float.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER), scope); + float result = (float)mh.invokeExact(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromPtr_RetPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, float.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_FLOAT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_FLOAT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment floatSegmt = allocator.allocate(C_FLOAT); + MemoryAccess.setFloat(floatSegmt, 6.79F); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(5.74F, floatSegmt.address(), upcallFuncAddr); + float result = MemoryAccess.getFloat(resultAddr.asSegment(C_FLOAT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, float.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_FLOAT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPtr_RetArgPtr, + FunctionDescriptor.of(C_POINTER, C_FLOAT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment floatSegmt = allocator.allocate(C_FLOAT); + MemoryAccess.setFloat(floatSegmt, 6.79F); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(5.74F, floatSegmt.address(), upcallFuncAddr); + float result = MemoryAccess.getFloat(resultAddr.asSegment(C_FLOAT.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_add2DoublesByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(double.class, double.class, double.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, C_DOUBLE, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoublesByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Doubles, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, C_DOUBLE), scope); + double result = (double)mh.invokeExact(159.748D, 262.795D, upcallFuncAddr); + Assert.assertEquals(result, 422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPointerByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(double.class, MemoryAddress.class, double.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_POINTER, C_DOUBLE, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPointer, + FunctionDescriptor.of(C_DOUBLE, C_POINTER, C_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment doubleSegmt = allocator.allocate(C_DOUBLE); + MemoryAccess.setDouble(doubleSegmt, 1159.748D); + double result = (double)mh.invokeExact(doubleSegmt.address(), 1262.795D, upcallFuncAddr); + Assert.assertEquals(result, 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromNativePtrByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(double.class, double.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPointer, + FunctionDescriptor.of(C_DOUBLE, C_POINTER, C_DOUBLE), scope); + double result = (double)mh.invokeExact(1262.795D, upcallFuncAddr); + Assert.assertEquals(result, 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, double.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment doubleSegmt = allocator.allocate(C_DOUBLE); + MemoryAccess.setDouble(doubleSegmt, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(doubleSegmt.address(), 1262.795D, upcallFuncAddr); + double result = MemoryAccess.getDouble(resultAddr.asSegment(C_DOUBLE.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, double.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetArgPtr, + FunctionDescriptor.of(C_POINTER, C_POINTER, C_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment doubleSegmt = allocator.allocate(C_DOUBLE); + MemoryAccess.setDouble(doubleSegmt, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(doubleSegmt.address(), 1262.795D, upcallFuncAddr); + double result = MemoryAccess.getDouble(resultAddr.asSegment(C_DOUBLE.byteSize(), resultAddr.scope())); + Assert.assertEquals(result, 2422.543D, 0.001D); + } + } + + @Test + public void test_qsortByUpcallMH() throws Throwable { + int expectedArray[] = {11, 12, 13, 14, 15, 16, 17}; + int expectedArrayLength = expectedArray.length; + + MethodType mt = MethodType.methodType(void.class, MemoryAddress.class, int.class, int.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_POINTER, C_INT, C_INT, C_POINTER); + Addressable functionSymbol = defaultLibLookup.lookup("qsort").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_compare, + FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment arraySegmt = allocator.allocateArray(C_INT, new int[]{17, 14, 13, 16, 15, 12, 11}); + mh.invokeExact(arraySegmt.address(), 7, 4, upcallFuncAddr); + int[] sortedArray = arraySegmt.toIntArray(); + for (int index = 0; index < expectedArrayLength; index++) { + Assert.assertEquals(sortedArray[index], expectedArray[index]); + } + } + } +} diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMHWithStructTests.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMHWithStructTests.java new file mode 100644 index 00000000000..2a1b48d4d87 --- /dev/null +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMHWithStructTests.java @@ -0,0 +1,3069 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep389.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.nio.ByteOrder; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; + +import jdk.incubator.foreign.Addressable; +import jdk.incubator.foreign.CLinker; +import static jdk.incubator.foreign.CLinker.*; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryHandles; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; + +/** + * Test cases for JEP 389: Foreign Linker API (Incubator) for argument/return struct in upcall. + * + * Note: the padding elements in the struct are only required by RI or VarHandle (accessing the + * data address) while they are totally ignored in OpenJ9 given the padding/alignment are + * computed by libffi automatically in native. + */ +@Test(groups = { "level.sanity" }) +public class UpcallMHWithStructTests { + private static String osName = System.getProperty("os.name").toLowerCase(); + private static String arch = System.getProperty("os.arch").toLowerCase(); + private static boolean isAixOS = osName.contains("aix"); + private static boolean isWinOS = osName.contains("win"); + /* The padding of struct is not required on Linux/s390x and Windows/x64 */ + private static boolean isStructPaddingNotRequired = isWinOS && (arch.equals("amd64") || arch.equals("x86_64")) + || osName.contains("linux") && arch.equals("s390x"); + /* long long is 64 bits on AIX/ppc64, which is the same as Windows */ + private static ValueLayout longLayout = (isWinOS || isAixOS) ? C_LONG_LONG : C_LONG; + private static CLinker clinker = CLinker.getInstance(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + public static boolean byteToBool(byte value) { + return (value != 0); + } + + @Test + public void test_addBoolAndBoolsFromStructWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithXor, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, (byte)0); + boolHandle2.set(structSegmt, (byte)1); + + boolean result = (boolean)mh.invokeExact(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAnd20BoolsFromStructWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, + C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, + C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR); + + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAnd20BoolsFromStructWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAnd20BoolsFromStructWithXor, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 3, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 4, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 5, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 6, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 7, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 8, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 9, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 10, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 11, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 12, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 13, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 14, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 15, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 16, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 17, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 18, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 19, (byte)1); + + boolean result = (boolean)mh.invokeExact(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(boolean.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolFromPointerAndBoolsFromStructWithXor, + FunctionDescriptor.of(C_CHAR, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment boolSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(boolSegmt, (byte)1); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, (byte)0); + boolHandle2.set(structSegmt, (byte)1); + + boolean result = (boolean)mh.invokeExact(boolSegmt.address(), structSegmt, upcallFuncAddr); + Assert.assertEquals(result, false); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR, C_CHAR); + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment boolSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(boolSegmt, (byte)0); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)1); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(boolSegmt.address(), structSegmt, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(C_CHAR.byteSize(), scope); + boolean result = byteToBool(MemoryAccess.getByte(resultSegmt)); + Assert.assertEquals(result, true); + Assert.assertEquals(resultAddr.toRawLongValue(), boolSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addBoolAndBoolsFromStructPointerWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructPointerWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructPointerWithXor, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, (byte)1); + boolHandle2.set(structSegmt, (byte)0); + + boolean result = (boolean)mh.invokeExact(false, structSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXorByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(8)); + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromNestedStructWithXor, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)1); + + boolean result = (boolean)mh.invokeExact(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(C_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(8)); + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromNestedStructWithXor_reverseOrder, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)1); + + boolean result = (boolean)mh.invokeExact(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArrayByUpcallMH() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(intArray.withName("array_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedBoolArray, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)0); + + boolean result = (boolean)mh.invokeExact(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), + intArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)0); + + boolean result = (boolean)mh.invokeExact(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + C_CHAR.withName("elem2")) : MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedStructArray, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 3, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 4, (byte)0); + + boolean result = (boolean)mh.invokeExact(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2")) : MemoryLayout.structLayout(C_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); + MethodType mt = MethodType.methodType(boolean.class, boolean.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)0); + MemoryAccess.setByteAtOffset(structSegmt, 3, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 4, (byte)0); + + boolean result = (boolean)mh.invokeExact(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolStructsWithXor_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, (byte)1); + boolHandle2.set(structSegmt1, (byte)0); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, (byte)1); + boolHandle2.set(structSegmt2, (byte)1); + + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(byteToBool((byte)boolHandle1.get(resultSegmt)), false); + Assert.assertEquals(byteToBool((byte)boolHandle2.get(resultSegmt)), true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolStructsWithXor_returnStructPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, (byte)1); + boolHandle2.set(structSegmt1, (byte)0); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, (byte)1); + boolHandle2.set(structSegmt2, (byte)1); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(structSegmt1.address(), structSegmt2, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(structLayout.byteSize(), scope); + Assert.assertEquals(byteToBool((byte)boolHandle1.get(resultSegmt)), false); + Assert.assertEquals(byteToBool((byte)boolHandle2.get(resultSegmt)), true); + } + } + + @Test + public void test_add3BoolStructsWithXor_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2"), + C_CHAR.withName("elem3")) : MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2"), + C_CHAR.withName("elem3"), MemoryLayout.paddingLayout(8)); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + VarHandle boolHandle3 = structLayout.varHandle(byte.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add3BoolStructsWithXor_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3BoolStructsWithXor_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, (byte)1); + boolHandle2.set(structSegmt1, (byte)0); + boolHandle3.set(structSegmt1, (byte)1); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, (byte)1); + boolHandle2.set(structSegmt2, (byte)1); + boolHandle3.set(structSegmt2, (byte)0); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(byteToBool((byte)boolHandle1.get(resultSegmt)), false); + Assert.assertEquals(byteToBool((byte)boolHandle2.get(resultSegmt)), true); + Assert.assertEquals(byteToBool((byte)boolHandle3.get(resultSegmt)), true); + } + } + + @Test + public void test_addByteAndBytesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStruct, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)8); + byteHandle2.set(structSegmt, (byte)9); + + byte result = (byte)mh.invokeExact((byte)6, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23); + } + } + + @Test + public void test_addByteAnd20BytesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, + C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR, + C_CHAR, C_CHAR, C_CHAR, C_CHAR, C_CHAR); + + MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAnd20BytesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAnd20BytesFromStruct, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)2); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)3); + MemoryAccess.setByteAtOffset(structSegmt, 3, (byte)4); + MemoryAccess.setByteAtOffset(structSegmt, 4, (byte)5); + MemoryAccess.setByteAtOffset(structSegmt, 5, (byte)6); + MemoryAccess.setByteAtOffset(structSegmt, 6, (byte)7); + MemoryAccess.setByteAtOffset(structSegmt, 7, (byte)8); + MemoryAccess.setByteAtOffset(structSegmt, 8, (byte)9); + MemoryAccess.setByteAtOffset(structSegmt, 9, (byte)10); + MemoryAccess.setByteAtOffset(structSegmt, 10, (byte)1); + MemoryAccess.setByteAtOffset(structSegmt, 11, (byte)2); + MemoryAccess.setByteAtOffset(structSegmt, 12, (byte)3); + MemoryAccess.setByteAtOffset(structSegmt, 13, (byte)4); + MemoryAccess.setByteAtOffset(structSegmt, 14, (byte)5); + MemoryAccess.setByteAtOffset(structSegmt, 15, (byte)6); + MemoryAccess.setByteAtOffset(structSegmt, 16, (byte)7); + MemoryAccess.setByteAtOffset(structSegmt, 17, (byte)8); + MemoryAccess.setByteAtOffset(structSegmt, 18, (byte)9); + MemoryAccess.setByteAtOffset(structSegmt, 19, (byte)10); + + byte result = (byte)mh.invokeExact((byte)11, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 121); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(byte.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteFromPointerAndBytesFromStruct, + FunctionDescriptor.of(C_CHAR, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment byteSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(byteSegmt, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)18); + byteHandle2.set(structSegmt, (byte)19); + + byte result = (byte)mh.invokeExact(byteSegmt.address(), structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 49); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStruct_returnBytePointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStruct_returnBytePointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteFromPointerAndBytesFromStruct_returnBytePointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment byteSegmt = allocator.allocate(C_CHAR); + MemoryAccess.setByte(byteSegmt, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)14); + byteHandle2.set(structSegmt, (byte)16); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(byteSegmt.address(), structSegmt, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(C_CHAR.byteSize(), scope); + VarHandle byteHandle = MemoryHandles.varHandle(byte.class, ByteOrder.nativeOrder()); + byte result = (byte)byteHandle.get(resultSegmt, 0); + Assert.assertEquals(result, 42); + Assert.assertEquals(resultAddr.toRawLongValue(), byteSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addByteAndBytesFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(byte.class, byte.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructPointer, + FunctionDescriptor.of(C_CHAR, C_CHAR, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)11); + byteHandle2.set(structSegmt, (byte)12); + + byte result = (byte)mh.invokeExact((byte)13, structSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, 36); + } + } + + @Test + public void test_addByteAndBytesFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(8)); + MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromNestedStruct, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)11); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)22); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)33); + + byte result = (byte)mh.invokeExact((byte)46, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 112); + } + } + + @Test + public void test_addByteAndBytesFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2")): MemoryLayout.structLayout(C_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(8)); + MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromNestedStruct_reverseOrder, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)12); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)24); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)36); + + byte result = (byte)mh.invokeExact((byte)48, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 120); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArrayByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, C_CHAR); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(byteArray.withName("array_elem1"), + C_CHAR.withName("elem2")): MemoryLayout.structLayout(byteArray.withName("array_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(8)); + MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedByteArray, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)11); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)12); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)13); + + byte result = (byte)mh.invokeExact((byte)14, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 50); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, C_CHAR); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_CHAR.withName("elem1"), + byteArray.withName("array_elem2")): MemoryLayout.structLayout(C_CHAR.withName("elem1"), + byteArray.withName("array_elem2"), MemoryLayout.paddingLayout(8)); + MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedByteArray_reverseOrder, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)12); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)14); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)16); + + byte result = (byte)mh.invokeExact((byte)18, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 60); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + C_CHAR.withName("elem2")) : MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); + MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedStructArray, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)11); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)12); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)13); + MemoryAccess.setByteAtOffset(structSegmt, 3, (byte)14); + MemoryAccess.setByteAtOffset(structSegmt, 4, (byte)15); + + byte result = (byte)mh.invokeExact((byte)16, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 81); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2")) : MemoryLayout.structLayout(C_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); + MethodType mt = MethodType.methodType(byte.class, byte.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(C_CHAR, C_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setByteAtOffset(structSegmt, 0, (byte)12); + MemoryAccess.setByteAtOffset(structSegmt, 1, (byte)14); + MemoryAccess.setByteAtOffset(structSegmt, 2, (byte)16); + MemoryAccess.setByteAtOffset(structSegmt, 3, (byte)18); + MemoryAccess.setByteAtOffset(structSegmt, 4, (byte)20); + + byte result = (byte)mh.invokeExact((byte)22, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 102); + } + } + + @Test + public void test_add1ByteStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add1ByteStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add1ByteStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + } + } + + @Test + public void test_add2ByteStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2ByteStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + } + } + + @Test + public void test_add2ByteStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2ByteStructs_returnStructPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(structSegmt1.address(), structSegmt2, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(structLayout.byteSize(), scope); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + } + } + + @Test + public void test_add3ByteStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2"), + C_CHAR.withName("elem3")) : MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2"), + C_CHAR.withName("elem3"), MemoryLayout.paddingLayout(8)); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(byte.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add3ByteStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3ByteStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + byteHandle3.set(structSegmt1, (byte)12); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + byteHandle3.set(structSegmt2, (byte)16); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + Assert.assertEquals((byte)byteHandle3.get(resultSegmt), (byte)28); + } + } + + @Test + public void test_addCharAndCharsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStruct, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'A'); + charHandle2.set(structSegmt, 'B'); + + char result = (char)mh.invokeExact('C', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'D'); + } + } + + @Test + public void test_addCharAnd10CharsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT, C_SHORT, C_SHORT, C_SHORT, + C_SHORT, C_SHORT, C_SHORT, C_SHORT, C_SHORT, C_SHORT); + + MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAnd10CharsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAnd10CharsFromStruct, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setCharAtOffset(structSegmt, 0, 'A'); + MemoryAccess.setCharAtOffset(structSegmt, 2, 'A'); + MemoryAccess.setCharAtOffset(structSegmt, 4, 'B'); + MemoryAccess.setCharAtOffset(structSegmt, 6, 'B'); + MemoryAccess.setCharAtOffset(structSegmt, 8, 'C'); + MemoryAccess.setCharAtOffset(structSegmt, 10, 'C'); + MemoryAccess.setCharAtOffset(structSegmt, 12, 'D'); + MemoryAccess.setCharAtOffset(structSegmt, 14, 'D'); + MemoryAccess.setCharAtOffset(structSegmt, 16, 'E'); + MemoryAccess.setCharAtOffset(structSegmt, 18, 'E'); + + char result = (char)mh.invokeExact('A', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'U'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(char.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharFromPointerAndCharsFromStruct, + FunctionDescriptor.of(C_SHORT, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment charSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setChar(charSegmt, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + char result = (char)mh.invokeExact(charSegmt.address(), structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'M'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStruct_returnCharPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStruct_returnCharPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharFromPointerAndCharsFromStruct_returnCharPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment charSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setChar(charSegmt, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(charSegmt.address(), structSegmt, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(C_SHORT.byteSize(), scope); + VarHandle charHandle = MemoryHandles.varHandle(char.class, ByteOrder.nativeOrder()); + char result = (char)charHandle.get(resultSegmt, 0); + Assert.assertEquals(result, 'M'); + Assert.assertEquals(resultSegmt.address().toRawLongValue(), charSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addCharAndCharsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(char.class, char.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructPointer, + FunctionDescriptor.of(C_SHORT, C_SHORT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'H'); + charHandle2.set(structSegmt, 'I'); + + char result = (char)mh.invokeExact('G', structSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, 'V'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_SHORT.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + + MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromNestedStruct, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setCharAtOffset(structSegmt, 0, 'E'); + MemoryAccess.setCharAtOffset(structSegmt, 2, 'F'); + MemoryAccess.setCharAtOffset(structSegmt, 4, 'G'); + + char result = (char)mh.invokeExact('H', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(C_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setCharAtOffset(structSegmt, 0, 'E'); + MemoryAccess.setCharAtOffset(structSegmt, 2, 'F'); + MemoryAccess.setCharAtOffset(structSegmt, 4, 'G'); + + char result = (char)mh.invokeExact('H', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArrayByUpcallMH() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, C_SHORT); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(charArray.withName("array_elem1"), + C_SHORT.withName("elem2")) : MemoryLayout.structLayout(charArray.withName("array_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedCharArray, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setCharAtOffset(structSegmt, 0, 'A'); + MemoryAccess.setCharAtOffset(structSegmt, 2, 'B'); + MemoryAccess.setCharAtOffset(structSegmt, 4, 'C'); + + char result = (char)mh.invokeExact('D', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, C_SHORT); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_SHORT.withName("elem1"), + charArray.withName("array_elem2")) : MemoryLayout.structLayout(C_SHORT.withName("elem1"), + charArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedCharArray_reverseOrder, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setCharAtOffset(structSegmt, 0, 'A'); + MemoryAccess.setCharAtOffset(structSegmt, 2, 'B'); + MemoryAccess.setCharAtOffset(structSegmt, 4, 'C'); + + char result = (char)mh.invokeExact('D', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), C_SHORT.withName("elem2")); + MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedStructArray, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setCharAtOffset(structSegmt, 0, 'E'); + MemoryAccess.setCharAtOffset(structSegmt, 2, 'F'); + MemoryAccess.setCharAtOffset(structSegmt, 4, 'G'); + MemoryAccess.setCharAtOffset(structSegmt, 6, 'H'); + MemoryAccess.setCharAtOffset(structSegmt, 8, 'I'); + + char result = (char)mh.invokeExact('J', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setCharAtOffset(structSegmt, 0, 'E'); + MemoryAccess.setCharAtOffset(structSegmt, 2, 'F'); + MemoryAccess.setCharAtOffset(structSegmt, 4, 'G'); + MemoryAccess.setCharAtOffset(structSegmt, 6, 'H'); + MemoryAccess.setCharAtOffset(structSegmt, 8, 'I'); + + char result = (char)mh.invokeExact('J', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_add2CharStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2CharStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(charHandle1.get(resultSegmt), 'C'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'E'); + } + } + + @Test + public void test_add2CharStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2CharStructs_returnStructPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(structSegmt1.address(), structSegmt2, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(structLayout.byteSize(), scope); + Assert.assertEquals(charHandle1.get(resultSegmt), 'C'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'E'); + } + } + + @Test + public void test_add3CharStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3")) : MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + VarHandle charHandle3 = structLayout.varHandle(char.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add3CharStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3CharStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + charHandle3.set(structSegmt1, 'C'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'B'); + charHandle2.set(structSegmt2, 'C'); + charHandle3.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(charHandle1.get(resultSegmt), 'B'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'D'); + Assert.assertEquals(charHandle3.get(resultSegmt), 'F'); + } + } + + @Test + public void test_addShortAndShortsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStruct, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)888); + shortHandle2.set(structSegmt, (short)999); + + short result = (short)mh.invokeExact((short)777, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2664); + } + } + + @Test + public void test_addShortAnd10ShortsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT, C_SHORT, C_SHORT, C_SHORT, + C_SHORT, C_SHORT, C_SHORT, C_SHORT, C_SHORT, C_SHORT); + + MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAnd10ShortsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAnd10ShortsFromStruct, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setShortAtOffset(structSegmt, 0, (short)10); + MemoryAccess.setShortAtOffset(structSegmt, 2, (short)20); + MemoryAccess.setShortAtOffset(structSegmt, 4, (short)30); + MemoryAccess.setShortAtOffset(structSegmt, 6, (short)40); + MemoryAccess.setShortAtOffset(structSegmt, 8, (short)50); + MemoryAccess.setShortAtOffset(structSegmt, 10, (short)60); + MemoryAccess.setShortAtOffset(structSegmt, 12, (short)70); + MemoryAccess.setShortAtOffset(structSegmt, 14, (short)80); + MemoryAccess.setShortAtOffset(structSegmt, 16, (short)90); + MemoryAccess.setShortAtOffset(structSegmt, 18, (short)100); + + short result = (short)mh.invokeExact((short)110, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 660); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(short.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortFromPointerAndShortsFromStruct, + FunctionDescriptor.of(C_SHORT, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setShort(shortSegmt, (short)1112); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)1118); + shortHandle2.set(structSegmt, (short)1119); + + short result = (short)mh.invokeExact(shortSegmt.address(), structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 3349); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStruct_returnShortPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStruct_returnShortPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortFromPointerAndShortsFromStruct_returnShortPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment shortSegmt = allocator.allocate(C_SHORT); + MemoryAccess.setShort(shortSegmt, (short)1112); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)1118); + shortHandle2.set(structSegmt, (short)1119); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(shortSegmt.address(), structSegmt, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(C_SHORT.byteSize(), scope); + VarHandle shortHandle = MemoryHandles.varHandle(short.class, ByteOrder.nativeOrder()); + short result = (short)shortHandle.get(resultSegmt, 0); + Assert.assertEquals(result, 3349); + Assert.assertEquals(resultSegmt.address().toRawLongValue(), shortSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addShortAndShortsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(short.class, short.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructPointer, + FunctionDescriptor.of(C_SHORT, C_SHORT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)2222); + shortHandle2.set(structSegmt, (short)4444); + + short result = (short)mh.invokeExact((short)6666, structSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, 13332); + } + } + + @Test + public void test_addShortAndShortsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_SHORT.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromNestedStruct, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setShortAtOffset(structSegmt, 0, (short)331); + MemoryAccess.setShortAtOffset(structSegmt, 2, (short)333); + MemoryAccess.setShortAtOffset(structSegmt, 4, (short)335); + + short result = (short)mh.invokeExact((short)337, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1336); + } + } + + @Test + public void test_addShortAndShortsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(C_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setShortAtOffset(structSegmt, 0, (short)331); + MemoryAccess.setShortAtOffset(structSegmt, 2, (short)333); + MemoryAccess.setShortAtOffset(structSegmt, 4, (short)335); + + short result = (short)mh.invokeExact((short)337, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1336); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArrayByUpcallMH() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, C_SHORT); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(shortArray.withName("array_elem1"), + C_SHORT.withName("elem2")) : MemoryLayout.structLayout(shortArray.withName("array_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedShortArray, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setShortAtOffset(structSegmt, 0, (short)1111); + MemoryAccess.setShortAtOffset(structSegmt, 2, (short)2222); + MemoryAccess.setShortAtOffset(structSegmt, 4, (short)3333); + + short result = (short)mh.invokeExact((short)4444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, C_SHORT); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_SHORT.withName("elem1"), + shortArray.withName("array_elem2")) : MemoryLayout.structLayout(C_SHORT.withName("elem1"), + shortArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedShortArray_reverseOrder, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setShortAtOffset(structSegmt, 0, (short)1111); + MemoryAccess.setShortAtOffset(structSegmt, 2, (short)2222); + MemoryAccess.setShortAtOffset(structSegmt, 4, (short)3333); + + short result = (short)mh.invokeExact((short)4444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struc_array_elem1"), C_SHORT.withName("elem2")); + MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedStructArray, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setShortAtOffset(structSegmt, 0, (short)1111); + MemoryAccess.setShortAtOffset(structSegmt, 2, (short)2222); + MemoryAccess.setShortAtOffset(structSegmt, 4, (short)3333); + MemoryAccess.setShortAtOffset(structSegmt, 6, (short)4444); + MemoryAccess.setShortAtOffset(structSegmt, 8, (short)5555); + + short result = (short)mh.invokeExact((short)6666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23331); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), structArray.withName("struc_array_elem2")); + MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setShortAtOffset(structSegmt, 0, (short)1111); + MemoryAccess.setShortAtOffset(structSegmt, 2, (short)2222); + MemoryAccess.setShortAtOffset(structSegmt, 4, (short)3333); + MemoryAccess.setShortAtOffset(structSegmt, 6, (short)4444); + MemoryAccess.setShortAtOffset(structSegmt, 8, (short)5555); + + short result = (short)mh.invokeExact((short)6666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23331); + } + } + + @Test + public void test_add2ShortStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2ShortStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)356); + shortHandle2.set(structSegmt1, (short)345); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)378); + shortHandle2.set(structSegmt2, (short)367); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)734); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)712); + } + } + + @Test + public void test_add2ShortStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2ShortStructs_returnStructPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)356); + shortHandle2.set(structSegmt1, (short)345); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)378); + shortHandle2.set(structSegmt2, (short)367); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(structSegmt1.address(), structSegmt2, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(structLayout.byteSize(), scope); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)734); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)712); + } + } + + @Test + public void test_add3ShortStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3")) : MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + VarHandle shortHandle3 = structLayout.varHandle(short.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add3ShortStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3ShortStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)325); + shortHandle2.set(structSegmt1, (short)326); + shortHandle3.set(structSegmt1, (short)327); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)334); + shortHandle2.set(structSegmt2, (short)335); + shortHandle3.set(structSegmt2, (short)336); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)659); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)661); + Assert.assertEquals((short)shortHandle3.get(resultSegmt), (short)663); + } + } + + @Test + public void test_addIntAndIntsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStruct, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1122334); + intHandle2.set(structSegmt, 1234567); + + int result = (int)mh.invokeExact(2244668, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 4601569); + } + } + + @Test + public void test_addIntAnd5IntsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2"), + C_INT.withName("elem3"), C_INT.withName("elem4"), C_INT.withName("elem5")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + VarHandle intHandle4 = structLayout.varHandle(int.class, PathElement.groupElement("elem4")); + VarHandle intHandle5 = structLayout.varHandle(int.class, PathElement.groupElement("elem5")); + + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAnd5IntsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAnd5IntsFromStruct, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1111111); + intHandle2.set(structSegmt, 2222222); + intHandle3.set(structSegmt, 3333333); + intHandle4.set(structSegmt, 2222222); + intHandle5.set(structSegmt, 1111111); + + int result = (int)mh.invokeExact(4444444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 14444443); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntFromPointerAndIntsFromStruct, + FunctionDescriptor.of(C_INT, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment intSegmt = allocator.allocate(C_INT); + MemoryAccess.setInt(intSegmt, 7654321); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1234567); + intHandle2.set(structSegmt, 2468024); + + int result = (int)mh.invokeExact(intSegmt.address(), structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11356912); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStruct_returnIntPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStruct_returnIntPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntFromPointerAndIntsFromStruct_returnIntPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment intSegmt = allocator.allocate(C_INT); + MemoryAccess.setInt(intSegmt, 1122333); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 4455666); + intHandle2.set(structSegmt, 7788999); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(intSegmt.address(), structSegmt, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(C_INT.byteSize(), scope); + VarHandle intHandle = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder()); + int result = (int)intHandle.get(resultSegmt, 0); + Assert.assertEquals(result, 13366998); + Assert.assertEquals(resultSegmt.address().toRawLongValue(), intSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addIntAndIntsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(int.class, int.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructPointer, + FunctionDescriptor.of(C_INT, C_INT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 11121314); + intHandle2.set(structSegmt, 15161718); + + int result = (int)mh.invokeExact(19202122, structSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, 45485154); + } + } + + @Test + public void test_addIntAndIntsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_INT.withName("elem2")); + + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromNestedStruct, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setIntAtOffset(structSegmt, 0, 21222324); + MemoryAccess.setIntAtOffset(structSegmt, 4, 25262728); + MemoryAccess.setIntAtOffset(structSegmt, 8, 29303132); + + int result = (int)mh.invokeExact(33343536, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setIntAtOffset(structSegmt, 0, 21222324); + MemoryAccess.setIntAtOffset(structSegmt, 4, 25262728); + MemoryAccess.setIntAtOffset(structSegmt, 8, 29303132); + + int result = (int)mh.invokeExact(33343536, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArrayByUpcallMH() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, C_INT); + GroupLayout structLayout = MemoryLayout.structLayout(intArray.withName("array_elem1"), C_INT.withName("elem2")); + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedIntArray, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setIntAtOffset(structSegmt, 0, 1111111); + MemoryAccess.setIntAtOffset(structSegmt, 4, 2222222); + MemoryAccess.setIntAtOffset(structSegmt, 8, 3333333); + + int result = (int)mh.invokeExact(4444444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, C_INT); + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), intArray.withName("array_elem2")); + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedIntArray_reverseOrder, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setIntAtOffset(structSegmt, 0, 1111111); + MemoryAccess.setIntAtOffset(structSegmt, 4, 2222222); + MemoryAccess.setIntAtOffset(structSegmt, 8, 3333333); + + int result = (int)mh.invokeExact(4444444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), C_INT.withName("elem2")); + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedStructArray, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setIntAtOffset(structSegmt, 0, 1111111); + MemoryAccess.setIntAtOffset(structSegmt, 4, 2222222); + MemoryAccess.setIntAtOffset(structSegmt, 8, 3333333); + MemoryAccess.setIntAtOffset(structSegmt, 12, 4444444); + MemoryAccess.setIntAtOffset(structSegmt, 16, 5555555); + + int result = (int)mh.invokeExact(6666666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), structArray.withName("struct_array_elem2")); + MethodType mt = MethodType.methodType(int.class, int.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(C_INT, C_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setIntAtOffset(structSegmt, 0, 1111111); + MemoryAccess.setIntAtOffset(structSegmt, 4, 2222222); + MemoryAccess.setIntAtOffset(structSegmt, 8, 3333333); + MemoryAccess.setIntAtOffset(structSegmt, 12, 4444444); + MemoryAccess.setIntAtOffset(structSegmt, 16, 5555555); + + int result = (int)mh.invokeExact(6666666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_add2IntStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224466); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113354); + } + } + + @Test + public void test_add2IntStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntStructs_returnStructPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(structSegmt1.address(), structSegmt2, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(structLayout.byteSize(), scope); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224466); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113354); + } + } + + @Test + public void test_add3IntStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2"), C_INT.withName("elem3")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add3IntStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3IntStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + intHandle3.set(structSegmt1, 99001122); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 33445566); + intHandle2.set(structSegmt2, 77889900); + intHandle3.set(structSegmt2, 44332211); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(intHandle1.get(resultSegmt), 44668910); + Assert.assertEquals(intHandle2.get(resultSegmt), 133557688); + Assert.assertEquals(intHandle3.get(resultSegmt), 143333333); + } + } + + @Test + public void test_addLongAndLongsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStruct, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 1234567890L); + longHandle2.set(structSegmt, 9876543210L); + + long result = (long)mh.invokeExact(2468024680L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 13579135780L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(long.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongFromPointerAndLongsFromStruct, + FunctionDescriptor.of(longLayout, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment longSegmt = allocator.allocate(longLayout); + MemoryAccess.setLong(longSegmt, 1111111111L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 3333333333L); + longHandle2.set(structSegmt, 5555555555L); + + long result = (long)mh.invokeExact(longSegmt.address(), structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 9999999999L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStruct_returnLongPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStruct_returnLongPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongFromPointerAndLongsFromStruct_returnLongPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment longSegmt = allocator.allocate(longLayout); + MemoryAccess.setLong(longSegmt, 1122334455L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 6677889900L); + longHandle2.set(structSegmt, 1234567890L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(longSegmt.address(), structSegmt, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(longLayout.byteSize(), scope); + VarHandle longHandle = MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder()); + long result = (long)longHandle.get(resultSegmt, 0); + Assert.assertEquals(result, 9034792245L); + Assert.assertEquals(resultSegmt.address().toRawLongValue(), longSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addLongAndLongsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(long.class, long.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructPointer, + FunctionDescriptor.of(longLayout, longLayout, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 224466880022L); + longHandle2.set(structSegmt, 446688002244L); + + long result = (long)mh.invokeExact(668800224466L, structSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, 1339955106732L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromNestedStruct, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setLongAtOffset(structSegmt, 0, 135791357913L); + MemoryAccess.setLongAtOffset(structSegmt, 8, 246802468024L); + MemoryAccess.setLongAtOffset(structSegmt, 16,112233445566L); + + long result = (long)mh.invokeExact(778899001122L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setLongAtOffset(structSegmt, 0, 135791357913L); + MemoryAccess.setLongAtOffset(structSegmt, 8, 246802468024L); + MemoryAccess.setLongAtOffset(structSegmt, 16,112233445566L); + + long result = (long)mh.invokeExact(778899001122L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArrayByUpcallMH() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, longLayout); + GroupLayout structLayout = MemoryLayout.structLayout(longArray.withName("array_elem1"), longLayout.withName("elem2")); + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedLongArray, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setLongAtOffset(structSegmt, 0, 11111111111L); + MemoryAccess.setLongAtOffset(structSegmt, 8, 22222222222L); + MemoryAccess.setLongAtOffset(structSegmt, 16, 33333333333L); + + long result = (long)mh.invokeExact(44444444444L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, longLayout); + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longArray.withName("array_elem2")); + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedLongArray_reverseOrder, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setLongAtOffset(structSegmt, 0, 11111111111L); + MemoryAccess.setLongAtOffset(structSegmt, 8, 22222222222L); + MemoryAccess.setLongAtOffset(structSegmt, 16, 33333333333L); + + long result = (long)mh.invokeExact(44444444444L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), longLayout.withName("elem2")); + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedStructArray, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setLongAtOffset(structSegmt, 0, 11111111111L); + MemoryAccess.setLongAtOffset(structSegmt, 8, 22222222222L); + MemoryAccess.setLongAtOffset(structSegmt, 16, 33333333333L); + MemoryAccess.setLongAtOffset(structSegmt, 24, 44444444444L); + MemoryAccess.setLongAtOffset(structSegmt, 32, 55555555555L); + + long result = (long)mh.invokeExact(66666666666L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 233333333331L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), structArray.withName("struct_array_elem2")); + MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(longLayout, longLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setLongAtOffset(structSegmt, 0, 11111111111L); + MemoryAccess.setLongAtOffset(structSegmt, 8, 22222222222L); + MemoryAccess.setLongAtOffset(structSegmt, 16, 33333333333L); + MemoryAccess.setLongAtOffset(structSegmt, 24, 44444444444L); + MemoryAccess.setLongAtOffset(structSegmt, 32, 55555555555L); + + long result = (long)mh.invokeExact(66666666666L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 233333333331L); + } + } + + @Test + public void test_add2LongStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2LongStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + } + } + + @Test + public void test_add2LongStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2LongStructs_returnStructPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 5566778899L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 9900112233L); + longHandle2.set(structSegmt2, 3344556677L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(structSegmt1.address(), structSegmt2, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(structLayout.byteSize(), scope); + Assert.assertEquals(longHandle1.get(resultSegmt), 11022446688L); + Assert.assertEquals(longHandle2.get(resultSegmt), 8911335576L); + } + } + + @Test + public void test_add3LongStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2"), longLayout.withName("elem3")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + VarHandle longHandle3 = structLayout.varHandle(long.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add3LongStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3LongStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + longHandle3.set(structSegmt1, 112233445566L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + longHandle3.set(structSegmt2, 778899001122L); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + Assert.assertEquals(longHandle3.get(resultSegmt), 891132446688L); + } + } + + @Test + public void test_addFloatAndFloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStruct, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 8.12F); + floatHandle2.set(structSegmt, 9.24F); + + float result = (float)mh.invokeExact(6.56F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23.92F, 0.01F); + } + } + + @Test + public void test_addFloatAnd5FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2"), + C_FLOAT.withName("elem3"), C_FLOAT.withName("elem4"), C_FLOAT.withName("elem5")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + VarHandle floatHandle4 = structLayout.varHandle(float.class, PathElement.groupElement("elem4")); + VarHandle floatHandle5 = structLayout.varHandle(float.class, PathElement.groupElement("elem5")); + + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAnd5FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAnd5FloatsFromStruct, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 1.01F); + floatHandle2.set(structSegmt, 1.02F); + floatHandle3.set(structSegmt, 1.03F); + floatHandle4.set(structSegmt, 1.04F); + floatHandle5.set(structSegmt, 1.05F); + + float result = (float)mh.invokeExact(1.06F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 6.21F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(float.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatFromPointerAndFloatsFromStruct, + FunctionDescriptor.of(C_FLOAT, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment floatSegmt = allocator.allocate(C_FLOAT); + MemoryAccess.setFloat(floatSegmt, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + float result = (float)mh.invokeExact(floatSegmt.address(), structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 49.69F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStruct_returnFloatPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStruct_returnFloatPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment floatSegmt = allocator.allocate(C_FLOAT); + MemoryAccess.setFloat(floatSegmt, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(floatSegmt.address(), structSegmt, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(C_FLOAT.byteSize(), scope); + VarHandle floatHandle = MemoryHandles.varHandle(float.class, ByteOrder.nativeOrder()); + float result = (float)floatHandle.get(resultSegmt, 0); + Assert.assertEquals(result, 49.69F, 0.01F); + Assert.assertEquals(resultSegmt.address().toRawLongValue(), floatSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addFloatAndFloatsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(float.class, float.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructPointer, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 35.11F); + floatHandle2.set(structSegmt, 46.22F); + + float result = (float)mh.invokeExact(79.33F, structSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, 160.66F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_FLOAT.withName("elem2")); + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromNestedStruct, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setFloatAtOffset(structSegmt, 0, 31.22F); + MemoryAccess.setFloatAtOffset(structSegmt, 4, 33.44F); + MemoryAccess.setFloatAtOffset(structSegmt, 8, 35.66F); + + float result = (float)mh.invokeExact(37.88F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setFloatAtOffset(structSegmt, 0, 31.22F); + MemoryAccess.setFloatAtOffset(structSegmt, 4, 33.44F); + MemoryAccess.setFloatAtOffset(structSegmt, 8, 35.66F); + + float result = (float)mh.invokeExact(37.88F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArrayByUpcallMH() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, C_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(floatArray.withName("array_elem1"), C_FLOAT.withName("elem2")); + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedFloatArray, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setFloatAtOffset(structSegmt, 0, 111.11F); + MemoryAccess.setFloatAtOffset(structSegmt, 4, 222.22F); + MemoryAccess.setFloatAtOffset(structSegmt, 8, 333.33F); + + float result = (float)mh.invokeExact(444.44F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, C_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), floatArray.withName("array_elem2")); + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setFloatAtOffset(structSegmt, 0, 111.11F); + MemoryAccess.setFloatAtOffset(structSegmt, 4, 222.22F); + MemoryAccess.setFloatAtOffset(structSegmt, 8, 333.33F); + + float result = (float)mh.invokeExact(444.44F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), C_FLOAT.withName("elem2")); + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedStructArray, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setFloatAtOffset(structSegmt, 0, 111.11F); + MemoryAccess.setFloatAtOffset(structSegmt, 4, 222.22F); + MemoryAccess.setFloatAtOffset(structSegmt, 8, 333.33F); + MemoryAccess.setFloatAtOffset(structSegmt, 12, 444.44F); + MemoryAccess.setFloatAtOffset(structSegmt, 16, 555.55F); + + float result = (float)mh.invokeExact(666.66F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), structArray.withName("struct_array_elem2")); + MethodType mt = MethodType.methodType(float.class, float.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(C_FLOAT, C_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setFloatAtOffset(structSegmt, 0, 111.11F); + MemoryAccess.setFloatAtOffset(structSegmt, 4, 222.22F); + MemoryAccess.setFloatAtOffset(structSegmt, 8, 333.33F); + MemoryAccess.setFloatAtOffset(structSegmt, 12, 444.44F); + MemoryAccess.setFloatAtOffset(structSegmt, 16, 555.55F); + + float result = (float)mh.invokeExact(666.66F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_add3FloatStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add3FloatStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3FloatStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + floatHandle3.set(structSegmt1, 45.67F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + floatHandle3.set(structSegmt2, 69.72F); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + Assert.assertEquals((float)floatHandle3.get(resultSegmt), 115.39, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2FloatStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2FloatStructs_returnStructPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(structSegmt1.address(), structSegmt2, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(structLayout.byteSize(), scope); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 2228.111D); + doubleHandle2.set(structSegmt, 2229.221D); + + double result = (double)mh.invokeExact(3336.333D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 7793.665D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleFromPointerAndDoublesFromStruct, + FunctionDescriptor.of(C_DOUBLE, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment doubleSegmt = allocator.allocate(C_DOUBLE); + MemoryAccess.setDouble(doubleSegmt, 112.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 118.456D); + doubleHandle2.set(structSegmt, 119.789D); + + double result = (double)mh.invokeExact(doubleSegmt.address(), structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 350.368D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStruct_returnDoublePointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment doubleSegmt = allocator.allocate(C_DOUBLE); + MemoryAccess.setDouble(doubleSegmt, 212.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 218.456D); + doubleHandle2.set(structSegmt, 219.789D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(doubleSegmt.address(), structSegmt, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(C_DOUBLE.byteSize(), scope); + VarHandle doubleHandle = MemoryHandles.varHandle(double.class, ByteOrder.nativeOrder()); + double result = (double)doubleHandle.get(resultSegmt, 0); + Assert.assertEquals(result, 650.368D, 0.001D); + Assert.assertEquals(resultSegmt.address().toRawLongValue(), doubleSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemoryAddress.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, C_POINTER, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructPointer, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, C_POINTER), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 22.111D); + doubleHandle2.set(structSegmt, 44.222D); + + double result = (double)mh.invokeExact(66.333D, structSegmt.address(), upcallFuncAddr); + Assert.assertEquals(result, 132.666D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_DOUBLE.withName("elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromNestedStruct, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setDoubleAtOffset(structSegmt, 0, 31.789D); + MemoryAccess.setDoubleAtOffset(structSegmt, 8, 33.456D); + MemoryAccess.setDoubleAtOffset(structSegmt, 16, 35.123D); + + double result = (double)mh.invokeExact(37.864D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromNestedStruct_reverseOrder, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setDoubleAtOffset(structSegmt, 0, 31.789D); + MemoryAccess.setDoubleAtOffset(structSegmt, 8, 33.456D); + MemoryAccess.setDoubleAtOffset(structSegmt, 16, 35.123D); + + double result = (double)mh.invokeExact(37.864D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArrayByUpcallMH() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, C_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(doubleArray.withName("array_elem1"), C_DOUBLE.withName("elem2")); + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedDoubleArray, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setDoubleAtOffset(structSegmt, 0, 111.111D); + MemoryAccess.setDoubleAtOffset(structSegmt, 8, 222.222D); + MemoryAccess.setDoubleAtOffset(structSegmt, 16, 333.333D); + + double result = (double)mh.invokeExact(444.444D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, C_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), doubleArray.withName("array_elem2")); + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setDoubleAtOffset(structSegmt, 0, 111.111D); + MemoryAccess.setDoubleAtOffset(structSegmt, 8, 222.222D); + MemoryAccess.setDoubleAtOffset(structSegmt, 16, 333.333D); + + double result = (double)mh.invokeExact(444.444D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), C_DOUBLE.withName("elem2")); + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedStructArray, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setDoubleAtOffset(structSegmt, 0, 111.111D); + MemoryAccess.setDoubleAtOffset(structSegmt, 8, 222.222D); + MemoryAccess.setDoubleAtOffset(structSegmt, 16, 333.333D); + MemoryAccess.setDoubleAtOffset(structSegmt, 24, 444.444D); + MemoryAccess.setDoubleAtOffset(structSegmt, 32, 555.555D); + + double result = (double)mh.invokeExact(666.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), structArray.withName("struct_array_elem2")); + MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + MemoryAccess.setDoubleAtOffset(structSegmt, 0, 111.111D); + MemoryAccess.setDoubleAtOffset(structSegmt, 8, 222.222D); + MemoryAccess.setDoubleAtOffset(structSegmt, 16, 333.333D); + MemoryAccess.setDoubleAtOffset(structSegmt, 24, 444.444D); + MemoryAccess.setDoubleAtOffset(structSegmt, 32, 555.555D); + + double result = (double)mh.invokeExact(666.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2DoubleStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MethodType mt = MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2DoubleStructs_returnStructPointer, + FunctionDescriptor.of(C_POINTER, C_POINTER, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invokeExact(structSegmt1.address(), structSegmt2, upcallFuncAddr); + MemorySegment resultSegmt = resultAddr.asSegment(structLayout.byteSize(), scope); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + } + } + + @Test + public void test_add3DoubleStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2"), C_DOUBLE.withName("elem3")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle doubleHandle3 = structLayout.varHandle(double.class, PathElement.groupElement("elem3")); + + MethodType mt = MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, MemoryAddress.class); + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, C_POINTER); + Addressable functionSymbol = nativeLibLookup.lookup("add3DoubleStructs_returnStructByUpcallMH").get(); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.ofScope(scope); + MethodHandle mh = clinker.downcallHandle(functionSymbol, allocator, mt, fd); + MemoryAddress upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3DoubleStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + doubleHandle3.set(structSegmt1, 33.123D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + doubleHandle3.set(structSegmt2, 55.456D); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + Assert.assertEquals((double)doubleHandle3.get(resultSegmt), 88.579D, 0.001D); + } + } +} diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMethodHandles.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMethodHandles.java new file mode 100644 index 00000000000..74e16a9b71a --- /dev/null +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/upcall/UpcallMethodHandles.java @@ -0,0 +1,2624 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep389.upcall; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import static java.lang.invoke.MethodType.methodType; +import java.lang.invoke.VarHandle; + +import static jdk.incubator.foreign.CLinker.*; +import jdk.incubator.foreign.CLinker.VaList; +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.ValueLayout; + +/** + * The helper class that contains all upcall method handles with primitive types or struct as arguments. + */ +public class UpcallMethodHandles { + private static final Lookup lookup = MethodHandles.lookup(); + private static ResourceScope scope = ResourceScope.newImplicitScope(); + private static String osName = System.getProperty("os.name").toLowerCase(); + private static boolean isAixOS = osName.contains("aix"); + private static boolean isWinOS = osName.contains("win"); + /* long long is 64 bits on AIX/ppc64, which is the same as Windows */ + private static ValueLayout longLayout = (isWinOS || isAixOS) ? C_LONG_LONG : C_LONG; + + static final MethodType MT_Bool_Bool_MemSegmt = methodType(boolean.class, boolean.class, MemorySegment.class); + static final MethodType MT_MemAddr_Bool_MemAddr = methodType(MemoryAddress.class, boolean.class, MemoryAddress.class); + static final MethodType MT_Char_Char_MemSegmt = methodType(char.class, char.class, MemorySegment.class); + static final MethodType MT_MemAddr_MemAddr_Char = methodType(MemoryAddress.class, MemoryAddress.class, char.class); + static final MethodType MT_Byte_Byte_MemSegmt = methodType(byte.class, byte.class, MemorySegment.class); + static final MethodType MT_MemAddr_Byte_MemAddr = methodType(MemoryAddress.class, byte.class, MemoryAddress.class); + static final MethodType MT_Short_Short_MemSegmt = methodType(short.class, short.class, MemorySegment.class); + static final MethodType MT_MemAddr_MemAddr_Short = methodType(MemoryAddress.class, MemoryAddress.class, short.class); + static final MethodType MT_Int_Int_MemSegmt = methodType(int.class, int.class, MemorySegment.class); + static final MethodType MT_MemAddr_Int_MemAddr = methodType(MemoryAddress.class, int.class, MemoryAddress.class); + static final MethodType MT_Long_Long_MemSegmt = methodType(long.class, long.class, MemorySegment.class); + static final MethodType MT_MemAddr_MemAddr_Long = methodType(MemoryAddress.class, MemoryAddress.class, long.class); + static final MethodType MT_Long_Int_MemSegmt = methodType(long.class, int.class, MemorySegment.class); + static final MethodType MT_Float_Float_MemSegmt = methodType(float.class, float.class, MemorySegment.class); + static final MethodType MT_MemAddr_Float_MemAddr = methodType(MemoryAddress.class, float.class, MemoryAddress.class); + static final MethodType MT_Double_Double_MemSegmt = methodType(double.class, double.class, MemorySegment.class); + static final MethodType MT_MemAddr_MemAddr_Double = methodType(MemoryAddress.class, MemoryAddress.class, double.class); + static final MethodType MT_MemAddr_MemAddr_MemSegmt = methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class); + static final MethodType MT_MemSegmt_MemSegmt_MemSegmt = methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class); + static final MethodType MT_MemSegmt = methodType(MemorySegment.class); + + public static final MethodHandle MH_add2BoolsWithOr; + public static final MethodHandle MH_addBoolAndBoolFromPointerWithOr; + public static final MethodHandle MH_addBoolAndBoolFromPtrWithOr_RetPtr; + public static final MethodHandle MH_addBoolAndBoolFromPtrWithOr_RetArgPtr; + public static final MethodHandle MH_createNewCharFrom2Chars; + public static final MethodHandle MH_createNewCharFromCharAndCharFromPointer; + public static final MethodHandle MH_createNewCharFromCharAndCharFromPtr_RetPtr; + public static final MethodHandle MH_createNewCharFromCharAndCharFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Bytes; + public static final MethodHandle MH_addByteAndByteFromPointer; + public static final MethodHandle MH_addByteAndByteFromPtr_RetPtr; + public static final MethodHandle MH_addByteAndByteFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Shorts; + public static final MethodHandle MH_addShortAndShortFromPointer; + public static final MethodHandle MH_addShortAndShortFromPtr_RetPtr; + public static final MethodHandle MH_addShortAndShortFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Ints; + public static final MethodHandle MH_addIntAndIntFromPointer; + public static final MethodHandle MH_addIntAndIntFromPtr_RetPtr; + public static final MethodHandle MH_addIntAndIntFromPtr_RetArgPtr; + public static final MethodHandle MH_add3Ints; + public static final MethodHandle MH_addIntAndChar; + public static final MethodHandle MH_add2IntsReturnVoid; + public static final MethodHandle MH_add2Longs; + public static final MethodHandle MH_addLongAndLongFromPointer; + public static final MethodHandle MH_addLongAndLongFromPtr_RetPtr; + public static final MethodHandle MH_addLongAndLongFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Floats; + public static final MethodHandle MH_addFloatAndFloatFromPointer; + public static final MethodHandle MH_addFloatAndFloatFromPtr_RetPtr; + public static final MethodHandle MH_addFloatAndFloatFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Doubles; + public static final MethodHandle MH_addDoubleAndDoubleFromPointer; + public static final MethodHandle MH_addDoubleAndDoubleFromPtr_RetPtr; + public static final MethodHandle MH_addDoubleAndDoubleFromPtr_RetArgPtr; + public static final MethodHandle MH_compare; + + public static final MethodHandle MH_addBoolAndBoolsFromStructWithXor; + public static final MethodHandle MH_addBoolAnd20BoolsFromStructWithXor; + public static final MethodHandle MH_addBoolFromPointerAndBoolsFromStructWithXor; + public static final MethodHandle MH_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer; + public static final MethodHandle MH_addBoolAndBoolsFromStructPointerWithXor; + public static final MethodHandle MH_addBoolAndBoolsFromNestedStructWithXor; + public static final MethodHandle MH_addBoolAndBoolsFromNestedStructWithXor_reverseOrder; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedBoolArray; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedStructArray; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2BoolStructsWithXor_returnStruct; + public static final MethodHandle MH_add2BoolStructsWithXor_returnStructPointer; + public static final MethodHandle MH_add3BoolStructsWithXor_returnStruct; + + public static final MethodHandle MH_addByteAndBytesFromStruct; + public static final MethodHandle MH_addByteAnd20BytesFromStruct; + public static final MethodHandle MH_addByteFromPointerAndBytesFromStruct; + public static final MethodHandle MH_addByteFromPointerAndBytesFromStruct_returnBytePointer; + public static final MethodHandle MH_addByteAndBytesFromStructPointer; + public static final MethodHandle MH_addByteAndBytesFromNestedStruct; + public static final MethodHandle MH_addByteAndBytesFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedByteArray; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedByteArray_reverseOrder; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedStructArray; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add1ByteStructs_returnStruct; + public static final MethodHandle MH_add2ByteStructs_returnStruct; + public static final MethodHandle MH_add2ByteStructs_returnStructPointer; + public static final MethodHandle MH_add3ByteStructs_returnStruct; + + public static final MethodHandle MH_addCharAndCharsFromStruct; + public static final MethodHandle MH_addCharAnd10CharsFromStruct; + public static final MethodHandle MH_addCharFromPointerAndCharsFromStruct; + public static final MethodHandle MH_addCharFromPointerAndCharsFromStruct_returnCharPointer; + public static final MethodHandle MH_addCharAndCharsFromStructPointer; + public static final MethodHandle MH_addCharAndCharsFromNestedStruct; + public static final MethodHandle MH_addCharAndCharsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedCharArray; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedCharArray_reverseOrder; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedStructArray; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2CharStructs_returnStruct; + public static final MethodHandle MH_add2CharStructs_returnStructPointer; + public static final MethodHandle MH_add3CharStructs_returnStruct; + + public static final MethodHandle MH_addShortAndShortsFromStruct; + public static final MethodHandle MH_addShortAnd10ShortsFromStruct; + public static final MethodHandle MH_addShortFromPointerAndShortsFromStruct; + public static final MethodHandle MH_addShortFromPointerAndShortsFromStruct_returnShortPointer; + public static final MethodHandle MH_addShortAndShortsFromStructPointer; + public static final MethodHandle MH_addShortAndShortsFromNestedStruct; + public static final MethodHandle MH_addShortAndShortsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedShortArray; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedShortArray_reverseOrder; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedStructArray; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2ShortStructs_returnStruct; + public static final MethodHandle MH_add2ShortStructs_returnStructPointer; + public static final MethodHandle MH_add3ShortStructs_returnStruct; + + public static final MethodHandle MH_addIntAndIntsFromStruct; + public static final MethodHandle MH_addIntAnd5IntsFromStruct; + public static final MethodHandle MH_addIntFromPointerAndIntsFromStruct; + public static final MethodHandle MH_addIntFromPointerAndIntsFromStruct_returnIntPointer; + public static final MethodHandle MH_addIntAndIntsFromStructPointer; + public static final MethodHandle MH_addIntAndIntsFromNestedStruct; + public static final MethodHandle MH_addIntAndIntsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedIntArray; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedIntArray_reverseOrder; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedStructArray; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2IntStructs_returnStruct; + public static final MethodHandle MH_add2IntStructs_returnStructPointer; + public static final MethodHandle MH_add3IntStructs_returnStruct; + + public static final MethodHandle MH_addLongAndLongsFromStruct; + public static final MethodHandle MH_addLongFromPointerAndLongsFromStruct; + public static final MethodHandle MH_addLongFromPointerAndLongsFromStruct_returnLongPointer; + public static final MethodHandle MH_addLongAndLongsFromStructPointer; + public static final MethodHandle MH_addLongAndLongsFromNestedStruct; + public static final MethodHandle MH_addLongAndLongsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedLongArray; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedLongArray_reverseOrder; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedStructArray; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2LongStructs_returnStruct; + public static final MethodHandle MH_add2LongStructs_returnStructPointer; + public static final MethodHandle MH_add3LongStructs_returnStruct; + + public static final MethodHandle MH_addFloatAndFloatsFromStruct; + public static final MethodHandle MH_addFloatAnd5FloatsFromStruct; + public static final MethodHandle MH_addFloatFromPointerAndFloatsFromStruct; + public static final MethodHandle MH_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer; + public static final MethodHandle MH_addFloatAndFloatsFromStructPointer; + public static final MethodHandle MH_addFloatAndFloatsFromNestedStruct; + public static final MethodHandle MH_addFloatAndFloatsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedFloatArray; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedStructArray; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2FloatStructs_returnStruct; + public static final MethodHandle MH_add2FloatStructs_returnStructPointer; + public static final MethodHandle MH_add3FloatStructs_returnStruct; + + public static final MethodHandle MH_addDoubleAndDoublesFromStruct; + public static final MethodHandle MH_addDoubleFromPointerAndDoublesFromStruct; + public static final MethodHandle MH_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer; + public static final MethodHandle MH_addDoubleAndDoublesFromStructPointer; + public static final MethodHandle MH_addDoubleAndDoublesFromNestedStruct; + public static final MethodHandle MH_addDoubleAndDoublesFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedDoubleArray; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedStructArray; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2DoubleStructs_returnStruct; + public static final MethodHandle MH_add2DoubleStructs_returnStructPointer; + public static final MethodHandle MH_add3DoubleStructs_returnStruct; + + public static final MethodHandle MH_addIntAndIntShortFromStruct; + public static final MethodHandle MH_addIntAndShortIntFromStruct; + public static final MethodHandle MH_addIntAndIntLongFromStruct; + public static final MethodHandle MH_addIntAndLongIntFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleIntFromStruct; + public static final MethodHandle MH_addDoubleAndFloatDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleFloatFromStruct; + public static final MethodHandle MH_addDoubleAnd2FloatsDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndDouble2FloatsFromStruct; + public static final MethodHandle MH_addFloatAndInt2FloatsFromStruct; + public static final MethodHandle MH_addFloatAndFloatIntFloatFromStruct; + public static final MethodHandle MH_addDoubleAndIntFloatDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndFloatIntDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndLongDoubleFromStruct; + public static final MethodHandle MH_addFloatAndInt3FloatsFromStruct; + public static final MethodHandle MH_addLongAndLong2FloatsFromStruct; + public static final MethodHandle MH_addFloatAnd3FloatsIntFromStruct; + public static final MethodHandle MH_addLongAndFloatLongFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleFloatIntFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleLongFromStruct; + public static final MethodHandle MH_addLongAnd2FloatsLongFromStruct; + public static final MethodHandle MH_addShortAnd3ShortsCharFromStruct; + public static final MethodHandle MH_addFloatAndIntFloatIntFloatFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleFloatFromStruct; + public static final MethodHandle MH_addDoubleAndFloatDoubleIntFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleIntFromStruct; + public static final MethodHandle MH_addDoubleAndFloatDoubleFloatFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleLongFromStruct; + public static final MethodHandle MH_return254BytesFromStruct; + public static final MethodHandle MH_return4KBytesFromStruct; + + static { + try { + MH_add2BoolsWithOr = lookup.findStatic(UpcallMethodHandles.class, "add2BoolsWithOr", methodType(boolean.class, boolean.class, boolean.class)); //$NON-NLS-1$ + MH_addBoolAndBoolFromPointerWithOr = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolFromPointerWithOr", methodType(boolean.class, boolean.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addBoolAndBoolFromPtrWithOr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolFromPtrWithOr_RetPtr", MT_MemAddr_Bool_MemAddr); //$NON-NLS-1$ + MH_addBoolAndBoolFromPtrWithOr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolFromPtrWithOr_RetArgPtr", MT_MemAddr_Bool_MemAddr); //$NON-NLS-1$ + + MH_createNewCharFrom2Chars = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFrom2Chars", methodType(char.class, char.class, char.class)); //$NON-NLS-1$ + MH_createNewCharFromCharAndCharFromPointer = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFromCharAndCharFromPointer", methodType(char.class, MemoryAddress.class, char.class)); //$NON-NLS-1$ + MH_createNewCharFromCharAndCharFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFromCharAndCharFromPtr_RetPtr", MT_MemAddr_MemAddr_Char); //$NON-NLS-1$ + MH_createNewCharFromCharAndCharFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFromCharAndCharFromPtr_RetArgPtr", MT_MemAddr_MemAddr_Char); //$NON-NLS-1$ + + MH_add2Bytes = lookup.findStatic(UpcallMethodHandles.class, "add2Bytes", methodType(byte.class, byte.class, byte.class)); //$NON-NLS-1$ + MH_addByteAndByteFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addByteAndByteFromPointer", methodType(byte.class, byte.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addByteAndByteFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addByteAndByteFromPtr_RetPtr", MT_MemAddr_Byte_MemAddr); //$NON-NLS-1$ + MH_addByteAndByteFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addByteAndByteFromPtr_RetArgPtr", MT_MemAddr_Byte_MemAddr); //$NON-NLS-1$ + + MH_add2Shorts = lookup.findStatic(UpcallMethodHandles.class, "add2Shorts", methodType(short.class, short.class, short.class)); //$NON-NLS-1$ + MH_addShortAndShortFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortFromPointer", methodType(short.class, MemoryAddress.class, short.class)); //$NON-NLS-1$ + MH_addShortAndShortFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortFromPtr_RetPtr", MT_MemAddr_MemAddr_Short); //$NON-NLS-1$ + MH_addShortAndShortFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortFromPtr_RetArgPtr", MT_MemAddr_MemAddr_Short); //$NON-NLS-1$ + + MH_add2Ints = lookup.findStatic(UpcallMethodHandles.class, "add2Ints", methodType(int.class, int.class, int.class)); //$NON-NLS-1$ + MH_addIntAndIntFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntFromPointer", methodType(int.class, int.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addIntAndIntFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntFromPtr_RetPtr", MT_MemAddr_Int_MemAddr); //$NON-NLS-1$ + MH_addIntAndIntFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntFromPtr_RetArgPtr", MT_MemAddr_Int_MemAddr); //$NON-NLS-1$ + MH_add3Ints = lookup.findStatic(UpcallMethodHandles.class, "add3Ints", methodType(int.class, int.class, int.class, int.class)); //$NON-NLS-1$ + MH_addIntAndChar = lookup.findStatic(UpcallMethodHandles.class, "addIntAndChar", methodType(int.class, int.class, char.class)); //$NON-NLS-1$ + MH_add2IntsReturnVoid = lookup.findStatic(UpcallMethodHandles.class, "add2IntsReturnVoid", methodType(void.class, int.class, int.class)); //$NON-NLS-1$ + + MH_add2Longs = lookup.findStatic(UpcallMethodHandles.class, "add2Longs", methodType(long.class, long.class, long.class)); //$NON-NLS-1$ + MH_addLongAndLongFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongFromPointer", methodType(long.class, MemoryAddress.class, long.class)); //$NON-NLS-1$ + MH_addLongAndLongFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongFromPtr_RetPtr", MT_MemAddr_MemAddr_Long); //$NON-NLS-1$ + MH_addLongAndLongFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongFromPtr_RetArgPtr", MT_MemAddr_MemAddr_Long); //$NON-NLS-1$ + + MH_add2Floats = lookup.findStatic(UpcallMethodHandles.class, "add2Floats", methodType(float.class, float.class, float.class)); //$NON-NLS-1$ + MH_addFloatAndFloatFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatFromPointer", methodType(float.class, float.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addFloatAndFloatFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatFromPtr_RetPtr", MT_MemAddr_Float_MemAddr); //$NON-NLS-1$ + MH_addFloatAndFloatFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatFromPtr_RetArgPtr", MT_MemAddr_Float_MemAddr); //$NON-NLS-1$ + + MH_add2Doubles = lookup.findStatic(UpcallMethodHandles.class, "add2Doubles", methodType(double.class, double.class, double.class)); //$NON-NLS-1$ + MH_addDoubleAndDoubleFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFromPointer", methodType(double.class, MemoryAddress.class, double.class)); //$NON-NLS-1$ + MH_addDoubleAndDoubleFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFromPtr_RetPtr", MT_MemAddr_MemAddr_Double); //$NON-NLS-1$ + MH_addDoubleAndDoubleFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFromPtr_RetArgPtr", MT_MemAddr_MemAddr_Double); //$NON-NLS-1$ + + MH_compare = lookup.findStatic(UpcallMethodHandles.class, "compare", methodType(int.class, MemoryAddress.class, MemoryAddress.class)); //$NON-NLS-1$ + + MH_addBoolAndBoolsFromStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithXor", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAnd20BoolsFromStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAnd20BoolsFromStructWithXor", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolFromPointerAndBoolsFromStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolFromPointerAndBoolsFromStructWithXor", methodType(boolean.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer = lookup.findStatic(UpcallMethodHandles.class, "addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructPointerWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructPointerWithXor", methodType(boolean.class, boolean.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addBoolAndBoolsFromNestedStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromNestedStructWithXor", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromNestedStructWithXor_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromNestedStructWithXor_reverseOrder", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedBoolArray = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedBoolArray", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedStructArray", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_add2BoolStructsWithXor_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2BoolStructsWithXor_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2BoolStructsWithXor_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2BoolStructsWithXor_returnStructPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3BoolStructsWithXor_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3BoolStructsWithXor_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addByteAndBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStruct", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAnd20BytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteAnd20BytesFromStruct", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteFromPointerAndBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteFromPointerAndBytesFromStruct", methodType(byte.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addByteFromPointerAndBytesFromStruct_returnBytePointer = lookup.findStatic(UpcallMethodHandles.class, "addByteFromPointerAndBytesFromStruct_returnBytePointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructPointer", methodType(byte.class, byte.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addByteAndBytesFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromNestedStruct", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromNestedStruct_reverseOrder", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedByteArray = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedByteArray", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedByteArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedByteArray_reverseOrder", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedStructArray", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedStructArray_reverseOrder", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_add1ByteStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add1ByteStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2ByteStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2ByteStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2ByteStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2ByteStructs_returnStructPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3ByteStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3ByteStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addCharAndCharsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStruct", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAnd10CharsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharAnd10CharsFromStruct", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharFromPointerAndCharsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharFromPointerAndCharsFromStruct", methodType(char.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addCharFromPointerAndCharsFromStruct_returnCharPointer = lookup.findStatic(UpcallMethodHandles.class, "addCharFromPointerAndCharsFromStruct_returnCharPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructPointer", methodType(char.class, char.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addCharAndCharsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromNestedStruct", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromNestedStruct_reverseOrder", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedCharArray = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedCharArray", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedCharArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedCharArray_reverseOrder", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedStructArray", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedStructArray_reverseOrder", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_add2CharStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2CharStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2CharStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2CharStructs_returnStructPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3CharStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3CharStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addShortAndShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAnd10ShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAnd10ShortsFromStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortFromPointerAndShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortFromPointerAndShortsFromStruct", methodType(short.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addShortFromPointerAndShortsFromStruct_returnShortPointer = lookup.findStatic(UpcallMethodHandles.class, "addShortFromPointerAndShortsFromStruct_returnShortPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructPointer", methodType(short.class, short.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addShortAndShortsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromNestedStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromNestedStruct_reverseOrder", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedShortArray = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedShortArray", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedShortArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedShortArray_reverseOrder", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedStructArray", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedStructArray_reverseOrder", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_add2ShortStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2ShortStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2ShortStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2ShortStructs_returnStructPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3ShortStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3ShortStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addIntAndIntsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAnd5IntsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAnd5IntsFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntFromPointerAndIntsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntFromPointerAndIntsFromStruct", methodType(int.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addIntFromPointerAndIntsFromStruct_returnIntPointer = lookup.findStatic(UpcallMethodHandles.class, "addIntFromPointerAndIntsFromStruct_returnIntPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructPointer", methodType(int.class, int.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addIntAndIntsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromNestedStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromNestedStruct_reverseOrder", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedIntArray = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedIntArray", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedIntArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedIntArray_reverseOrder", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedStructArray", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedStructArray_reverseOrder", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_add2IntStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2IntStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2IntStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2IntStructs_returnStructPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3IntStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3IntStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addLongAndLongsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongFromPointerAndLongsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongFromPointerAndLongsFromStruct", methodType(long.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addLongFromPointerAndLongsFromStruct_returnLongPointer = lookup.findStatic(UpcallMethodHandles.class, "addLongFromPointerAndLongsFromStruct_returnLongPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructPointer", methodType(long.class, long.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addLongAndLongsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromNestedStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromNestedStruct_reverseOrder", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedLongArray = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedLongArray", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedLongArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedLongArray_reverseOrder", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedStructArray", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedStructArray_reverseOrder", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_add2LongStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2LongStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2LongStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2LongStructs_returnStructPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3LongStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3LongStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addFloatAndFloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAnd5FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAnd5FloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatFromPointerAndFloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatFromPointerAndFloatsFromStruct", methodType(float.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer = lookup.findStatic(UpcallMethodHandles.class, "addFloatFromPointerAndFloatsFromStruct_returnFloatPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructPointer", methodType(float.class, float.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addFloatAndFloatsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromNestedStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromNestedStruct_reverseOrder", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedFloatArray = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedFloatArray", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedStructArray", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_add2FloatStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2FloatStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2FloatStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2FloatStructs_returnStructPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3FloatStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3FloatStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addDoubleAndDoublesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleFromPointerAndDoublesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleFromPointerAndDoublesFromStruct", methodType(double.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer = lookup.findStatic(UpcallMethodHandles.class, "addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructPointer", methodType(double.class, double.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromNestedStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromNestedStruct_reverseOrder", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedDoubleArray = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedDoubleArray", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedStructArray", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_add2DoubleStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2DoubleStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2DoubleStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2DoubleStructs_returnStructPointer", MT_MemAddr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3DoubleStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3DoubleStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addIntAndIntShortFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntShortFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndShortIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndShortIntFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntLongFromStruct", MT_Long_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndLongIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndLongIntFromStruct", MT_Long_Int_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFloatFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAnd2FloatsDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAnd2FloatsDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDouble2FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDouble2FloatsFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndInt2FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndInt2FloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatIntFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatIntFloatFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntFloatDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntFloatDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatIntDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatIntDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndLongDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndLongDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndInt3FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndInt3FloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLong2FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLong2FloatsFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addFloatAnd3FloatsIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAnd3FloatsIntFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addLongAndFloatLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndFloatLongFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleFloatIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFloatIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleLongFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addLongAnd2FloatsLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAnd2FloatsLongFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addShortAnd3ShortsCharFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAnd3ShortsCharFromStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndIntFloatIntFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndIntFloatIntFloatFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleFloatFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatDoubleIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatDoubleIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatDoubleFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatDoubleFloatFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleLongFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_return254BytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "return254BytesFromStruct", MT_MemSegmt); //$NON-NLS-1$ + MH_return4KBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "return4KBytesFromStruct", MT_MemSegmt); //$NON-NLS-1$ + + } catch (IllegalAccessException | NoSuchMethodException e) { + throw new InternalError(e); + } + } + + public static boolean byteToBool(byte value) { + return (value != 0); + } + + public static byte boolToByte(boolean value) { + int intValue = (value == true) ? 1 : 0; + return (byte)intValue; + } + + public static boolean add2BoolsWithOr(boolean boolArg1, boolean boolArg2) { + boolean result = boolArg1 || boolArg2; + return result; + } + + public static boolean addBoolAndBoolFromPointerWithOr(boolean boolArg1, MemoryAddress boolArg2Addr) { + MemorySegment boolArg2Segmt = boolArg2Addr.asSegment(C_CHAR.byteSize(), scope); + byte boolArg2 = MemoryAccess.getByte(boolArg2Segmt); + boolean result = boolArg1 || byteToBool(boolArg2); + return result; + } + + public static MemoryAddress addBoolAndBoolFromPtrWithOr_RetPtr(boolean boolArg1, MemoryAddress boolArg2Addr) { + MemorySegment boolArg2Segmt = boolArg2Addr.asSegment(C_CHAR.byteSize(), scope); + byte boolArg2 = MemoryAccess.getByte(boolArg2Segmt); + boolean result = boolArg1 || byteToBool(boolArg2); + MemorySegment resultSegmt = MemorySegment.allocateNative(C_CHAR.byteSize(), scope); + MemoryAccess.setByte(resultSegmt, boolToByte(result)); + return resultSegmt.address(); + } + + public static MemoryAddress addBoolAndBoolFromPtrWithOr_RetArgPtr(boolean boolArg1, MemoryAddress boolArg2Addr) { + MemorySegment boolArg2Segmt = boolArg2Addr.asSegment(C_CHAR.byteSize(), scope); + byte boolArg2 = MemoryAccess.getByte(boolArg2Segmt); + boolean result = boolArg1 || byteToBool(boolArg2); + MemoryAccess.setByte(boolArg2Segmt, boolToByte(result)); + return boolArg2Addr; + } + + public static char createNewCharFrom2Chars(char charArg1, char charArg2) { + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + return result; + } + + public static char createNewCharFromCharAndCharFromPointer(MemoryAddress charArg1Addr, char charArg2) { + MemorySegment charArg1Segmt = charArg1Addr.asSegment(C_SHORT.byteSize(), scope); + short charArg1 = MemoryAccess.getShort(charArg1Segmt); + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + return result; + } + + public static MemoryAddress createNewCharFromCharAndCharFromPtr_RetPtr(MemoryAddress charArg1Addr, char charArg2) { + MemorySegment charArg1Segmt = charArg1Addr.asSegment(C_SHORT.byteSize(), scope); + short charArg1 = MemoryAccess.getShort(charArg1Segmt); + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + MemorySegment resultSegmt = MemorySegment.allocateNative(C_SHORT.byteSize(), scope); + MemoryAccess.setChar(resultSegmt, result); + return resultSegmt.address(); + } + + public static MemoryAddress createNewCharFromCharAndCharFromPtr_RetArgPtr(MemoryAddress charArg1Addr, char charArg2) { + MemorySegment charArg1Segmt = charArg1Addr.asSegment(C_SHORT.byteSize(), scope); + short charArg1 = MemoryAccess.getShort(charArg1Segmt); + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + MemoryAccess.setChar(charArg1Segmt, result); + return charArg1Addr; + } + + public static byte add2Bytes(byte byteArg1, byte byteArg2) { + byte byteSum = (byte)(byteArg1 + byteArg2); + return byteSum; + } + + public static byte addByteAndByteFromPointer(byte byteArg1, MemoryAddress byteArg2Addr) { + MemorySegment byteArg2Segmt = byteArg2Addr.asSegment(C_CHAR.byteSize(), scope); + byte byteArg2 = MemoryAccess.getByte(byteArg2Segmt); + byte byteSum = (byte)(byteArg1 + byteArg2); + return byteSum; + } + + public static MemoryAddress addByteAndByteFromPtr_RetPtr(byte byteArg1, MemoryAddress byteArg2Addr) { + MemorySegment byteArg2Segmt = byteArg2Addr.asSegment(C_CHAR.byteSize(), scope); + byte byteArg2 = MemoryAccess.getByte(byteArg2Segmt); + byte byteSum = (byte)(byteArg1 + byteArg2); + MemorySegment resultSegmt = MemorySegment.allocateNative(C_CHAR.byteSize(), scope); + MemoryAccess.setByte(resultSegmt, byteSum); + return resultSegmt.address(); + } + + public static MemoryAddress addByteAndByteFromPtr_RetArgPtr(byte byteArg1, MemoryAddress byteArg2Addr) { + MemorySegment byteArg2Segmt = byteArg2Addr.asSegment(C_CHAR.byteSize(), scope); + byte byteArg2 = MemoryAccess.getByte(byteArg2Segmt); + byte byteSum = (byte)(byteArg1 + byteArg2); + MemoryAccess.setByte(byteArg2Segmt, byteSum); + return byteArg2Addr; + } + + public static short add2Shorts(short shortArg1, short shortArg2) { + short shortSum = (short)(shortArg1 + shortArg2); + return shortSum; + } + + public static short addShortAndShortFromPointer(MemoryAddress shortArg1Addr, short shortArg2) { + MemorySegment shortArg1Segmt = shortArg1Addr.asSegment(C_SHORT.byteSize(), scope); + short shortArg1 = MemoryAccess.getShort(shortArg1Segmt); + short shortSum = (short)(shortArg1 + shortArg2); + return shortSum; + } + + public static MemoryAddress addShortAndShortFromPtr_RetPtr(MemoryAddress shortArg1Addr, short shortArg2) { + MemorySegment shortArg1Segmt = shortArg1Addr.asSegment(C_SHORT.byteSize(), scope); + short shortArg1 = MemoryAccess.getShort(shortArg1Segmt); + short shortSum = (short)(shortArg1 + shortArg2); + MemorySegment resultSegmt = MemorySegment.allocateNative(C_SHORT.byteSize(), scope); + MemoryAccess.setShort(resultSegmt, shortSum); + return resultSegmt.address(); + } + + public static MemoryAddress addShortAndShortFromPtr_RetArgPtr(MemoryAddress shortArg1Addr, short shortArg2) { + MemorySegment shortArg1Segmt = shortArg1Addr.asSegment(C_SHORT.byteSize(), scope); + short shortArg1 = MemoryAccess.getShort(shortArg1Segmt); + short shortSum = (short)(shortArg1 + shortArg2); + MemoryAccess.setShort(shortArg1Segmt, shortSum); + return shortArg1Addr; + } + + public static int add2Ints(int intArg1, int intArg2) { + int intSum = intArg1 + intArg2; + return intSum; + } + + public static int addIntAndIntFromPointer(int intArg1, MemoryAddress intArg2Addr) { + MemorySegment intArg2Segmt = intArg2Addr.asSegment(C_INT.byteSize(), scope); + int intArg2 = MemoryAccess.getInt(intArg2Segmt); + int intSum = intArg1 + intArg2; + return intSum; + } + + public static MemoryAddress addIntAndIntFromPtr_RetPtr(int intArg1, MemoryAddress intArg2Addr) { + MemorySegment intArg2Segmt = intArg2Addr.asSegment(C_INT.byteSize(), scope); + int intArg2 = MemoryAccess.getInt(intArg2Segmt); + int intSum = intArg1 + intArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(C_INT.byteSize(), scope); + MemoryAccess.setInt(resultSegmt, intSum); + return resultSegmt.address(); + } + + public static MemoryAddress addIntAndIntFromPtr_RetArgPtr(int intArg1, MemoryAddress intArg2Addr) { + MemorySegment intArg2Segmt = intArg2Addr.asSegment(C_INT.byteSize(), scope); + int intArg2 = MemoryAccess.getInt(intArg2Segmt); + int intSum = intArg1 + intArg2; + MemoryAccess.setInt(intArg2Segmt, intSum); + return intArg2Addr; + } + + public static int add3Ints(int intArg1, int intArg2, int intArg3) { + int intSum = intArg1 + intArg2 + intArg3; + return intSum; + } + + public static int addIntAndChar(int intArg, char charArg) { + int sum = intArg + charArg; + return sum; + } + + public static void add2IntsReturnVoid(int intArg1, int intArg2) { + int intSum = intArg1 + intArg2; + System.out.println("add2IntsReturnVoid: intSum = " + intSum + "\n"); + } + + public static long add2Longs(long longArg1, long longArg2) { + long longSum = longArg1 + longArg2; + return longSum; + } + + public static long addLongAndLongFromPointer(MemoryAddress longArg1Addr, long longArg2) { + MemorySegment longArg1Segmt = longArg1Addr.asSegment(longLayout.byteSize(), scope); + long longArg1 = MemoryAccess.getLong(longArg1Segmt); + long longSum = longArg1 + longArg2; + return longSum; + } + + public static MemoryAddress addLongAndLongFromPtr_RetPtr(MemoryAddress longArg1Addr, long longArg2) { + MemorySegment longArg1Segmt = longArg1Addr.asSegment(longLayout.byteSize(), scope); + long longArg1 = MemoryAccess.getLong(longArg1Segmt); + long longSum = longArg1 + longArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(longLayout.byteSize(), scope); + MemoryAccess.setLong(resultSegmt, longSum); + return resultSegmt.address(); + } + + public static MemoryAddress addLongAndLongFromPtr_RetArgPtr(MemoryAddress longArg1Addr, long longArg2) { + MemorySegment longArg1Segmt = longArg1Addr.asSegment(longLayout.byteSize(), scope); + long longArg1 = MemoryAccess.getLong(longArg1Segmt); + long longSum = longArg1 + longArg2; + MemoryAccess.setLong(longArg1Segmt, longSum); + return longArg1Addr; + } + + public static float add2Floats(float floatArg1, float floatArg2) { + float floatSum = floatArg1 + floatArg2; + return floatSum; + } + + public static float addFloatAndFloatFromPointer(float floatArg1, MemoryAddress floatArg2Addr) { + MemorySegment floatArg2Segmt = floatArg2Addr.asSegment(C_FLOAT.byteSize(), scope); + float floatArg2 = MemoryAccess.getFloat(floatArg2Segmt); + float floatSum = floatArg1 + floatArg2; + return floatSum; + } + + public static MemoryAddress addFloatAndFloatFromPtr_RetPtr(float floatArg1, MemoryAddress floatArg2Addr) { + MemorySegment floatArg2Segmt = floatArg2Addr.asSegment(C_FLOAT.byteSize(), scope); + float floatArg2 = MemoryAccess.getFloat(floatArg2Segmt); + float floatSum = floatArg1 + floatArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(C_FLOAT.byteSize(), scope); + MemoryAccess.setFloat(resultSegmt, floatSum); + return resultSegmt.address(); + } + + public static MemoryAddress addFloatAndFloatFromPtr_RetArgPtr(float floatArg1, MemoryAddress floatArg2Addr) { + MemorySegment floatArg2Segmt = floatArg2Addr.asSegment(C_FLOAT.byteSize(), scope); + float floatArg2 = MemoryAccess.getFloat(floatArg2Segmt); + float floatSum = floatArg1 + floatArg2; + MemoryAccess.setFloat(floatArg2Segmt, floatSum); + return floatArg2Addr; + } + + public static double add2Doubles(double doubleArg1, double doubleArg2) { + double doubleSum = doubleArg1 + doubleArg2; + return doubleSum; + } + + public static double addDoubleAndDoubleFromPointer(MemoryAddress doubleArg1Addr, double doubleArg2) { + MemorySegment doubleArg1Segmt = doubleArg1Addr.asSegment(C_DOUBLE.byteSize(), scope); + double doubleArg1 = MemoryAccess.getDouble(doubleArg1Segmt); + double doubleSum = doubleArg1 + doubleArg2; + return doubleSum; + } + + public static MemoryAddress addDoubleAndDoubleFromPtr_RetPtr(MemoryAddress doubleArg1Addr, double doubleArg2) { + MemorySegment doubleArg1Segmt = doubleArg1Addr.asSegment(C_DOUBLE.byteSize(), scope); + double doubleArg1 = MemoryAccess.getDouble(doubleArg1Segmt); + double doubleSum = doubleArg1 + doubleArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(C_DOUBLE.byteSize(), scope); + MemoryAccess.setDouble(resultSegmt, doubleSum); + return resultSegmt.address(); + } + + public static MemoryAddress addDoubleAndDoubleFromPtr_RetArgPtr(MemoryAddress doubleArg1Addr, double doubleArg2) { + MemorySegment doubleArg1Segmt = doubleArg1Addr.asSegment(C_DOUBLE.byteSize(), scope); + double doubleArg1 = MemoryAccess.getDouble(doubleArg1Segmt); + double doubleSum = doubleArg1 + doubleArg2; + MemoryAccess.setDouble(doubleArg1Segmt, doubleSum); + return doubleArg1Addr; + } + + public static int compare(MemoryAddress argAddr1, MemoryAddress argAddr2) { + int intArg1 = MemoryAccess.getInt(argAddr1.asSegment(C_INT.byteSize(), scope)); + int intArg2 = MemoryAccess.getInt(argAddr2.asSegment(C_INT.byteSize(), scope)); + return (intArg1 - intArg2); + } + + public static boolean addBoolAndBoolsFromStructWithXor(boolean arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + boolean boolSum = arg1 ^ byteToBool((byte)boolHandle1.get(arg2)) ^ byteToBool((byte)boolHandle2.get(arg2)); + return boolSum; + } + + public static boolean addBoolAnd20BoolsFromStructWithXor(boolean arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2"), + C_CHAR.withName("elem3"), C_CHAR.withName("elem4"), C_CHAR.withName("elem5"), C_CHAR.withName("elem6"), + C_CHAR.withName("elem7"), C_CHAR.withName("elem8"), C_CHAR.withName("elem9"), C_CHAR.withName("elem10"), + C_CHAR.withName("elem11"), C_CHAR.withName("elem12"), C_CHAR.withName("elem13"), C_CHAR.withName("elem14"), + C_CHAR.withName("elem15"), C_CHAR.withName("elem16"), C_CHAR.withName("elem17"), C_CHAR.withName("elem18"), + C_CHAR.withName("elem19"), C_CHAR.withName("elem20")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + VarHandle boolHandle3 = structLayout.varHandle(byte.class, PathElement.groupElement("elem3")); + VarHandle boolHandle4 = structLayout.varHandle(byte.class, PathElement.groupElement("elem4")); + VarHandle boolHandle5 = structLayout.varHandle(byte.class, PathElement.groupElement("elem5")); + VarHandle boolHandle6 = structLayout.varHandle(byte.class, PathElement.groupElement("elem6")); + VarHandle boolHandle7 = structLayout.varHandle(byte.class, PathElement.groupElement("elem7")); + VarHandle boolHandle8 = structLayout.varHandle(byte.class, PathElement.groupElement("elem8")); + VarHandle boolHandle9 = structLayout.varHandle(byte.class, PathElement.groupElement("elem9")); + VarHandle boolHandle10 = structLayout.varHandle(byte.class, PathElement.groupElement("elem10")); + VarHandle boolHandle11 = structLayout.varHandle(byte.class, PathElement.groupElement("elem11")); + VarHandle boolHandle12 = structLayout.varHandle(byte.class, PathElement.groupElement("elem12")); + VarHandle boolHandle13 = structLayout.varHandle(byte.class, PathElement.groupElement("elem13")); + VarHandle boolHandle14 = structLayout.varHandle(byte.class, PathElement.groupElement("elem14")); + VarHandle boolHandle15 = structLayout.varHandle(byte.class, PathElement.groupElement("elem15")); + VarHandle boolHandle16 = structLayout.varHandle(byte.class, PathElement.groupElement("elem16")); + VarHandle boolHandle17 = structLayout.varHandle(byte.class, PathElement.groupElement("elem17")); + VarHandle boolHandle18 = structLayout.varHandle(byte.class, PathElement.groupElement("elem18")); + VarHandle boolHandle19 = structLayout.varHandle(byte.class, PathElement.groupElement("elem19")); + VarHandle boolHandle20 = structLayout.varHandle(byte.class, PathElement.groupElement("elem20")); + + boolean boolSum = arg1 ^ byteToBool((byte)boolHandle1.get(arg2)) ^ byteToBool((byte)boolHandle2.get(arg2)) + ^ byteToBool((byte)boolHandle3.get(arg2)) ^ byteToBool((byte)boolHandle4.get(arg2)) ^ byteToBool((byte)boolHandle5.get(arg2)) + ^ byteToBool((byte)boolHandle6.get(arg2)) ^ byteToBool((byte)boolHandle7.get(arg2)) ^ byteToBool((byte)boolHandle8.get(arg2)) + ^ byteToBool((byte)boolHandle9.get(arg2)) ^ byteToBool((byte)boolHandle10.get(arg2)) ^ byteToBool((byte)boolHandle11.get(arg2)) + ^ byteToBool((byte)boolHandle12.get(arg2)) ^ byteToBool((byte)boolHandle13.get(arg2)) ^ byteToBool((byte)boolHandle14.get(arg2)) + ^ byteToBool((byte)boolHandle15.get(arg2)) ^ byteToBool((byte)boolHandle16.get(arg2)) ^ byteToBool((byte)boolHandle17.get(arg2)) + ^ byteToBool((byte)boolHandle18.get(arg2)) ^ byteToBool((byte)boolHandle19.get(arg2)) ^ byteToBool((byte)boolHandle20.get(arg2)); + return boolSum; + } + + public static boolean addBoolFromPointerAndBoolsFromStructWithXor(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_CHAR.byteSize(), arg1Addr.scope()); + byte arg1 = MemoryAccess.getByte(arg1Segmt); + boolean boolSum = byteToBool(arg1) ^ byteToBool((byte)boolHandle1.get(arg2)) ^ byteToBool((byte)boolHandle2.get(arg2)); + return boolSum; + } + + public static MemoryAddress addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_CHAR.byteSize(), arg1Addr.scope()); + byte arg1 = MemoryAccess.getByte(arg1Segmt); + boolean boolSum = byteToBool(arg1) ^ byteToBool((byte)boolHandle1.get(arg2)) ^ byteToBool((byte)boolHandle2.get(arg2)); + MemoryAccess.setByte(arg1Segmt, boolToByte(boolSum)); + return arg1Addr; + } + + public static boolean addBoolAndBoolsFromStructPointerWithXor(boolean arg1, MemoryAddress arg2Addr) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment arg2 = arg2Addr.asSegment(structLayout.byteSize(), arg2Addr.scope()); + boolean boolSum = arg1 ^ byteToBool((byte)boolHandle1.get(arg2)) ^ byteToBool((byte)boolHandle2.get(arg2)); + return boolSum; + } + + public static boolean addBoolAndBoolsFromNestedStructWithXor(boolean arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(16)); + + boolean nestedStructElem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 0)); + boolean nestedStructElem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 1)); + boolean structElem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 2)); + boolean boolSum = arg1 ^ nestedStructElem1 ^ nestedStructElem2 ^ structElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromNestedStructWithXor_reverseOrder(boolean arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + + boolean structElem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 0)); + boolean nestedStructElem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 1)); + boolean nestedStructElem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 2)); + boolean boolSum = arg1 ^ structElem1 ^ nestedStructElem1 ^ nestedStructElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedBoolArray(boolean arg1, MemorySegment arg2) { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray.withName("array_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(16)); + + boolean nestedBoolArrayElem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 0)); + boolean nestedBoolArrayElem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 1)); + boolean structElem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 2)); + + boolean boolSum = arg1 ^ nestedBoolArrayElem1 ^ nestedBoolArrayElem2 ^ structElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder(boolean arg1, MemorySegment arg2) { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), + byteArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + + boolean structElem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 0)); + boolean nestedBoolArrayElem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 1)); + boolean nestedBoolArrayElem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 2)); + + boolean boolSum = arg1 ^ structElem1 ^ nestedBoolArrayElem1 ^ nestedBoolArrayElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedStructArray(boolean arg1, MemorySegment arg2) { + GroupLayout byteStruct = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); + + boolean nestedStructArrayElem1_Elem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 0)); + boolean nestedStructArrayElem1_Elem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 1)); + boolean nestedStructArrayElem2_Elem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 2)); + boolean nestedStructArrayElem2_Elem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 3)); + boolean structElem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 4)); + + boolean boolSum = arg1 ^ structElem2 + ^ nestedStructArrayElem1_Elem1 ^ nestedStructArrayElem1_Elem2 + ^ nestedStructArrayElem2_Elem1 ^ nestedStructArrayElem2_Elem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder(boolean arg1, MemorySegment arg2) { + GroupLayout byteStruct = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); + + boolean structElem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 0)); + boolean nestedStructArrayElem1_Elem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 1)); + boolean nestedStructArrayElem1_Elem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 2)); + boolean nestedStructArrayElem2_Elem1 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 3)); + boolean nestedStructArrayElem2_Elem2 = byteToBool(MemoryAccess.getByteAtOffset(arg2, 4)); + + boolean boolSum = arg1 ^ structElem1 + ^ nestedStructArrayElem1_Elem1 ^ nestedStructArrayElem1_Elem2 + ^ nestedStructArrayElem2_Elem1 ^ nestedStructArrayElem2_Elem2; + return boolSum; + } + + public static MemorySegment add2BoolStructsWithXor_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment boolStructSegmt = MemorySegment.allocateNative(structLayout, scope); + boolean boolStruct_Elem1 = byteToBool((byte)boolHandle1.get(arg1)) ^ byteToBool((byte)boolHandle1.get(arg2)); + boolean boolStruct_Elem2 = byteToBool((byte)boolHandle2.get(arg1)) ^ byteToBool((byte)boolHandle2.get(arg2)); + boolHandle1.set(boolStructSegmt, boolToByte(boolStruct_Elem1)); + boolHandle2.set(boolStructSegmt, boolToByte(boolStruct_Elem2)); + return boolStructSegmt; + } + + public static MemoryAddress add2BoolStructsWithXor_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment arg1 = arg1Addr.asSegment(structLayout.byteSize(), arg1Addr.scope()); + boolean boolStruct_Elem1 = byteToBool((byte)boolHandle1.get(arg1)) ^ byteToBool((byte)boolHandle1.get(arg2)); + boolean boolStruct_Elem2 = byteToBool((byte)boolHandle2.get(arg1)) ^ byteToBool((byte)boolHandle2.get(arg2)); + boolHandle1.set(arg1, boolToByte(boolStruct_Elem1)); + boolHandle2.set(arg1, boolToByte(boolStruct_Elem2)); + return arg1Addr; + } + + public static MemorySegment add3BoolStructsWithXor_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2"), + C_CHAR.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle boolHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + VarHandle boolHandle3 = structLayout.varHandle(byte.class, PathElement.groupElement("elem3")); + + MemorySegment boolStructSegmt = MemorySegment.allocateNative(structLayout, scope); + boolean boolStruct_Elem1 = byteToBool((byte)boolHandle1.get(arg1)) ^ byteToBool((byte)boolHandle1.get(arg2)); + boolean boolStruct_Elem2 = byteToBool((byte)boolHandle2.get(arg1)) ^ byteToBool((byte)boolHandle2.get(arg2)); + boolean boolStruct_Elem3 = byteToBool((byte)boolHandle3.get(arg1)) ^ byteToBool((byte)boolHandle3.get(arg2)); + boolHandle1.set(boolStructSegmt, boolToByte(boolStruct_Elem1)); + boolHandle2.set(boolStructSegmt, boolToByte(boolStruct_Elem2)); + boolHandle3.set(boolStructSegmt, boolToByte(boolStruct_Elem3)); + return boolStructSegmt; + } + + public static byte addByteAndBytesFromStruct(byte arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + byte byteSum = (byte)(arg1 + (byte)byteHandle1.get(arg2) + (byte)byteHandle2.get(arg2)); + return byteSum; + } + + public static byte addByteAnd20BytesFromStruct(byte arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2"), + C_CHAR.withName("elem3"), C_CHAR.withName("elem4"), C_CHAR.withName("elem5"), C_CHAR.withName("elem6"), + C_CHAR.withName("elem7"), C_CHAR.withName("elem8"), C_CHAR.withName("elem9"), C_CHAR.withName("elem10"), + C_CHAR.withName("elem11"), C_CHAR.withName("elem12"), C_CHAR.withName("elem13"), C_CHAR.withName("elem14"), + C_CHAR.withName("elem15"), C_CHAR.withName("elem16"), C_CHAR.withName("elem17"), C_CHAR.withName("elem18"), + C_CHAR.withName("elem19"), C_CHAR.withName("elem20")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(byte.class, PathElement.groupElement("elem3")); + VarHandle byteHandle4 = structLayout.varHandle(byte.class, PathElement.groupElement("elem4")); + VarHandle byteHandle5 = structLayout.varHandle(byte.class, PathElement.groupElement("elem5")); + VarHandle byteHandle6 = structLayout.varHandle(byte.class, PathElement.groupElement("elem6")); + VarHandle byteHandle7 = structLayout.varHandle(byte.class, PathElement.groupElement("elem7")); + VarHandle byteHandle8 = structLayout.varHandle(byte.class, PathElement.groupElement("elem8")); + VarHandle byteHandle9 = structLayout.varHandle(byte.class, PathElement.groupElement("elem9")); + VarHandle byteHandle10 = structLayout.varHandle(byte.class, PathElement.groupElement("elem10")); + VarHandle byteHandle11 = structLayout.varHandle(byte.class, PathElement.groupElement("elem11")); + VarHandle byteHandle12 = structLayout.varHandle(byte.class, PathElement.groupElement("elem12")); + VarHandle byteHandle13 = structLayout.varHandle(byte.class, PathElement.groupElement("elem13")); + VarHandle byteHandle14 = structLayout.varHandle(byte.class, PathElement.groupElement("elem14")); + VarHandle byteHandle15 = structLayout.varHandle(byte.class, PathElement.groupElement("elem15")); + VarHandle byteHandle16 = structLayout.varHandle(byte.class, PathElement.groupElement("elem16")); + VarHandle byteHandle17 = structLayout.varHandle(byte.class, PathElement.groupElement("elem17")); + VarHandle byteHandle18 = structLayout.varHandle(byte.class, PathElement.groupElement("elem18")); + VarHandle byteHandle19 = structLayout.varHandle(byte.class, PathElement.groupElement("elem19")); + VarHandle byteHandle20 = structLayout.varHandle(byte.class, PathElement.groupElement("elem20")); + + byte bytelSum = (byte)(arg1 + (byte)byteHandle1.get(arg2) + (byte)byteHandle2.get(arg2) + + (byte)byteHandle3.get(arg2) + (byte)byteHandle4.get(arg2) + (byte)byteHandle5.get(arg2) + + (byte)byteHandle6.get(arg2) + (byte)byteHandle7.get(arg2) + (byte)byteHandle8.get(arg2) + + (byte)byteHandle9.get(arg2) + (byte)byteHandle10.get(arg2) + (byte)byteHandle11.get(arg2) + + (byte)byteHandle12.get(arg2) + (byte)byteHandle13.get(arg2) + (byte)byteHandle14.get(arg2) + + (byte)byteHandle15.get(arg2) + (byte)byteHandle16.get(arg2) + (byte)byteHandle17.get(arg2) + + (byte)byteHandle18.get(arg2) + (byte)byteHandle19.get(arg2) + (byte)byteHandle20.get(arg2)); + return bytelSum; + } + + public static byte addByteFromPointerAndBytesFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_CHAR.byteSize(), arg1Addr.scope()); + byte arg1 = MemoryAccess.getByte(arg1Segmt); + byte byteSum = (byte)(arg1 + (byte)byteHandle1.get(arg2) + (byte)byteHandle2.get(arg2)); + return byteSum; + } + + public static MemoryAddress addByteFromPointerAndBytesFromStruct_returnBytePointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_CHAR.byteSize(), arg1Addr.scope()); + byte arg1 = MemoryAccess.getByte(arg1Segmt); + byte byteSum = (byte)(arg1 + (byte)byteHandle1.get(arg2) + (byte)byteHandle2.get(arg2)); + MemoryAccess.setByte(arg1Segmt, byteSum); + return arg1Addr; + } + + public static byte addByteAndBytesFromStructPointer(byte arg1, MemoryAddress arg2Addr) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment arg2 = arg2Addr.asSegment(structLayout.byteSize(), arg2Addr.scope()); + byte byteSum = (byte)(arg1 + (byte)byteHandle1.get(arg2) + (byte)byteHandle2.get(arg2)); + return byteSum; + } + + public static byte addByteAndBytesFromNestedStruct(byte arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(16)); + + byte nestedStructElem1 = MemoryAccess.getByteAtOffset(arg2, 0); + byte nestedStructElem2 = MemoryAccess.getByteAtOffset(arg2, 1); + byte structElem2 = MemoryAccess.getByteAtOffset(arg2, 2); + + byte byteSum = (byte)(arg1 + nestedStructElem1 + nestedStructElem2 + structElem2); + return byteSum; + } + + public static byte addByteAndBytesFromNestedStruct_reverseOrder(byte arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + + byte structElem1 = MemoryAccess.getByteAtOffset(arg2, 0); + byte nestedStructElem1 = MemoryAccess.getByteAtOffset(arg2, 1); + byte nestedStructElem2 = MemoryAccess.getByteAtOffset(arg2, 2); + + byte byteSum = (byte)(arg1 + structElem1 + nestedStructElem1 + nestedStructElem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedByteArray(byte arg1, MemorySegment arg2) { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray.withName("array_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(16)); + + byte nestedByteArrayElem1 = MemoryAccess.getByteAtOffset(arg2, 0); + byte nestedByteArrayElem2 = MemoryAccess.getByteAtOffset(arg2, 1); + byte structElem2 = MemoryAccess.getByteAtOffset(arg2, 2); + + byte byteSum = (byte)(arg1 + nestedByteArrayElem1 + nestedByteArrayElem2 + structElem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedByteArray_reverseOrder(byte arg1, MemorySegment arg2) { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), + byteArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + + byte structElem1 = MemoryAccess.getByteAtOffset(arg2, 0); + byte nestedByteArrayElem1 = MemoryAccess.getByteAtOffset(arg2, 1); + byte nestedByteArrayElem2 = MemoryAccess.getByteAtOffset(arg2, 2); + + byte byteSum = (byte)(arg1 + structElem1 + nestedByteArrayElem1 + nestedByteArrayElem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedStructArray(byte arg1, MemorySegment arg2) { + GroupLayout byteStruct = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + C_CHAR.withName("elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); + + byte nestedStructArrayElem1_Elem1 = MemoryAccess.getByteAtOffset(arg2, 0); + byte nestedStructArrayElem1_Elem2 = MemoryAccess.getByteAtOffset(arg2, 1); + byte nestedStructArrayElem2_Elem1 = MemoryAccess.getByteAtOffset(arg2, 2); + byte nestedStructArrayElem2_Elem2 = MemoryAccess.getByteAtOffset(arg2, 3); + byte structElem2 = MemoryAccess.getByteAtOffset(arg2, 4); + + byte byteSum = (byte)(arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedStructArray_reverseOrder(byte arg1, MemorySegment arg2) { + GroupLayout byteStruct = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(C_CHAR.bitSize() * 3)); + + byte structElem1 = MemoryAccess.getByteAtOffset(arg2, 0); + byte nestedStructArrayElem1_Elem1 = MemoryAccess.getByteAtOffset(arg2, 1); + byte nestedStructArrayElem1_Elem2 = MemoryAccess.getByteAtOffset(arg2, 2); + byte nestedStructArrayElem2_Elem1 = MemoryAccess.getByteAtOffset(arg2, 3); + byte nestedStructArrayElem2_Elem2 = MemoryAccess.getByteAtOffset(arg2, 4); + + byte byteSum = (byte)(arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return byteSum; + } + + public static MemorySegment add1ByteStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + + MemorySegment byteStructSegmt = MemorySegment.allocateNative(structLayout, scope); + byte byteStruct_Elem1 = (byte)((byte)byteHandle1.get(arg1) + (byte)byteHandle1.get(arg2)); + byteHandle1.set(byteStructSegmt, byteStruct_Elem1); + return byteStructSegmt; + } + + public static MemorySegment add2ByteStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment byteStructSegmt = MemorySegment.allocateNative(structLayout, scope); + byte byteStruct_Elem1 = (byte)((byte)byteHandle1.get(arg1) + (byte)byteHandle1.get(arg2)); + byte byteStruct_Elem2 = (byte)((byte)byteHandle2.get(arg1) + (byte)byteHandle2.get(arg2)); + byteHandle1.set(byteStructSegmt, byteStruct_Elem1); + byteHandle2.set(byteStructSegmt, byteStruct_Elem2); + return byteStructSegmt; + } + + public static MemoryAddress add2ByteStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + + MemorySegment arg1 = arg1Addr.asSegment(structLayout.byteSize(), arg1Addr.scope()); + byte byteStruct_Elem1 = (byte)((byte)byteHandle1.get(arg1) + (byte)byteHandle1.get(arg2)); + byte byteStruct_Elem2 = (byte)((byte)byteHandle2.get(arg1) + (byte)byteHandle2.get(arg2)); + byteHandle1.set(arg1, byteStruct_Elem1); + byteHandle2.set(arg1, byteStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3ByteStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_CHAR.withName("elem1"), C_CHAR.withName("elem2"), + C_CHAR.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle byteHandle1 = structLayout.varHandle(byte.class, PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(byte.class, PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(byte.class, PathElement.groupElement("elem3")); + + MemorySegment byteStructSegmt = MemorySegment.allocateNative(structLayout, scope); + byte byteStruct_Elem1 = (byte)((byte)byteHandle1.get(arg1) + (byte)byteHandle1.get(arg2)); + byte byteStruct_Elem2 = (byte)((byte)byteHandle2.get(arg1) + (byte)byteHandle2.get(arg2)); + byte byteStruct_Elem3 = (byte)((byte)byteHandle3.get(arg1) + (byte)byteHandle3.get(arg2)); + byteHandle1.set(byteStructSegmt, byteStruct_Elem1); + byteHandle2.set(byteStructSegmt, byteStruct_Elem2); + byteHandle3.set(byteStructSegmt, byteStruct_Elem3); + return byteStructSegmt; + } + + public static char addCharAndCharsFromStruct(char arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + char result = (char)(arg1 + (char)charHandle1.get(arg2) + (char)charHandle2.get(arg2) - 2 * 'A'); + return result; + } + + public static char addCharAnd10CharsFromStruct(char arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3"), C_SHORT.withName("elem4"), C_SHORT.withName("elem5"), + C_SHORT.withName("elem6"), C_SHORT.withName("elem7"), C_SHORT.withName("elem8"), + C_SHORT.withName("elem9"), C_SHORT.withName("elem10")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + VarHandle charHandle3 = structLayout.varHandle(char.class, PathElement.groupElement("elem3")); + VarHandle charHandle4 = structLayout.varHandle(char.class, PathElement.groupElement("elem4")); + VarHandle charHandle5 = structLayout.varHandle(char.class, PathElement.groupElement("elem5")); + VarHandle charHandle6 = structLayout.varHandle(char.class, PathElement.groupElement("elem6")); + VarHandle charHandle7 = structLayout.varHandle(char.class, PathElement.groupElement("elem7")); + VarHandle charHandle8 = structLayout.varHandle(char.class, PathElement.groupElement("elem8")); + VarHandle charHandle9 = structLayout.varHandle(char.class, PathElement.groupElement("elem9")); + VarHandle charHandle10 = structLayout.varHandle(char.class, PathElement.groupElement("elem10")); + + char result = (char)(arg1 + (char)charHandle1.get(arg2) + (char)charHandle2.get(arg2) + + (char)charHandle3.get(arg2) + (char)charHandle4.get(arg2) + (char)charHandle5.get(arg2) + + (char)charHandle6.get(arg2) + (char)charHandle7.get(arg2) + (char)charHandle8.get(arg2) + + (char)charHandle9.get(arg2) + (char)charHandle10.get(arg2) - 10 * 'A'); + return result; + } + + public static char addCharFromPointerAndCharsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_SHORT.byteSize(), arg1Addr.scope()); + char arg1 = MemoryAccess.getChar(arg1Segmt); + char result = (char)(arg1 + (char)charHandle1.get(arg2) + (char)charHandle2.get(arg2) - 2 * 'A'); + return result; + } + + public static MemoryAddress addCharFromPointerAndCharsFromStruct_returnCharPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_SHORT.byteSize(), arg1Addr.scope()); + char arg1 = MemoryAccess.getChar(arg1Segmt); + char result = (char)(arg1 + (char)charHandle1.get(arg2) + (char)charHandle2.get(arg2) - 2 * 'A'); + MemoryAccess.setChar(arg1Segmt, result); + return arg1Addr; + } + + public static char addCharAndCharsFromStructPointer(char arg1, MemoryAddress arg2Addr) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MemorySegment arg2 = arg2Addr.asSegment(structLayout.byteSize(), arg2Addr.scope()); + char result = (char)(arg1 + (char)charHandle1.get(arg2) + (char)charHandle2.get(arg2) - 2 * 'A'); + return result; + } + + public static char addCharAndCharsFromNestedStruct(char arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + + char nestedStructElem1 = MemoryAccess.getCharAtOffset(arg2, 0); + char nestedStructElem2 = MemoryAccess.getCharAtOffset(arg2, 2); + char structElem2 = MemoryAccess.getCharAtOffset(arg2, 4); + + char result = (char)(arg1 + nestedStructElem1 + nestedStructElem2 + structElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromNestedStruct_reverseOrder(char arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + + char structElem1 = MemoryAccess.getCharAtOffset(arg2, 0); + char nestedStructElem1 = MemoryAccess.getCharAtOffset(arg2, 2); + char nestedStructElem2 = MemoryAccess.getCharAtOffset(arg2, 4); + + char result = (char)(arg1 + structElem1 + nestedStructElem1 + nestedStructElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedCharArray(char arg1, MemorySegment arg2) { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, C_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(charArray.withName("array_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + + char nestedCharArrayElem1 = MemoryAccess.getCharAtOffset(arg2, 0); + char nestedCharArrayElem2 = MemoryAccess.getCharAtOffset(arg2, 2); + char structElem2 = MemoryAccess.getCharAtOffset(arg2, 4); + + char result = (char)(arg1 + nestedCharArrayElem1 + nestedCharArrayElem2 + structElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedCharArray_reverseOrder(char arg1, MemorySegment arg2) { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, C_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), + charArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + + char structElem1 = MemoryAccess.getCharAtOffset(arg2, 0); + char nestedCharArrayElem1 = MemoryAccess.getCharAtOffset(arg2, 2); + char nestedCharArrayElem2 = MemoryAccess.getCharAtOffset(arg2, 4); + + char result = (char)(arg1 + structElem1 + nestedCharArrayElem1 + nestedCharArrayElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedStructArray(char arg1, MemorySegment arg2) { + GroupLayout charStruct = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), C_SHORT.withName("elem2")); + + char nestedStructArrayElem1_Elem1 = MemoryAccess.getCharAtOffset(arg2, 0); + char nestedStructArrayElem1_Elem2 = MemoryAccess.getCharAtOffset(arg2, 2); + char nestedStructArrayElem2_Elem1 = MemoryAccess.getCharAtOffset(arg2, 4); + char nestedStructArrayElem2_Elem2 = MemoryAccess.getCharAtOffset(arg2, 6); + char structElem2 = MemoryAccess.getCharAtOffset(arg2, 8); + + char result = (char)(arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2 - 5 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedStructArray_reverseOrder(char arg1, MemorySegment arg2) { + GroupLayout charStruct = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(16)); + + char structElem1 = MemoryAccess.getCharAtOffset(arg2, 0); + char nestedStructArrayElem1_Elem1 = MemoryAccess.getCharAtOffset(arg2, 2); + char nestedStructArrayElem1_Elem2 = MemoryAccess.getCharAtOffset(arg2, 4); + char nestedStructArrayElem2_Elem1 = MemoryAccess.getCharAtOffset(arg2, 6); + char nestedStructArrayElem2_Elem2 = MemoryAccess.getCharAtOffset(arg2, 8); + + char result = (char)(arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2 - 5 * 'A'); + return result; + } + + public static MemorySegment add2CharStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MemorySegment charStructSegmt = MemorySegment.allocateNative(structLayout, scope); + char charStruct_Elem1 = (char)((char)charHandle1.get(arg1) + (char)charHandle1.get(arg2) - 'A'); + char charStruct_Elem2 = (char)((char)charHandle2.get(arg1) + (char)charHandle2.get(arg2) - 'A'); + charHandle1.set(charStructSegmt, charStruct_Elem1); + charHandle2.set(charStructSegmt, charStruct_Elem2); + return charStructSegmt; + } + + public static MemoryAddress add2CharStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + + MemorySegment arg1 = arg1Addr.asSegment(structLayout.byteSize(), arg1Addr.scope()); + char charStruct_Elem1 = (char)((char)charHandle1.get(arg1) + (char)charHandle1.get(arg2) - 'A'); + char charStruct_Elem2 = (char)((char)charHandle2.get(arg1) + (char)charHandle2.get(arg2) - 'A'); + charHandle1.set(arg1, charStruct_Elem1); + charHandle2.set(arg1, charStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3CharStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle charHandle1 = structLayout.varHandle(char.class, PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(char.class, PathElement.groupElement("elem2")); + VarHandle charHandle3 = structLayout.varHandle(char.class, PathElement.groupElement("elem3")); + + MemorySegment charStructSegmt = MemorySegment.allocateNative(structLayout, scope); + char charStruct_Elem1 = (char)((char)charHandle1.get(arg1) + (char)charHandle1.get(arg2) - 'A'); + char charStruct_Elem2 = (char)((char)charHandle2.get(arg1) + (char)charHandle2.get(arg2) - 'A'); + char charStruct_Elem3 = (char)((char)charHandle3.get(arg1) + (char)charHandle3.get(arg2) - 'A'); + charHandle1.set(charStructSegmt, charStruct_Elem1); + charHandle2.set(charStructSegmt, charStruct_Elem2); + charHandle3.set(charStructSegmt, charStruct_Elem3); + return charStructSegmt; + } + + public static short addShortAndShortsFromStruct(short arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + short shortSum = (short)(arg1 + (short)shortHandle1.get(arg2) + (short)shortHandle2.get(arg2)); + return shortSum; + } + + public static short addShortAnd10ShortsFromStruct(short arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3"), C_SHORT.withName("elem4"), C_SHORT.withName("elem5"), + C_SHORT.withName("elem6"), C_SHORT.withName("elem7"), C_SHORT.withName("elem8"), + C_SHORT.withName("elem9"), C_SHORT.withName("elem10")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + VarHandle shortHandle3 = structLayout.varHandle(short.class, PathElement.groupElement("elem3")); + VarHandle shortHandle4 = structLayout.varHandle(short.class, PathElement.groupElement("elem4")); + VarHandle shortHandle5 = structLayout.varHandle(short.class, PathElement.groupElement("elem5")); + VarHandle shortHandle6 = structLayout.varHandle(short.class, PathElement.groupElement("elem6")); + VarHandle shortHandle7 = structLayout.varHandle(short.class, PathElement.groupElement("elem7")); + VarHandle shortHandle8 = structLayout.varHandle(short.class, PathElement.groupElement("elem8")); + VarHandle shortHandle9 = structLayout.varHandle(short.class, PathElement.groupElement("elem9")); + VarHandle shortHandle10 = structLayout.varHandle(short.class, PathElement.groupElement("elem10")); + + short shortSum = (short)(arg1 + (short)shortHandle1.get(arg2) + (short)shortHandle2.get(arg2) + + (short)shortHandle3.get(arg2) + (short)shortHandle4.get(arg2) + (short)shortHandle5.get(arg2) + + (short)shortHandle6.get(arg2) + (short)shortHandle7.get(arg2) + (short)shortHandle8.get(arg2) + + (short)shortHandle9.get(arg2) + (short)shortHandle10.get(arg2)); + return shortSum; + } + + public static short addShortFromPointerAndShortsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_SHORT.byteSize(), arg1Addr.scope()); + short arg1 = MemoryAccess.getShort(arg1Segmt); + short shortSum = (short)(arg1 + (short)shortHandle1.get(arg2) + (short)shortHandle2.get(arg2)); + return shortSum; + } + + public static MemoryAddress addShortFromPointerAndShortsFromStruct_returnShortPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_SHORT.byteSize(), arg1Addr.scope()); + short arg1 = MemoryAccess.getShort(arg1Segmt); + short shortSum = (short)(arg1 + (short)shortHandle1.get(arg2) + (short)shortHandle2.get(arg2)); + MemoryAccess.setShort(arg1Segmt, shortSum); + return arg1Addr; + } + + public static short addShortAndShortsFromStructPointer(short arg1, MemoryAddress arg2Addr) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MemorySegment arg2 = arg2Addr.asSegment(structLayout.byteSize(), arg2Addr.scope()); + short shortSum = (short)(arg1 + (short)shortHandle1.get(arg2) + (short)shortHandle2.get(arg2)); + return shortSum; + } + + public static short addShortAndShortsFromNestedStruct(short arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + + short nestedStructElem1 = MemoryAccess.getShortAtOffset(arg2, 0); + short nestedStructElem2 = MemoryAccess.getShortAtOffset(arg2, 2); + short structElem2 = MemoryAccess.getShortAtOffset(arg2, 4); + + short shortSum = (short)(arg1 + nestedStructElem1 + nestedStructElem2 + structElem2); + return shortSum; + } + + public static short addShortAndShortsFromNestedStruct_reverseOrder(short arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + + short structElem1 = MemoryAccess.getShortAtOffset(arg2, 0); + short nestedStructElem1 = MemoryAccess.getShortAtOffset(arg2, 2); + short nestedStructElem2 = MemoryAccess.getShortAtOffset(arg2, 4); + + short shortSum = (short)(arg1 + structElem1 + nestedStructElem1 + nestedStructElem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedShortArray(short arg1, MemorySegment arg2) { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, C_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(shortArray.withName("array_elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + + short nestedShortArrayElem1 = MemoryAccess.getShortAtOffset(arg2, 0); + short nestedShortArrayElem2 = MemoryAccess.getShortAtOffset(arg2, 2); + short structElem2 = MemoryAccess.getShortAtOffset(arg2, 4); + + short shortSum = (short)(arg1 + nestedShortArrayElem1 + nestedShortArrayElem2 + structElem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedShortArray_reverseOrder(short arg1, MemorySegment arg2) { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, C_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), + shortArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + + short structElem1 = MemoryAccess.getShortAtOffset(arg2, 0); + short nestedShortArrayElem1 = MemoryAccess.getShortAtOffset(arg2, 2); + short nestedShortArrayElem2 = MemoryAccess.getShortAtOffset(arg2, 4); + + short shortSum = (short)(arg1 + structElem1 + nestedShortArrayElem1 + nestedShortArrayElem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedStructArray(short arg1, MemorySegment arg2) { + GroupLayout shortStruct = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struc_array_elem1"), C_SHORT.withName("elem2")); + + short nestedStructArrayElem1_Elem1 = MemoryAccess.getShortAtOffset(arg2, 0); + short nestedStructArrayElem1_Elem2 = MemoryAccess.getShortAtOffset(arg2, 2); + short nestedStructArrayElem2_Elem1 = MemoryAccess.getShortAtOffset(arg2, 4); + short nestedStructArrayElem2_Elem2 = MemoryAccess.getShortAtOffset(arg2, 6); + short structElem2 = MemoryAccess.getShortAtOffset(arg2, 8); + + short shortSum = (short)(arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedStructArray_reverseOrder(short arg1, MemorySegment arg2) { + GroupLayout shortStruct = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), structArray.withName("struc_array_elem2")); + + short structElem1 = MemoryAccess.getShortAtOffset(arg2, 0); + short nestedStructArrayElem1_Elem1 = MemoryAccess.getShortAtOffset(arg2, 2); + short nestedStructArrayElem1_Elem2 = MemoryAccess.getShortAtOffset(arg2, 4); + short nestedStructArrayElem2_Elem1 = MemoryAccess.getShortAtOffset(arg2, 6); + short nestedStructArrayElem2_Elem2 = MemoryAccess.getShortAtOffset(arg2, 8); + + short shortSum = (short)(arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return shortSum; + } + + public static MemorySegment add2ShortStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MemorySegment shortStructSegmt = MemorySegment.allocateNative(structLayout, scope); + short shortStruct_Elem1 = (short)((short)shortHandle1.get(arg1) + (short)shortHandle1.get(arg2)); + short shortStruct_Elem2 = (short)((short)shortHandle2.get(arg1) + (short)shortHandle2.get(arg2)); + shortHandle1.set(shortStructSegmt, shortStruct_Elem1); + shortHandle2.set(shortStructSegmt, shortStruct_Elem2); + return shortStructSegmt; + } + + public static MemoryAddress add2ShortStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + MemorySegment arg1 = arg1Addr.asSegment(structLayout.byteSize(), arg1Addr.scope()); + short shortStruct_Elem1 = (short)((short)shortHandle1.get(arg1) + (short)shortHandle1.get(arg2)); + short shortStruct_Elem2 = (short)((short)shortHandle2.get(arg1) + (short)shortHandle2.get(arg2)); + shortHandle1.set(arg1, shortStruct_Elem1); + shortHandle2.set(arg1, shortStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3ShortStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"), + C_SHORT.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle shortHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + VarHandle shortHandle3 = structLayout.varHandle(short.class, PathElement.groupElement("elem3")); + + MemorySegment shortStructSegmt = MemorySegment.allocateNative(structLayout, scope); + short shortStruct_Elem1 = (short)((short)shortHandle1.get(arg1) + (short)shortHandle1.get(arg2)); + short shortStruct_Elem2 = (short)((short)shortHandle2.get(arg1) + (short)shortHandle2.get(arg2)); + short shortStruct_Elem3 = (short)((short)shortHandle3.get(arg1) + (short)shortHandle3.get(arg2)); + shortHandle1.set(shortStructSegmt, shortStruct_Elem1); + shortHandle2.set(shortStructSegmt, shortStruct_Elem2); + shortHandle3.set(shortStructSegmt, shortStruct_Elem3); + return shortStructSegmt; + } + + public static int addIntAndIntsFromStruct(int arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + int intSum = arg1 + (int)intHandle1.get(arg2) + (int)intHandle2.get(arg2); + return intSum; + } + + public static int addIntAnd5IntsFromStruct(int arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2"), + C_INT.withName("elem3"), C_INT.withName("elem4"), C_INT.withName("elem5")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + VarHandle intHandle4 = structLayout.varHandle(int.class, PathElement.groupElement("elem4")); + VarHandle intHandle5 = structLayout.varHandle(int.class, PathElement.groupElement("elem5")); + + int intSum = arg1 + (int)intHandle1.get(arg2) + (int)intHandle2.get(arg2) + + (int)intHandle3.get(arg2) + (int)intHandle4.get(arg2) + (int)intHandle5.get(arg2); + return intSum; + } + + public static int addIntFromPointerAndIntsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_INT.byteSize(), arg1Addr.scope()); + int arg1 = MemoryAccess.getInt(arg1Segmt); + int intSum = arg1 + (int)intHandle1.get(arg2) + (int)intHandle2.get(arg2); + return intSum; + } + + public static MemoryAddress addIntFromPointerAndIntsFromStruct_returnIntPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_INT.byteSize(), arg1Addr.scope()); + int arg1 = MemoryAccess.getInt(arg1Segmt); + int intSum = arg1 + (int)intHandle1.get(arg2) + (int)intHandle2.get(arg2); + MemoryAccess.setInt(arg1Segmt, intSum); + return arg1Addr; + } + + public static int addIntAndIntsFromStructPointer(int arg1, MemoryAddress arg2Addr) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MemorySegment arg2 = arg2Addr.asSegment(structLayout.byteSize(), arg2Addr.scope()); + int intSum = arg1 + (int)intHandle1.get(arg2) + (int)intHandle2.get(arg2); + return intSum; + } + + public static int addIntAndIntsFromNestedStruct(int arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_INT.withName("elem2")); + + int nestedStructElem1 = MemoryAccess.getIntAtOffset(arg2, 0); + int nestedStructElem2 = MemoryAccess.getIntAtOffset(arg2, 4); + int structElem2 = MemoryAccess.getIntAtOffset(arg2, 8); + + int intSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return intSum; + } + + public static int addIntAndIntsFromNestedStruct_reverseOrder(int arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + int structElem1 = MemoryAccess.getIntAtOffset(arg2, 0); + int nestedStructElem1 = MemoryAccess.getIntAtOffset(arg2, 4); + int nestedStructElem2 = MemoryAccess.getIntAtOffset(arg2, 8); + + int intSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedIntArray(int arg1, MemorySegment arg2) { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, C_INT); + GroupLayout structLayout = MemoryLayout.structLayout(intArray.withName("array_elem1"), C_INT.withName("elem2")); + + int nestedIntArrayElem1 = MemoryAccess.getIntAtOffset(arg2, 0); + int nestedIntArrayElem2 = MemoryAccess.getIntAtOffset(arg2, 4); + int structElem2 = MemoryAccess.getIntAtOffset(arg2, 8); + + int intSum = arg1 + nestedIntArrayElem1 + nestedIntArrayElem2 + structElem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedIntArray_reverseOrder(int arg1, MemorySegment arg2) { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, C_INT); + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), intArray.withName("array_elem2")); + + int structElem1 = MemoryAccess.getIntAtOffset(arg2, 0); + int nestedIntArrayElem1 = MemoryAccess.getIntAtOffset(arg2, 4); + int nestedIntArrayElem2 = MemoryAccess.getIntAtOffset(arg2, 8); + + int intSum = arg1 + structElem1 + nestedIntArrayElem1 + nestedIntArrayElem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedStructArray(int arg1, MemorySegment arg2) { + GroupLayout intStruct = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), C_INT.withName("elem2")); + + int nestedStructArrayElem1_Elem1 = MemoryAccess.getIntAtOffset(arg2, 0); + int nestedStructArrayElem1_Elem2 = MemoryAccess.getIntAtOffset(arg2, 4); + int nestedStructArrayElem2_Elem1 = MemoryAccess.getIntAtOffset(arg2, 8); + int nestedStructArrayElem2_Elem2 = MemoryAccess.getIntAtOffset(arg2, 12); + int structElem2 = MemoryAccess.getIntAtOffset(arg2, 16); + + int intSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedStructArray_reverseOrder(int arg1, MemorySegment arg2) { + GroupLayout intStruct = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), structArray.withName("struct_array_elem2")); + + int structElem1 = MemoryAccess.getIntAtOffset(arg2, 0); + int nestedStructArrayElem1_Elem1 = MemoryAccess.getIntAtOffset(arg2, 4); + int nestedStructArrayElem1_Elem2 = MemoryAccess.getIntAtOffset(arg2, 8); + int nestedStructArrayElem2_Elem1 = MemoryAccess.getIntAtOffset(arg2, 12); + int nestedStructArrayElem2_Elem2 = MemoryAccess.getIntAtOffset(arg2, 16); + + int intSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return intSum; + } + + public static MemorySegment add2IntStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MemorySegment intStructSegmt = MemorySegment.allocateNative(structLayout, scope); + int intStruct_Elem1 = (int)intHandle1.get(arg1) + (int)intHandle1.get(arg2); + int intStruct_Elem2 = (int)intHandle2.get(arg1) + (int)intHandle2.get(arg2); + intHandle1.set(intStructSegmt, intStruct_Elem1); + intHandle2.set(intStructSegmt, intStruct_Elem2); + return intStructSegmt; + } + + public static MemoryAddress add2IntStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + MemorySegment arg1 = arg1Addr.asSegment(structLayout.byteSize(), arg1Addr.scope()); + int intSum_Elem1 = (int)intHandle1.get(arg1) + (int)intHandle1.get(arg2); + int intSum_Elem2 = (int)intHandle2.get(arg1) + (int)intHandle2.get(arg2); + intHandle1.set(arg1, intSum_Elem1); + intHandle2.set(arg1, intSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3IntStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), C_INT.withName("elem2"), C_INT.withName("elem3")); + VarHandle intHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + + MemorySegment intStructSegmt = MemorySegment.allocateNative(structLayout, scope); + int intStruct_Elem1 = (int)intHandle1.get(arg1) + (int)intHandle1.get(arg2); + int intStruct_Elem2 = (int)intHandle2.get(arg1) + (int)intHandle2.get(arg2); + int intStruct_Elem3 = (int)intHandle3.get(arg1) + (int)intHandle3.get(arg2); + intHandle1.set(intStructSegmt, intStruct_Elem1); + intHandle2.set(intStructSegmt, intStruct_Elem2); + intHandle3.set(intStructSegmt, intStruct_Elem3); + return intStructSegmt; + } + + public static long addLongAndLongsFromStruct(long arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + long longSum = arg1 + (long)longHandle1.get(arg2) + (long)longHandle2.get(arg2); + return longSum; + } + + public static long addLongFromPointerAndLongsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(longLayout.byteSize(), arg1Addr.scope()); + long arg1 = MemoryAccess.getLong(arg1Segmt); + long longSum = arg1 + (long)longHandle1.get(arg2) + (long)longHandle2.get(arg2); + return longSum; + } + + public static MemoryAddress addLongFromPointerAndLongsFromStruct_returnLongPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(longLayout.byteSize(), arg1Addr.scope()); + long arg1 = MemoryAccess.getLong(arg1Segmt); + long longSum = arg1 + (long)longHandle1.get(arg2) + (long)longHandle2.get(arg2); + MemoryAccess.setLong(arg1Segmt, longSum); + return arg1Addr; + } + + public static long addLongAndLongsFromStructPointer(long arg1, MemoryAddress arg2Addr) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MemorySegment arg2 = arg2Addr.asSegment(structLayout.byteSize(), arg2Addr.scope()); + long longSum = arg1 + (long)longHandle1.get(arg2) + (long)longHandle2.get(arg2); + return longSum; + } + + public static long addLongAndLongsFromNestedStruct(long arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + long nestedStructElem1 = MemoryAccess.getLongAtOffset(arg2, 0); + long nestedStructElem2 = MemoryAccess.getLongAtOffset(arg2, 8); + long structElem2 = MemoryAccess.getLongAtOffset(arg2, 16); + + long longSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return longSum; + } + + public static long addLongAndLongsFromNestedStruct_reverseOrder(long arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + long structElem1 = MemoryAccess.getLongAtOffset(arg2, 0); + long nestedStructElem1 = MemoryAccess.getLongAtOffset(arg2, 8); + long nestedStructElem2 = MemoryAccess.getLongAtOffset(arg2, 16); + + long longSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedLongArray(long arg1, MemorySegment arg2) { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, longLayout); + GroupLayout structLayout = MemoryLayout.structLayout(longArray.withName("array_elem1"), longLayout.withName("elem2")); + + long nestedLongrrayElem1 = MemoryAccess.getLongAtOffset(arg2, 0); + long nestedLongrrayElem2 = MemoryAccess.getLongAtOffset(arg2, 8); + long structElem2 = MemoryAccess.getLongAtOffset(arg2, 16); + + long longSum = arg1 + nestedLongrrayElem1 + nestedLongrrayElem2 + structElem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedLongArray_reverseOrder(long arg1, MemorySegment arg2) { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, longLayout); + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longArray.withName("array_elem2")); + + long structElem1 = MemoryAccess.getLongAtOffset(arg2, 0); + long nestedLongrrayElem1 = MemoryAccess.getLongAtOffset(arg2, 8); + long nestedLongrrayElem2 = MemoryAccess.getLongAtOffset(arg2, 16); + + long longSum = arg1 + structElem1 + nestedLongrrayElem1 + nestedLongrrayElem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedStructArray(long arg1, MemorySegment arg2) { + GroupLayout longStruct = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), longLayout.withName("elem2")); + + long nestedStructArrayElem1_Elem1 = MemoryAccess.getLongAtOffset(arg2, 0); + long nestedStructArrayElem1_Elem2 = MemoryAccess.getLongAtOffset(arg2, 8); + long nestedStructArrayElem2_Elem1 = MemoryAccess.getLongAtOffset(arg2, 16); + long nestedStructArrayElem2_Elem2 = MemoryAccess.getLongAtOffset(arg2, 24); + long structElem2 = MemoryAccess.getLongAtOffset(arg2, 32); + + long longSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedStructArray_reverseOrder(long arg1, MemorySegment arg2) { + GroupLayout longStruct = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), structArray.withName("struct_array_elem2")); + + long structElem1 = MemoryAccess.getLongAtOffset(arg2, 0); + long nestedStructArrayElem1_Elem1 = MemoryAccess.getLongAtOffset(arg2, 8); + long nestedStructArrayElem1_Elem2 = MemoryAccess.getLongAtOffset(arg2, 16); + long nestedStructArrayElem2_Elem1 = MemoryAccess.getLongAtOffset(arg2, 24); + long nestedStructArrayElem2_Elem2 = MemoryAccess.getLongAtOffset(arg2, 32); + + long longSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return longSum; + } + + public static MemorySegment add2LongStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MemorySegment longStructSegmt = MemorySegment.allocateNative(structLayout, scope); + long longStruct_Elem1 = (long)longHandle1.get(arg1) + (long)longHandle1.get(arg2); + long longStruct_Elem2 = (long)longHandle2.get(arg1) + (long)longHandle2.get(arg2); + longHandle1.set(longStructSegmt, longStruct_Elem1); + longHandle2.set(longStructSegmt, longStruct_Elem2); + return longStructSegmt; + } + + public static MemoryAddress add2LongStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + MemorySegment arg1 = arg1Addr.asSegment(structLayout.byteSize(), arg1Addr.scope()); + long longSum_Elem1 = (long)longHandle1.get(arg1) + (long)longHandle1.get(arg2); + long longSum_Elem2 = (long)longHandle2.get(arg1) + (long)longHandle2.get(arg2); + longHandle1.set(arg1, longSum_Elem1); + longHandle2.set(arg1, longSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3LongStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), longLayout.withName("elem2"), longLayout.withName("elem3")); + VarHandle longHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + VarHandle longHandle3 = structLayout.varHandle(long.class, PathElement.groupElement("elem3")); + + MemorySegment longStructSegmt = MemorySegment.allocateNative(structLayout, scope); + long longStruct_Elem1 = (long)longHandle1.get(arg1) + (long)longHandle1.get(arg2); + long longStruct_Elem2 = (long)longHandle2.get(arg1) + (long)longHandle2.get(arg2); + long longStruct_Elem3 = (long)longHandle3.get(arg1) + (long)longHandle3.get(arg2); + longHandle1.set(longStructSegmt, longStruct_Elem1); + longHandle2.set(longStructSegmt, longStruct_Elem2); + longHandle3.set(longStructSegmt, longStruct_Elem3); + return longStructSegmt; + } + + public static float addFloatAndFloatsFromStruct(float arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + float floatSum = arg1 + (float)floatHandle1.get(arg2) + (float)floatHandle2.get(arg2); + return floatSum; + } + + public static float addFloatAnd5FloatsFromStruct(float arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2"), + C_FLOAT.withName("elem3"), C_FLOAT.withName("elem4"), C_FLOAT.withName("elem5")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + VarHandle floatHandle4 = structLayout.varHandle(float.class, PathElement.groupElement("elem4")); + VarHandle floatHandle5 = structLayout.varHandle(float.class, PathElement.groupElement("elem5")); + + float floatSum = arg1 + (float)floatHandle1.get(arg2) + (float)floatHandle2.get(arg2) + + (float)floatHandle3.get(arg2) + (float)floatHandle4.get(arg2) + (float)floatHandle5.get(arg2); + return floatSum; + } + + public static float addFloatFromPointerAndFloatsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_FLOAT.byteSize(), arg1Addr.scope()); + float arg1 = MemoryAccess.getFloat(arg1Segmt); + float floatSum = arg1 + (float)floatHandle1.get(arg2) + (float)floatHandle2.get(arg2); + return floatSum; + } + + public static MemoryAddress addFloatFromPointerAndFloatsFromStruct_returnFloatPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_FLOAT.byteSize(), arg1Addr.scope()); + float arg1 = MemoryAccess.getFloat(arg1Segmt); + float floatSum = arg1 + (float)floatHandle1.get(arg2) + (float)floatHandle2.get(arg2); + MemoryAccess.setFloat(arg1Segmt, floatSum); + return arg1Addr; + } + + public static float addFloatAndFloatsFromStructPointer(float arg1, MemoryAddress arg2Addr) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MemorySegment arg2 = arg2Addr.asSegment(structLayout.byteSize(), arg2Addr.scope()); + float floatSum = arg1 + (float)floatHandle1.get(arg2) + (float)floatHandle2.get(arg2); + return floatSum; + } + + public static float addFloatAndFloatsFromNestedStruct(float arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_FLOAT.withName("elem2")); + + float nestedStructElem1 = MemoryAccess.getFloatAtOffset(arg2, 0); + float nestedStructElem2 = MemoryAccess.getFloatAtOffset(arg2, 4); + float structElem2 = MemoryAccess.getFloatAtOffset(arg2, 8); + + float floatSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromNestedStruct_reverseOrder(float arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + float structElem1 = MemoryAccess.getFloatAtOffset(arg2, 0); + float nestedStructElem1 = MemoryAccess.getFloatAtOffset(arg2, 4); + float nestedStructElem2 = MemoryAccess.getFloatAtOffset(arg2, 8); + + float floatSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedFloatArray(float arg1, MemorySegment arg2) { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, C_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(floatArray.withName("array_elem1"), C_FLOAT.withName("elem2")); + + float nestedFloatArrayElem1 = MemoryAccess.getFloatAtOffset(arg2, 0); + float nestedFloatArrayElem2 = MemoryAccess.getFloatAtOffset(arg2, 4); + float structElem2 = MemoryAccess.getFloatAtOffset(arg2, 8); + + float floatSum = arg1 + nestedFloatArrayElem1 + nestedFloatArrayElem2 + structElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder(float arg1, MemorySegment arg2) { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, C_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), floatArray.withName("array_elem2")); + + float structElem1 = MemoryAccess.getFloatAtOffset(arg2, 0); + float nestedFloatArrayElem1 = MemoryAccess.getFloatAtOffset(arg2, 4); + float nestedFloatArrayElem2 = MemoryAccess.getFloatAtOffset(arg2, 8); + + float floatSum = arg1 + structElem1 + nestedFloatArrayElem1 + nestedFloatArrayElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedStructArray(float arg1, MemorySegment arg2) { + GroupLayout floatStruct = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), C_FLOAT.withName("elem2")); + + float nestedStructArrayElem1_Elem1 = MemoryAccess.getFloatAtOffset(arg2, 0); + float nestedStructArrayElem1_Elem2 = MemoryAccess.getFloatAtOffset(arg2, 4); + float nestedStructArrayElem2_Elem1 = MemoryAccess.getFloatAtOffset(arg2, 8); + float nestedStructArrayElem2_Elem2 = MemoryAccess.getFloatAtOffset(arg2, 12); + float structElem2 = MemoryAccess.getFloatAtOffset(arg2, 16); + + float floatSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder(float arg1, MemorySegment arg2) { + GroupLayout floatStruct = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), structArray.withName("struct_array_elem2")); + + float structElem1 = MemoryAccess.getFloatAtOffset(arg2, 0); + float nestedStructArrayElem1_Elem1 = MemoryAccess.getFloatAtOffset(arg2, 4); + float nestedStructArrayElem1_Elem2 = MemoryAccess.getFloatAtOffset(arg2, 8); + float nestedStructArrayElem2_Elem1 = MemoryAccess.getFloatAtOffset(arg2, 12); + float nestedStructArrayElem2_Elem2 = MemoryAccess.getFloatAtOffset(arg2, 16); + + float floatSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return floatSum; + } + + public static MemorySegment add2FloatStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MemorySegment floatStructSegmt = MemorySegment.allocateNative(structLayout, scope); + float floatStruct_Elem1 = (float)floatHandle1.get(arg1) + (float)floatHandle1.get(arg2); + float floatStruct_Elem2 = (float)floatHandle2.get(arg1) + (float)floatHandle2.get(arg2); + floatHandle1.set(floatStructSegmt, floatStruct_Elem1); + floatHandle2.set(floatStructSegmt, floatStruct_Elem2); + return floatStructSegmt; + } + + public static MemoryAddress add2FloatStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + MemorySegment arg1 = arg1Addr.asSegment(structLayout.byteSize(), arg1Addr.scope()); + float floatSum_Elem1 = (float)floatHandle1.get(arg1) + (float)floatHandle1.get(arg2); + float floatSum_Elem2 = (float)floatHandle2.get(arg1) + (float)floatHandle2.get(arg2); + floatHandle1.set(arg1, floatSum_Elem1); + floatHandle2.set(arg1, floatSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3FloatStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle floatHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + MemorySegment floatStructSegmt = MemorySegment.allocateNative(structLayout, scope); + float floatStruct_Elem1 = (float)floatHandle1.get(arg1) + (float)floatHandle1.get(arg2); + float floatStruct_Elem2 = (float)floatHandle2.get(arg1) + (float)floatHandle2.get(arg2); + float floatStruct_Elem3 = (float)floatHandle3.get(arg1) + (float)floatHandle3.get(arg2); + floatHandle1.set(floatStructSegmt, floatStruct_Elem1); + floatHandle2.set(floatStructSegmt, floatStruct_Elem2); + floatHandle3.set(floatStructSegmt, floatStruct_Elem3); + return floatStructSegmt; + } + + public static double addDoubleAndDoublesFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + double doubleSum = arg1 + (double)doubleHandle1.get(arg2) + (double)doubleHandle2.get(arg2); + return doubleSum; + } + + public static double addDoubleFromPointerAndDoublesFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_DOUBLE.byteSize(), arg1Addr.scope()); + double arg1 = MemoryAccess.getDouble(arg1Segmt); + double doubleSum = arg1 + (double)doubleHandle1.get(arg2) + (double)doubleHandle2.get(arg2); + return doubleSum; + } + + public static MemoryAddress addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MemorySegment arg1Segmt = arg1Addr.asSegment(C_DOUBLE.byteSize(), arg1Addr.scope()); + double arg1 = MemoryAccess.getDouble(arg1Segmt); + double doubleSum = arg1 + (double)doubleHandle1.get(arg2) + (double)doubleHandle2.get(arg2); + MemoryAccess.setDouble(arg1Segmt, doubleSum); + return arg1Addr; + } + + public static double addDoubleAndDoublesFromStructPointer(double arg1, MemoryAddress arg2Addr) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MemorySegment arg2 = arg2Addr.asSegment(structLayout.byteSize(), arg2Addr.scope()); + double doubleSum = arg1 + (double)doubleHandle1.get(arg2) + (double)doubleHandle2.get(arg2); + return doubleSum; + } + + public static double addDoubleAndDoublesFromNestedStruct(double arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), C_DOUBLE.withName("elem2")); + + double nestedStructElem1 = MemoryAccess.getDoubleAtOffset(arg2, 0); + double nestedStructElem2 = MemoryAccess.getDoubleAtOffset(arg2, 8); + double structElem2 = MemoryAccess.getDoubleAtOffset(arg2, 16); + + double doubleSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromNestedStruct_reverseOrder(double arg1, MemorySegment arg2) { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + double structElem1 = MemoryAccess.getDoubleAtOffset(arg2, 0); + double nestedStructElem1 = MemoryAccess.getDoubleAtOffset(arg2, 8); + double nestedStructElem2 = MemoryAccess.getDoubleAtOffset(arg2, 16); + + double doubleSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedDoubleArray(double arg1, MemorySegment arg2) { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, C_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(doubleArray.withName("array_elem1"), C_DOUBLE.withName("elem2")); + + double nestedDoubleArrayElem1 = MemoryAccess.getDoubleAtOffset(arg2, 0); + double nestedDoubleArrayElem2 = MemoryAccess.getDoubleAtOffset(arg2, 8); + double structElem2 = MemoryAccess.getDoubleAtOffset(arg2, 16); + + double doubleSum = arg1 + nestedDoubleArrayElem1 + nestedDoubleArrayElem2 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder(double arg1, MemorySegment arg2) { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, C_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), doubleArray.withName("array_elem2")); + + double structElem1 = MemoryAccess.getDoubleAtOffset(arg2, 0); + double nestedDoubleArrayElem1 = MemoryAccess.getDoubleAtOffset(arg2, 8); + double nestedDoubleArrayElem2 = MemoryAccess.getDoubleAtOffset(arg2, 16); + + double doubleSum = arg1 + structElem1 + nestedDoubleArrayElem1 + nestedDoubleArrayElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedStructArray(double arg1, MemorySegment arg2) { + GroupLayout doubleStruct = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), C_DOUBLE.withName("elem2")); + + double nestedStructArrayElem1_Elem1 = MemoryAccess.getDoubleAtOffset(arg2, 0); + double nestedStructArrayElem1_Elem2 = MemoryAccess.getDoubleAtOffset(arg2, 8); + double nestedStructArrayElem2_Elem1 = MemoryAccess.getDoubleAtOffset(arg2, 16); + double nestedStructArrayElem2_Elem2 = MemoryAccess.getDoubleAtOffset(arg2, 24); + double structElem2 = MemoryAccess.getDoubleAtOffset(arg2, 32); + + double doubleSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder(double arg1, MemorySegment arg2) { + GroupLayout doubleStruct = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), structArray.withName("struct_array_elem2")); + + double structElem1 = MemoryAccess.getDoubleAtOffset(arg2, 0); + double nestedStructArrayElem1_Elem1 = MemoryAccess.getDoubleAtOffset(arg2, 8); + double nestedStructArrayElem1_Elem2 = MemoryAccess.getDoubleAtOffset(arg2, 16); + double nestedStructArrayElem2_Elem1 = MemoryAccess.getDoubleAtOffset(arg2, 24); + double nestedStructArrayElem2_Elem2 = MemoryAccess.getDoubleAtOffset(arg2, 32); + + double doubleSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return doubleSum; + } + + public static MemorySegment add2DoubleStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MemorySegment doubleStructSegmt = MemorySegment.allocateNative(structLayout, scope); + double doubleStruct_Elem1 = (double)doubleHandle1.get(arg1) + (double)doubleHandle1.get(arg2); + double doubleStruct_Elem2 = (double)doubleHandle2.get(arg1) + (double)doubleHandle2.get(arg2); + doubleHandle1.set(doubleStructSegmt, doubleStruct_Elem1); + doubleHandle2.set(doubleStructSegmt, doubleStruct_Elem2); + return doubleStructSegmt; + } + + public static MemoryAddress add2DoubleStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + MemorySegment arg1 = arg1Addr.asSegment(structLayout.byteSize(), arg1Addr.scope()); + double doubleSum_Elem1 = (double)doubleHandle1.get(arg1) + (double)doubleHandle1.get(arg2); + double doubleSum_Elem2 = (double)doubleHandle2.get(arg1) + (double)doubleHandle2.get(arg2); + doubleHandle1.set(arg1, doubleSum_Elem1); + doubleHandle2.set(arg1, doubleSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3DoubleStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2"), C_DOUBLE.withName("elem3")); + VarHandle doubleHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle doubleHandle3 = structLayout.varHandle(double.class, PathElement.groupElement("elem3")); + + MemorySegment doubleStructSegmt = MemorySegment.allocateNative(structLayout, scope); + double doubleStruct_Elem1 = (double)doubleHandle1.get(arg1) + (double)doubleHandle1.get(arg2); + double doubleStruct_Elem2 = (double)doubleHandle2.get(arg1) + (double)doubleHandle2.get(arg2); + double doubleStruct_Elem3 = (double)doubleHandle3.get(arg1) + (double)doubleHandle3.get(arg2); + doubleHandle1.set(doubleStructSegmt, doubleStruct_Elem1); + doubleHandle2.set(doubleStructSegmt, doubleStruct_Elem2); + doubleHandle3.set(doubleStructSegmt, doubleStruct_Elem3); + return doubleStructSegmt; + } + + public static int addIntAndIntShortFromStruct(int arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + + int intSum = arg1 + (int)elemHandle1.get(arg2) + (short)elemHandle2.get(arg2); + return intSum; + } + + public static int addIntAndShortIntFromStruct(int arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), + MemoryLayout.paddingLayout(16), C_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + int intSum = arg1 + (short)elemHandle1.get(arg2) + (int)elemHandle2.get(arg2); + return intSum; + } + + public static long addIntAndIntLongFromStruct(int arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), longLayout.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + long longSum = arg1 + (int)elemHandle1.get(arg2) + (long)elemHandle2.get(arg2); + return longSum; + } + + public static long addIntAndLongIntFromStruct(int arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), + C_INT.withName("elem2"), MemoryLayout.paddingLayout(32)); + VarHandle elemHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + long longSum = arg1 + (long)elemHandle1.get(arg2) + (int)elemHandle2.get(arg2); + return longSum; + } + + public static double addDoubleAndIntDoubleFromStruct(double arg1, MemorySegment arg2) { + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(C_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + double doubleSum = arg1 + (int)elemHandle1.get(arg2) + (double)elemHandle2.get(arg2); + return doubleSum; + } + + public static double addDoubleAndDoubleIntFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + + double doubleSum = arg1 + (double)elemHandle1.get(arg2) + (int)elemHandle2.get(arg2); + return doubleSum; + } + + public static double addDoubleAndFloatDoubleFromStruct(double arg1, MemorySegment arg2) { + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + double doubleSum = arg1 + (float)elemHandle1.get(arg2) + (double)elemHandle2.get(arg2); + return doubleSum; + } + + public static double addDoubleAndDoubleFloatFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), C_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + + double doubleSum = arg1 + (double)elemHandle1.get(arg2) + (float)elemHandle2.get(arg2); + return doubleSum; + } + + public static double addDoubleAnd2FloatsDoubleFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_FLOAT.withName("elem2"), C_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(double.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (float)elemHandle1.get(arg2) + (float)elemHandle2.get(arg2) + (double)elemHandle3.get(arg2); + return doubleSum; + } + + public static double addDoubleAndDouble2FloatsFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (double)elemHandle1.get(arg2) + (float)elemHandle2.get(arg2) + (float)elemHandle3.get(arg2); + return doubleSum; + } + + public static float addFloatAndInt2FloatsFromStruct(float arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + float floatSum = arg1 + (int)elemHandle1.get(arg2) + (float)elemHandle2.get(arg2) + (float)elemHandle3.get(arg2); + return floatSum; + } + + public static float addFloatAndFloatIntFloatFromStruct(float arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_INT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + float structElem2 = Integer.valueOf((int)elemHandle2.get(arg2)).floatValue(); + float floatSum = arg1 + (float)elemHandle1.get(arg2) + structElem2 + (float)elemHandle3.get(arg2); + return floatSum; + } + + public static double addDoubleAndIntFloatDoubleFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_FLOAT.withName("elem2"), C_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(double.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (int)elemHandle1.get(arg2) + (float)elemHandle2.get(arg2) + (double)elemHandle3.get(arg2); + return doubleSum; + } + + public static double addDoubleAndFloatIntDoubleFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_INT.withName("elem2"), C_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(int.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(double.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (float)elemHandle1.get(arg2) + (int)elemHandle2.get(arg2) + (double)elemHandle3.get(arg2); + return doubleSum; + } + + public static double addDoubleAndLongDoubleFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), C_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + + double doubleSum = arg1 + (long)elemHandle1.get(arg2) + (double)elemHandle2.get(arg2); + return doubleSum; + } + + public static float addFloatAndInt3FloatsFromStruct(float arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3"), C_FLOAT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(float.class, PathElement.groupElement("elem4")); + + float floatSum = arg1 + (int)elemHandle1.get(arg2) + (float)elemHandle2.get(arg2) + + (float)elemHandle3.get(arg2) + (float)elemHandle4.get(arg2); + return floatSum; + } + + public static long addLongAndLong2FloatsFromStruct(long arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(longLayout.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(long.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + long structElem1 = (long)elemHandle1.get(arg2); + long structElem2 = Float.valueOf((float)elemHandle2.get(arg2)).longValue(); + long structElem3 = Float.valueOf((float)elemHandle3.get(arg2)).longValue(); + long longSum = arg1 + structElem1 + structElem2 + structElem3; + return longSum; + } + + public static float addFloatAnd3FloatsIntFromStruct(float arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_FLOAT.withName("elem2"), C_FLOAT.withName("elem3"), C_INT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(int.class, PathElement.groupElement("elem4")); + + float floatSum = arg1 + (float)elemHandle1.get(arg2) + (float)elemHandle2.get(arg2) + + (float)elemHandle3.get(arg2) + (int)elemHandle4.get(arg2); + return floatSum; + } + + public static long addLongAndFloatLongFromStruct(long arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), longLayout.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + long structElem1 = Float.valueOf((float)elemHandle1.get(arg2)).longValue(); + long longSum = arg1 + structElem1 + (long)elemHandle2.get(arg2); + return longSum; + } + + public static double addDoubleAndDoubleFloatIntFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), + C_FLOAT.withName("elem2"), C_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (double)elemHandle1.get(arg2) + (float)elemHandle2.get(arg2) + (int)elemHandle3.get(arg2); + return doubleSum; + } + + public static double addDoubleAndDoubleLongFromStruct(double arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_DOUBLE.withName("elem1"), longLayout.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(double.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(long.class, PathElement.groupElement("elem2")); + + double doubleSum = arg1 + (double)elemHandle1.get(arg2) + (long)elemHandle2.get(arg2); + return doubleSum; + } + + public static long addLongAnd2FloatsLongFromStruct(long arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_FLOAT.withName("elem2"), longLayout.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(long.class, PathElement.groupElement("elem3")); + + long structElem1 = Float.valueOf((float)elemHandle1.get(arg2)).longValue(); + long structElem2 = Float.valueOf((float)elemHandle2.get(arg2)).longValue(); + long structElem3 = (long)elemHandle3.get(arg2); + long longSum = arg1 + structElem1 + structElem2 + structElem3; + return longSum; + } + + public static short addShortAnd3ShortsCharFromStruct(short arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_SHORT.withName("elem1"), + C_SHORT.withName("elem2"), C_SHORT.withName("elem3"), C_SHORT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(short.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(short.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(short.class, PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(char.class, PathElement.groupElement("elem4")); + + short shortSum = (short)(arg1 + (short)elemHandle1.get(arg2) + (short)elemHandle2.get(arg2) + + (short)elemHandle3.get(arg2) + (char)elemHandle4.get(arg2)); + return shortSum; + } + + public static float addFloatAndIntFloatIntFloatFromStruct(float arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(C_INT.withName("elem1"), + C_FLOAT.withName("elem2"), C_INT.withName("elem3"), C_FLOAT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(float.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(float.class, PathElement.groupElement("elem4")); + + float floatSum = arg1 + (int)elemHandle1.get(arg2) + (float)elemHandle2.get(arg2) + + (int)elemHandle3.get(arg2) + (float)elemHandle4.get(arg2); + return floatSum; + } + + public static double addDoubleAndIntDoubleFloatFromStruct(double arg1, MemorySegment arg2) { + /* The size of [int, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2"), C_FLOAT.withName("elem3")) + : MemoryLayout.structLayout(C_INT.withName("elem1"), MemoryLayout.paddingLayout(32), + C_DOUBLE.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (int)elemHandle1.get(arg2) + (double)elemHandle2.get(arg2) + (float)elemHandle3.get(arg2); + return doubleSum; + } + + public static double addDoubleAndFloatDoubleIntFromStruct(double arg1, MemorySegment arg2) { + /* The size of [float, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_DOUBLE.withName("elem2"), C_INT.withName("elem3")) + : MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), C_DOUBLE.withName("elem2"), + C_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (float)elemHandle1.get(arg2) + (double)elemHandle2.get(arg2) + (int)elemHandle3.get(arg2); + return doubleSum; + } + + public static double addDoubleAndIntDoubleIntFromStruct(double arg1, MemorySegment arg2) { + /* The size of [int, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2"), C_INT.withName("elem3")) + : MemoryLayout.structLayout(C_INT.withName("elem1"), MemoryLayout.paddingLayout(32), + C_DOUBLE.withName("elem2"), C_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(int.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (int)elemHandle1.get(arg2) + (double)elemHandle2.get(arg2) + (int)elemHandle3.get(arg2); + return doubleSum; + } + + public static double addDoubleAndFloatDoubleFloatFromStruct(double arg1, MemorySegment arg2) { + /* The size of [float, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_FLOAT.withName("elem1"), + C_DOUBLE.withName("elem2"), C_FLOAT.withName("elem3")) + : MemoryLayout.structLayout(C_FLOAT.withName("elem1"), MemoryLayout.paddingLayout(32), + C_DOUBLE.withName("elem2"), C_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(float.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(float.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (float)elemHandle1.get(arg2) + (double)elemHandle2.get(arg2) + (float)elemHandle3.get(arg2); + return doubleSum; + } + + public static double addDoubleAndIntDoubleLongFromStruct(double arg1, MemorySegment arg2) { + /* The size of [int, double, long] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 24 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(C_INT.withName("elem1"), + C_DOUBLE.withName("elem2"), longLayout.withName("elem3")) + : MemoryLayout.structLayout(C_INT.withName("elem1"), MemoryLayout.paddingLayout(32), + C_DOUBLE.withName("elem2"), longLayout.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(int.class, PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(double.class, PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(long.class, PathElement.groupElement("elem3")); + + double doubleSum = arg1 + (int)elemHandle1.get(arg2) + (double)elemHandle2.get(arg2) + (long)elemHandle3.get(arg2); + return doubleSum; + } + + public static MemorySegment return254BytesFromStruct() { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(254, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + MemorySegment byteArrStruSegment = MemorySegment.allocateNative(structLayout, scope); + + for (int i = 0; i < 254; i++) { + MemoryAccess.setByteAtOffset(byteArrStruSegment, i, (byte)i); + } + return byteArrStruSegment; + } + + public static MemorySegment return4KBytesFromStruct() { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(4096, C_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + MemorySegment byteArrStruSegment = MemorySegment.allocateNative(structLayout, scope); + + for (int i = 0; i < 4096; i++) { + MemoryAccess.setByteAtOffset(byteArrStruSegment, i, (byte)i); + } + return byteArrStruSegment; + } +} diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/valist/ApiTests.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/valist/ApiTests.java new file mode 100644 index 00000000000..8da17fa7253 --- /dev/null +++ b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/valist/ApiTests.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2022, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep389.valist; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.VarHandle; + +import jdk.incubator.foreign.CLinker; +import static jdk.incubator.foreign.CLinker.*; +import static jdk.incubator.foreign.CLinker.VaList.Builder; +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; + +/** + * Test cases for JEP 389: Foreign Linker API (Incubator) for the vararg list in VaList API specific cases. + */ +@Test(groups = { "level.sanity" }) +public class ApiTests { +} diff --git a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/valist/VaListTests.java b/test/functional/Java17andUp/src_170/org/openj9/test/jep389/valist/VaListTests.java deleted file mode 100644 index de6d2d3ec53..00000000000 --- a/test/functional/Java17andUp/src_170/org/openj9/test/jep389/valist/VaListTests.java +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2021, 2022 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ -package org.openj9.test.jep389.valist; - -import org.testng.annotations.Test; -import org.testng.Assert; -import org.testng.AssertJUnit; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; - -import jdk.incubator.foreign.Addressable; -import jdk.incubator.foreign.CLinker; -import static jdk.incubator.foreign.CLinker.*; -import static jdk.incubator.foreign.CLinker.VaList.Builder; -import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.MemoryAccess; -import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemorySegment; -import jdk.incubator.foreign.ResourceScope; -import jdk.incubator.foreign.SegmentAllocator; -import jdk.incubator.foreign.SymbolLookup; -import jdk.incubator.foreign.ValueLayout; - -/** - * Test cases for JEP 389: Foreign Linker API (Incubator) DownCall for the vararg list. - */ -@Test(groups = { "level.sanity" }) -public class VaListTests { - private static String osName = System.getProperty("os.name").toLowerCase(); - private static boolean isAixOS = osName.contains("aix"); - private static boolean isWinOS = osName.contains("win"); - /* long long is 64 bits on AIX/ppc64, which is the same as Windows */ - private static ValueLayout longLayout = (isWinOS || isAixOS) ? C_LONG_LONG : C_LONG; - private static CLinker clinker = CLinker.getInstance(); - - static { - System.loadLibrary("clinkerffitests"); - } - private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); - private static final SymbolLookup defaultLibLookup = (!isAixOS) ? CLinker.systemLookup() : null; - - @Test - public void test_addIntsWithVaList() throws Throwable { - Addressable functionSymbol = nativeLibLookup.lookup("addIntsFromVaList").get(); - MethodType mt = MethodType.methodType(int.class, int.class, VaList.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_VA_LIST); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - VaList vaList = CLinker.VaList.make(vaListBuilder -> vaListBuilder.vargFromInt(C_INT, 700) - .vargFromInt(C_INT, 800) - .vargFromInt(C_INT, 900) - .vargFromInt(C_INT, 1000), scope); - int result = (int)mh.invoke(4, vaList); - Assert.assertEquals(result, 3400); - } - } - - @Test - public void test_addLongsWithVaList() throws Throwable { - Addressable functionSymbol = nativeLibLookup.lookup("addLongsFromVaList").get(); - MethodType mt = MethodType.methodType(long.class, int.class, VaList.class); - FunctionDescriptor fd = FunctionDescriptor.of(longLayout, C_INT, C_VA_LIST); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - VaList vaList = CLinker.VaList.make(vaListBuilder -> vaListBuilder.vargFromLong(longLayout, 700000L) - .vargFromLong(longLayout, 800000L) - .vargFromLong(longLayout, 900000L) - .vargFromLong(longLayout, 1000000L), scope); - long result = (long)mh.invoke(4, vaList); - Assert.assertEquals(result, 3400000L); - } - } - - @Test - public void test_addDoublesWithVaList() throws Throwable { - Addressable functionSymbol = nativeLibLookup.lookup("addDoublesFromVaList").get(); - MethodType mt = MethodType.methodType(double.class, int.class, VaList.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_INT, C_VA_LIST); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - VaList vaList = CLinker.VaList.make(vaListBuilder -> vaListBuilder.vargFromDouble(C_DOUBLE, 150.1001D) - .vargFromDouble(C_DOUBLE, 160.2002D) - .vargFromDouble(C_DOUBLE, 170.1001D) - .vargFromDouble(C_DOUBLE, 180.2002D), scope); - double result = (double)mh.invoke(4, vaList); - Assert.assertEquals(result, 660.6006D); - } - } - - @Test - public void test_vprintfFromDefaultLibWithVaList() throws Throwable { - /* Disable the test on Windows given a misaligned access exception coming from - * java.base/java.lang.invoke.MemoryAccessVarHandleBase triggered by CLinker.toCString() - * is also captured on OpenJDK/Hotspot. - */ - if (!isWinOS) { - Addressable functionSymbol = defaultLibLookup.lookup("vprintf").get(); - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, VaList.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_VA_LIST); - MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd); - - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment formatMemSegment = CLinker.toCString("%d * %d = %d\n", scope); - VaList vaList = CLinker.VaList.make(vaListBuilder -> vaListBuilder.vargFromInt(C_INT, 7) - .vargFromInt(C_INT, 8) - .vargFromInt(C_INT, 56), scope); - mh.invoke(formatMemSegment.address(), vaList); - } - } - } - - @Test - public void test_vprintfFromDefaultLibWithVaList_fromMemAddr() throws Throwable { - /* Disable the test on Windows given a misaligned access exception coming from - * java.base/java.lang.invoke.MemoryAccessVarHandleBase triggered by CLinker.toCString() - * is also captured on OpenJDK/Hotspot. - */ - if (!isWinOS) { - Addressable functionSymbol = defaultLibLookup.lookup("vprintf").get(); - MemoryAddress memAddr = functionSymbol.address(); - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class, VaList.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_POINTER, C_VA_LIST); - MethodHandle mh = clinker.downcallHandle(memAddr, mt, fd); - - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - MemorySegment formatMemSegment = CLinker.toCString("%d * %d = %d\n", scope); - VaList vaList = CLinker.VaList.make(vaListBuilder -> vaListBuilder.vargFromInt(C_INT, 7) - .vargFromInt(C_INT, 8) - .vargFromInt(C_INT, 56), scope); - mh.invoke(formatMemSegment.address(), vaList); - } - } - } -} diff --git a/test/functional/Java17andUp/testng_170.xml b/test/functional/Java17andUp/testng_170.xml index a6bc668c82a..c163d8114b7 100644 --- a/test/functional/Java17andUp/testng_170.xml +++ b/test/functional/Java17andUp/testng_170.xml @@ -32,6 +32,7 @@ + @@ -39,9 +40,19 @@ + + + + + + + + + + - + diff --git a/test/functional/Java18andUp/playlist.xml b/test/functional/Java18andUp/playlist.xml index d7317f33df3..ff01df786a9 100644 --- a/test/functional/Java18andUp/playlist.xml +++ b/test/functional/Java18andUp/playlist.xml @@ -36,7 +36,7 @@ -excludegroups $(DEFAULT_EXCLUDE); \ $(TEST_STATUS) - bits.64,^arch.x86,^arch.aarch64,^arch.ppc,^arch.390,^arch.arm,^arch.riscv,^os.zos,^os.sunos + bits.64,^arch.x86,^arch.arm,^arch.riscv,^os.zos,^os.sunos sanity @@ -50,6 +50,37 @@ 18 + + + Jep419Tests_testClinkerFfi_UpCall + + --enable-preview + + $(ADD_JVM_LIB_DIR_TO_LIBPATH) $(JAVA_COMMAND) $(JVM_OPTIONS) \ + --add-modules jdk.incubator.foreign \ + --enable-native-access=ALL-UNNAMED \ + -Dforeign.restricted=permit \ + -cp $(Q)$(LIB_DIR)$(D)asm.jar$(P)$(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(TEST_RESROOT)$(D)GeneralTest.jar$(Q) \ + org.testng.TestNG -d $(REPORTDIR) $(Q)$(TEST_RESROOT)$(D)testng_180.xml$(Q) -testnames Jep419Tests_testClinkerFfi_UpCall \ + -groups $(TEST_GROUP) \ + -excludegroups $(DEFAULT_EXCLUDE); \ + $(TEST_STATUS) + + bits.64,^arch.x86,^arch.arm,^arch.riscv,^os.zos,^os.sunos + + sanity + + + functional + + + openj9 + + + 18 + + + Jep419Tests_testClinkerFfi_VaList diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/InvalidDownCallTests.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/InvalidDownCallTests.java index 960ffb85837..ebe5da0ce5c 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/InvalidDownCallTests.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/InvalidDownCallTests.java @@ -34,16 +34,14 @@ import jdk.incubator.foreign.SymbolLookup; import static jdk.incubator.foreign.ValueLayout.*; - /** - * Test cases for JEP 419: Foreign Linker API (Second Incubator) DownCall for primitive types, + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for primitive types in downcall, * which verifies the illegal cases including unsupported layouts, etc. * Note: the majority of illegal cases are removed given the corresponding method type * is deduced from the function descriptor which is verified in OpenJDK. */ @Test(groups = { "level.sanity" }) public class InvalidDownCallTests { - private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); private static CLinker clinker = CLinker.systemCLinker(); static { @@ -61,33 +59,17 @@ public void test_invalidMemoryLayoutForIntType() throws Throwable { @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Unsupported layout.*") public void test_invalidMemoryLayoutForMemoryAddress() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (isAixOS) { - throw new IllegalArgumentException("Unsupported layout"); - } else { - NativeSymbol functionSymbol = clinker.lookup("strlen").get(); - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, MemoryLayout.paddingLayout(64)); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - fail("Failed to throw out IllegalArgumentException in the case of the invalid MemoryLayout"); - } + NativeSymbol functionSymbol = clinker.lookup("strlen").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, MemoryLayout.paddingLayout(64)); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + fail("Failed to throw out IllegalArgumentException in the case of the invalid MemoryLayout"); } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Unsupported layout.*") public void test_invalidMemoryLayoutForReturnType() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (isAixOS) { - throw new IllegalArgumentException("Unsupported layout"); - } else { - NativeSymbol functionSymbol = clinker.lookup("strlen").get(); - FunctionDescriptor fd = FunctionDescriptor.of(MemoryLayout.paddingLayout(64), JAVA_LONG); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - fail("Failed to throw out IllegalArgumentException in the case of the invalid MemoryLayout"); - } + NativeSymbol functionSymbol = clinker.lookup("strlen").get(); + FunctionDescriptor fd = FunctionDescriptor.of(MemoryLayout.paddingLayout(64), JAVA_LONG); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + fail("Failed to throw out IllegalArgumentException in the case of the invalid MemoryLayout"); } } diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiCallTests.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiCallTests.java index dc26a91a554..04afaad75b2 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiCallTests.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiCallTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2021 IBM Corp. and others + * Copyright (c) 2021, 2022 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -33,7 +33,7 @@ import static jdk.incubator.foreign.ValueLayout.*; /** - * Test cases for JEP 419: Foreign Linker API (Second Incubator) DownCall for primitive types, + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for primitive types in downcall, * which verifies multiple downcalls with the same or different layouts or argument/return types. */ @Test(groups = { "level.sanity" }) diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests1.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests1.java index da6c491abaf..25d0d2513ff 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests1.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests1.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2021 IBM Corp. and others + * Copyright (c) 2021, 2022 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -28,13 +28,17 @@ import java.lang.invoke.MethodHandle; import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.SymbolLookup; import static jdk.incubator.foreign.ValueLayout.*; /** - * Test cases for JEP 419: Foreign Linker API (Second Incubator) DownCall for primitive types, - * which verifies the downcalls with the same layout & argument and return types in multithreading. + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for primitive types in downcall, + * which verifies the downcalls with the same downcall handlder (cached as soft reference in OpenJDK) + * in multithreading. */ @Test(groups = { "level.sanity" }) public class MultiThreadingTests1 implements Thread.UncaughtExceptionHandler { @@ -53,37 +57,49 @@ public void uncaughtException(Thread thr, Throwable t) { } @Test - public void test_twoThreadsWithSameFuncDescriptor() throws Throwable { + public void test_twoThreadsWithSameFuncDesc_SameDowncallHandler() throws Throwable { Thread thr1 = new Thread(){ public void run() { try { - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add2Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - int result = (int)mh.invokeExact(112, 123); - Assert.assertEquals(result, 235); + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointer").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 215); + int result = (int)mh.invoke(321, intSegmt); + Assert.assertEquals(result, 536); + } } catch (Throwable t) { throw new RuntimeException(t); } } }; - thr1.setUncaughtExceptionHandler(this); - thr1.start(); Thread thr2 = new Thread(){ public void run() { try { - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add2Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - int result = (int)mh.invokeExact(235, 439); - Assert.assertEquals(result, 674); + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointer").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 215); + int result = (int)mh.invoke(322, intSegmt); + Assert.assertEquals(result, 537); + } } catch (Throwable t) { throw new RuntimeException(t); } } }; + + thr1.setUncaughtExceptionHandler(this); thr2.setUncaughtExceptionHandler(this); + + thr1.start(); thr2.start(); thr1.join(); diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests2.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests2.java index dd2cdc35fa9..bdc0d4f312e 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests2.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests2.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2021 IBM Corp. and others + * Copyright (c) 2021, 2022 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -26,15 +26,25 @@ import org.testng.AssertJUnit; import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.SymbolLookup; import static jdk.incubator.foreign.ValueLayout.*; + /** - * Test cases for JEP 419: Foreign Linker API (Second Incubator) DownCall for primitive types, - * which verifies the downcalls with the diffrent layouts and arguments/return types in multithreading. + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for primitive types in downcall, + * which verifies the downcalls with the shared downcall handlder (cached as soft reference in OpenJDK) + * in multithreading. */ @Test(groups = { "level.sanity" }) public class MultiThreadingTests2 implements Thread.UncaughtExceptionHandler { @@ -44,7 +54,10 @@ public class MultiThreadingTests2 implements Thread.UncaughtExceptionHandler { static { System.loadLibrary("clinkerffitests"); } - private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + private static final GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + private static final FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + private static final NativeSymbol functionSymbol = SymbolLookup.loaderLookup().lookup("add2IntStructs_returnStruct").get(); + private static final MethodHandle mh = CLinker.systemCLinker().downcallHandle(functionSymbol, fd); @Test(enabled=false) @Override @@ -53,15 +66,26 @@ public void uncaughtException(Thread thr, Throwable t) { } @Test - public void test_twoThreadsWithDiffFuncDescriptor() throws Throwable { + public void test_twoThreadsWithSameFuncDesc_SharedDowncallHandler() throws Throwable { Thread thr1 = new Thread(){ public void run() { try { - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add2Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - int result = (int)mh.invokeExact(112, 123); - Assert.assertEquals(result, 235); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224466); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113354); + } } catch (Throwable t) { throw new RuntimeException(t); } @@ -71,11 +95,22 @@ public void run() { Thread thr2 = new Thread(){ public void run() { try { - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add3Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - int result = (int)mh.invokeExact(112, 123, 235); - Assert.assertEquals(result, 470); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001123); + intHandle2.set(structSegmt2, 33445567); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224467); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113355); + } } catch (Throwable t) { throw new RuntimeException(t); } diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests3.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests3.java index bf2c22f47d8..88ec4f06c58 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests3.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests3.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2021 IBM Corp. and others + * Copyright (c) 2021, 2022 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -33,8 +33,8 @@ import static jdk.incubator.foreign.ValueLayout.*; /** - * Test cases for JEP 419: Foreign Linker API (Second Incubator) DownCall for primitive types, - * which verifies the downcalls with the diffrent return types in multithreading. + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for primitive types in downcall, + * which verifies the downcalls with the diffrent layouts and arguments/return types in multithreading. */ @Test(groups = { "level.sanity" }) public class MultiThreadingTests3 implements Thread.UncaughtExceptionHandler { @@ -53,7 +53,7 @@ public void uncaughtException(Thread thr, Throwable t) { } @Test - public void test_twoThreadsWithDiffReturnType() throws Throwable { + public void test_twoThreadsWithDiffFuncDescriptor() throws Throwable { Thread thr1 = new Thread(){ public void run() { try { @@ -71,10 +71,11 @@ public void run() { Thread thr2 = new Thread(){ public void run() { try { - FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoid").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3Ints").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - mh.invokeExact(454, 398); + int result = (int)mh.invokeExact(112, 123, 235); + Assert.assertEquals(result, 470); } catch (Throwable t) { throw new RuntimeException(t); } diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests4.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests4.java index 142f843354f..e9739e56bb6 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests4.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests4.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2021 IBM Corp. and others + * Copyright (c) 2021, 2022 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -33,8 +33,8 @@ import static jdk.incubator.foreign.ValueLayout.*; /** - * Test cases for JEP 419: Foreign Linker API (Second Incubator) DownCall for primitive types, - * which verifies multiple downcalls combined with the diffrent layouts/arguments/return types in multithreading. + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for primitive types in downcall, + * which verifies the downcalls with the diffrent return types in multithreading. */ @Test(groups = { "level.sanity" }) public class MultiThreadingTests4 implements Thread.UncaughtExceptionHandler { @@ -53,15 +53,15 @@ public void uncaughtException(Thread thr, Throwable t) { } @Test - public void test_multiThreadsWithMixedFuncDescriptors() throws Throwable { + public void test_twoThreadsWithDiffReturnType() throws Throwable { Thread thr1 = new Thread(){ public void run() { try { FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); NativeSymbol functionSymbol = nativeLibLookup.lookup("add2Ints").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - int result = (int)mh.invokeExact(128, 246); - Assert.assertEquals(result, 374); + int result = (int)mh.invokeExact(112, 123); + Assert.assertEquals(result, 235); } catch (Throwable t) { throw new RuntimeException(t); } @@ -71,67 +71,10 @@ public void run() { Thread thr2 = new Thread(){ public void run() { try { - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add3Ints").get(); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoid").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - int result = (int)mh.invokeExact(112, 642, 971); - Assert.assertEquals(result, 1725); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - }; - - Thread thr3 = new Thread(){ - public void run() { - try { - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - boolean result = (boolean)mh.invokeExact(true, false); - Assert.assertEquals(result, true); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - }; - - Thread thr4 = new Thread(){ - public void run() { - try { - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add2Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - int result = (int)mh.invokeExact(416, 728); - Assert.assertEquals(result, 1144); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - }; - - Thread thr5 = new Thread(){ - public void run() { - try { - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add3Ints").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - int result = (int)mh.invokeExact(1012, 1023, 2035); - Assert.assertEquals(result, 4070); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - }; - - Thread thr6 = new Thread(){ - public void run() { - try { - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN); - NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - boolean result = (boolean)mh.invokeExact(false, false); - Assert.assertEquals(result, false); + mh.invokeExact(454, 398); } catch (Throwable t) { throw new RuntimeException(t); } @@ -140,24 +83,12 @@ public void run() { thr1.setUncaughtExceptionHandler(this); thr2.setUncaughtExceptionHandler(this); - thr3.setUncaughtExceptionHandler(this); - thr4.setUncaughtExceptionHandler(this); - thr5.setUncaughtExceptionHandler(this); - thr6.setUncaughtExceptionHandler(this); thr1.start(); thr2.start(); - thr3.start(); - thr4.start(); - thr5.start(); - thr6.start(); - thr6.join(); - thr5.join(); - thr4.join(); - thr3.join(); - thr2.join(); thr1.join(); + thr2.join(); if (initException != null){ throw new RuntimeException(initException); diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests5.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests5.java new file mode 100644 index 00000000000..3fc7fed4825 --- /dev/null +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/MultiThreadingTests5.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep419.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.SymbolLookup; +import static jdk.incubator.foreign.ValueLayout.*; + +/** + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for primitive types in downcall, + * which verifies multiple downcalls combined with the diffrent layouts/arguments/return types in multithreading. + */ +@Test(groups = { "level.sanity" }) +public class MultiThreadingTests5 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static CLinker clinker = CLinker.systemCLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_multiThreadsWithMixedFuncDescriptors() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(128, 246); + Assert.assertEquals(result, 374); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr2 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3Ints").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(112, 642, 971); + Assert.assertEquals(result, 1725); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr3 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + boolean result = (boolean)mh.invokeExact(true, false); + Assert.assertEquals(result, true); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr4 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(416, 728); + Assert.assertEquals(result, 1144); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr5 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3Ints").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(1012, 1023, 2035); + Assert.assertEquals(result, 4070); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr6 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + boolean result = (boolean)mh.invokeExact(false, false); + Assert.assertEquals(result, false); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + thr1.setUncaughtExceptionHandler(this); + thr2.setUncaughtExceptionHandler(this); + thr3.setUncaughtExceptionHandler(this); + thr4.setUncaughtExceptionHandler(this); + thr5.setUncaughtExceptionHandler(this); + thr6.setUncaughtExceptionHandler(this); + + thr1.start(); + thr2.start(); + thr3.start(); + thr4.start(); + thr5.start(); + thr6.start(); + + thr6.join(); + thr5.join(); + thr4.join(); + thr3.join(); + thr2.join(); + thr1.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/PrimitiveTypeTests1.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/PrimitiveTypeTests1.java index 191bb151691..97a11dd8407 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/PrimitiveTypeTests1.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/PrimitiveTypeTests1.java @@ -45,7 +45,6 @@ */ @Test(groups = { "level.sanity" }) public class PrimitiveTypeTests1 { - private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); private static CLinker clinker = CLinker.systemCLinker(); private static ResourceScope resourceScope = ResourceScope.newImplicitScope(); private static SegmentAllocator nativeAllocator = SegmentAllocator.nativeAllocator(resourceScope); @@ -262,53 +261,35 @@ public void test_addDoubleAndDoubleFromPointer_1() throws Throwable { @Test public void test_strlenFromDefaultLibWithMemAddr_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - NativeSymbol strlenSymbol = clinker.lookup("strlen").get(); - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS); - MethodHandle mh = clinker.downcallHandle(strlenSymbol, fd); - MemorySegment funcSegmt = nativeAllocator.allocateUtf8String("JEP419 DOWNCALL TEST SUITES"); - long strLength = (long)mh.invoke(funcSegmt); - Assert.assertEquals(strLength, 27); - } + NativeSymbol strlenSymbol = clinker.lookup("strlen").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS); + MethodHandle mh = clinker.downcallHandle(strlenSymbol, fd); + MemorySegment funcSegmt = nativeAllocator.allocateUtf8String("JEP419 DOWNCALL TEST SUITES"); + long strLength = (long)mh.invoke(funcSegmt); + Assert.assertEquals(strLength, 27); } @Test public void test_memoryAllocFreeFromDefaultLib_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - NativeSymbol allocSymbol = clinker.lookup("malloc").get(); - FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(ADDRESS, JAVA_LONG); - MethodHandle allocHandle = clinker.downcallHandle(allocSymbol, allocFuncDesc); - MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); - allocMemAddr.set(JAVA_INT, 0, 15); - Assert.assertEquals(allocMemAddr.get(JAVA_INT, 0), 15); - - NativeSymbol freeSymbol = clinker.lookup("free").get(); - FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(ADDRESS); - MethodHandle freeHandle = clinker.downcallHandle(freeSymbol, freeFuncDesc); - freeHandle.invoke(allocMemAddr); - } + NativeSymbol allocSymbol = clinker.lookup("malloc").get(); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(ADDRESS, JAVA_LONG); + MethodHandle allocHandle = clinker.downcallHandle(allocSymbol, allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); + allocMemAddr.set(JAVA_INT, 0, 15); + Assert.assertEquals(allocMemAddr.get(JAVA_INT, 0), 15); + + NativeSymbol freeSymbol = clinker.lookup("free").get(); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(ADDRESS); + MethodHandle freeHandle = clinker.downcallHandle(freeSymbol, freeFuncDesc); + freeHandle.invoke(allocMemAddr); } @Test public void test_printfFromDefaultLibWithMemAddr_1() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - NativeSymbol functionSymbol = clinker.lookup("printf").get(); - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - MemorySegment formatSegmt = nativeAllocator.allocateUtf8String("\n%d + %d = %d\n"); - mh.invoke(formatSegmt, 15, 27, 42); - } + NativeSymbol functionSymbol = clinker.lookup("printf").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + MemorySegment formatSegmt = nativeAllocator.allocateUtf8String("\n%d + %d = %d\n"); + mh.invoke(formatSegmt, 15, 27, 42); } } diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/PrimitiveTypeTests2.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/PrimitiveTypeTests2.java index 7d9ffcb9869..2b708c3228f 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/PrimitiveTypeTests2.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/PrimitiveTypeTests2.java @@ -47,7 +47,6 @@ */ @Test(groups = { "level.sanity" }) public class PrimitiveTypeTests2 { - private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); private static CLinker clinker = CLinker.systemCLinker(); private static ResourceScope resourceScope = ResourceScope.newImplicitScope(); private static SegmentAllocator nativeAllocator = SegmentAllocator.nativeAllocator(resourceScope); @@ -264,53 +263,35 @@ public void test_addDoubleAndDoubleFromPointer_2() throws Throwable { @Test public void test_strlenFromDefaultLibWithMemAddr_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - NativeSymbol strlenSymbol = clinker.lookup("strlen").get(); - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS); - MethodHandle mh = clinker.downcallHandle(fd); - MemorySegment funcSegmt = nativeAllocator.allocateUtf8String("JEP419 DOWNCALL TEST SUITES"); - long strLength = (long)mh.invoke(strlenSymbol, funcSegmt); - Assert.assertEquals(strLength, 27); - } + NativeSymbol strlenSymbol = clinker.lookup("strlen").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS); + MethodHandle mh = clinker.downcallHandle(fd); + MemorySegment funcSegmt = nativeAllocator.allocateUtf8String("JEP419 DOWNCALL TEST SUITES"); + long strLength = (long)mh.invoke(strlenSymbol, funcSegmt); + Assert.assertEquals(strLength, 27); } @Test public void test_memoryAllocFreeFromDefaultLib_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - NativeSymbol allocSymbol = clinker.lookup("malloc").get(); - FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(ADDRESS, JAVA_LONG); - MethodHandle allocHandle = clinker.downcallHandle(allocFuncDesc); - MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(allocSymbol, 10L); - allocMemAddr.set(JAVA_INT, 0, 15); - Assert.assertEquals(allocMemAddr.get(JAVA_INT, 0), 15); - - NativeSymbol freeSymbol = clinker.lookup("free").get(); - FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(ADDRESS); - MethodHandle freeHandle = clinker.downcallHandle(freeFuncDesc); - freeHandle.invoke(freeSymbol, allocMemAddr); - } + NativeSymbol allocSymbol = clinker.lookup("malloc").get(); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(ADDRESS, JAVA_LONG); + MethodHandle allocHandle = clinker.downcallHandle(allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(allocSymbol, 10L); + allocMemAddr.set(JAVA_INT, 0, 15); + Assert.assertEquals(allocMemAddr.get(JAVA_INT, 0), 15); + + NativeSymbol freeSymbol = clinker.lookup("free").get(); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(ADDRESS); + MethodHandle freeHandle = clinker.downcallHandle(freeFuncDesc); + freeHandle.invoke(freeSymbol, allocMemAddr); } @Test public void test_printfFromDefaultLibWithMemAddr_2() throws Throwable { - /* Temporarily disable the default library loading on AIX till we figure out a way - * around to handle the case as the official implementation in OpenJDK17 doesn't - * help to load the static libray (libc.a). - */ - if (!isAixOS) { - NativeSymbol functionSymbol = clinker.lookup("printf").get(); - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT); - MethodHandle mh = clinker.downcallHandle(fd); - MemorySegment formatSegmt = nativeAllocator.allocateUtf8String("\n%d + %d = %d\n"); - mh.invoke(functionSymbol, formatSegmt, 15, 27, 42); - } + NativeSymbol functionSymbol = clinker.lookup("printf").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT); + MethodHandle mh = clinker.downcallHandle(fd); + MemorySegment formatSegmt = nativeAllocator.allocateUtf8String("\n%d + %d = %d\n"); + mh.invoke(functionSymbol, formatSegmt, 15, 27, 42); } } diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/StructTests1.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/StructTests1.java index 469305b1e4a..5520f165495 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/StructTests1.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/StructTests1.java @@ -31,9 +31,7 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.GroupLayout; -import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemoryLayout.PathElement; import jdk.incubator.foreign.MemorySegment; @@ -154,7 +152,8 @@ public void test_addBoolAndBoolsFromStructPointerWithXor_1() throws Throwable { @Test public void test_addBoolAndBoolsFromNestedStructWithXor_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -174,8 +173,8 @@ public void test_addBoolAndBoolsFromNestedStructWithXor_1() throws Throwable { @Test public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrder_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), nestedStructLayout.withName("struct_elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor_reverseOrder").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -195,7 +194,8 @@ public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrder_1() throws @Test public void test_addBoolAndBoolsFromNestedStructWithXor_withoutLayoutName_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -215,8 +215,8 @@ public void test_addBoolAndBoolsFromNestedStructWithXor_withoutLayoutName_1() th @Test public void test_addBoolAndBoolsFromStructWithNestedBoolArray_1() throws Throwable { SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); - GroupLayout structLayout = MemoryLayout.structLayout(boolArray.withName("array_elem1"), JAVA_BOOLEAN.withName("elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray.withName("array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -236,8 +236,8 @@ public void test_addBoolAndBoolsFromStructWithNestedBoolArray_1() throws Throwab @Test public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder_1() throws Throwable { SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); - GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), boolArray.withName("array_elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + boolArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -257,7 +257,8 @@ public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder_1() t @Test public void test_addBoolAndBoolsFromStructWithNestedBoolArray_withoutLayoutName_1() throws Throwable { SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); - GroupLayout structLayout = MemoryLayout.structLayout(boolArray, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -278,8 +279,8 @@ public void test_addBoolAndBoolsFromStructWithNestedBoolArray_withoutLayoutName_ public void test_addBoolAndBoolsFromStructWithNestedStructArray_1() throws Throwable { GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_BOOLEAN.withName("elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -302,8 +303,8 @@ public void test_addBoolAndBoolsFromStructWithNestedStructArray_1() throws Throw public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder_1() throws Throwable { GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); - GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), structArray.withName("struct_array_elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -326,7 +327,8 @@ public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder_1() public void test_addBoolAndBoolsFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -515,7 +517,8 @@ public void test_addByteAndBytesFromStructPointer_1() throws Throwable { @Test public void test_addByteAndBytesFromNestedStruct_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -556,7 +559,8 @@ public void test_addByteAndBytesFromNestedStruct_reverseOrder_1() throws Throwab @Test public void test_addByteAndBytesFromNestedStruct_withoutLayoutName_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -618,7 +622,8 @@ public void test_addByteAndBytesFromStructWithNestedByteArray_reverseOrder_1() t @Test public void test_addByteAndBytesFromStructWithNestedByteArray_withoutLayoutName_1() throws Throwable { SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); - GroupLayout structLayout = MemoryLayout.structLayout(byteArray, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -687,7 +692,8 @@ public void test_addByteAndBytesFromStructWithNestedStructArray_reverseOrder_1() public void test_addByteAndBytesFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -714,11 +720,10 @@ public void test_add2ByteStructs_returnStruct_1() throws Throwable { FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStruct").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - MemorySegment structSegmt1 = allocator.allocate(structLayout); byteHandle1.set(structSegmt1, (byte)25); byteHandle2.set(structSegmt1, (byte)11); @@ -877,7 +882,8 @@ public void test_addCharAndCharsFromStructPointer_1() throws Throwable { @Test public void test_addCharAndCharsFromNestedStruct_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -1099,7 +1105,8 @@ public void test_add2CharStructs_returnStructPointer_1() throws Throwable { @Test public void test_add3CharStructs_returnStruct_1() throws Throwable { - GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), JAVA_CHAR.withName("elem3")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); VarHandle charHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); @@ -1141,6 +1148,7 @@ public void test_addShortAndShortsFromStruct_1() throws Throwable { MemorySegment structSegmt = allocator.allocate(structLayout); shortHandle1.set(structSegmt, (short)8); shortHandle2.set(structSegmt, (short)9); + short result = (short)mh.invokeExact((short)6, structSegmt); Assert.assertEquals(result, 23); } @@ -1257,7 +1265,8 @@ public void test_addShortAndShortsFromNestedStruct_reverseOrder_1() throws Throw @Test public void test_addShortAndShortsFromNestedStruct_withoutLayoutName_1() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT, JAVA_SHORT); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_SHORT, + MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct").get(); MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); @@ -1901,6 +1910,7 @@ public void test_addLongAndLongsFromStruct_1() throws Throwable { MemorySegment structSegmt = allocator.allocate(structLayout); longHandle1.set(structSegmt, 1234567890L); longHandle2.set(structSegmt, 9876543210L); + long result = (long)mh.invokeExact(2468024680L, structSegmt); Assert.assertEquals(result, 13579135780L); } @@ -2299,6 +2309,7 @@ public void test_addFloatAndFloatsFromStruct_1() throws Throwable { MemorySegment structSegmt = allocator.allocate(structLayout); floatHandle1.set(structSegmt, 8.12F); floatHandle2.set(structSegmt, 9.24F); + float result = (float)mh.invokeExact(6.56F, structSegmt); Assert.assertEquals(result, 23.92F, 0.01F); } @@ -2653,6 +2664,7 @@ public void test_addDoubleAndDoublesFromStruct_1() throws Throwable { MemorySegment structSegmt = allocator.allocate(structLayout); doubleHandle1.set(structSegmt, 2228.111D); doubleHandle2.set(structSegmt, 2229.221D); + double result = (double)mh.invokeExact(3336.333D, structSegmt); Assert.assertEquals(result, 7793.665D, 0.001D); } @@ -2660,33 +2672,24 @@ public void test_addDoubleAndDoublesFromStruct_1() throws Throwable { @Test public void test_addDoubleAndFloatDoubleFromStruct_1() throws Throwable { - GroupLayout structLayout = null; - MemorySegment structSegmt = null; + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_FLOAT.bitSize()), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); - - /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default - * while the same struct is 16 bytes with padding on other platforms. - */ - if (isAixOS) { - structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_DOUBLE.withName("elem2")); - structSegmt = allocator.allocate(structLayout); - structSegmt.set(JAVA_FLOAT, 0, 18.444F); - structSegmt.set(JAVA_DOUBLE, 4, 619.777D); - } else { - structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), - MemoryLayout.paddingLayout(JAVA_FLOAT.bitSize()), JAVA_DOUBLE.withName("elem2")); - VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); - VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); - structSegmt = allocator.allocate(structLayout); - elemHandle1.set(structSegmt, 18.444F); - elemHandle2.set(structSegmt, 619.777D); - } - - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); - NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18.444F); + elemHandle2.set(structSegmt, 619.777D); double result = (double)mh.invokeExact(113.567D, structSegmt); Assert.assertEquals(result, 751.788D, 0.001D); @@ -2695,33 +2698,24 @@ public void test_addDoubleAndFloatDoubleFromStruct_1() throws Throwable { @Test public void test_addDoubleAndIntDoubleFromStruct_1() throws Throwable { - GroupLayout structLayout = null; - MemorySegment structSegmt = null; + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_INT.bitSize()), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); - - /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default - * while the same struct is 16 bytes with padding on other platforms. - */ - if (isAixOS) { - structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_DOUBLE.withName("elem2")); - structSegmt = allocator.allocate(structLayout); - structSegmt.set(JAVA_INT, 0, 18); - structSegmt.set(JAVA_DOUBLE, 4, 619.777D); - } else { - structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), - MemoryLayout.paddingLayout(JAVA_INT.bitSize()), JAVA_DOUBLE.withName("elem2")); - VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); - VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); - structSegmt = allocator.allocate(structLayout); - elemHandle1.set(structSegmt, 18); - elemHandle2.set(structSegmt, 619.777D); - } - - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); - NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18); + elemHandle2.set(structSegmt, 619.777D); double result = (double)mh.invokeExact(113.567D, structSegmt); Assert.assertEquals(result, 751.344D, 0.001D); diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/StructTests2.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/StructTests2.java index 7aed1f3c7bb..279ba188d9d 100644 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/StructTests2.java +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/downcall/StructTests2.java @@ -31,9 +31,7 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.GroupLayout; -import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryHandles; import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.MemoryLayout.PathElement; import jdk.incubator.foreign.MemorySegment; @@ -154,7 +152,8 @@ public void test_addBoolAndBoolsFromStructPointerWithXor_2() throws Throwable { @Test public void test_addBoolAndBoolsFromNestedStructWithXor_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -174,8 +173,8 @@ public void test_addBoolAndBoolsFromNestedStructWithXor_2() throws Throwable { @Test public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrder_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), nestedStructLayout.withName("struct_elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor_reverseOrder").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -195,7 +194,8 @@ public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrder_2() throws @Test public void test_addBoolAndBoolsFromNestedStructWithXor_withoutLayoutName_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -215,8 +215,8 @@ public void test_addBoolAndBoolsFromNestedStructWithXor_withoutLayoutName_2() th @Test public void test_addBoolAndBoolsFromStructWithNestedBoolArray_2() throws Throwable { SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); - GroupLayout structLayout = MemoryLayout.structLayout(boolArray.withName("array_elem1"), JAVA_BOOLEAN.withName("elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray.withName("array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -236,8 +236,8 @@ public void test_addBoolAndBoolsFromStructWithNestedBoolArray_2() throws Throwab @Test public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder_2() throws Throwable { SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); - GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), boolArray.withName("array_elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + boolArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -257,7 +257,8 @@ public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder_2() t @Test public void test_addBoolAndBoolsFromStructWithNestedBoolArray_withoutLayoutName_2() throws Throwable { SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); - GroupLayout structLayout = MemoryLayout.structLayout(boolArray, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -278,8 +279,8 @@ public void test_addBoolAndBoolsFromStructWithNestedBoolArray_withoutLayoutName_ public void test_addBoolAndBoolsFromStructWithNestedStructArray_2() throws Throwable { GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_BOOLEAN.withName("elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -302,8 +303,8 @@ public void test_addBoolAndBoolsFromStructWithNestedStructArray_2() throws Throw public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder_2() throws Throwable { GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); - GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), structArray.withName("struct_array_elem2"), - MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -326,7 +327,8 @@ public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder_2() public void test_addBoolAndBoolsFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -515,7 +517,8 @@ public void test_addByteAndBytesFromStructPointer_2() throws Throwable { @Test public void test_addByteAndBytesFromNestedStruct_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -556,7 +559,8 @@ public void test_addByteAndBytesFromNestedStruct_reverseOrder_2() throws Throwab @Test public void test_addByteAndBytesFromNestedStruct_withoutLayoutName_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -618,7 +622,8 @@ public void test_addByteAndBytesFromStructWithNestedByteArray_reverseOrder_2() t @Test public void test_addByteAndBytesFromStructWithNestedByteArray_withoutLayoutName_2() throws Throwable { SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); - GroupLayout structLayout = MemoryLayout.structLayout(byteArray, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -687,7 +692,8 @@ public void test_addByteAndBytesFromStructWithNestedStructArray_reverseOrder_2() public void test_addByteAndBytesFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE); SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); - GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -877,7 +883,8 @@ public void test_addCharAndCharsFromStructPointer_2() throws Throwable { @Test public void test_addCharAndCharsFromNestedStruct_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -1099,7 +1106,8 @@ public void test_add2CharStructs_returnStructPointer_2() throws Throwable { @Test public void test_add3CharStructs_returnStruct_2() throws Throwable { - GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), JAVA_CHAR.withName("elem3")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); VarHandle charHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); @@ -1257,7 +1265,8 @@ public void test_addShortAndShortsFromNestedStruct_reverseOrder_2() throws Throw @Test public void test_addShortAndShortsFromNestedStruct_withoutLayoutName_2() throws Throwable { GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT, JAVA_SHORT); - GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_SHORT, + MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct").get(); MethodHandle mh = clinker.downcallHandle(fd); @@ -2660,33 +2669,24 @@ public void test_addDoubleAndDoublesFromStruct_2() throws Throwable { @Test public void test_addDoubleAndFloatDoubleFromStruct_2() throws Throwable { - GroupLayout structLayout = null; - MemorySegment structSegmt = null; + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_FLOAT.bitSize()), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); + MethodHandle mh = clinker.downcallHandle(fd); try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); - - /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default - * while the same struct is 16 bytes with padding on other platforms. - */ - if (isAixOS) { - structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_DOUBLE.withName("elem2")); - structSegmt = allocator.allocate(structLayout); - structSegmt.set(JAVA_FLOAT, 0, 18.444F); - structSegmt.set(JAVA_DOUBLE, 4, 619.777D); - } else { - structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), - MemoryLayout.paddingLayout(JAVA_FLOAT.bitSize()), JAVA_DOUBLE.withName("elem2")); - VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); - VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); - structSegmt = allocator.allocate(structLayout); - elemHandle1.set(structSegmt, 18.444F); - elemHandle2.set(structSegmt, 619.777D); - } - - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); - NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); - MethodHandle mh = clinker.downcallHandle(fd); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18.444F); + elemHandle2.set(structSegmt, 619.777D); double result = (double)mh.invokeExact(functionSymbol, 113.567D, structSegmt); Assert.assertEquals(result, 751.788D, 0.001D); @@ -2695,33 +2695,24 @@ public void test_addDoubleAndFloatDoubleFromStruct_2() throws Throwable { @Test public void test_addDoubleAndIntDoubleFromStruct_2() throws Throwable { - GroupLayout structLayout = null; - MemorySegment structSegmt = null; + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_INT.bitSize()), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); + MethodHandle mh = clinker.downcallHandle(fd); try (ResourceScope scope = ResourceScope.newConfinedScope()) { SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); - - /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default - * while the same struct is 16 bytes with padding on other platforms. - */ - if (isAixOS) { - structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_DOUBLE.withName("elem2")); - structSegmt = allocator.allocate(structLayout); - structSegmt.set(JAVA_INT, 0, 18); - structSegmt.set(JAVA_DOUBLE, 4, 619.777D); - } else { - structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), - MemoryLayout.paddingLayout(JAVA_INT.bitSize()), JAVA_DOUBLE.withName("elem2")); - VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); - VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); - structSegmt = allocator.allocate(structLayout); - elemHandle1.set(structSegmt, 18); - elemHandle2.set(structSegmt, 619.777D); - } - - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); - NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); - MethodHandle mh = clinker.downcallHandle(fd); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18); + elemHandle2.set(structSegmt, 619.777D); double result = (double)mh.invokeExact(functionSymbol, 113.567D, structSegmt); Assert.assertEquals(result, 751.344D, 0.001D); diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/MultiUpcallMHTests.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/MultiUpcallMHTests.java new file mode 100644 index 00000000000..f91083f49a7 --- /dev/null +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/MultiUpcallMHTests.java @@ -0,0 +1,560 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep419.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; +import static jdk.incubator.foreign.ValueLayout.*; + +/** + * Test cases for JEP 419: Foreign Linker API (Second Incubator) intended for + * the situations when the multiple primitive specific upcalls happen within + * the same resource scope or from different resource scopes. + */ +@Test(groups = { "level.sanity" }) +public class MultiUpcallMHTests { + private static CLinker clinker = CLinker.systemCLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addTwoBoolsWithOrByUpcallMH_SameScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BoolsWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), scope); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr1); + Assert.assertEquals(result, true); + + NativeSymbol upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), scope); + result = (boolean)mh.invoke(true, false, upcallFuncAddr2); + Assert.assertEquals(result, true); + + NativeSymbol upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), scope); + result = (boolean)mh.invoke(true, false, upcallFuncAddr3); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addTwoBoolsWithOrByUpcallMH_DiffScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BoolsWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), scope); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), scope); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), scope); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPointerByUpcallMH_SameScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), scope); + MemorySegment charSegmt1 = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt1, 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + + NativeSymbol upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), scope); + MemorySegment charSegmt2 = allocator.allocate(JAVA_CHAR, 'B'); + result = (char)mh.invoke(charSegmt2, 'D', upcallFuncAddr2); + Assert.assertEquals(result, 'C'); + + NativeSymbol upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), scope); + MemorySegment charSegmt3 = allocator.allocate(JAVA_CHAR, 'B'); + result = (char)mh.invoke(charSegmt3, 'D', upcallFuncAddr3); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPointerByUpcallMH_DiffScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt, 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt, 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt, 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_addByteAndByteFromNativePtrByUpcallMH_SameScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndByteFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), scope); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr1); + Assert.assertEquals(result, (byte)88); + + NativeSymbol upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), scope); + result = (byte)mh.invoke((byte)33, upcallFuncAddr2); + Assert.assertEquals(result, (byte)88); + + NativeSymbol upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), scope); + result = (byte)mh.invoke((byte)33, upcallFuncAddr3); + Assert.assertEquals(result, (byte)88); + } + } + + @Test + public void test_addByteAndByteFromNativePtrByUpcallMH_DiffScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndByteFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), scope); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), scope); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), scope); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetPtr_ByUpcallMH_SameScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), scope); + MemorySegment shortSegmt1 = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr1 = (MemoryAddress)mh.invoke(shortSegmt1, (short)555, upcallFuncAddr1); + Assert.assertEquals(resultAddr1.get(JAVA_SHORT, 0), (short)999); + + NativeSymbol upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), scope); + MemorySegment shortSegmt2 = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr2 = (MemoryAddress)mh.invoke(shortSegmt2, (short)555, upcallFuncAddr2); + Assert.assertEquals(resultAddr2.get(JAVA_SHORT, 0), (short)999); + + NativeSymbol upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), scope); + MemorySegment shortSegmt3 = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr3 = (MemoryAddress)mh.invoke(shortSegmt3, (short)555, upcallFuncAddr3); + Assert.assertEquals(resultAddr3.get(JAVA_SHORT, 0), (short)999); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetPtr_ByUpcallMH_DiffScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), (short)999); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), (short)999); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), (short)999); + } + } + + @Test + public void test_addTwoIntsByUpcallMH_SameScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr1); + Assert.assertEquals(result, 222235); + + NativeSymbol upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + result = (int)mh.invoke(111112, 111123, upcallFuncAddr2); + Assert.assertEquals(result, 222235); + + NativeSymbol upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + result = (int)mh.invoke(111112, 111123, upcallFuncAddr3); + Assert.assertEquals(result, 222235); + } + } + + @Test + public void test_addTwoIntsByUpcallMH_DiffScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + } + + @Test + public void test_addTwoIntsReturnVoidByUpcallMH_SameScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoidByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), scope); + mh.invoke(111454, 111398, upcallFuncAddr1); + + NativeSymbol upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), scope); + mh.invoke(111454, 111398, upcallFuncAddr2); + + NativeSymbol upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), scope); + mh.invoke(111454, 111398, upcallFuncAddr3); + } + } + + @Test + public void test_addTwoIntsReturnVoidByUpcallMH_DiffScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoidByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), scope); + mh.invoke(111454, 111398, upcallFuncAddr); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), scope); + mh.invoke(111454, 111398, upcallFuncAddr); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), scope); + mh.invoke(111454, 111398, upcallFuncAddr); + } + } + + @Test + public void test_addLongAndLongFromPointerByUpcallMH_SameScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), scope); + MemorySegment longSegmt1 = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt1, 6666698235L, upcallFuncAddr1); + Assert.assertEquals(result, 12409155659L); + + NativeSymbol upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), scope); + MemorySegment longSegmt2 = allocator.allocate(JAVA_LONG, 5742457424L); + result = (long)mh.invoke(longSegmt2, 6666698235L, upcallFuncAddr2); + Assert.assertEquals(result, 12409155659L); + + NativeSymbol upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), scope); + MemorySegment longSegmt3 = allocator.allocate(JAVA_LONG, 5742457424L); + result = (long)mh.invoke(longSegmt3, 6666698235L, upcallFuncAddr3); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addLongAndLongFromPointerByUpcallMH_DiffScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addFloatAndFloatFromNativePtrByUpcallMH_SameScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), scope); + float result = (float)mh.invoke(5.74F, upcallFuncAddr1); + Assert.assertEquals(result, 12.53F, 0.01F); + + NativeSymbol upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), scope); + result = (float)mh.invoke(5.74F, upcallFuncAddr2); + Assert.assertEquals(result, 12.53F, 0.01F); + + NativeSymbol upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), scope); + result = (float)mh.invoke(5.74F, upcallFuncAddr3); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromNativePtrByUpcallMH_DiffScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), scope); + float result = (float)mh.invoke(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), scope); + float result = (float)mh.invoke(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), scope); + float result = (float)mh.invoke(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH_SameScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + + NativeSymbol upcallFuncAddr1 = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), scope); + MemorySegment doubleSegmt1 = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr1 = (MemoryAddress)mh.invoke(doubleSegmt1, 1262.795D, upcallFuncAddr1); + Assert.assertEquals(resultAddr1.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + + NativeSymbol upcallFuncAddr2 = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), scope); + MemorySegment doubleSegmt2 = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr2 = (MemoryAddress)mh.invoke(doubleSegmt2, 1262.795D, upcallFuncAddr2); + Assert.assertEquals(resultAddr2.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + + NativeSymbol upcallFuncAddr3 = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), scope); + MemorySegment doubleSegmt3 = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr3 = (MemoryAddress)mh.invoke(doubleSegmt3, 1262.795D, upcallFuncAddr3); + Assert.assertEquals(resultAddr3.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH_DiffScope() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + } +} diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/MultiUpcallThrdsMHTests1.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/MultiUpcallThrdsMHTests1.java new file mode 100644 index 00000000000..a3d7bc99558 --- /dev/null +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/MultiUpcallThrdsMHTests1.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep419.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; +import static jdk.incubator.foreign.ValueLayout.*; + +/** + * Test cases for JEP 419: Foreign Linker API (Second Incubator) intended for + * the situation when the multi-threading specific upcalls happen to the same + * upcall method handle within different resource scopes, in which case the upcall + * metadata and the generated thunk are allocated separately. + */ +@Test(groups = { "level.sanity" }) +public class MultiUpcallThrdsMHTests1 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static CLinker clinker = CLinker.systemCLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_multiUpcallThrdsWithDiffScopes() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr1.setUncaughtExceptionHandler(this); + thr1.start(); + + Thread thr2 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + int result = (int)mh.invoke(111113, 111124, upcallFuncAddr); + Assert.assertEquals(result, 222237); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr2.setUncaughtExceptionHandler(this); + thr2.start(); + + Thread thr3 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + int result = (int)mh.invoke(111114, 111125, upcallFuncAddr); + Assert.assertEquals(result, 222239); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr3.setUncaughtExceptionHandler(this); + thr3.start(); + + thr1.join(); + thr2.join(); + thr3.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/MultiUpcallThrdsMHTests2.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/MultiUpcallThrdsMHTests2.java new file mode 100644 index 00000000000..91de80f0b8b --- /dev/null +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/MultiUpcallThrdsMHTests2.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep419.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; +import static jdk.incubator.foreign.ValueLayout.*; + +/** + * Test cases for JEP 419: Foreign Linker API (Second Incubator) intended for + * the situation when the multi-threading specific upcalls happen to the same + * upcall method handle within the same resource scope, in which case the upcall + * metadata and the generated thunk are only allocated once and shared among + * these threads. + */ +@Test(groups = { "level.sanity" }) +public class MultiUpcallThrdsMHTests2 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static CLinker clinker = CLinker.systemCLinker(); + private static ResourceScope resourceScope = ResourceScope.newImplicitScope(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_multiUpcallThrdsWithSameScope() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), resourceScope); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr1.setUncaughtExceptionHandler(this); + thr1.start(); + + Thread thr2 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), resourceScope); + int result = (int)mh.invoke(111113, 111124, upcallFuncAddr); + Assert.assertEquals(result, 222237); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr2.setUncaughtExceptionHandler(this); + thr2.start(); + + Thread thr3 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), resourceScope); + int result = (int)mh.invoke(111114, 111125, upcallFuncAddr); + Assert.assertEquals(result, 222239); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr3.setUncaughtExceptionHandler(this); + thr3.start(); + + thr1.join(); + thr2.join(); + thr3.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMHWithMixedSigStruTests.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMHWithMixedSigStruTests.java new file mode 100644 index 00000000000..059362d8f06 --- /dev/null +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMHWithMixedSigStruTests.java @@ -0,0 +1,892 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep419.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; +import static jdk.incubator.foreign.ValueLayout.*; + +/** + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for the mixed native signatures + * in argument/return struct in upcall, which are not covered in UpcallMHWithStructTests and + * specially designed to validate the native signature types required in the genenerated thunk. + * + * Note: the padding elements in the struct are only required by RI or VarHandle (accessing the + * data address) while they are totally ignored in OpenJ9 given the padding/alignment are + * computed by libffi automatically in native. + */ +@Test(groups = { "level.sanity" }) +public class UpcallMHWithMixedSigStruTests { + private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); + private static CLinker clinker = CLinker.systemCLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addIntAndIntShortFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntShortFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntShortFromStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, (short)32766); + + int result = (int)mh.invoke(22334455, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 33590565); + } + } + + @Test + public void test_addIntAndShortIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + MemoryLayout.paddingLayout(16), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndShortIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndShortIntFromStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, (short)32766); + elemHandle2.set(structSegmt, 22446688); + + int result = (int)mh.invoke(11335577, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 33815031); + } + } + + @Test + public void test_addIntAndIntLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntLongFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, 667788990011L); + + long result = (long)mh.invoke(22446688, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 667822660043L); + } + } + + @Test + public void test_addIntAndLongIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), + JAVA_INT.withName("elem2"), MemoryLayout.paddingLayout(32)); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndLongIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndLongIntFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 667788990011L); + elemHandle2.set(structSegmt, 11223344); + + long result = (long)mh.invoke(1234567, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 667801447922L); + } + } + + @Test + public void test_addDoubleAndIntDoubleFromStructByUpcallMH() throws Throwable { + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111111); + elemHandle2.set(structSegmt, 619.777D); + + double result = (double)mh.invoke(113.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111844.344D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleIntFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 111111111); + + double result = (double)mh.invoke(216.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111546.221D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleFromStructByUpcallMH() throws Throwable { + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2")) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18.444F); + elemHandle2.set(structSegmt, 619.777D); + + double result = (double)mh.invoke(113.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 751.788D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFloatFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19.22F); + + double result = (double)mh.invoke(216.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 454.441D, 0.001D); + } + } + + public static void test_addDoubleAndDoubleFloatPlusPaddingFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), + JAVA_FLOAT.withName("elem2"), MemoryLayout.paddingLayout(32)); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFloatFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19.22F); + + double result = (double)mh.invoke(216.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 454.441D, 0.001D); + } + } + + @Test + public void test_addDoubleAnd2FloatsDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAnd2FloatsDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAnd2FloatsDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.22F); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 333.444D); + + double result = (double)mh.invoke(111.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 478.105D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDouble2FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDouble2FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDouble2FloatsFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 333.444D); + elemHandle2.set(structSegmt, 11.22F); + elemHandle3.set(structSegmt, 22.33F); + + double result = (double)mh.invoke(111.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 478.105D, 0.001D); + } + } + + @Test + public void test_addFloatAndInt2FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndInt2FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndInt2FloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111); + elemHandle2.set(structSegmt, 11.22F); + elemHandle3.set(structSegmt, 22.33F); + + float result = (float)mh.invoke(55.567F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111200.12F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatIntFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_INT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatIntFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatIntFloatFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.22F); + elemHandle2.set(structSegmt, 111111); + elemHandle3.set(structSegmt, 22.33F); + + float result = (float)mh.invoke(55.567F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111200.12F, 0.01F); + } + } + + @Test + public void test_addDoubleAndIntFloatDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndIntFloatDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntFloatDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111111); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 333.444D); + + double result = (double)mh.invoke(555.55D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111112022.324D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatIntDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_INT.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatIntDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatIntDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 22.33F); + elemHandle2.set(structSegmt, 111111111); + elemHandle3.set(structSegmt, 333.444D); + + double result = (double)mh.invoke(555.55D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111112022.324D, 0.001D); + } + } + + @Test + public void test_addDoubleAndLongDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndLongDoubleFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndLongDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 22222222222222L); + elemHandle2.set(structSegmt, 33333.444D); + + double result = (double)mh.invoke(55555.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 22222222311110.555D, 0.001D); + } + } + + @Test + public void test_addFloatAndInt3FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3"), JAVA_FLOAT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndInt3FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndInt3FloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 77777777); + elemHandle2.set(structSegmt, 11.22F); + elemHandle3.set(structSegmt, 22.33F); + elemHandle4.set(structSegmt, 44.55F); + + float result = (float)mh.invoke(66.678F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 77777921.778F, 0.001F); + } + } + + @Test + public void test_addLongAndLong2FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLong2FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLong2FloatsFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 777777777777L); + elemHandle2.set(structSegmt, 11.25F); + elemHandle3.set(structSegmt, 22.75F); + + long result = (long)mh.invoke(555555555555L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1333333333365L); + } + } + + @Test + public void test_addFloatAnd3FloatsIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3"), JAVA_INT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAnd3FloatsIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAnd3FloatsIntFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.22F); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 44.55F); + elemHandle4.set(structSegmt, 77777777); + + float result = (float)mh.invoke(66.456F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 77777921.556F, 0.001F); + } + } + + @Test + public void test_addLongAndFloatLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndFloatLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndFloatLongFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 55.11F); + elemHandle2.set(structSegmt, 150000000000L); + + long result = (long)mh.invoke(5555555555L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 155555555610L); + } + } + + @Test + public void test_addDoubleAndDoubleFloatIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFloatIntFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 333.444D); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 111111111); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111112022.341D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleLongFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 33333.444D); + elemHandle2.set(structSegmt, 222222222222L); + + double result = (double)mh.invoke(55555.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 222222311110.555D, 0.001D); + } + } + + @Test + public void test_addLongAnd2FloatsLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_LONG.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAnd2FloatsLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAnd2FloatsLongFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.11F); + elemHandle2.set(structSegmt, 22.11F); + elemHandle3.set(structSegmt, 4444444444L); + + long result = (long)mh.invoke(11111111111L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 15555555588L); + } + } + + @Test + public void test_addShortAnd3ShortsCharFromStructByUpcallMH() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(3, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(shortArray, JAVA_CHAR); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAnd3ShortsCharFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAnd3ShortsCharFromStruct, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1000); + structSegmt.set(JAVA_SHORT, 2, (short)2000); + structSegmt.set(JAVA_SHORT, 4, (short)3000); + structSegmt.set(JAVA_CHAR, 6, 'A'); + + short result = (short)mh.invoke((short)4000, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 10065); + } + } + + @Test + public void test_addFloatAndIntFloatIntFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_INT.withName("elem3"), JAVA_FLOAT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndIntFloatIntFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndIntFloatIntFloatFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 555555555); + elemHandle2.set(structSegmt, 11.222F); + elemHandle3.set(structSegmt, 666666666); + elemHandle4.set(structSegmt, 33.444F); + + float result = (float)mh.invoke(77.456F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1222222343.122F, 0.001F); + } + } + + @Test + public void test_addDoubleAndIntDoubleFloatFromStructByUpcallMH() throws Throwable { + /* The size of [int, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2"), JAVA_FLOAT.withName("elem3")) + : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2"), + JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleFloatFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 7777); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 33.444F); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 8584.566D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleIntFromStructByUpcallMH() throws Throwable { + /* The size of [float, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2"), JAVA_INT.withName("elem3")) + : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), MemoryLayout.paddingLayout(32), + JAVA_DOUBLE.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatDoubleIntFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 33.444F); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 7777); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 8584.566D, 0.001D); + } + } + + @Test + public void test_addDoubleAndIntDoubleIntFromStructByUpcallMH() throws Throwable { + /* The size of [int, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2"), JAVA_INT.withName("elem3")) + : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), MemoryLayout.paddingLayout(32), + JAVA_DOUBLE.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleIntFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleIntFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 6666); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 7777); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 15217.122D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleFloatFromStructByUpcallMH() throws Throwable { + /* The size of [float, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2"), JAVA_FLOAT.withName("elem3")) + : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), MemoryLayout.paddingLayout(32), + JAVA_DOUBLE.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatDoubleFloatFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.222F); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 33.444F); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 818.788D, 0.001D); + } + } + + @Test + public void test_addDoubleAndIntDoubleLongFromStructByUpcallMH() throws Throwable { + /* The size of [int, double, long] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 24 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2"), JAVA_LONG.withName("elem3")) + : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), MemoryLayout.paddingLayout(32), + JAVA_DOUBLE.withName("elem2"), JAVA_LONG.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleLongFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleLongFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111111); + elemHandle2.set(structSegmt, 619.777D); + elemHandle3.set(structSegmt, 888888888888L); + + double result = (double)mh.invoke(113.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 889000000732.344D, 0.001D); + } + } + + @Test + public void test_return254BytesFromStructByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(254, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("return254BytesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_return254BytesFromStruct, + FunctionDescriptor.of(structLayout), scope); + MemorySegment byteArrStruSegment = (MemorySegment)mh.invoke(allocator, upcallFuncAddr); + for (int i = 0; i < 254; i++) { + Assert.assertEquals(byteArrStruSegment.get(JAVA_BYTE, i), (byte)i); + } + } + } + + @Test + public void test_return4KBytesFromStructByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(4096, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("return4KBytesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_return4KBytesFromStruct, + FunctionDescriptor.of(structLayout), scope); + MemorySegment byteArrStruSegment = (MemorySegment)mh.invoke(allocator, upcallFuncAddr); + for (int i = 0; i < 4096; i++) { + Assert.assertEquals(byteArrStruSegment.get(JAVA_BYTE, i), (byte)i); + } + } + } +} diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMHWithPrimTests.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMHWithPrimTests.java new file mode 100644 index 00000000000..a9c686f5962 --- /dev/null +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMHWithPrimTests.java @@ -0,0 +1,724 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep419.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; +import static jdk.incubator.foreign.ValueLayout.*; + +/** + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for primitive types in upcall. + */ +@Test(groups = { "level.sanity" }) +public class UpcallMHWithPrimTests { + private static CLinker clinker = CLinker.systemCLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addTwoBoolsWithOrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BoolsWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), scope); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolFromPointerWithOrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPointerWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPointerWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS), scope); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, scope); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + boolean result = (boolean)mh.invoke(false, boolSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolFromNativePtrWithOrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromNativePtrWithOrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPointerWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS), scope); + boolean result = (boolean)mh.invoke(false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_BOOLEAN, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPtrWithOr_RetPtr, + FunctionDescriptor.of(ADDRESS, JAVA_BOOLEAN, ADDRESS), scope); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, scope); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(false, boolSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), true); + } + } + + @Test + public void test_addBoolAndBoolFromPtrWithOr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_BOOLEAN, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPtrWithOr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, JAVA_BOOLEAN, ADDRESS), scope); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, scope); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(false, boolSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), true); + } + } + + @Test + public void test_addTwoBytesByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BytesByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Bytes, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, JAVA_BYTE), scope); + byte result = (byte)mh.invoke((byte)6, (byte)3, upcallFuncAddr); + Assert.assertEquals(result, 9); + } + } + + @Test + public void test_addByteAndByteFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)7); + byte result = (byte)mh.invoke((byte)8, byteSegmt, upcallFuncAddr); + Assert.assertEquals(result, 15); + } + } + + @Test + public void test_addByteAndByteFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndByteFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), scope); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr); + Assert.assertEquals(result, 88); + } + } + + @Test + public void test_addByteAndByteFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_BYTE, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, JAVA_BYTE, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)35); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke((byte)47, byteSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 82); + } + } + + @Test + public void test_addByteAndByteFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_BYTE, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, JAVA_BYTE, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)35); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke((byte)47, byteSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 82); + } + } + + @Test + public void test_createNewCharFrom2CharsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("createNewCharFrom2CharsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFrom2Chars, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, JAVA_CHAR), scope); + char result = (char)mh.invoke('B', 'D', upcallFuncAddr); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt, 'D', upcallFuncAddr); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), scope); + char result = (char)mh.invoke('D', upcallFuncAddr); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_CHAR, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_CHAR), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(charSegmt, 'D', upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_CHAR, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_CHAR), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(charSegmt, 'D', upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'C'); + } + } + + @Test + public void test_addTwoShortsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2ShortsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Shorts, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT), scope); + short result = (short)mh.invoke((short)1111, (short)2222, upcallFuncAddr); + Assert.assertEquals(result, 3333); + } + } + + @Test + public void test_addShortAndShortFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, ADDRESS, JAVA_SHORT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPointer, + FunctionDescriptor.of(JAVA_SHORT, ADDRESS, JAVA_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)2222); + short result = (short)mh.invoke(shortSegmt, (short)3333, upcallFuncAddr); + Assert.assertEquals(result, 5555); + } + } + + @Test + public void test_addShortAndShortFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPointer, + FunctionDescriptor.of(JAVA_SHORT, ADDRESS, JAVA_SHORT), scope); + short result = (short)mh.invoke((short)789, upcallFuncAddr); + Assert.assertEquals(result, 1245); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 999); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 999); + } + } + + @Test + public void test_addTwoIntsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), scope); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + } + + @Test + public void test_addIntAndIntFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPointer, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 222215); + int result = (int)mh.invoke(333321, intSegmt, upcallFuncAddr); + Assert.assertEquals(result, 555536); + } + } + + @Test + public void test_addIntAndIntFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPointer, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), scope); + int result = (int)mh.invoke(222222, upcallFuncAddr); + Assert.assertEquals(result, 666666); + } + } + + @Test + public void test_addIntAndIntFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_INT, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, JAVA_INT, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 222215); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(333321, intSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 555536); + } + } + + @Test + public void test_addIntAndIntFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_INT, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, JAVA_INT, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 222215); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(333321, intSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 555536); + } + } + + @Test + public void test_add3IntsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3IntsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT), scope); + int result = (int)mh.invoke(111112, 111123, 111124, upcallFuncAddr); + Assert.assertEquals(result, 333359); + } + } + + @Test + public void test_addIntAndCharByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_CHAR, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndCharByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndChar, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_CHAR), scope); + int result = (int)mh.invoke(555558, 'A', upcallFuncAddr); + Assert.assertEquals(result, 555623); + } + } + + @Test + public void test_addTwoIntsReturnVoidByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoidByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), scope); + mh.invoke(44454, 333398, upcallFuncAddr); + } + } + + @Test + public void test_addTwoLongsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, JAVA_LONG, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2LongsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Longs, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, JAVA_LONG), scope); + long result = (long)mh.invoke(333333222222L, 111111555555L, upcallFuncAddr); + Assert.assertEquals(result, 444444777777L); + } + } + + @Test + public void test_addLongAndLongFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addLongAndLongFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), scope); + long result = (long)mh.invoke(5555555555L, upcallFuncAddr); + Assert.assertEquals(result, 8888888888L); + } + } + + @Test + public void test_addLongAndLongFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_LONG, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_LONG), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 12409155659L); + } + } + + @Test + public void test_addLongAndLongFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_LONG, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_LONG), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 12409155659L); + } + } + + @Test + public void test_addTwoFloatsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2FloatsByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Floats, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT), scope); + float result = (float)mh.invoke(15.74F, 16.79F, upcallFuncAddr); + Assert.assertEquals(result, 32.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 6.79F); + float result = (float)mh.invoke(5.74F, floatSegmt, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), scope); + float result = (float)mh.invoke(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_FLOAT, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, JAVA_FLOAT, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 6.79F); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(5.74F, floatSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_FLOAT, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, JAVA_FLOAT, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 6.79F); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(5.74F, floatSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 12.53F, 0.01F); + } + } + + @Test + public void test_add2DoublesByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2DoublesByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2Doubles, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, JAVA_DOUBLE), scope); + double result = (double)mh.invoke(159.748D, 262.795D, upcallFuncAddr); + Assert.assertEquals(result, 422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, JAVA_DOUBLE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPointer, + FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, JAVA_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + double result = (double)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(result, 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromNativePtrByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPointer, + FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, JAVA_DOUBLE), scope); + double result = (double)mh.invoke(1262.795D, upcallFuncAddr); + Assert.assertEquals(result, 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + } + + @Test + public void test_qsortByUpcallMH() throws Throwable { + int expectedArray[] = {11, 12, 13, 14, 15, 16, 17}; + int expectedArrayLength = expectedArray.length; + + FunctionDescriptor fd = FunctionDescriptor.ofVoid(ADDRESS, JAVA_INT, JAVA_INT, ADDRESS); + NativeSymbol functionSymbol = clinker.lookup("qsort").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_compare, + FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment arraySegmt = allocator.allocateArray(JAVA_INT, new int[]{17, 14, 13, 16, 15, 12, 11}); + mh.invoke(arraySegmt, 7, 4, upcallFuncAddr); + int[] sortedArray = arraySegmt.toArray(JAVA_INT); + for (int index = 0; index < expectedArrayLength; index++) { + Assert.assertEquals(sortedArray[index], expectedArray[index]); + } + } + } +} diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMHWithStructTests.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMHWithStructTests.java new file mode 100644 index 00000000000..aab3d19e94e --- /dev/null +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMHWithStructTests.java @@ -0,0 +1,2886 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep419.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import jdk.incubator.foreign.CLinker; +import jdk.incubator.foreign.FunctionDescriptor; +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.NativeSymbol; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.SymbolLookup; +import jdk.incubator.foreign.ValueLayout; +import static jdk.incubator.foreign.ValueLayout.*; + +/** + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for argument/return struct in upcall. + * + * Note: the padding elements in the struct are only required by RI or VarHandle (accessing the + * data address) while they are totally ignored in OpenJ9 given the padding/alignment are + * computed by libffi automatically in native. + */ +@Test(groups = { "level.sanity" }) +public class UpcallMHWithStructTests { + private static String osName = System.getProperty("os.name").toLowerCase(); + private static String arch = System.getProperty("os.arch").toLowerCase(); + /* The padding of struct is not required on Linux/s390x and Windows/x64 */ + private static boolean isStructPaddingNotRequired = osName.contains("win") && (arch.equals("amd64") || arch.equals("x86_64")) + || osName.contains("linux") && arch.equals("s390x"); + private static CLinker clinker = CLinker.systemCLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addBoolAndBoolsFromStructWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, false); + boolHandle2.set(structSegmt, true); + + boolean result = (boolean)mh.invoke(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAnd20BoolsFromStructWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN, + JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, + JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, + JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN + ); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAnd20BoolsFromStructWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAnd20BoolsFromStructWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + structSegmt.set(JAVA_BOOLEAN, 5, true); + structSegmt.set(JAVA_BOOLEAN, 6, false); + structSegmt.set(JAVA_BOOLEAN, 7, true); + structSegmt.set(JAVA_BOOLEAN, 8, false); + structSegmt.set(JAVA_BOOLEAN, 9, true); + structSegmt.set(JAVA_BOOLEAN, 10, false); + structSegmt.set(JAVA_BOOLEAN, 11, true); + structSegmt.set(JAVA_BOOLEAN, 12, false); + structSegmt.set(JAVA_BOOLEAN, 13, true); + structSegmt.set(JAVA_BOOLEAN, 14, false); + structSegmt.set(JAVA_BOOLEAN, 15, true); + structSegmt.set(JAVA_BOOLEAN, 16, false); + structSegmt.set(JAVA_BOOLEAN, 17, true); + structSegmt.set(JAVA_BOOLEAN, 18, false); + structSegmt.set(JAVA_BOOLEAN, 19, true); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolFromPointerAndBoolsFromStructWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, structLayout), scope); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, scope); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, false); + boolHandle2.set(structSegmt, true); + + boolean result = (boolean)mh.invoke(boolSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, false); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, scope); + boolSegmt.set(JAVA_BOOLEAN, 0, false); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(boolSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), true); + Assert.assertEquals(resultAddr.toRawLongValue(), boolSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addBoolAndBoolsFromStructPointerWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructPointerWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructPointerWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, true); + boolHandle2.set(structSegmt, false); + + boolean result = (boolean)mh.invoke(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXorByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BOOLEAN.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXorByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromNestedStructWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromNestedStructWithXor_reverseOrder, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArrayByUpcallMH() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray.withName("array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedBoolArray, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + + boolean result = (boolean)mh.invoke(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + boolArray.withName("array_elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + + boolean result = (boolean)mh.invoke(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BOOLEAN.withName("elem2")) : MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + structArray.withName("struct_array_elem2")) : MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolStructsWithXor_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(boolHandle1.get(resultSegmt), false); + Assert.assertEquals(boolHandle2.get(resultSegmt), true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2BoolStructsWithXor_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), false); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 1), true); + } + } + + @Test + public void test_add3BoolStructsWithXor_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2"), + JAVA_BOOLEAN.withName("elem3")) : MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2"), + JAVA_BOOLEAN.withName("elem3"), MemoryLayout.paddingLayout(8)); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle boolHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3BoolStructsWithXor_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3BoolStructsWithXor_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + boolHandle3.set(structSegmt1, true); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + boolHandle3.set(structSegmt2, false); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(boolHandle1.get(resultSegmt), false); + Assert.assertEquals(boolHandle2.get(resultSegmt), true); + Assert.assertEquals(boolHandle3.get(resultSegmt), true); + } + } + + @Test + public void test_addByteAndBytesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStruct, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)8); + byteHandle2.set(structSegmt, (byte)9); + + byte result = (byte)mh.invoke((byte)6, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23); + } + } + + @Test + public void test_addByteAnd20BytesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE, + JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, + JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, + JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE + ); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAnd20BytesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAnd20BytesFromStruct, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)1); + structSegmt.set(JAVA_BYTE, 1, (byte)2); + structSegmt.set(JAVA_BYTE, 2, (byte)3); + structSegmt.set(JAVA_BYTE, 3, (byte)4); + structSegmt.set(JAVA_BYTE, 4, (byte)5); + structSegmt.set(JAVA_BYTE, 5, (byte)6); + structSegmt.set(JAVA_BYTE, 6, (byte)7); + structSegmt.set(JAVA_BYTE, 7, (byte)8); + structSegmt.set(JAVA_BYTE, 8, (byte)9); + structSegmt.set(JAVA_BYTE, 9, (byte)10); + structSegmt.set(JAVA_BYTE, 10, (byte)1); + structSegmt.set(JAVA_BYTE, 11, (byte)2); + structSegmt.set(JAVA_BYTE, 12, (byte)3); + structSegmt.set(JAVA_BYTE, 13, (byte)4); + structSegmt.set(JAVA_BYTE, 14, (byte)5); + structSegmt.set(JAVA_BYTE, 15, (byte)6); + structSegmt.set(JAVA_BYTE, 16, (byte)7); + structSegmt.set(JAVA_BYTE, 17, (byte)8); + structSegmt.set(JAVA_BYTE, 18, (byte)9); + structSegmt.set(JAVA_BYTE, 19, (byte)10); + + byte result = (byte)mh.invoke((byte)11, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 121); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteFromPointerAndBytesFromStruct, + FunctionDescriptor.of(JAVA_BYTE, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)18); + byteHandle2.set(structSegmt, (byte)19); + + byte result = (byte)mh.invoke(byteSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 49); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStruct_returnBytePointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStruct_returnBytePointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteFromPointerAndBytesFromStruct_returnBytePointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)14); + byteHandle2.set(structSegmt, (byte)16); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(byteSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 42); + Assert.assertEquals(resultAddr.toRawLongValue(), byteSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addByteAndBytesFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)11); + byteHandle2.set(structSegmt, (byte)12); + byte result = (byte)mh.invoke((byte)13, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 36); + } + } + + @Test + public void test_addByteAndBytesFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BYTE.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromNestedStruct, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)22); + structSegmt.set(JAVA_BYTE, 2, (byte)33); + + byte result = (byte)mh.invoke((byte)46, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 112); + } + } + + @Test + public void test_addByteAndBytesFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)24); + structSegmt.set(JAVA_BYTE, 2, (byte)36); + + byte result = (byte)mh.invoke((byte)48, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 120); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArrayByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(byteArray.withName("array_elem1"), + JAVA_BYTE.withName("elem2")) : MemoryLayout.structLayout(byteArray.withName("array_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedByteArray, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)22); + structSegmt.set(JAVA_BYTE, 2, (byte)33); + + byte result = (byte)mh.invoke((byte)14, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 80); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + byteArray.withName("array_elem2")) : MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + byteArray.withName("array_elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedByteArray_reverseOrder, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)14); + structSegmt.set(JAVA_BYTE, 2, (byte)16); + + byte result = (byte)mh.invoke((byte)18, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 60); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BYTE.withName("elem2")) : MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + structSegmt.set(JAVA_BYTE, 3, (byte)14); + structSegmt.set(JAVA_BYTE, 4, (byte)15); + + byte result = (byte)mh.invoke((byte)16, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 81); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + structArray.withName("struct_array_elem2")) : MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)14); + structSegmt.set(JAVA_BYTE, 2, (byte)16); + structSegmt.set(JAVA_BYTE, 3, (byte)18); + structSegmt.set(JAVA_BYTE, 4, (byte)20); + + byte result = (byte)mh.invoke((byte)22, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 102); + } + } + + @Test + public void test_add1ByteStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add1ByteStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add1ByteStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + } + } + + @Test + public void test_add2ByteStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2ByteStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + } + } + + @Test + public void test_add2ByteStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2ByteStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 49); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 1), 24); + } + } + + @Test + public void test_add3ByteStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2"), + JAVA_BYTE.withName("elem3")) : MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2"), + JAVA_BYTE.withName("elem3"), MemoryLayout.paddingLayout(8)); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3ByteStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3ByteStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + byteHandle3.set(structSegmt1, (byte)12); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + byteHandle3.set(structSegmt2, (byte)16); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + Assert.assertEquals((byte)byteHandle3.get(resultSegmt), (byte)28); + } + } + + @Test + public void test_addCharAndCharsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStruct, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'A'); + charHandle2.set(structSegmt, 'B'); + + char result = (char)mh.invoke('C', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'D'); + } + } + + @Test + public void test_addCharAnd10CharsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, + JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, JAVA_CHAR); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAnd10CharsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAnd10CharsFromStruct, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'A'); + structSegmt.set(JAVA_CHAR, 4, 'B'); + structSegmt.set(JAVA_CHAR, 6, 'B'); + structSegmt.set(JAVA_CHAR, 8, 'C'); + structSegmt.set(JAVA_CHAR, 10, 'C'); + structSegmt.set(JAVA_CHAR, 12, 'D'); + structSegmt.set(JAVA_CHAR, 14, 'D'); + structSegmt.set(JAVA_CHAR, 16, 'E'); + structSegmt.set(JAVA_CHAR, 18, 'E'); + + char result = (char)mh.invoke('A', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'U'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharFromPointerAndCharsFromStruct, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + char result = (char)mh.invoke(charSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'M'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStruct_returnCharPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStruct_returnCharPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharFromPointerAndCharsFromStruct_returnCharPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(charSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'M'); + Assert.assertEquals(resultAddr.toRawLongValue(), charSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addCharAndCharsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructPointer, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'H'); + charHandle2.set(structSegmt, 'I'); + + char result = (char)mh.invoke('G', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'V'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_CHAR.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromNestedStruct, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + + char result = (char)mh.invoke('H', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + + char result = (char)mh.invoke('H', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArrayByUpcallMH() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(charArray.withName("array_elem1"), + JAVA_CHAR.withName("elem2")) : MemoryLayout.structLayout(charArray.withName("array_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedCharArray, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invoke('D', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + charArray.withName("array_elem2")) : MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + charArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedCharArray_reverseOrder, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invoke('D', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_CHAR.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invoke('J', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invoke('J', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_add2CharStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2CharStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(charHandle1.get(resultSegmt), 'C'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'E'); + } + } + + @Test + public void test_add2CharStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2CharStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'C'); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 2), 'E'); + } + } + + @Test + public void test_add3CharStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3")) : MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle charHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3CharStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3CharStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + charHandle3.set(structSegmt1, 'C'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'B'); + charHandle2.set(structSegmt2, 'C'); + charHandle3.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(charHandle1.get(resultSegmt), 'B'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'D'); + Assert.assertEquals(charHandle3.get(resultSegmt), 'F'); + } + } + + @Test + public void test_addShortAndShortsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStruct, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)888); + shortHandle2.set(structSegmt, (short)999); + + short result = (short)mh.invoke((short)777, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2664); + } + } + + @Test + public void test_addShortAnd10ShortsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, + JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, JAVA_SHORT); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAnd10ShortsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAnd10ShortsFromStruct, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)10); + structSegmt.set(JAVA_SHORT, 2, (short)20); + structSegmt.set(JAVA_SHORT, 4, (short)30); + structSegmt.set(JAVA_SHORT, 6, (short)40); + structSegmt.set(JAVA_SHORT, 8, (short)50); + structSegmt.set(JAVA_SHORT, 10, (short)60); + structSegmt.set(JAVA_SHORT, 12, (short)70); + structSegmt.set(JAVA_SHORT, 14, (short)80); + structSegmt.set(JAVA_SHORT, 16, (short)90); + structSegmt.set(JAVA_SHORT, 18, (short)100); + + short result = (short)mh.invoke((short)110, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 660); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortFromPointerAndShortsFromStruct, + FunctionDescriptor.of(JAVA_SHORT, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)1112); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)1118); + shortHandle2.set(structSegmt, (short)1119); + + short result = (short)mh.invoke(shortSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 3349); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStruct_returnShortPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStruct_returnShortPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortFromPointerAndShortsFromStruct_returnShortPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)1112); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)1118); + shortHandle2.set(structSegmt, (short)1119); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 3349); + Assert.assertEquals(resultAddr.toRawLongValue(), shortSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addShortAndShortsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructPointer, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)2222); + shortHandle2.set(structSegmt, (short)4444); + + short result = (short)mh.invoke((short)6666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 13332); + } + } + + @Test + public void test_addShortAndShortsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_SHORT.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromNestedStruct, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)331); + structSegmt.set(JAVA_SHORT, 2, (short)333); + structSegmt.set(JAVA_SHORT, 4, (short)335); + + short result = (short)mh.invoke((short)337, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1336); + } + } + + @Test + public void test_addShortAndShortsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)331); + structSegmt.set(JAVA_SHORT, 2, (short)333); + structSegmt.set(JAVA_SHORT, 4, (short)335); + + short result = (short)mh.invoke((short)337, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1336); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArrayByUpcallMH() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(shortArray.withName("array_elem1"), + JAVA_SHORT.withName("elem2")) : MemoryLayout.structLayout(shortArray.withName("array_elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedShortArray, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1111); + structSegmt.set(JAVA_SHORT, 2, (short)2222); + structSegmt.set(JAVA_SHORT, 4, (short)3333); + + short result = (short)mh.invoke((short)4444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + shortArray.withName("array_elem2")) : MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + shortArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedShortArray_reverseOrder, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1111); + structSegmt.set(JAVA_SHORT, 2, (short)2222); + structSegmt.set(JAVA_SHORT, 4, (short)3333); + + short result = (short)mh.invoke((short)4444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struc_array_elem1"), JAVA_SHORT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1111); + structSegmt.set(JAVA_SHORT, 2, (short)2222); + structSegmt.set(JAVA_SHORT, 4, (short)3333); + structSegmt.set(JAVA_SHORT, 6, (short)4444); + structSegmt.set(JAVA_SHORT, 8, (short)5555); + + short result = (short)mh.invoke((short)6666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23331); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), structArray.withName("struc_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1111); + structSegmt.set(JAVA_SHORT, 2, (short)2222); + structSegmt.set(JAVA_SHORT, 4, (short)3333); + structSegmt.set(JAVA_SHORT, 6, (short)4444); + structSegmt.set(JAVA_SHORT, 8, (short)5555); + + short result = (short)mh.invoke((short)6666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23331); + } + } + + @Test + public void test_add2ShortStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2ShortStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)356); + shortHandle2.set(structSegmt1, (short)345); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)378); + shortHandle2.set(structSegmt2, (short)367); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)734); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)712); + } + } + + @Test + public void test_add2ShortStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2ShortStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)356); + shortHandle2.set(structSegmt1, (short)345); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)378); + shortHandle2.set(structSegmt2, (short)367); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 734); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 2), 712); + } + } + + @Test + public void test_add3ShortStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2"), + JAVA_SHORT.withName("elem3")) : MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2"), + JAVA_SHORT.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle shortHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3ShortStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3ShortStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)325); + shortHandle2.set(structSegmt1, (short)326); + shortHandle3.set(structSegmt1, (short)327); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)334); + shortHandle2.set(structSegmt2, (short)335); + shortHandle3.set(structSegmt2, (short)336); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)659); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)661); + Assert.assertEquals((short)shortHandle3.get(resultSegmt), (short)663); + } + } + + @Test + public void test_addIntAndIntsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1122334); + intHandle2.set(structSegmt, 1234567); + + int result = (int)mh.invoke(2244668, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 4601569); + } + } + + @Test + public void test_addIntAnd5IntsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2"), + JAVA_INT.withName("elem3"), JAVA_INT.withName("elem4"), JAVA_INT.withName("elem5")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle intHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle intHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAnd5IntsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAnd5IntsFromStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1111111); + intHandle2.set(structSegmt, 2222222); + intHandle3.set(structSegmt, 3333333); + intHandle4.set(structSegmt, 2222222); + intHandle5.set(structSegmt, 1111111); + + int result = (int)mh.invoke(4444444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 14444443); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntFromPointerAndIntsFromStruct, + FunctionDescriptor.of(JAVA_INT, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 7654321); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1234567); + intHandle2.set(structSegmt, 2468024); + + int result = (int)mh.invoke(intSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11356912); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStruct_returnIntPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStruct_returnIntPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntFromPointerAndIntsFromStruct_returnIntPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 1122333); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 4455666); + intHandle2.set(structSegmt, 7788999); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(intSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 13366998); + Assert.assertEquals(resultAddr.toRawLongValue(), intSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addIntAndIntsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructPointer, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 11121314); + intHandle2.set(structSegmt, 15161718); + + int result = (int)mh.invoke(19202122, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 45485154); + } + } + + @Test + public void test_addIntAndIntsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_INT.withName("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromNestedStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invoke(33343536, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invoke(33343536, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArrayByUpcallMH() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(intArray.withName("array_elem1"), JAVA_INT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedIntArray, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invoke(4444444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), intArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedIntArray_reverseOrder, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invoke(4444444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_INT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invoke(6666666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invoke(6666666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_add2IntStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224466); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113354); + } + } + + @Test + public void test_add2IntStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2IntStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 110224466); + Assert.assertEquals(resultAddr.get(JAVA_INT, 4), 89113354); + } + } + + @Test + public void test_add3IntStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3IntStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3IntStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + intHandle3.set(structSegmt1, 99001122); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 33445566); + intHandle2.set(structSegmt2, 77889900); + intHandle3.set(structSegmt2, 44332211); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(intHandle1.get(resultSegmt), 44668910); + Assert.assertEquals(intHandle2.get(resultSegmt), 133557688); + Assert.assertEquals(intHandle3.get(resultSegmt), 143333333); + } + } + + @Test + public void test_addLongAndLongsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 1234567890L); + longHandle2.set(structSegmt, 9876543210L); + + long result = (long)mh.invoke(2468024680L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 13579135780L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongFromPointerAndLongsFromStruct, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 1111111111L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 3333333333L); + longHandle2.set(structSegmt, 5555555555L); + + long result = (long)mh.invoke(longSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 9999999999L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStruct_returnLongPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStruct_returnLongPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongFromPointerAndLongsFromStruct_returnLongPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 1122334455L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 6677889900L); + longHandle2.set(structSegmt, 1234567890L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(longSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 9034792245L); + Assert.assertEquals(resultAddr.toRawLongValue(), longSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addLongAndLongsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructPointer, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 224466880022L); + longHandle2.set(structSegmt, 446688002244L); + + long result = (long)mh.invoke(668800224466L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1339955106732L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromNestedStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invoke(778899001122L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invoke(778899001122L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArrayByUpcallMH() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(longArray.withName("array_elem1"), JAVA_LONG.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedLongArray, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 11111111111L); + structSegmt.set(JAVA_LONG, 8, 22222222222L); + structSegmt.set(JAVA_LONG, 16, 33333333333L); + + long result = (long)mh.invoke(44444444444L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), longArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedLongArray_reverseOrder, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 11111111111L); + structSegmt.set(JAVA_LONG, 8, 22222222222L); + structSegmt.set(JAVA_LONG, 16, 33333333333L); + + long result = (long)mh.invoke(44444444444L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_LONG.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 11111111111L); + structSegmt.set(JAVA_LONG, 8, 22222222222L); + structSegmt.set(JAVA_LONG, 16, 33333333333L); + structSegmt.set(JAVA_LONG, 24, 44444444444L); + structSegmt.set(JAVA_LONG, 32, 55555555555L); + + long result = (long)mh.invoke(66666666666L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 233333333331L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 11111111111L); + structSegmt.set(JAVA_LONG, 8, 22222222222L); + structSegmt.set(JAVA_LONG, 16, 33333333333L); + structSegmt.set(JAVA_LONG, 24, 44444444444L); + structSegmt.set(JAVA_LONG, 32, 55555555555L); + + long result = (long)mh.invoke(66666666666L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 233333333331L); + } + } + + @Test + public void test_add2LongStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2LongStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + } + } + + @Test + public void test_add2LongStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2LongStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 5566778899L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 9900112233L); + longHandle2.set(structSegmt2, 3344556677L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 11022446688L); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 8), 8911335576L); + } + } + + @Test + public void test_add3LongStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2"), JAVA_LONG.withName("elem3")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle longHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3LongStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3LongStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + longHandle3.set(structSegmt1, 112233445566L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + longHandle3.set(structSegmt2, 778899001122L); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + Assert.assertEquals(longHandle3.get(resultSegmt), 891132446688L); + } + } + + @Test + public void test_addFloatAndFloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 8.12F); + floatHandle2.set(structSegmt, 9.24F); + + float result = (float)mh.invoke(6.56F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23.92F, 0.01F); + } + } + + @Test + public void test_addFloatAnd5FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2"), + JAVA_FLOAT.withName("elem3"), JAVA_FLOAT.withName("elem4"), JAVA_FLOAT.withName("elem5")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle floatHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle floatHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAnd5FloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAnd5FloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 1.01F); + floatHandle2.set(structSegmt, 1.02F); + floatHandle3.set(structSegmt, 1.03F); + floatHandle4.set(structSegmt, 1.04F); + floatHandle5.set(structSegmt, 1.05F); + + float result = (float)mh.invoke(1.06F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 6.21F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatFromPointerAndFloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + float result = (float)mh.invoke(floatSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 49.69F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStruct_returnFloatPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStruct_returnFloatPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(floatSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 49.69F, 0.01F); + Assert.assertEquals(resultAddr.toRawLongValue(), floatSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addFloatAndFloatsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 35.11F); + floatHandle2.set(structSegmt, 46.22F); + + float result = (float)mh.invoke(79.33F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 160.66F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromNestedStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invoke(37.88F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invoke(37.88F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArrayByUpcallMH() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(floatArray.withName("array_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedFloatArray, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invoke(444.44F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), floatArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invoke(444.44F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invoke(666.66F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invoke(666.66F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_add3FloatStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3FloatStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3FloatStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + floatHandle3.set(structSegmt1, 45.67F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + floatHandle3.set(structSegmt2, 69.72F); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + Assert.assertEquals((float)floatHandle3.get(resultSegmt), 115.39, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2FloatStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2FloatStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 49.46F, 0.01F); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 4), 24.68F, 0.01F); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 2228.111D); + doubleHandle2.set(structSegmt, 2229.221D); + + double result = (double)mh.invoke(3336.333D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 7793.665D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleFromPointerAndDoublesFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 112.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 118.456D); + doubleHandle2.set(structSegmt, 119.789D); + + double result = (double)mh.invoke(doubleSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 350.368D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStruct_returnDoublePointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 212.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 218.456D); + doubleHandle2.set(structSegmt, 219.789D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 650.368D, 0.001D); + Assert.assertEquals(resultAddr.toRawLongValue(), doubleSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructPointer, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 22.111D); + doubleHandle2.set(structSegmt, 44.222D); + + double result = (double)mh.invoke(66.333D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 132.666D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_DOUBLE.withName("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromNestedStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invoke(37.864D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invoke(37.864D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArrayByUpcallMH() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(doubleArray.withName("array_elem1"), JAVA_DOUBLE.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedDoubleArray, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invoke(444.444D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), doubleArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invoke(444.444D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_DOUBLE.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invoke(666.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invoke(666.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2DoubleStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add2DoubleStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 44.666D, 0.001D); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 8), 66.888D, 0.001D); + } + } + + @Test + public void test_add3DoubleStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle doubleHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + NativeSymbol functionSymbol = nativeLibLookup.lookup("add3DoubleStructs_returnStructByUpcallMH").get(); + MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); + + try (ResourceScope scope = ResourceScope.newConfinedScope()) { + NativeSymbol upcallFuncAddr = clinker.upcallStub(UpcallMethodHandles.MH_add3DoubleStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), scope); + SegmentAllocator allocator = SegmentAllocator.nativeAllocator(scope); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + doubleHandle3.set(structSegmt1, 33.123D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + doubleHandle3.set(structSegmt2, 55.456D); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + Assert.assertEquals((double)doubleHandle3.get(resultSegmt), 88.579D, 0.001D); + } + } +} diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMethodHandles.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMethodHandles.java new file mode 100644 index 00000000000..f3cb05cf430 --- /dev/null +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/upcall/UpcallMethodHandles.java @@ -0,0 +1,1887 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep419.upcall; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import static java.lang.invoke.MethodType.methodType; +import java.lang.invoke.VarHandle; + +import jdk.incubator.foreign.Addressable; +import static jdk.incubator.foreign.CLinker.*; +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.SequenceLayout; +import jdk.incubator.foreign.ValueLayout; +import static jdk.incubator.foreign.ValueLayout.*; +import jdk.incubator.foreign.VaList; + +/** + * The helper class that contains all upcall method handles with primitive types or struct + * as arguments. + */ +public class UpcallMethodHandles { + private static final Lookup lookup = MethodHandles.lookup(); + private static ResourceScope scope = ResourceScope.newImplicitScope(); + private static SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope); + private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); + + static final MethodType MT_Bool_Bool_MemSegmt = methodType(boolean.class, boolean.class, MemorySegment.class); + static final MethodType MT_Addr_Bool_MemAddr = methodType(Addressable.class, boolean.class, MemoryAddress.class); + static final MethodType MT_Char_Char_MemSegmt = methodType(char.class, char.class, MemorySegment.class); + static final MethodType MT_Addr_MemAddr_Char = methodType(Addressable.class, MemoryAddress.class, char.class); + static final MethodType MT_Byte_Byte_MemSegmt = methodType(byte.class, byte.class, MemorySegment.class); + static final MethodType MT_Addr_Byte_MemAddr = methodType(Addressable.class, byte.class, MemoryAddress.class); + static final MethodType MT_Short_Short_MemSegmt = methodType(short.class, short.class, MemorySegment.class); + static final MethodType MT_Addr_MemAddr_Short = methodType(Addressable.class, MemoryAddress.class, short.class); + static final MethodType MT_Int_Int_MemSegmt = methodType(int.class, int.class, MemorySegment.class); + static final MethodType MT_Addr_Int_MemAddr = methodType(Addressable.class, int.class, MemoryAddress.class); + static final MethodType MT_Long_Long_MemSegmt = methodType(long.class, long.class, MemorySegment.class); + static final MethodType MT_Addr_MemAddr_Long = methodType(Addressable.class, MemoryAddress.class, long.class); + static final MethodType MT_Long_Int_MemSegmt = methodType(long.class, int.class, MemorySegment.class); + static final MethodType MT_Float_Float_MemSegmt = methodType(float.class, float.class, MemorySegment.class); + static final MethodType MT_Addr_Float_MemAddr = methodType(Addressable.class, float.class, MemoryAddress.class); + static final MethodType MT_Double_Double_MemSegmt = methodType(double.class, double.class, MemorySegment.class); + static final MethodType MT_Addr_MemAddr_Double = methodType(Addressable.class, MemoryAddress.class, double.class); + static final MethodType MT_Addr_MemAddr_MemSegmt = methodType(Addressable.class, MemoryAddress.class, MemorySegment.class); + static final MethodType MT_MemSegmt_MemSegmt_MemSegmt = methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class); + static final MethodType MT_MemSegmt = methodType(MemorySegment.class); + + public static final MethodHandle MH_add2BoolsWithOr; + public static final MethodHandle MH_addBoolAndBoolFromPointerWithOr; + public static final MethodHandle MH_addBoolAndBoolFromPtrWithOr_RetPtr; + public static final MethodHandle MH_addBoolAndBoolFromPtrWithOr_RetArgPtr; + public static final MethodHandle MH_createNewCharFrom2Chars; + public static final MethodHandle MH_createNewCharFromCharAndCharFromPointer; + public static final MethodHandle MH_createNewCharFromCharAndCharFromPtr_RetPtr; + public static final MethodHandle MH_createNewCharFromCharAndCharFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Bytes; + public static final MethodHandle MH_addByteAndByteFromPointer; + public static final MethodHandle MH_addByteAndByteFromPtr_RetPtr; + public static final MethodHandle MH_addByteAndByteFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Shorts; + public static final MethodHandle MH_addShortAndShortFromPointer; + public static final MethodHandle MH_addShortAndShortFromPtr_RetPtr; + public static final MethodHandle MH_addShortAndShortFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Ints; + public static final MethodHandle MH_addIntAndIntFromPointer; + public static final MethodHandle MH_addIntAndIntFromPtr_RetPtr; + public static final MethodHandle MH_addIntAndIntFromPtr_RetArgPtr; + public static final MethodHandle MH_add3Ints; + public static final MethodHandle MH_addIntAndChar; + public static final MethodHandle MH_add2IntsReturnVoid; + public static final MethodHandle MH_add2Longs; + public static final MethodHandle MH_addLongAndLongFromPointer; + public static final MethodHandle MH_addLongAndLongFromPtr_RetPtr; + public static final MethodHandle MH_addLongAndLongFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Floats; + public static final MethodHandle MH_addFloatAndFloatFromPointer; + public static final MethodHandle MH_addFloatAndFloatFromPtr_RetPtr; + public static final MethodHandle MH_addFloatAndFloatFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Doubles; + public static final MethodHandle MH_addDoubleAndDoubleFromPointer; + public static final MethodHandle MH_addDoubleAndDoubleFromPtr_RetPtr; + public static final MethodHandle MH_addDoubleAndDoubleFromPtr_RetArgPtr; + public static final MethodHandle MH_compare; + + public static final MethodHandle MH_addBoolAndBoolsFromStructWithXor; + public static final MethodHandle MH_addBoolAnd20BoolsFromStructWithXor; + public static final MethodHandle MH_addBoolFromPointerAndBoolsFromStructWithXor; + public static final MethodHandle MH_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer; + public static final MethodHandle MH_addBoolAndBoolsFromStructPointerWithXor; + public static final MethodHandle MH_addBoolAndBoolsFromNestedStructWithXor; + public static final MethodHandle MH_addBoolAndBoolsFromNestedStructWithXor_reverseOrder; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedBoolArray; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedStructArray; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2BoolStructsWithXor_returnStruct; + public static final MethodHandle MH_add2BoolStructsWithXor_returnStructPointer; + public static final MethodHandle MH_add3BoolStructsWithXor_returnStruct; + + public static final MethodHandle MH_addByteAndBytesFromStruct; + public static final MethodHandle MH_addByteAnd20BytesFromStruct; + public static final MethodHandle MH_addByteFromPointerAndBytesFromStruct; + public static final MethodHandle MH_addByteFromPointerAndBytesFromStruct_returnBytePointer; + public static final MethodHandle MH_addByteAndBytesFromStructPointer; + public static final MethodHandle MH_addByteAndBytesFromNestedStruct; + public static final MethodHandle MH_addByteAndBytesFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedByteArray; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedByteArray_reverseOrder; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedStructArray; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add1ByteStructs_returnStruct; + public static final MethodHandle MH_add2ByteStructs_returnStruct; + public static final MethodHandle MH_add2ByteStructs_returnStructPointer; + public static final MethodHandle MH_add3ByteStructs_returnStruct; + + public static final MethodHandle MH_addCharAndCharsFromStruct; + public static final MethodHandle MH_addCharAnd10CharsFromStruct; + public static final MethodHandle MH_addCharFromPointerAndCharsFromStruct; + public static final MethodHandle MH_addCharFromPointerAndCharsFromStruct_returnCharPointer; + public static final MethodHandle MH_addCharAndCharsFromStructPointer; + public static final MethodHandle MH_addCharAndCharsFromNestedStruct; + public static final MethodHandle MH_addCharAndCharsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedCharArray; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedCharArray_reverseOrder; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedStructArray; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2CharStructs_returnStruct; + public static final MethodHandle MH_add2CharStructs_returnStructPointer; + public static final MethodHandle MH_add3CharStructs_returnStruct; + + public static final MethodHandle MH_addShortAndShortsFromStruct; + public static final MethodHandle MH_addShortAnd10ShortsFromStruct; + public static final MethodHandle MH_addShortFromPointerAndShortsFromStruct; + public static final MethodHandle MH_addShortFromPointerAndShortsFromStruct_returnShortPointer; + public static final MethodHandle MH_addShortAndShortsFromStructPointer; + public static final MethodHandle MH_addShortAndShortsFromNestedStruct; + public static final MethodHandle MH_addShortAndShortsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedShortArray; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedShortArray_reverseOrder; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedStructArray; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2ShortStructs_returnStruct; + public static final MethodHandle MH_add2ShortStructs_returnStructPointer; + public static final MethodHandle MH_add3ShortStructs_returnStruct; + + public static final MethodHandle MH_addIntAndIntsFromStruct; + public static final MethodHandle MH_addIntAnd5IntsFromStruct; + public static final MethodHandle MH_addIntFromPointerAndIntsFromStruct; + public static final MethodHandle MH_addIntFromPointerAndIntsFromStruct_returnIntPointer; + public static final MethodHandle MH_addIntAndIntsFromStructPointer; + public static final MethodHandle MH_addIntAndIntsFromNestedStruct; + public static final MethodHandle MH_addIntAndIntsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedIntArray; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedIntArray_reverseOrder; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedStructArray; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2IntStructs_returnStruct; + public static final MethodHandle MH_add2IntStructs_returnStructPointer; + public static final MethodHandle MH_add3IntStructs_returnStruct; + + public static final MethodHandle MH_addLongAndLongsFromStruct; + public static final MethodHandle MH_addLongFromPointerAndLongsFromStruct; + public static final MethodHandle MH_addLongFromPointerAndLongsFromStruct_returnLongPointer; + public static final MethodHandle MH_addLongAndLongsFromStructPointer; + public static final MethodHandle MH_addLongAndLongsFromNestedStruct; + public static final MethodHandle MH_addLongAndLongsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedLongArray; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedLongArray_reverseOrder; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedStructArray; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2LongStructs_returnStruct; + public static final MethodHandle MH_add2LongStructs_returnStructPointer; + public static final MethodHandle MH_add3LongStructs_returnStruct; + + public static final MethodHandle MH_addFloatAndFloatsFromStruct; + public static final MethodHandle MH_addFloatAnd5FloatsFromStruct; + public static final MethodHandle MH_addFloatFromPointerAndFloatsFromStruct; + public static final MethodHandle MH_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer; + public static final MethodHandle MH_addFloatAndFloatsFromStructPointer; + public static final MethodHandle MH_addFloatAndFloatsFromNestedStruct; + public static final MethodHandle MH_addFloatAndFloatsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedFloatArray; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedStructArray; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2FloatStructs_returnStruct; + public static final MethodHandle MH_add2FloatStructs_returnStructPointer; + public static final MethodHandle MH_add3FloatStructs_returnStruct; + + public static final MethodHandle MH_addDoubleAndDoublesFromStruct; + public static final MethodHandle MH_addDoubleFromPointerAndDoublesFromStruct; + public static final MethodHandle MH_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer; + public static final MethodHandle MH_addDoubleAndDoublesFromStructPointer; + public static final MethodHandle MH_addDoubleAndDoublesFromNestedStruct; + public static final MethodHandle MH_addDoubleAndDoublesFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedDoubleArray; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedStructArray; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2DoubleStructs_returnStruct; + public static final MethodHandle MH_add2DoubleStructs_returnStructPointer; + public static final MethodHandle MH_add3DoubleStructs_returnStruct; + + public static final MethodHandle MH_addIntAndIntShortFromStruct; + public static final MethodHandle MH_addIntAndShortIntFromStruct; + public static final MethodHandle MH_addIntAndIntLongFromStruct; + public static final MethodHandle MH_addIntAndLongIntFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleIntFromStruct; + public static final MethodHandle MH_addDoubleAndFloatDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleFloatFromStruct; + public static final MethodHandle MH_addDoubleAnd2FloatsDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndDouble2FloatsFromStruct; + public static final MethodHandle MH_addFloatAndInt2FloatsFromStruct; + public static final MethodHandle MH_addFloatAndFloatIntFloatFromStruct; + public static final MethodHandle MH_addDoubleAndIntFloatDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndFloatIntDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndLongDoubleFromStruct; + public static final MethodHandle MH_addFloatAndInt3FloatsFromStruct; + public static final MethodHandle MH_addLongAndLong2FloatsFromStruct; + public static final MethodHandle MH_addFloatAnd3FloatsIntFromStruct; + public static final MethodHandle MH_addLongAndFloatLongFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleFloatIntFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleLongFromStruct; + public static final MethodHandle MH_addLongAnd2FloatsLongFromStruct; + public static final MethodHandle MH_addShortAnd3ShortsCharFromStruct; + public static final MethodHandle MH_addFloatAndIntFloatIntFloatFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleFloatFromStruct; + public static final MethodHandle MH_addDoubleAndFloatDoubleIntFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleIntFromStruct; + public static final MethodHandle MH_addDoubleAndFloatDoubleFloatFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleLongFromStruct; + public static final MethodHandle MH_return254BytesFromStruct; + public static final MethodHandle MH_return4KBytesFromStruct; + + static { + try { + MH_add2BoolsWithOr = lookup.findStatic(UpcallMethodHandles.class, "add2BoolsWithOr", methodType(boolean.class, boolean.class, boolean.class)); //$NON-NLS-1$ + MH_addBoolAndBoolFromPointerWithOr = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolFromPointerWithOr", methodType(boolean.class, boolean.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addBoolAndBoolFromPtrWithOr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolFromPtrWithOr_RetPtr", MT_Addr_Bool_MemAddr); //$NON-NLS-1$ + MH_addBoolAndBoolFromPtrWithOr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolFromPtrWithOr_RetArgPtr", MT_Addr_Bool_MemAddr); //$NON-NLS-1$ + + MH_createNewCharFrom2Chars = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFrom2Chars", methodType(char.class, char.class, char.class)); //$NON-NLS-1$ + MH_createNewCharFromCharAndCharFromPointer = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFromCharAndCharFromPointer", methodType(char.class, MemoryAddress.class, char.class)); //$NON-NLS-1$ + MH_createNewCharFromCharAndCharFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFromCharAndCharFromPtr_RetPtr", MT_Addr_MemAddr_Char); //$NON-NLS-1$ + MH_createNewCharFromCharAndCharFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFromCharAndCharFromPtr_RetArgPtr", MT_Addr_MemAddr_Char); //$NON-NLS-1$ + + MH_add2Bytes = lookup.findStatic(UpcallMethodHandles.class, "add2Bytes", methodType(byte.class, byte.class, byte.class)); //$NON-NLS-1$ + MH_addByteAndByteFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addByteAndByteFromPointer", methodType(byte.class, byte.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addByteAndByteFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addByteAndByteFromPtr_RetPtr", MT_Addr_Byte_MemAddr); //$NON-NLS-1$ + MH_addByteAndByteFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addByteAndByteFromPtr_RetArgPtr", MT_Addr_Byte_MemAddr); //$NON-NLS-1$ + + MH_add2Shorts = lookup.findStatic(UpcallMethodHandles.class, "add2Shorts", methodType(short.class, short.class, short.class)); //$NON-NLS-1$ + MH_addShortAndShortFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortFromPointer", methodType(short.class, MemoryAddress.class, short.class)); //$NON-NLS-1$ + MH_addShortAndShortFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortFromPtr_RetPtr", MT_Addr_MemAddr_Short); //$NON-NLS-1$ + MH_addShortAndShortFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortFromPtr_RetArgPtr", MT_Addr_MemAddr_Short); //$NON-NLS-1$ + + MH_add2Ints = lookup.findStatic(UpcallMethodHandles.class, "add2Ints", methodType(int.class, int.class, int.class)); //$NON-NLS-1$ + MH_addIntAndIntFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntFromPointer", methodType(int.class, int.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addIntAndIntFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntFromPtr_RetPtr", MT_Addr_Int_MemAddr); //$NON-NLS-1$ + MH_addIntAndIntFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntFromPtr_RetArgPtr", MT_Addr_Int_MemAddr); //$NON-NLS-1$ + MH_add3Ints = lookup.findStatic(UpcallMethodHandles.class, "add3Ints", methodType(int.class, int.class, int.class, int.class)); //$NON-NLS-1$ + MH_addIntAndChar = lookup.findStatic(UpcallMethodHandles.class, "addIntAndChar", methodType(int.class, int.class, char.class)); //$NON-NLS-1$ + MH_add2IntsReturnVoid = lookup.findStatic(UpcallMethodHandles.class, "add2IntsReturnVoid", methodType(void.class, int.class, int.class)); //$NON-NLS-1$ + + MH_add2Longs = lookup.findStatic(UpcallMethodHandles.class, "add2Longs", methodType(long.class, long.class, long.class)); //$NON-NLS-1$ + MH_addLongAndLongFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongFromPointer", methodType(long.class, MemoryAddress.class, long.class)); //$NON-NLS-1$ + MH_addLongAndLongFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongFromPtr_RetPtr", MT_Addr_MemAddr_Long); //$NON-NLS-1$ + MH_addLongAndLongFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongFromPtr_RetArgPtr", MT_Addr_MemAddr_Long); //$NON-NLS-1$ + + MH_add2Floats = lookup.findStatic(UpcallMethodHandles.class, "add2Floats", methodType(float.class, float.class, float.class)); //$NON-NLS-1$ + MH_addFloatAndFloatFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatFromPointer", methodType(float.class, float.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addFloatAndFloatFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatFromPtr_RetPtr", MT_Addr_Float_MemAddr); //$NON-NLS-1$ + MH_addFloatAndFloatFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatFromPtr_RetArgPtr", MT_Addr_Float_MemAddr); //$NON-NLS-1$ + + MH_add2Doubles = lookup.findStatic(UpcallMethodHandles.class, "add2Doubles", methodType(double.class, double.class, double.class)); //$NON-NLS-1$ + MH_addDoubleAndDoubleFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFromPointer", methodType(double.class, MemoryAddress.class, double.class)); //$NON-NLS-1$ + MH_addDoubleAndDoubleFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFromPtr_RetPtr", MT_Addr_MemAddr_Double); //$NON-NLS-1$ + MH_addDoubleAndDoubleFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFromPtr_RetArgPtr", MT_Addr_MemAddr_Double); //$NON-NLS-1$ + + MH_compare = lookup.findStatic(UpcallMethodHandles.class, "compare", methodType(int.class, MemoryAddress.class, MemoryAddress.class)); //$NON-NLS-1$ + + MH_addBoolAndBoolsFromStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithXor", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAnd20BoolsFromStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAnd20BoolsFromStructWithXor", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolFromPointerAndBoolsFromStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolFromPointerAndBoolsFromStructWithXor", methodType(boolean.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer = lookup.findStatic(UpcallMethodHandles.class, "addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructPointerWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructPointerWithXor", methodType(boolean.class, boolean.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addBoolAndBoolsFromNestedStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromNestedStructWithXor", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromNestedStructWithXor_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromNestedStructWithXor_reverseOrder", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedBoolArray = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedBoolArray", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedStructArray", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_add2BoolStructsWithXor_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2BoolStructsWithXor_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2BoolStructsWithXor_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2BoolStructsWithXor_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3BoolStructsWithXor_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3BoolStructsWithXor_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addByteAndBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStruct", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAnd20BytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteAnd20BytesFromStruct", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteFromPointerAndBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteFromPointerAndBytesFromStruct", methodType(byte.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addByteFromPointerAndBytesFromStruct_returnBytePointer = lookup.findStatic(UpcallMethodHandles.class, "addByteFromPointerAndBytesFromStruct_returnBytePointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructPointer", methodType(byte.class, byte.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addByteAndBytesFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromNestedStruct", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromNestedStruct_reverseOrder", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedByteArray = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedByteArray", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedByteArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedByteArray_reverseOrder", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedStructArray", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedStructArray_reverseOrder", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_add1ByteStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add1ByteStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2ByteStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2ByteStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2ByteStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2ByteStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3ByteStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3ByteStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addCharAndCharsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStruct", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAnd10CharsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharAnd10CharsFromStruct", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharFromPointerAndCharsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharFromPointerAndCharsFromStruct", methodType(char.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addCharFromPointerAndCharsFromStruct_returnCharPointer = lookup.findStatic(UpcallMethodHandles.class, "addCharFromPointerAndCharsFromStruct_returnCharPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructPointer", methodType(char.class, char.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addCharAndCharsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromNestedStruct", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromNestedStruct_reverseOrder", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedCharArray = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedCharArray", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedCharArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedCharArray_reverseOrder", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedStructArray", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedStructArray_reverseOrder", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_add2CharStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2CharStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2CharStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2CharStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3CharStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3CharStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addShortAndShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAnd10ShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAnd10ShortsFromStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortFromPointerAndShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortFromPointerAndShortsFromStruct", methodType(short.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addShortFromPointerAndShortsFromStruct_returnShortPointer = lookup.findStatic(UpcallMethodHandles.class, "addShortFromPointerAndShortsFromStruct_returnShortPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructPointer", methodType(short.class, short.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addShortAndShortsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromNestedStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromNestedStruct_reverseOrder", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedShortArray = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedShortArray", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedShortArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedShortArray_reverseOrder", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedStructArray", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedStructArray_reverseOrder", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_add2ShortStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2ShortStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2ShortStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2ShortStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3ShortStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3ShortStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addIntAndIntsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAnd5IntsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAnd5IntsFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntFromPointerAndIntsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntFromPointerAndIntsFromStruct", methodType(int.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addIntFromPointerAndIntsFromStruct_returnIntPointer = lookup.findStatic(UpcallMethodHandles.class, "addIntFromPointerAndIntsFromStruct_returnIntPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructPointer", methodType(int.class, int.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addIntAndIntsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromNestedStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromNestedStruct_reverseOrder", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedIntArray = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedIntArray", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedIntArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedIntArray_reverseOrder", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedStructArray", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedStructArray_reverseOrder", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_add2IntStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2IntStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2IntStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2IntStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3IntStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3IntStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addLongAndLongsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongFromPointerAndLongsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongFromPointerAndLongsFromStruct", methodType(long.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addLongFromPointerAndLongsFromStruct_returnLongPointer = lookup.findStatic(UpcallMethodHandles.class, "addLongFromPointerAndLongsFromStruct_returnLongPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructPointer", methodType(long.class, long.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addLongAndLongsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromNestedStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromNestedStruct_reverseOrder", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedLongArray = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedLongArray", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedLongArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedLongArray_reverseOrder", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedStructArray", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedStructArray_reverseOrder", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_add2LongStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2LongStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2LongStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2LongStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3LongStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3LongStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addFloatAndFloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAnd5FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAnd5FloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatFromPointerAndFloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatFromPointerAndFloatsFromStruct", methodType(float.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer = lookup.findStatic(UpcallMethodHandles.class, "addFloatFromPointerAndFloatsFromStruct_returnFloatPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructPointer", methodType(float.class, float.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addFloatAndFloatsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromNestedStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromNestedStruct_reverseOrder", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedFloatArray = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedFloatArray", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedStructArray", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_add2FloatStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2FloatStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2FloatStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2FloatStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3FloatStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3FloatStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addDoubleAndDoublesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleFromPointerAndDoublesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleFromPointerAndDoublesFromStruct", methodType(double.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer = lookup.findStatic(UpcallMethodHandles.class, "addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructPointer", methodType(double.class, double.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromNestedStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromNestedStruct_reverseOrder", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedDoubleArray = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedDoubleArray", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedStructArray", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_add2DoubleStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2DoubleStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2DoubleStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2DoubleStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3DoubleStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3DoubleStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addIntAndIntShortFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntShortFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndShortIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndShortIntFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntLongFromStruct", MT_Long_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndLongIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndLongIntFromStruct", MT_Long_Int_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFloatFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAnd2FloatsDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAnd2FloatsDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDouble2FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDouble2FloatsFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndInt2FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndInt2FloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatIntFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatIntFloatFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntFloatDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntFloatDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatIntDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatIntDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndLongDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndLongDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndInt3FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndInt3FloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLong2FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLong2FloatsFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addFloatAnd3FloatsIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAnd3FloatsIntFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addLongAndFloatLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndFloatLongFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleFloatIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFloatIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleLongFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addLongAnd2FloatsLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAnd2FloatsLongFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addShortAnd3ShortsCharFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAnd3ShortsCharFromStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndIntFloatIntFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndIntFloatIntFloatFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleFloatFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatDoubleIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatDoubleIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatDoubleFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatDoubleFloatFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleLongFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_return254BytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "return254BytesFromStruct", MT_MemSegmt); //$NON-NLS-1$ + MH_return4KBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "return4KBytesFromStruct", MT_MemSegmt); //$NON-NLS-1$ + + } catch (IllegalAccessException | NoSuchMethodException e) { + throw new InternalError(e); + } + } + + public static boolean add2BoolsWithOr(boolean boolArg1, boolean boolArg2) { + boolean result = boolArg1 || boolArg2; + return result; + } + + public static boolean addBoolAndBoolFromPointerWithOr(boolean boolArg1, MemoryAddress boolArg2Addr) { + boolean result = boolArg1 || boolArg2Addr.get(JAVA_BOOLEAN, 0); + return result; + } + + public static Addressable addBoolAndBoolFromPtrWithOr_RetPtr(boolean boolArg1, MemoryAddress boolArg2Addr) { + boolean result = boolArg1 || boolArg2Addr.get(JAVA_BOOLEAN, 0); + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, scope); + resultSegmt.set(JAVA_BOOLEAN, 0, result); + return resultSegmt.address(); + } + + public static Addressable addBoolAndBoolFromPtrWithOr_RetArgPtr(boolean boolArg1, MemoryAddress boolArg2Addr) { + boolean result = boolArg1 || boolArg2Addr.get(JAVA_BOOLEAN, 0); + boolArg2Addr.set(JAVA_BOOLEAN, 0, result); + return boolArg2Addr; + } + + public static char createNewCharFrom2Chars(char charArg1, char charArg2) { + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + return result; + } + + public static char createNewCharFromCharAndCharFromPointer(MemoryAddress charArg1Addr, char charArg2) { + char charArg1 = charArg1Addr.get(JAVA_CHAR, 0); + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + return result; + } + + public static Addressable createNewCharFromCharAndCharFromPtr_RetPtr(MemoryAddress charArg1Addr, char charArg2) { + char charArg1 = charArg1Addr.get(JAVA_CHAR, 0); + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_CHAR.byteSize(), scope); + resultSegmt.set(JAVA_CHAR, 0, result); + return resultSegmt.address(); + } + + public static Addressable createNewCharFromCharAndCharFromPtr_RetArgPtr(MemoryAddress charArg1Addr, char charArg2) { + char charArg1 = charArg1Addr.get(JAVA_CHAR, 0); + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + charArg1Addr.set(JAVA_CHAR, 0, result); + return charArg1Addr; + } + + public static byte add2Bytes(byte byteArg1, byte byteArg2) { + byte byteSum = (byte)(byteArg1 + byteArg2); + return byteSum; + } + + public static byte addByteAndByteFromPointer(byte byteArg1, MemoryAddress byteArg2Addr) { + byte byteArg2 = byteArg2Addr.get(JAVA_BYTE, 0); + byte byteSum = (byte)(byteArg1 + byteArg2); + return byteSum; + } + + public static Addressable addByteAndByteFromPtr_RetPtr(byte byteArg1, MemoryAddress byteArg2Addr) { + byte byteArg2 = byteArg2Addr.get(JAVA_BYTE, 0); + byte byteSum = (byte)(byteArg1 + byteArg2); + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_BYTE.byteSize(), scope); + resultSegmt.set(JAVA_BYTE, 0, byteSum); + return resultSegmt.address(); + } + + public static Addressable addByteAndByteFromPtr_RetArgPtr(byte byteArg1, MemoryAddress byteArg2Addr) { + byte byteArg2 = byteArg2Addr.get(JAVA_BYTE, 0); + byte byteSum = (byte)(byteArg1 + byteArg2); + byteArg2Addr.set(JAVA_BYTE, 0, byteSum); + return byteArg2Addr; + } + + public static short add2Shorts(short shortArg1, short shortArg2) { + short shortSum = (short)(shortArg1 + shortArg2); + return shortSum; + } + + public static short addShortAndShortFromPointer(MemoryAddress shortArg1Addr, short shortArg2) { + short shortArg1 = shortArg1Addr.get(JAVA_SHORT, 0); + short shortSum = (short)(shortArg1 + shortArg2); + return shortSum; + } + + public static Addressable addShortAndShortFromPtr_RetPtr(MemoryAddress shortArg1Addr, short shortArg2) { + short shortArg1 = shortArg1Addr.get(JAVA_SHORT, 0); + short shortSum = (short)(shortArg1 + shortArg2); + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_SHORT.byteSize(), scope); + resultSegmt.set(JAVA_SHORT, 0, shortSum); + return resultSegmt.address(); + } + + public static Addressable addShortAndShortFromPtr_RetArgPtr(MemoryAddress shortArg1Addr, short shortArg2) { + short shortArg1 = shortArg1Addr.get(JAVA_SHORT, 0); + short shortSum = (short)(shortArg1 + shortArg2); + shortArg1Addr.set(JAVA_SHORT, 0, shortSum); + return shortArg1Addr; + } + + public static int add2Ints(int intArg1, int intArg2) { + int intSum = intArg1 + intArg2; + return intSum; + } + + public static int addIntAndIntFromPointer(int intArg1, MemoryAddress intArg2Addr) { + int intArg2 = intArg2Addr.get(JAVA_INT, 0); + int intSum = intArg1 + intArg2; + return intSum; + } + + public static Addressable addIntAndIntFromPtr_RetPtr(int intArg1, MemoryAddress intArg2Addr) { + int intArg2 = intArg2Addr.get(JAVA_INT, 0); + int intSum = intArg1 + intArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_INT.byteSize(), scope); + resultSegmt.set(JAVA_INT, 0, intSum); + return resultSegmt.address(); + } + + public static Addressable addIntAndIntFromPtr_RetArgPtr(int intArg1, MemoryAddress intArg2Addr) { + int intArg2 = intArg2Addr.get(JAVA_INT, 0); + int intSum = intArg1 + intArg2; + intArg2Addr.set(JAVA_INT, 0, intSum); + return intArg2Addr; + } + + public static int add3Ints(int intArg1, int intArg2, int intArg3) { + int intSum = intArg1 + intArg2 + intArg3; + return intSum; + } + + public static int addIntAndChar(int intArg, char charArg) { + int sum = intArg + charArg; + return sum; + } + + public static void add2IntsReturnVoid(int intArg1, int intArg2) { + int intSum = intArg1 + intArg2; + System.out.println("add2IntsReturnVoid: intSum = " + intSum + "\n"); + } + + public static long add2Longs(long longArg1, long longArg2) { + long longSum = longArg1 + longArg2; + return longSum; + } + + public static long addLongAndLongFromPointer(MemoryAddress longArg1Addr, long longArg2) { + long longArg1 = longArg1Addr.get(JAVA_LONG, 0); + long longSum = longArg1 + longArg2; + return longSum; + } + + public static Addressable addLongAndLongFromPtr_RetPtr(MemoryAddress longArg1Addr, long longArg2) { + long longArg1 = longArg1Addr.get(JAVA_LONG, 0); + long longSum = longArg1 + longArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_LONG.byteSize(), scope); + resultSegmt.set(JAVA_LONG, 0, longSum); + return resultSegmt.address(); + } + + public static Addressable addLongAndLongFromPtr_RetArgPtr(MemoryAddress longArg1Addr, long longArg2) { + long longArg1 = longArg1Addr.get(JAVA_LONG, 0); + long longSum = longArg1 + longArg2; + longArg1Addr.set(JAVA_LONG, 0, longSum); + return longArg1Addr; + } + + public static float add2Floats(float floatArg1, float floatArg2) { + float floatSum = floatArg1 + floatArg2; + return floatSum; + } + + public static float addFloatAndFloatFromPointer(float floatArg1, MemoryAddress floatArg2Addr) { + float floatArg2 = floatArg2Addr.get(JAVA_FLOAT, 0); + float floatSum = floatArg1 + floatArg2; + return floatSum; + } + + public static Addressable addFloatAndFloatFromPtr_RetPtr(float floatArg1, MemoryAddress floatArg2Addr) { + float floatArg2 = floatArg2Addr.get(JAVA_FLOAT, 0); + float floatSum = floatArg1 + floatArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_FLOAT.byteSize(), scope); + resultSegmt.set(JAVA_FLOAT, 0, floatSum); + return resultSegmt.address(); + } + + public static Addressable addFloatAndFloatFromPtr_RetArgPtr(float floatArg1, MemoryAddress floatArg2Addr) { + float floatArg2 = floatArg2Addr.get(JAVA_FLOAT, 0); + float floatSum = floatArg1 + floatArg2; + floatArg2Addr.set(JAVA_FLOAT, 0, floatSum); + return floatArg2Addr; + } + + public static double add2Doubles(double doubleArg1, double doubleArg2) { + double doubleSum = doubleArg1 + doubleArg2; + return doubleSum; + } + + public static double addDoubleAndDoubleFromPointer(MemoryAddress doubleArg1Addr, double doubleArg2) { + double doubleArg1 = doubleArg1Addr.get(JAVA_DOUBLE, 0); + double doubleSum = doubleArg1 + doubleArg2; + return doubleSum; + } + + public static Addressable addDoubleAndDoubleFromPtr_RetPtr(MemoryAddress doubleArg1Addr, double doubleArg2) { + double doubleArg1 = doubleArg1Addr.get(JAVA_DOUBLE, 0); + double doubleSum = doubleArg1 + doubleArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_DOUBLE.byteSize(), scope); + resultSegmt.set(JAVA_DOUBLE, 0, doubleSum); + return resultSegmt.address(); + } + + public static Addressable addDoubleAndDoubleFromPtr_RetArgPtr(MemoryAddress doubleArg1Addr, double doubleArg2) { + double doubleArg1 = doubleArg1Addr.get(JAVA_DOUBLE, 0); + double doubleSum = doubleArg1 + doubleArg2; + doubleArg1Addr.set(JAVA_DOUBLE, 0, doubleSum); + return doubleArg1Addr; + } + + public static int compare(MemoryAddress argAddr1, MemoryAddress argAddr2) { + int intArg1 = argAddr1.get(JAVA_INT, 0); + int intArg2 = argAddr2.get(JAVA_INT, 0); + return (intArg1 - intArg2); + } + + public static boolean addBoolAndBoolsFromStructWithXor(boolean arg1, MemorySegment arg2) { + boolean boolSum = arg1 ^ arg2.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 1); + return boolSum; + } + + public static boolean addBoolAnd20BoolsFromStructWithXor(boolean arg1, MemorySegment arg2) { + boolean boolSum = arg1 ^ arg2.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 1) + ^ arg2.get(JAVA_BOOLEAN, 2) ^ arg2.get(JAVA_BOOLEAN, 3) ^ arg2.get(JAVA_BOOLEAN, 4) + ^ arg2.get(JAVA_BOOLEAN, 5) ^ arg2.get(JAVA_BOOLEAN, 6) ^ arg2.get(JAVA_BOOLEAN, 7) + ^ arg2.get(JAVA_BOOLEAN, 8) ^ arg2.get(JAVA_BOOLEAN, 9) ^ arg2.get(JAVA_BOOLEAN, 10) + ^ arg2.get(JAVA_BOOLEAN, 11) ^ arg2.get(JAVA_BOOLEAN, 12) ^ arg2.get(JAVA_BOOLEAN, 13) + ^ arg2.get(JAVA_BOOLEAN, 14) ^ arg2.get(JAVA_BOOLEAN, 15) ^ arg2.get(JAVA_BOOLEAN, 16) + ^ arg2.get(JAVA_BOOLEAN, 17) ^ arg2.get(JAVA_BOOLEAN, 18) ^ arg2.get(JAVA_BOOLEAN, 19); + return boolSum; + } + + public static boolean addBoolFromPointerAndBoolsFromStructWithXor(MemoryAddress arg1Addr, MemorySegment arg2) { + boolean boolSum = arg1Addr.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 1); + return boolSum; + } + + public static Addressable addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + boolean boolSum = arg1Addr.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 1); + arg1Addr.set(JAVA_BOOLEAN, 0, boolSum); + return arg1Addr; + } + + public static boolean addBoolAndBoolsFromStructPointerWithXor(boolean arg1, MemoryAddress arg2Addr) { + boolean boolSum = arg1 ^ arg2Addr.get(JAVA_BOOLEAN, 0) ^ arg2Addr.get(JAVA_BOOLEAN, 1); + return boolSum; + } + + public static boolean addBoolAndBoolsFromNestedStructWithXor(boolean arg1, MemorySegment arg2) { + boolean nestedStructElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedStructElem2 = arg2.get(JAVA_BOOLEAN, 1); + boolean structElem2 = arg2.get(JAVA_BOOLEAN, 2); + boolean boolSum = arg1 ^ nestedStructElem1 ^ nestedStructElem2 ^ structElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromNestedStructWithXor_reverseOrder(boolean arg1, MemorySegment arg2) { + boolean structElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedStructElem1 = arg2.get(JAVA_BOOLEAN, 1); + boolean nestedStructElem2 = arg2.get(JAVA_BOOLEAN, 2); + boolean boolSum = arg1 ^ structElem1 ^ nestedStructElem1 ^ nestedStructElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedBoolArray(boolean arg1, MemorySegment arg2) { + boolean nestedBoolArrayElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedBoolArrayElem2 = arg2.get(JAVA_BOOLEAN, 1); + boolean structElem2 = arg2.get(JAVA_BOOLEAN, 2); + + boolean boolSum = arg1 ^ nestedBoolArrayElem1 ^ nestedBoolArrayElem2 ^ structElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder(boolean arg1, MemorySegment arg2) { + boolean structElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedBoolArrayElem1 = arg2.get(JAVA_BOOLEAN, 1); + boolean nestedBoolArrayElem2 = arg2.get(JAVA_BOOLEAN, 2); + + boolean boolSum = arg1 ^ structElem1 ^ nestedBoolArrayElem1 ^ nestedBoolArrayElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedStructArray(boolean arg1, MemorySegment arg2) { + boolean nestedStructArrayElem1_Elem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedStructArrayElem1_Elem2 = arg2.get(JAVA_BOOLEAN, 1); + boolean nestedStructArrayElem2_Elem1 = arg2.get(JAVA_BOOLEAN, 2); + boolean nestedStructArrayElem2_Elem2 = arg2.get(JAVA_BOOLEAN, 3); + boolean structElem2 = arg2.get(JAVA_BOOLEAN, 4); + + boolean boolSum = arg1 ^ structElem2 + ^ nestedStructArrayElem1_Elem1 ^ nestedStructArrayElem1_Elem2 + ^ nestedStructArrayElem2_Elem1 ^ nestedStructArrayElem2_Elem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder(boolean arg1, MemorySegment arg2) { + boolean structElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedStructArrayElem1_Elem1 = arg2.get(JAVA_BOOLEAN, 1); + boolean nestedStructArrayElem1_Elem2 = arg2.get(JAVA_BOOLEAN, 2); + boolean nestedStructArrayElem2_Elem1 = arg2.get(JAVA_BOOLEAN, 3); + boolean nestedStructArrayElem2_Elem2 = arg2.get(JAVA_BOOLEAN, 4); + + boolean boolSum = arg1 ^ structElem1 + ^ nestedStructArrayElem1_Elem1 ^ nestedStructArrayElem1_Elem2 + ^ nestedStructArrayElem2_Elem1 ^ nestedStructArrayElem2_Elem2; + return boolSum; + } + + public static MemorySegment add2BoolStructsWithXor_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + MemorySegment boolStructSegmt = MemorySegment.allocateNative(structLayout, scope); + boolean boolStruct_Elem1 = arg1.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0); + boolean boolStruct_Elem2 = arg1.get(JAVA_BOOLEAN, 1) ^ arg2.get(JAVA_BOOLEAN, 1); + boolStructSegmt.set(JAVA_BOOLEAN, 0, boolStruct_Elem1); + boolStructSegmt.set(JAVA_BOOLEAN, 1, boolStruct_Elem2); + return boolStructSegmt; + } + + public static Addressable add2BoolStructsWithXor_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + boolean boolStruct_Elem1 = arg1Addr.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0); + boolean boolStruct_Elem2 = arg1Addr.get(JAVA_BOOLEAN, 1) ^ arg2.get(JAVA_BOOLEAN, 1); + arg1Addr.set(JAVA_BOOLEAN, 0, boolStruct_Elem1); + arg1Addr.set(JAVA_BOOLEAN, 1, boolStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3BoolStructsWithXor_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + JAVA_BOOLEAN.withName("elem2"), JAVA_BOOLEAN.withName("elem3"), MemoryLayout.paddingLayout(8)); + MemorySegment boolStructSegmt = MemorySegment.allocateNative(structLayout, scope); + boolean boolStruct_Elem1 = arg1.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0); + boolean boolStruct_Elem2 = arg1.get(JAVA_BOOLEAN, 1) ^ arg2.get(JAVA_BOOLEAN, 1); + boolean boolStruct_Elem3 = arg1.get(JAVA_BOOLEAN, 2) ^ arg2.get(JAVA_BOOLEAN, 2); + boolStructSegmt.set(JAVA_BOOLEAN, 0, boolStruct_Elem1); + boolStructSegmt.set(JAVA_BOOLEAN, 1, boolStruct_Elem2); + boolStructSegmt.set(JAVA_BOOLEAN, 2, boolStruct_Elem3); + return boolStructSegmt; + } + + public static byte addByteAndBytesFromStruct(byte arg1, MemorySegment arg2) { + byte byteSum = (byte)(arg1 + arg2.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 1)); + return byteSum; + } + + public static byte addByteAnd20BytesFromStruct(byte arg1, MemorySegment arg2) { + byte byteSum = (byte)(arg1 + arg2.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 1) + + arg2.get(JAVA_BYTE, 2) + arg2.get(JAVA_BYTE, 3) + arg2.get(JAVA_BYTE, 4) + + arg2.get(JAVA_BYTE, 5) + arg2.get(JAVA_BYTE, 6) + arg2.get(JAVA_BYTE, 7) + + arg2.get(JAVA_BYTE, 8) + arg2.get(JAVA_BYTE, 9) + arg2.get(JAVA_BYTE, 10) + + arg2.get(JAVA_BYTE, 11) + arg2.get(JAVA_BYTE, 12) + arg2.get(JAVA_BYTE, 13) + + arg2.get(JAVA_BYTE, 14) + arg2.get(JAVA_BYTE, 15) + arg2.get(JAVA_BYTE, 16) + + arg2.get(JAVA_BYTE, 17) + arg2.get(JAVA_BYTE, 18) + arg2.get(JAVA_BYTE, 19)); + return byteSum; + } + + public static byte addByteFromPointerAndBytesFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + byte byteSum = (byte)(arg1Addr.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 1)); + return byteSum; + } + + public static Addressable addByteFromPointerAndBytesFromStruct_returnBytePointer(MemoryAddress arg1Addr, MemorySegment arg2) { + byte byteSum = (byte)(arg1Addr.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 1)); + arg1Addr.set(JAVA_BYTE, 0, byteSum); + return arg1Addr; + } + + public static byte addByteAndBytesFromStructPointer(byte arg1, MemoryAddress arg2Addr) { + byte byteSum = (byte)(arg1 + arg2Addr.get(JAVA_BYTE, 0) + arg2Addr.get(JAVA_BYTE, 1)); + return byteSum; + } + + public static byte addByteAndBytesFromNestedStruct(byte arg1, MemorySegment arg2) { + byte nestedStructElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedStructElem2 = arg2.get(JAVA_BYTE, 1); + byte structElem2 = arg2.get(JAVA_BYTE, 2); + + byte byteSum = (byte)(arg1 + nestedStructElem1 + nestedStructElem2 + structElem2); + return byteSum; + } + + public static byte addByteAndBytesFromNestedStruct_reverseOrder(byte arg1, MemorySegment arg2) { + byte structElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedStructElem1 = arg2.get(JAVA_BYTE, 1); + byte nestedStructElem2 = arg2.get(JAVA_BYTE, 2); + + byte byteSum = (byte)(arg1 + structElem1 + nestedStructElem1 + nestedStructElem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedByteArray(byte arg1, MemorySegment arg2) { + byte nestedByteArrayElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedByteArrayElem2 = arg2.get(JAVA_BYTE, 1); + byte structElem2 = arg2.get(JAVA_BYTE, 2); + + byte byteSum = (byte)(arg1 + nestedByteArrayElem1 + nestedByteArrayElem2 + structElem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedByteArray_reverseOrder(byte arg1, MemorySegment arg2) { + byte structElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedByteArrayElem1 = arg2.get(JAVA_BYTE, 1); + byte nestedByteArrayElem2 = arg2.get(JAVA_BYTE, 2); + + byte byteSum = (byte)(arg1 + structElem1 + nestedByteArrayElem1 + nestedByteArrayElem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedStructArray(byte arg1, MemorySegment arg2) { + byte nestedStructArrayElem1_Elem1 = arg2.get(JAVA_BYTE, 0); + byte nestedStructArrayElem1_Elem2 = arg2.get(JAVA_BYTE, 1); + byte nestedStructArrayElem2_Elem1 = arg2.get(JAVA_BYTE, 2); + byte nestedStructArrayElem2_Elem2 = arg2.get(JAVA_BYTE, 3); + byte structElem2 = arg2.get(JAVA_BYTE, 4); + + byte byteSum = (byte)(arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedStructArray_reverseOrder(byte arg1, MemorySegment arg2) { + byte structElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedStructArrayElem1_Elem1 = arg2.get(JAVA_BYTE, 1); + byte nestedStructArrayElem1_Elem2 = arg2.get(JAVA_BYTE, 2); + byte nestedStructArrayElem2_Elem1 = arg2.get(JAVA_BYTE, 3); + byte nestedStructArrayElem2_Elem2 = arg2.get(JAVA_BYTE, 4); + + byte byteSum = (byte)(arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return byteSum; + } + + public static MemorySegment add1ByteStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1")); + MemorySegment byteStructSegmt = MemorySegment.allocateNative(structLayout, scope); + byte byteStruct_Elem1 = (byte)(arg1.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0)); + byteStructSegmt.set(JAVA_BYTE, 0, byteStruct_Elem1); + return byteStructSegmt; + } + + public static MemorySegment add2ByteStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + MemorySegment byteStructSegmt = MemorySegment.allocateNative(structLayout, scope); + byte byteStruct_Elem1 = (byte)(arg1.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0)); + byte byteStruct_Elem2 = (byte)(arg1.get(JAVA_BYTE, 1) + arg2.get(JAVA_BYTE, 1)); + byteStructSegmt.set(JAVA_BYTE, 0, byteStruct_Elem1); + byteStructSegmt.set(JAVA_BYTE, 1, byteStruct_Elem2); + return byteStructSegmt; + } + + public static Addressable add2ByteStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + byte byteStruct_Elem1 = (byte)(arg1Addr.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0)); + byte byteStruct_Elem2 = (byte)(arg1Addr.get(JAVA_BYTE, 1) + arg2.get(JAVA_BYTE, 1)); + arg1Addr.set(JAVA_BYTE, 0, byteStruct_Elem1); + arg1Addr.set(JAVA_BYTE, 1, byteStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3ByteStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2"), + JAVA_BYTE.withName("elem3"), MemoryLayout.paddingLayout(8)); + MemorySegment byteStructSegmt = MemorySegment.allocateNative(structLayout, scope); + byte byteStruct_Elem1 = (byte)(arg1.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0)); + byte byteStruct_Elem2 = (byte)(arg1.get(JAVA_BYTE, 1) + arg2.get(JAVA_BYTE, 1)); + byte byteStruct_Elem3 = (byte)(arg1.get(JAVA_BYTE, 2) + arg2.get(JAVA_BYTE, 2)); + byteStructSegmt.set(JAVA_BYTE, 0, byteStruct_Elem1); + byteStructSegmt.set(JAVA_BYTE, 1, byteStruct_Elem2); + byteStructSegmt.set(JAVA_BYTE, 2, byteStruct_Elem3); + return byteStructSegmt; + } + + public static char addCharAndCharsFromStruct(char arg1, MemorySegment arg2) { + char result = (char)(arg1 + arg2.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 2) - 2 * 'A'); + return result; + } + + public static char addCharAnd10CharsFromStruct(char arg1, MemorySegment arg2) { + char result = (char)(arg1 + arg2.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 2) + + arg2.get(JAVA_CHAR, 4) + arg2.get(JAVA_CHAR, 6) + arg2.get(JAVA_CHAR, 8) + + arg2.get(JAVA_CHAR, 10) + arg2.get(JAVA_CHAR, 12) + arg2.get(JAVA_CHAR, 14) + + arg2.get(JAVA_CHAR, 16) + arg2.get(JAVA_CHAR, 18) - 10 * 'A'); + return result; + } + + public static char addCharFromPointerAndCharsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + char result = (char)(arg1Addr.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 2) - 2 * 'A'); + return result; + } + + public static Addressable addCharFromPointerAndCharsFromStruct_returnCharPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + char result = (char)(arg1Addr.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 2) - 2 * 'A'); + arg1Addr.set(JAVA_CHAR, 0, result); + return arg1Addr; + } + + public static char addCharAndCharsFromStructPointer(char arg1, MemoryAddress arg2Addr) { + char result = (char)(arg1 + arg2Addr.get(JAVA_CHAR, 0) + arg2Addr.get(JAVA_CHAR, 2) - 2 * 'A'); + return result; + } + + public static char addCharAndCharsFromNestedStruct(char arg1, MemorySegment arg2) { + char nestedStructElem1 = arg2.get(JAVA_CHAR, 0); + char nestedStructElem2 = arg2.get(JAVA_CHAR, 2); + char structElem2 = arg2.get(JAVA_CHAR, 4); + + char result = (char)(arg1 + nestedStructElem1 + nestedStructElem2 + structElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromNestedStruct_reverseOrder(char arg1, MemorySegment arg2) { + char structElem1 = arg2.get(JAVA_CHAR, 0); + char nestedStructElem1 = arg2.get(JAVA_CHAR, 2); + char nestedStructElem2 = arg2.get(JAVA_CHAR, 4); + + char result = (char)(arg1 + structElem1 + nestedStructElem1 + nestedStructElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedCharArray(char arg1, MemorySegment arg2) { + char nestedCharArrayElem1 = arg2.get(JAVA_CHAR, 0); + char nestedCharArrayElem2 = arg2.get(JAVA_CHAR, 2); + char structElem2 = arg2.get(JAVA_CHAR, 4); + + char result = (char)(arg1 + nestedCharArrayElem1 + nestedCharArrayElem2 + structElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedCharArray_reverseOrder(char arg1, MemorySegment arg2) { + char structElem1 = arg2.get(JAVA_CHAR, 0); + char nestedCharArrayElem1 = arg2.get(JAVA_CHAR, 2); + char nestedCharArrayElem2 = arg2.get(JAVA_CHAR, 4); + + char result = (char)(arg1 + structElem1 + nestedCharArrayElem1 + nestedCharArrayElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedStructArray(char arg1, MemorySegment arg2) { + char nestedStructArrayElem1_Elem1 = arg2.get(JAVA_CHAR, 0); + char nestedStructArrayElem1_Elem2 = arg2.get(JAVA_CHAR, 2); + char nestedStructArrayElem2_Elem1 = arg2.get(JAVA_CHAR, 4); + char nestedStructArrayElem2_Elem2 = arg2.get(JAVA_CHAR, 6); + char structElem2 = arg2.get(JAVA_CHAR, 8); + + char result = (char)(arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2 - 5 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedStructArray_reverseOrder(char arg1, MemorySegment arg2) { + char structElem1 = arg2.get(JAVA_CHAR, 0); + char nestedStructArrayElem1_Elem1 = arg2.get(JAVA_CHAR, 2); + char nestedStructArrayElem1_Elem2 = arg2.get(JAVA_CHAR, 4); + char nestedStructArrayElem2_Elem1 = arg2.get(JAVA_CHAR, 6); + char nestedStructArrayElem2_Elem2 = arg2.get(JAVA_CHAR, 8); + + char result = (char)(arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2 - 5 * 'A'); + return result; + } + + public static MemorySegment add2CharStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + MemorySegment charStructSegmt = MemorySegment.allocateNative(structLayout, scope); + char charStruct_Elem1 = (char)(arg1.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) - 'A'); + char charStruct_Elem2 = (char)(arg1.get(JAVA_CHAR, 2) + arg2.get(JAVA_CHAR, 2) - 'A'); + charStructSegmt.set(JAVA_CHAR, 0, charStruct_Elem1); + charStructSegmt.set(JAVA_CHAR, 2, charStruct_Elem2); + return charStructSegmt; + } + + public static Addressable add2CharStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + char charStruct_Elem1 = (char)(arg1Addr.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) - 'A'); + char charStruct_Elem2 = (char)(arg1Addr.get(JAVA_CHAR, 2) + arg2.get(JAVA_CHAR, 2) - 'A'); + arg1Addr.set(JAVA_CHAR, 0, charStruct_Elem1); + arg1Addr.set(JAVA_CHAR, 2, charStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3CharStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3"), MemoryLayout.paddingLayout(16)); + MemorySegment charStructSegmt = MemorySegment.allocateNative(structLayout, scope); + char charStruct_Elem1 = (char)(arg1.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) - 'A'); + char charStruct_Elem2 = (char)(arg1.get(JAVA_CHAR, 2) + arg2.get(JAVA_CHAR, 2) - 'A'); + char charStruct_Elem3 = (char)(arg1.get(JAVA_CHAR, 4) + arg2.get(JAVA_CHAR, 4) - 'A'); + charStructSegmt.set(JAVA_CHAR, 0, charStruct_Elem1); + charStructSegmt.set(JAVA_CHAR, 2, charStruct_Elem2); + charStructSegmt.set(JAVA_CHAR, 4, charStruct_Elem3); + return charStructSegmt; + } + + public static short addShortAndShortsFromStruct(short arg1, MemorySegment arg2) { + short shortSum = (short)(arg1 + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2)); + return shortSum; + } + + public static short addShortAnd10ShortsFromStruct(short arg1, MemorySegment arg2) { + short shortSum = (short)(arg1 + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2) + + arg2.get(JAVA_SHORT, 4) + arg2.get(JAVA_SHORT, 6) + arg2.get(JAVA_SHORT, 8) + + arg2.get(JAVA_SHORT, 10) + arg2.get(JAVA_SHORT, 12) + arg2.get(JAVA_SHORT, 14) + + arg2.get(JAVA_SHORT, 16) + arg2.get(JAVA_SHORT, 18)); + return shortSum; + } + + public static short addShortFromPointerAndShortsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + short shortSum = (short)(arg1Addr.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2)); + return shortSum; + } + + public static Addressable addShortFromPointerAndShortsFromStruct_returnShortPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + short shortSum = (short)(arg1Addr.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2)); + arg1Addr.set(JAVA_SHORT, 0, shortSum); + return arg1Addr; + } + + public static short addShortAndShortsFromStructPointer(short arg1, MemoryAddress arg2Addr) { + short shortSum = (short)(arg1 + arg2Addr.get(JAVA_SHORT, 0) + arg2Addr.get(JAVA_SHORT, 2)); + return shortSum; + } + + public static short addShortAndShortsFromNestedStruct(short arg1, MemorySegment arg2) { + short nestedStructElem1 = arg2.get(JAVA_SHORT, 0); + short nestedStructElem2 = arg2.get(JAVA_SHORT, 2); + short structElem2 = arg2.get(JAVA_SHORT, 4); + + short shortSum = (short)(arg1 + nestedStructElem1 + nestedStructElem2 + structElem2); + return shortSum; + } + + public static short addShortAndShortsFromNestedStruct_reverseOrder(short arg1, MemorySegment arg2) { + short structElem1 = arg2.get(JAVA_SHORT, 0); + short nestedStructElem1 = arg2.get(JAVA_SHORT, 2); + short nestedStructElem2 = arg2.get(JAVA_SHORT, 4); + + short shortSum = (short)(arg1 + structElem1 + nestedStructElem1 + nestedStructElem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedShortArray(short arg1, MemorySegment arg2) { + short nestedShortArrayElem1 = arg2.get(JAVA_SHORT, 0); + short nestedShortArrayElem2 = arg2.get(JAVA_SHORT, 2); + short structElem2 = arg2.get(JAVA_SHORT, 4); + + short shortSum = (short)(arg1 + nestedShortArrayElem1 + nestedShortArrayElem2 + structElem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedShortArray_reverseOrder(short arg1, MemorySegment arg2) { + short structElem1 = arg2.get(JAVA_SHORT, 0); + short nestedShortArrayElem1 = arg2.get(JAVA_SHORT, 2); + short nestedShortArrayElem2 = arg2.get(JAVA_SHORT, 4); + + short shortSum = (short)(arg1 + structElem1 + nestedShortArrayElem1 + nestedShortArrayElem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedStructArray(short arg1, MemorySegment arg2) { + short nestedStructArrayElem1_Elem1 = arg2.get(JAVA_SHORT, 0); + short nestedStructArrayElem1_Elem2 = arg2.get(JAVA_SHORT, 2); + short nestedStructArrayElem2_Elem1 = arg2.get(JAVA_SHORT, 4); + short nestedStructArrayElem2_Elem2 = arg2.get(JAVA_SHORT, 6); + short structElem2 = arg2.get(JAVA_SHORT, 8); + + short shortSum = (short)(arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedStructArray_reverseOrder(short arg1, MemorySegment arg2) { + short structElem1 = arg2.get(JAVA_SHORT, 0); + short nestedStructArrayElem1_Elem1 = arg2.get(JAVA_SHORT, 2); + short nestedStructArrayElem1_Elem2 = arg2.get(JAVA_SHORT, 4); + short nestedStructArrayElem2_Elem1 = arg2.get(JAVA_SHORT, 6); + short nestedStructArrayElem2_Elem2 = arg2.get(JAVA_SHORT, 8); + + short shortSum = (short)(arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return shortSum; + } + + public static MemorySegment add2ShortStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + MemorySegment shortStructSegmt = MemorySegment.allocateNative(structLayout, scope); + short shortStruct_Elem1 = (short)(arg1.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0)); + short shortStruct_Elem2 = (short)(arg1.get(JAVA_SHORT, 2) + arg2.get(JAVA_SHORT, 2)); + shortStructSegmt.set(JAVA_SHORT, 0, shortStruct_Elem1); + shortStructSegmt.set(JAVA_SHORT, 2, shortStruct_Elem2); + return shortStructSegmt; + } + + public static Addressable add2ShortStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + short shortStruct_Elem1 = (short)(arg1Addr.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0)); + short shortStruct_Elem2 = (short)(arg1Addr.get(JAVA_SHORT, 2) + arg2.get(JAVA_SHORT, 2)); + arg1Addr.set(JAVA_SHORT, 0, shortStruct_Elem1); + arg1Addr.set(JAVA_SHORT, 2, shortStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3ShortStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2"), + JAVA_SHORT.withName("elem3"), MemoryLayout.paddingLayout(16)); + MemorySegment shortStructSegmt = MemorySegment.allocateNative(structLayout, scope); + short shortStruct_Elem1 = (short)(arg1.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0)); + short shortStruct_Elem2 = (short)(arg1.get(JAVA_SHORT, 2) + arg2.get(JAVA_SHORT, 2)); + short shortStruct_Elem3 = (short)(arg1.get(JAVA_SHORT, 4) + arg2.get(JAVA_SHORT, 4)); + shortStructSegmt.set(JAVA_SHORT, 0, shortStruct_Elem1); + shortStructSegmt.set(JAVA_SHORT, 2, shortStruct_Elem2); + shortStructSegmt.set(JAVA_SHORT, 4, shortStruct_Elem3); + return shortStructSegmt; + } + + public static int addIntAndIntsFromStruct(int arg1, MemorySegment arg2) { + int intSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 4); + return intSum; + } + + public static int addIntAnd5IntsFromStruct(int arg1, MemorySegment arg2) { + int intSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 4) + + arg2.get(JAVA_INT, 8) + arg2.get(JAVA_INT, 12) + arg2.get(JAVA_INT, 16); + return intSum; + } + + public static int addIntFromPointerAndIntsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + int intSum = arg1Addr.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 4); + return intSum; + } + + public static Addressable addIntFromPointerAndIntsFromStruct_returnIntPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + int intSum = arg1Addr.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 4); + arg1Addr.set(JAVA_INT, 0, intSum); + return arg1Addr; + } + + public static int addIntAndIntsFromStructPointer(int arg1, MemoryAddress arg2Addr) { + int intSum = arg1 + arg2Addr.get(JAVA_INT, 0) + arg2Addr.get(JAVA_INT, 4); + return intSum; + } + + public static int addIntAndIntsFromNestedStruct(int arg1, MemorySegment arg2) { + int nestedStructElem1 = arg2.get(JAVA_INT, 0); + int nestedStructElem2 = arg2.get(JAVA_INT, 4); + int structElem2 = arg2.get(JAVA_INT, 8); + + int intSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return intSum; + } + + public static int addIntAndIntsFromNestedStruct_reverseOrder(int arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + int nestedStructElem1 = arg2.get(JAVA_INT, 4); + int nestedStructElem2 = arg2.get(JAVA_INT, 8); + + int intSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedIntArray(int arg1, MemorySegment arg2) { + int nestedIntArrayElem1 = arg2.get(JAVA_INT, 0); + int nestedIntArrayElem2 = arg2.get(JAVA_INT, 4); + int structElem2 = arg2.get(JAVA_INT, 8); + + int intSum = arg1 + nestedIntArrayElem1 + nestedIntArrayElem2 + structElem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedIntArray_reverseOrder(int arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + int nestedIntArrayElem1 = arg2.get(JAVA_INT, 4); + int nestedIntArrayElem2 = arg2.get(JAVA_INT, 8); + + int intSum = arg1 + structElem1 + nestedIntArrayElem1 + nestedIntArrayElem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedStructArray(int arg1, MemorySegment arg2) { + int nestedStructArrayElem1_Elem1 = arg2.get(JAVA_INT, 0); + int nestedStructArrayElem1_Elem2 = arg2.get(JAVA_INT, 4); + int nestedStructArrayElem2_Elem1 = arg2.get(JAVA_INT, 8); + int nestedStructArrayElem2_Elem2 = arg2.get(JAVA_INT, 12); + int structElem2 = arg2.get(JAVA_INT, 16); + + int intSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedStructArray_reverseOrder(int arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + int nestedStructArrayElem1_Elem1 = arg2.get(JAVA_INT, 4); + int nestedStructArrayElem1_Elem2 = arg2.get(JAVA_INT, 8); + int nestedStructArrayElem2_Elem1 = arg2.get(JAVA_INT, 12); + int nestedStructArrayElem2_Elem2 = arg2.get(JAVA_INT, 16); + + int intSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return intSum; + } + + public static MemorySegment add2IntStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + MemorySegment intStructSegmt = MemorySegment.allocateNative(structLayout, scope); + int intStruct_Elem1 = arg1.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0); + int intStruct_Elem2 = arg1.get(JAVA_INT, 4) + arg2.get(JAVA_INT, 4); + intStructSegmt.set(JAVA_INT, 0, intStruct_Elem1); + intStructSegmt.set(JAVA_INT, 4, intStruct_Elem2); + return intStructSegmt; + } + + public static Addressable add2IntStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + int intSum_Elem1 = arg1Addr.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0); + int intSum_Elem2 = arg1Addr.get(JAVA_INT, 4) + arg2.get(JAVA_INT, 4); + arg1Addr.set(JAVA_INT, 0, intSum_Elem1); + arg1Addr.set(JAVA_INT, 4, intSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3IntStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2"), JAVA_INT.withName("elem3")); + MemorySegment intStructSegmt = MemorySegment.allocateNative(structLayout, scope); + int intStruct_Elem1 = arg1.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0); + int intStruct_Elem2 = arg1.get(JAVA_INT, 4) + arg2.get(JAVA_INT, 4); + int intStruct_Elem3 = arg1.get(JAVA_INT, 8) + arg2.get(JAVA_INT, 8); + intStructSegmt.set(JAVA_INT, 0, intStruct_Elem1); + intStructSegmt.set(JAVA_INT, 4, intStruct_Elem2); + intStructSegmt.set(JAVA_INT, 8, intStruct_Elem3); + return intStructSegmt; + } + + public static long addLongAndLongsFromStruct(long arg1, MemorySegment arg2) { + long longSum = arg1 + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 8); + return longSum; + } + + public static long addLongFromPointerAndLongsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + long longSum = arg1Addr.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 8); + return longSum; + } + + public static Addressable addLongFromPointerAndLongsFromStruct_returnLongPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + long longSum = arg1Addr.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 8); + arg1Addr.set(JAVA_LONG, 0, longSum); + return arg1Addr; + } + + public static long addLongAndLongsFromStructPointer(long arg1, MemoryAddress arg2Addr) { + long longSum = arg1 + arg2Addr.get(JAVA_LONG, 0) + arg2Addr.get(JAVA_LONG, 8); + return longSum; + } + + public static long addLongAndLongsFromNestedStruct(long arg1, MemorySegment arg2) { + long nestedStructElem1 = arg2.get(JAVA_LONG, 0); + long nestedStructElem2 = arg2.get(JAVA_LONG, 8); + long structElem2 = arg2.get(JAVA_LONG, 16); + + long longSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return longSum; + } + + public static long addLongAndLongsFromNestedStruct_reverseOrder(long arg1, MemorySegment arg2) { + long structElem1 = arg2.get(JAVA_LONG, 0); + long nestedStructElem1 = arg2.get(JAVA_LONG, 8); + long nestedStructElem2 = arg2.get(JAVA_LONG, 16); + + long longSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedLongArray(long arg1, MemorySegment arg2) { + long nestedLongrrayElem1 = arg2.get(JAVA_LONG, 0); + long nestedLongrrayElem2 = arg2.get(JAVA_LONG, 8); + long structElem2 = arg2.get(JAVA_LONG, 16); + + long longSum = arg1 + nestedLongrrayElem1 + nestedLongrrayElem2 + structElem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedLongArray_reverseOrder(long arg1, MemorySegment arg2) { + long structElem1 = arg2.get(JAVA_LONG, 0); + long nestedLongrrayElem1 = arg2.get(JAVA_LONG, 8); + long nestedLongrrayElem2 = arg2.get(JAVA_LONG, 16); + + long longSum = arg1 + structElem1 + nestedLongrrayElem1 + nestedLongrrayElem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedStructArray(long arg1, MemorySegment arg2) { + long nestedStructArrayElem1_Elem1 = arg2.get(JAVA_LONG, 0); + long nestedStructArrayElem1_Elem2 = arg2.get(JAVA_LONG, 8); + long nestedStructArrayElem2_Elem1 = arg2.get(JAVA_LONG, 16); + long nestedStructArrayElem2_Elem2 = arg2.get(JAVA_LONG, 24); + long structElem2 = arg2.get(JAVA_LONG, 32); + + long longSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedStructArray_reverseOrder(long arg1, MemorySegment arg2) { + long structElem1 = arg2.get(JAVA_LONG, 0); + long nestedStructArrayElem1_Elem1 = arg2.get(JAVA_LONG, 8); + long nestedStructArrayElem1_Elem2 = arg2.get(JAVA_LONG, 16); + long nestedStructArrayElem2_Elem1 = arg2.get(JAVA_LONG, 24); + long nestedStructArrayElem2_Elem2 = arg2.get(JAVA_LONG, 32); + + long longSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return longSum; + } + + public static MemorySegment add2LongStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + MemorySegment longStructSegmt = MemorySegment.allocateNative(structLayout, scope); + long longStruct_Elem1 = arg1.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0); + long longStruct_Elem2 = arg1.get(JAVA_LONG, 8) + arg2.get(JAVA_LONG, 8); + longStructSegmt.set(JAVA_LONG, 0, longStruct_Elem1); + longStructSegmt.set(JAVA_LONG, 8, longStruct_Elem2); + return longStructSegmt; + } + + public static Addressable add2LongStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + long longSum_Elem1 = arg1Addr.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0); + long longSum_Elem2 = arg1Addr.get(JAVA_LONG, 8) + arg2.get(JAVA_LONG, 8); + arg1Addr.set(JAVA_LONG, 0, longSum_Elem1); + arg1Addr.set(JAVA_LONG, 8, longSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3LongStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2"), JAVA_LONG.withName("elem3")); + MemorySegment longStructSegmt = MemorySegment.allocateNative(structLayout, scope); + long longStruct_Elem1 = arg1.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0); + long longStruct_Elem2 = arg1.get(JAVA_LONG, 8) + arg2.get(JAVA_LONG, 8); + long longStruct_Elem3 = arg1.get(JAVA_LONG, 16) + arg2.get(JAVA_LONG, 16); + longStructSegmt.set(JAVA_LONG, 0, longStruct_Elem1); + longStructSegmt.set(JAVA_LONG, 8, longStruct_Elem2); + longStructSegmt.set(JAVA_LONG, 16, longStruct_Elem3); + return longStructSegmt; + } + + public static float addFloatAndFloatsFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4); + return floatSum; + } + + public static float addFloatAnd5FloatsFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4) + + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_FLOAT, 12) + arg2.get(JAVA_FLOAT, 16); + return floatSum; + } + + public static float addFloatFromPointerAndFloatsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + float floatSum = arg1Addr.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4); + return floatSum; + } + + public static Addressable addFloatFromPointerAndFloatsFromStruct_returnFloatPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + float floatSum = arg1Addr.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4); + arg1Addr.set(JAVA_FLOAT, 0, floatSum); + return arg1Addr; + } + + public static float addFloatAndFloatsFromStructPointer(float arg1, MemoryAddress arg2Addr) { + float floatSum = arg1 + arg2Addr.get(JAVA_FLOAT, 0) + arg2Addr.get(JAVA_FLOAT, 4); + return floatSum; + } + + public static float addFloatAndFloatsFromNestedStruct(float arg1, MemorySegment arg2) { + float nestedStructElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedStructElem2 = arg2.get(JAVA_FLOAT, 4); + float structElem2 = arg2.get(JAVA_FLOAT, 8); + + float floatSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromNestedStruct_reverseOrder(float arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedStructElem1 = arg2.get(JAVA_FLOAT, 4); + float nestedStructElem2 = arg2.get(JAVA_FLOAT, 8); + + float floatSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedFloatArray(float arg1, MemorySegment arg2) { + float nestedFloatArrayElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedFloatArrayElem2 = arg2.get(JAVA_FLOAT, 4); + float structElem2 = arg2.get(JAVA_FLOAT, 8); + + float floatSum = arg1 + nestedFloatArrayElem1 + nestedFloatArrayElem2 + structElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder(float arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedFloatArrayElem1 = arg2.get(JAVA_FLOAT, 4); + float nestedFloatArrayElem2 = arg2.get(JAVA_FLOAT, 8); + + float floatSum = arg1 + structElem1 + nestedFloatArrayElem1 + nestedFloatArrayElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedStructArray(float arg1, MemorySegment arg2) { + float nestedStructArrayElem1_Elem1 = arg2.get(JAVA_FLOAT, 0); + float nestedStructArrayElem1_Elem2 = arg2.get(JAVA_FLOAT, 4); + float nestedStructArrayElem2_Elem1 = arg2.get(JAVA_FLOAT, 8); + float nestedStructArrayElem2_Elem2 = arg2.get(JAVA_FLOAT, 12); + float structElem2 = arg2.get(JAVA_FLOAT, 16); + + float floatSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder(float arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedStructArrayElem1_Elem1 = arg2.get(JAVA_FLOAT, 4); + float nestedStructArrayElem1_Elem2 = arg2.get(JAVA_FLOAT, 8); + float nestedStructArrayElem2_Elem1 = arg2.get(JAVA_FLOAT, 12); + float nestedStructArrayElem2_Elem2 = arg2.get(JAVA_FLOAT, 16); + + float floatSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return floatSum; + } + + public static MemorySegment add2FloatStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + MemorySegment floatStructSegmt = MemorySegment.allocateNative(structLayout, scope); + float floatStruct_Elem1 = arg1.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0); + float floatStruct_Elem2 = arg1.get(JAVA_FLOAT, 4) + arg2.get(JAVA_FLOAT, 4); + floatStructSegmt.set(JAVA_FLOAT, 0, floatStruct_Elem1); + floatStructSegmt.set(JAVA_FLOAT, 4, floatStruct_Elem2); + return floatStructSegmt; + } + + public static Addressable add2FloatStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + float floatSum_Elem1 = arg1Addr.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0); + float floatSum_Elem2 = arg1Addr.get(JAVA_FLOAT, 4) + arg2.get(JAVA_FLOAT, 4); + arg1Addr.set(JAVA_FLOAT, 0, floatSum_Elem1); + arg1Addr.set(JAVA_FLOAT, 4, floatSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3FloatStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + MemorySegment floatStructSegmt = MemorySegment.allocateNative(structLayout, scope); + float floatStruct_Elem1 = arg1.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0); + float floatStruct_Elem2 = arg1.get(JAVA_FLOAT, 4) + arg2.get(JAVA_FLOAT, 4); + float floatStruct_Elem3 = arg1.get(JAVA_FLOAT, 8) + arg2.get(JAVA_FLOAT, 8); + floatStructSegmt.set(JAVA_FLOAT, 0, floatStruct_Elem1); + floatStructSegmt.set(JAVA_FLOAT, 4, floatStruct_Elem2); + floatStructSegmt.set(JAVA_FLOAT, 8, floatStruct_Elem3); + return floatStructSegmt; + } + + public static double addDoubleAndDoublesFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleFromPointerAndDoublesFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + double doubleSum = arg1Addr.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static Addressable addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer(MemoryAddress arg1Addr, MemorySegment arg2) { + double doubleSum = arg1Addr.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 8); + arg1Addr.set(JAVA_DOUBLE, 0, doubleSum); + return arg1Addr; + } + + public static double addDoubleAndDoublesFromStructPointer(double arg1, MemoryAddress arg2Addr) { + double doubleSum = arg1 + arg2Addr.get(JAVA_DOUBLE, 0) + arg2Addr.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleAndDoublesFromNestedStruct(double arg1, MemorySegment arg2) { + double nestedStructElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedStructElem2 = arg2.get(JAVA_DOUBLE, 8); + double structElem2 = arg2.get(JAVA_DOUBLE, 16); + + double doubleSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromNestedStruct_reverseOrder(double arg1, MemorySegment arg2) { + double structElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedStructElem1 = arg2.get(JAVA_DOUBLE, 8); + double nestedStructElem2 = arg2.get(JAVA_DOUBLE, 16); + + double doubleSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedDoubleArray(double arg1, MemorySegment arg2) { + double nestedDoubleArrayElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedDoubleArrayElem2 = arg2.get(JAVA_DOUBLE, 8); + double structElem2 = arg2.get(JAVA_DOUBLE, 16); + + double doubleSum = arg1 + nestedDoubleArrayElem1 + nestedDoubleArrayElem2 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder(double arg1, MemorySegment arg2) { + double structElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedDoubleArrayElem1 = arg2.get(JAVA_DOUBLE, 8); + double nestedDoubleArrayElem2 = arg2.get(JAVA_DOUBLE, 16); + + double doubleSum = arg1 + structElem1 + nestedDoubleArrayElem1 + nestedDoubleArrayElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedStructArray(double arg1, MemorySegment arg2) { + double nestedStructArrayElem1_Elem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedStructArrayElem1_Elem2 = arg2.get(JAVA_DOUBLE, 8); + double nestedStructArrayElem2_Elem1 = arg2.get(JAVA_DOUBLE, 16); + double nestedStructArrayElem2_Elem2 = arg2.get(JAVA_DOUBLE, 24); + double structElem2 = arg2.get(JAVA_DOUBLE, 32); + + double doubleSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder(double arg1, MemorySegment arg2) { + double structElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedStructArrayElem1_Elem1 = arg2.get(JAVA_DOUBLE, 8); + double nestedStructArrayElem1_Elem2 = arg2.get(JAVA_DOUBLE, 16); + double nestedStructArrayElem2_Elem1 = arg2.get(JAVA_DOUBLE, 24); + double nestedStructArrayElem2_Elem2 = arg2.get(JAVA_DOUBLE, 32); + + double doubleSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return doubleSum; + } + + public static MemorySegment add2DoubleStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + MemorySegment doubleStructSegmt = MemorySegment.allocateNative(structLayout, scope); + double doubleStruct_Elem1 = arg1.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0); + double doubleStruct_Elem2 = arg1.get(JAVA_DOUBLE, 8) + arg2.get(JAVA_DOUBLE, 8); + doubleStructSegmt.set(JAVA_DOUBLE, 0, doubleStruct_Elem1); + doubleStructSegmt.set(JAVA_DOUBLE, 8, doubleStruct_Elem2); + return doubleStructSegmt; + } + + public static Addressable add2DoubleStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + double doubleSum_Elem1 = arg1Addr.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0); + double doubleSum_Elem2 = arg1Addr.get(JAVA_DOUBLE, 8) + arg2.get(JAVA_DOUBLE, 8); + arg1Addr.set(JAVA_DOUBLE, 0, doubleSum_Elem1); + arg1Addr.set(JAVA_DOUBLE, 8, doubleSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3DoubleStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + MemorySegment doubleStructSegmt = MemorySegment.allocateNative(structLayout, scope); + double doubleStruct_Elem1 = arg1.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0); + double doubleStruct_Elem2 = arg1.get(JAVA_DOUBLE, 8) + arg2.get(JAVA_DOUBLE, 8); + double doubleStruct_Elem3 = arg1.get(JAVA_DOUBLE, 16) + arg2.get(JAVA_DOUBLE, 16); + doubleStructSegmt.set(JAVA_DOUBLE, 0, doubleStruct_Elem1); + doubleStructSegmt.set(JAVA_DOUBLE, 8, doubleStruct_Elem2); + doubleStructSegmt.set(JAVA_DOUBLE, 16, doubleStruct_Elem3); + return doubleStructSegmt; + } + + public static int addIntAndIntShortFromStruct(int arg1, MemorySegment arg2) { + int intSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_SHORT, 4); + return intSum; + } + + public static int addIntAndShortIntFromStruct(int arg1, MemorySegment arg2) { + int intSum = arg1 + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_INT, 4); + return intSum; + } + + public static long addIntAndIntLongFromStruct(int arg1, MemorySegment arg2) { + long longSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_LONG, 8); + return longSum; + } + + public static long addIntAndLongIntFromStruct(int arg1, MemorySegment arg2) { + long longSum = arg1 + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_INT, 8); + return longSum; + } + + public static double addDoubleAndIntDoubleFromStruct(double arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + double structElem2 = arg2.get(JAVA_DOUBLE, isAixOS ? 4 : 8); + double doubleSum = arg1 + structElem1 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoubleIntFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_INT, 8); + return doubleSum; + } + + public static double addDoubleAndFloatDoubleFromStruct(double arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + double structElem2 = arg2.get(JAVA_DOUBLE, isAixOS ? 4 : 8); + double doubleSum = arg1 + structElem1 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoubleFloatFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_FLOAT, 8); + return doubleSum; + } + + public static double addDoubleAnd2FloatsDoubleFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleAndDouble2FloatsFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_FLOAT, 12); + return doubleSum; + } + + public static float addFloatAndInt2FloatsFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_FLOAT, 4) + arg2.get(JAVA_FLOAT, 8); + return floatSum; + } + + public static float addFloatAndFloatIntFloatFromStruct(float arg1, MemorySegment arg2) { + float structElem2 = Integer.valueOf(arg2.get(JAVA_INT, 4)).floatValue(); + float floatSum = arg1 + arg2.get(JAVA_FLOAT, 0) + structElem2 + arg2.get(JAVA_FLOAT, 8); + return floatSum; + } + + public static double addDoubleAndIntFloatDoubleFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_FLOAT, 4) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleAndFloatIntDoubleFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_INT, 4) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleAndLongDoubleFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static float addFloatAndInt3FloatsFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_FLOAT, 4) + + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_FLOAT, 12); + return floatSum; + } + + public static long addLongAndLong2FloatsFromStruct(long arg1, MemorySegment arg2) { + long structElem1 = arg2.get(JAVA_LONG, 0); + long structElem2 = Float.valueOf(arg2.get(JAVA_FLOAT, 8)).longValue(); + long structElem3 = Float.valueOf(arg2.get(JAVA_FLOAT, 12)).longValue(); + long longSum = arg1 + structElem1 + structElem2 + structElem3; + return longSum; + } + + public static float addFloatAnd3FloatsIntFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4) + + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_INT, 12); + return floatSum; + } + + public static long addLongAndFloatLongFromStruct(long arg1, MemorySegment arg2) { + long structElem1 = Float.valueOf(arg2.get(JAVA_FLOAT, 0)).longValue(); + long structElem2 = arg2.get(JAVA_LONG, 8); + long longSum = arg1 + structElem1 + structElem2; + return longSum; + } + + public static double addDoubleAndDoubleFloatIntFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_INT, 12); + return doubleSum; + } + + public static double addDoubleAndDoubleLongFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_LONG, 8); + return doubleSum; + } + + public static long addLongAnd2FloatsLongFromStruct(long arg1, MemorySegment arg2) { + long structElem1 = Float.valueOf(arg2.get(JAVA_FLOAT, 0)).longValue(); + long structElem2 = Float.valueOf(arg2.get(JAVA_FLOAT, 4)).longValue(); + long structElem3 = arg2.get(JAVA_LONG, 8); + long longSum = arg1 + structElem1 + structElem2 + structElem3; + return longSum; + } + + public static short addShortAnd3ShortsCharFromStruct(short arg1, MemorySegment arg2) { + short shortSum = (short)(arg1 + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2) + + arg2.get(JAVA_SHORT, 4) + arg2.get(JAVA_CHAR, 6)); + return shortSum; + } + + public static float addFloatAndIntFloatIntFloatFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_FLOAT, 4)+ arg2.get(JAVA_INT, 8) + arg2.get(JAVA_FLOAT, 12); + return floatSum; + } + + public static double addDoubleAndIntDoubleFloatFromStruct(double arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + /* The size of [int, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + double structElem2 = arg2.get(JAVA_DOUBLE, isAixOS ? 4 : 8); + float structElem3 = arg2.get(JAVA_FLOAT, isAixOS ? 12 : 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static double addDoubleAndFloatDoubleIntFromStruct(double arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + /* The size of [float, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + double structElem2 = arg2.get(JAVA_DOUBLE, isAixOS ? 4 : 8); + int structElem3 = arg2.get(JAVA_INT, isAixOS ? 12 : 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static double addDoubleAndIntDoubleIntFromStruct(double arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + /* The size of [int, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + double structElem2 = arg2.get(JAVA_DOUBLE, isAixOS ? 4 : 8); + int structElem3 = arg2.get(JAVA_INT, isAixOS ? 12 : 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static double addDoubleAndFloatDoubleFloatFromStruct(double arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + /* The size of [float, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + double structElem2 = arg2.get(JAVA_DOUBLE, isAixOS ? 4 : 8); + float structElem3 = arg2.get(JAVA_FLOAT, isAixOS ? 12 : 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static double addDoubleAndIntDoubleLongFromStruct(double arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + /* The size of [int, double, long] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 24 bytes with padding on other platforms. + */ + double structElem2 = arg2.get(JAVA_DOUBLE, isAixOS ? 4 : 8); + double structElem3 = arg2.get(JAVA_LONG, isAixOS ? 12 : 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static MemorySegment return254BytesFromStruct() { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(254, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + MemorySegment byteArrStruSegment = MemorySegment.allocateNative(structLayout, scope); + + for (int i = 0; i < 254; i++) { + byteArrStruSegment.set(JAVA_BYTE, i, (byte)i); + } + return byteArrStruSegment; + } + + public static MemorySegment return4KBytesFromStruct() { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(4096, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + MemorySegment byteArrStruSegment = MemorySegment.allocateNative(structLayout, scope); + + for (int i = 0; i < 4096; i++) { + byteArrStruSegment.set(JAVA_BYTE, i, (byte)i); + } + return byteArrStruSegment; + } +} diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/valist/ApiTests.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/valist/ApiTests.java new file mode 100644 index 00000000000..c8c07f74e33 --- /dev/null +++ b/test/functional/Java18andUp/src/org/openj9/test/jep419/valist/ApiTests.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2022, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep419.valist; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.VarHandle; + +import jdk.incubator.foreign.GroupLayout; +import jdk.incubator.foreign.MemoryAddress; +import jdk.incubator.foreign.MemoryLayout; +import jdk.incubator.foreign.MemoryLayout.PathElement; +import jdk.incubator.foreign.MemorySegment; +import jdk.incubator.foreign.ResourceScope; +import jdk.incubator.foreign.SegmentAllocator; +import jdk.incubator.foreign.VaList; +import static jdk.incubator.foreign.ValueLayout.*; +import static jdk.incubator.foreign.VaList.Builder; + +/** + * Test cases for JEP 419: Foreign Linker API (Second Incubator) for the vararg list in VaList API specific cases. + */ +@Test(groups = { "level.sanity" }) +public class ApiTests { +} diff --git a/test/functional/Java18andUp/src/org/openj9/test/jep419/valist/VaListTests.java b/test/functional/Java18andUp/src/org/openj9/test/jep419/valist/VaListTests.java deleted file mode 100644 index e7fc6989f9a..00000000000 --- a/test/functional/Java18andUp/src/org/openj9/test/jep419/valist/VaListTests.java +++ /dev/null @@ -1,128 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2021, 2022 IBM Corp. and others - * - * This program and the accompanying materials are made available under - * the terms of the Eclipse Public License 2.0 which accompanies this - * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ - * or the Apache License, Version 2.0 which accompanies this distribution and - * is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * This Source Code may also be made available under the following - * Secondary Licenses when the conditions for such availability set - * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU - * General Public License, version 2 with the GNU Classpath - * Exception [1] and GNU General Public License, version 2 with the - * OpenJDK Assembly Exception [2]. - * - * [1] https://www.gnu.org/software/classpath/license.html - * [2] http://openjdk.java.net/legal/assembly-exception.html - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception - *******************************************************************************/ -package org.openj9.test.jep419.valist; - -import org.testng.annotations.Test; -import org.testng.Assert; -import org.testng.AssertJUnit; - -import org.testng.annotations.Test; -import org.testng.Assert; -import org.testng.AssertJUnit; - -import java.lang.invoke.MethodHandle; -import jdk.incubator.foreign.CLinker; -import jdk.incubator.foreign.FunctionDescriptor; -import jdk.incubator.foreign.MemoryAddress; -import jdk.incubator.foreign.MemoryLayout; -import jdk.incubator.foreign.MemorySegment; -import jdk.incubator.foreign.NativeSymbol; -import jdk.incubator.foreign.ResourceScope; -import jdk.incubator.foreign.SegmentAllocator; -import jdk.incubator.foreign.SymbolLookup; -import jdk.incubator.foreign.VaList; -import static jdk.incubator.foreign.ValueLayout.*; -import static jdk.incubator.foreign.VaList.Builder; - -/** - * Test cases for JEP 419: Foreign Linker API (Second Incubator) for the vararg list in downcall. - */ -@Test(groups = { "level.sanity" }) -public class VaListTests { - private static boolean isWinOS = System.getProperty("os.name").toLowerCase().contains("win"); - private static CLinker clinker = CLinker.systemCLinker(); - - static { - System.loadLibrary("clinkerffitests"); - } - private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); - - @Test - public void test_addIntsWithVaList() throws Throwable { - NativeSymbol functionSymbol = nativeLibLookup.lookup("addIntsFromVaList").get(); - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); - - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) - .addVarg(JAVA_INT, 800) - .addVarg(JAVA_INT, 900) - .addVarg(JAVA_INT, 1000), scope); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - int result = (int)mh.invoke(4, vaList); - Assert.assertEquals(result, 3400); - } - } - - @Test - public void test_addLongsWithVaList() throws Throwable { - NativeSymbol functionSymbol = nativeLibLookup.lookup("addLongsFromVaList").get(); - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS); - - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_LONG, 700000L) - .addVarg(JAVA_LONG, 800000L) - .addVarg(JAVA_LONG, 900000L) - .addVarg(JAVA_LONG, 1000000L), scope); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - long result = (long)mh.invoke(4, vaList); - Assert.assertEquals(result, 3400000L); - } - } - - @Test - public void test_addDoublesWithVaList() throws Throwable { - NativeSymbol functionSymbol = nativeLibLookup.lookup("addDoublesFromVaList").get(); - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS); - - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_DOUBLE, 150.1001D) - .addVarg(JAVA_DOUBLE, 160.2002D) - .addVarg(JAVA_DOUBLE, 170.1001D) - .addVarg(JAVA_DOUBLE, 180.2002D), scope); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - double result = (double)mh.invoke(4, vaList); - Assert.assertEquals(result, 660.6006D); - } - } - - @Test - public void test_vprintfFromDefaultLibWithVaList() throws Throwable { - /* Disable the test on Windows given a misaligned access exception coming from - * java.base/java.lang.invoke.MemoryAccessVarHandleBase triggered by CLinker.toCString() - * is also captured on OpenJDK/Hotspot. - */ - if (!isWinOS) { - NativeSymbol functionSymbol = clinker.lookup("vprintf").get(); - FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS); - - try (ResourceScope scope = ResourceScope.newConfinedScope()) { - SegmentAllocator nativeAllocator = SegmentAllocator.nativeAllocator(scope); - MemorySegment formatSegmt = nativeAllocator.allocateUtf8String("%d * %d = %d\n"); - VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 7) - .addVarg(JAVA_INT, 8) - .addVarg(JAVA_INT, 56), scope); - MethodHandle mh = clinker.downcallHandle(functionSymbol, fd); - mh.invoke(formatSegmt, vaList); - } - } - } -} diff --git a/test/functional/Java18andUp/testng_180.xml b/test/functional/Java18andUp/testng_180.xml index b051d9a0662..4f790572845 100644 --- a/test/functional/Java18andUp/testng_180.xml +++ b/test/functional/Java18andUp/testng_180.xml @@ -32,15 +32,26 @@ + + + + + + + + + + + - + diff --git a/test/functional/Java19andUp/playlist.xml b/test/functional/Java19andUp/playlist.xml index 456f485ea6e..ca82d3366c1 100644 --- a/test/functional/Java19andUp/playlist.xml +++ b/test/functional/Java19andUp/playlist.xml @@ -52,4 +52,91 @@ 19+ + + + Jep424Tests_testLinkerFfi_DownCall + + --enable-preview + + $(ADD_JVM_LIB_DIR_TO_LIBPATH) $(JAVA_COMMAND) $(JVM_OPTIONS) \ + --enable-native-access=ALL-UNNAMED \ + -Dforeign.restricted=permit \ + -cp $(Q)$(LIB_DIR)$(D)asm.jar$(P)$(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(TEST_RESROOT)$(D)GeneralTest.jar$(Q) \ + org.testng.TestNG -d $(REPORTDIR) $(Q)$(TEST_RESROOT)$(D)testng_190.xml$(Q) -testnames Jep424Tests_testLinkerFfi_DownCall \ + -groups $(TEST_GROUP) \ + -excludegroups $(DEFAULT_EXCLUDE); \ + $(TEST_STATUS) + + bits.64,^arch.x86,^arch.arm,^arch.riscv,^os.zos,^os.sunos + + sanity + + + functional + + + openj9 + + + 19+ + + + + + Jep424Tests_testLinkerFfi_UpCall + + --enable-preview + + $(ADD_JVM_LIB_DIR_TO_LIBPATH) $(JAVA_COMMAND) $(JVM_OPTIONS) \ + --enable-native-access=ALL-UNNAMED \ + -Dforeign.restricted=permit \ + -cp $(Q)$(LIB_DIR)$(D)asm.jar$(P)$(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(TEST_RESROOT)$(D)GeneralTest.jar$(Q) \ + org.testng.TestNG -d $(REPORTDIR) $(Q)$(TEST_RESROOT)$(D)testng_190.xml$(Q) -testnames Jep424Tests_testLinkerFfi_UpCall \ + -groups $(TEST_GROUP) \ + -excludegroups $(DEFAULT_EXCLUDE); \ + $(TEST_STATUS) + + bits.64,^arch.x86,^arch.arm,^arch.riscv,^os.zos,^os.sunos + + sanity + + + functional + + + openj9 + + + 19+ + + + + + Jep424Tests_testLinkerFfi_VaList + + --enable-preview + + $(ADD_JVM_LIB_DIR_TO_LIBPATH) $(JAVA_COMMAND) $(JVM_OPTIONS) \ + --enable-native-access=ALL-UNNAMED \ + -Dforeign.restricted=permit \ + -cp $(Q)$(LIB_DIR)$(D)asm.jar$(P)$(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(TEST_RESROOT)$(D)GeneralTest.jar$(Q) \ + org.testng.TestNG -d $(REPORTDIR) $(Q)$(TEST_RESROOT)$(D)testng_190.xml$(Q) -testnames Jep424Tests_testLinkerFfi_VaList \ + -groups $(TEST_GROUP) \ + -excludegroups $(DEFAULT_EXCLUDE); \ + $(TEST_STATUS) + + bits.64,^arch.x86,^arch.aarch64,^arch.390,^arch.arm,^arch.riscv,^os.zos,^os.sunos + + sanity + + + functional + + + openj9 + + + 19+ + + diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/InvalidDownCallTests.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/InvalidDownCallTests.java new file mode 100644 index 00000000000..e5557dc4db7 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/InvalidDownCallTests.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; +import static org.testng.Assert.fail; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.SymbolLookup; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in downcall, + * which verifies the illegal cases including unsupported layouts, etc. + * Note: the majority of illegal cases are removed given the corresponding method type + * is deduced from the function descriptor which is verified in OpenJDK. + */ +@Test(groups = { "level.sanity" }) +public class InvalidDownCallTests { + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + private static final SymbolLookup defaultLibLookup = linker.defaultLookup(); + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Unsupported layout.*") + public void test_invalidMemoryLayoutForIntType() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, MemoryLayout.paddingLayout(32)); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoid").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + fail("Failed to throw out IllegalArgumentException in the case of the invalid MemoryLayout"); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Unsupported layout.*") + public void test_invalidMemoryLayoutForMemoryAddress() throws Throwable { + Addressable functionSymbol = defaultLibLookup.lookup("strlen").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, MemoryLayout.paddingLayout(64)); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + fail("Failed to throw out IllegalArgumentException in the case of the invalid MemoryLayout"); + } + + @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Unsupported layout.*") + public void test_invalidMemoryLayoutForReturnType() throws Throwable { + Addressable functionSymbol = defaultLibLookup.lookup("strlen").get(); + FunctionDescriptor fd = FunctionDescriptor.of(MemoryLayout.paddingLayout(64), JAVA_LONG); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + fail("Failed to throw out IllegalArgumentException in the case of the invalid MemoryLayout"); + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiCallTests.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiCallTests.java new file mode 100644 index 00000000000..7ed0559e2b7 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiCallTests.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.SymbolLookup; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in downcall, + * which verifies multiple downcalls with the same or different layouts or argument/return types. + */ +@Test(groups = { "level.sanity" }) +public class MultiCallTests { + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_twoCallsWithSameFuncDescriptor() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(112, 123); + Assert.assertEquals(result, 235); + + mh = linker.downcallHandle(functionSymbol, fd); + result = (int)mh.invokeExact(235, 439); + Assert.assertEquals(result, 674); + } + + @Test + public void test_twoCallsWithDiffFuncDescriptor() throws Throwable { + FunctionDescriptor fd1 = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol1 = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol1, fd1); + int result = (int)mh.invokeExact(112, 123); + Assert.assertEquals(result, 235); + + FunctionDescriptor fd2 = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol2 = nativeLibLookup.lookup("add3Ints").get(); + mh = linker.downcallHandle(functionSymbol2, fd2); + result = (int)mh.invokeExact(112, 123, 235); + Assert.assertEquals(result, 470); + } + + @Test + public void test_multiCallsWithMixedFuncDescriptors() throws Throwable { + FunctionDescriptor fd1 = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol1 = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol1, fd1); + int result = (int)mh.invokeExact(112, 123); + Assert.assertEquals(result, 235); + + FunctionDescriptor fd2 = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol2 = nativeLibLookup.lookup("add3Ints").get(); + mh = linker.downcallHandle(functionSymbol2, fd2); + result = (int)mh.invokeExact(112, 123, 235); + Assert.assertEquals(result, 470); + + FunctionDescriptor fd3 = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT); + Addressable functionSymbol3 = nativeLibLookup.lookup("add2IntsReturnVoid").get(); + mh = linker.downcallHandle(functionSymbol3, fd3); + mh.invokeExact(454, 398); + + mh = linker.downcallHandle(functionSymbol1, fd1); + result = (int)mh.invokeExact(234, 567); + Assert.assertEquals(result, 801); + + mh = linker.downcallHandle(functionSymbol2, fd2); + result = (int)mh.invokeExact(312, 323, 334); + Assert.assertEquals(result, 969); + + mh = linker.downcallHandle(functionSymbol3, fd3); + mh.invokeExact(539, 672); + } + + @Test + public void test_twoCallsWithDiffReturnType() throws Throwable { + FunctionDescriptor fd1 = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol1 = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol1, fd1); + int result = (int)mh.invokeExact(112, 123); + Assert.assertEquals(result, 235); + + FunctionDescriptor fd2 = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT); + Addressable functionSymbol2 = nativeLibLookup.lookup("add2IntsReturnVoid").get(); + mh = linker.downcallHandle(functionSymbol2, fd2); + mh.invokeExact(454, 398); + } + + @Test + public void test_multiCallsWithSameArgLayouts() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol1 = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol1, fd); + int intResult = (int)mh.invokeExact(112, 123); + Assert.assertEquals(intResult, 235); + + mh = linker.downcallHandle(functionSymbol1, fd); + intResult = (int)mh.invokeExact(234, 567); + Assert.assertEquals(intResult, 801); + + FunctionDescriptor fd2 = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT); + Addressable functionSymbol2 = nativeLibLookup.lookup("add2IntsReturnVoid").get(); + mh = linker.downcallHandle(functionSymbol2, fd2); + mh.invokeExact(454, 398); + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests1.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests1.java new file mode 100644 index 00000000000..667ee373595 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests1.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.SegmentAllocator; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in downcall, which + * verifies the downcalls with the same downcall handlder (cached as soft reference in OpenJDK) + * in multithreading. + */ +@Test(groups = { "level.sanity" }) +public class MultiThreadingTests1 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_twoThreadsWithSameFuncDesc_SameDowncallHandler() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 215); + int result = (int)mh.invoke(321, intSegmt); + Assert.assertEquals(result, 536); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr2 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 215); + int result = (int)mh.invoke(322, intSegmt); + Assert.assertEquals(result, 537); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + thr1.setUncaughtExceptionHandler(this); + thr2.setUncaughtExceptionHandler(this); + + thr1.start(); + thr2.start(); + + thr1.join(); + thr2.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests2.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests2.java new file mode 100644 index 00000000000..5f5ceac981f --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests2.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SymbolLookup; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in downcall, which + * verifies the downcalls with the shared downcall handlder (cached as soft reference in OpenJDK) + * in multithreading. + */ +@Test(groups = { "level.sanity" }) +public class MultiThreadingTests2 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + + static { + System.loadLibrary("clinkerffitests"); + } + private static final GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + private static final FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + private static final Addressable functionSymbol = SymbolLookup.loaderLookup().lookup("add2IntStructs_returnStruct").get(); + private static final MethodHandle mh = Linker.nativeLinker().downcallHandle(functionSymbol, fd); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_twoThreadsWithSameFuncDesc_SharedDowncallHandler() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224466); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113354); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr2 = new Thread(){ + public void run() { + try { + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001123); + intHandle2.set(structSegmt2, 33445567); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224467); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113355); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + thr1.setUncaughtExceptionHandler(this); + thr2.setUncaughtExceptionHandler(this); + + thr1.start(); + thr2.start(); + + thr1.join(); + thr2.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests3.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests3.java new file mode 100644 index 00000000000..51efde78825 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests3.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.SymbolLookup; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in downcall, + * which verifies the downcalls with the diffrent layouts and arguments/return types in multithreading. + */ +@Test(groups = { "level.sanity" }) +public class MultiThreadingTests3 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_twoThreadsWithDiffFuncDescriptor() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(112, 123); + Assert.assertEquals(result, 235); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr2 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add3Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(112, 123, 235); + Assert.assertEquals(result, 470); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + thr1.setUncaughtExceptionHandler(this); + thr2.setUncaughtExceptionHandler(this); + + thr1.start(); + thr2.start(); + + thr1.join(); + thr2.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests4.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests4.java new file mode 100644 index 00000000000..9d3ff9869df --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests4.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.SymbolLookup; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in downcall, + * which verifies the downcalls with the diffrent return types in multithreading. + */ +@Test(groups = { "level.sanity" }) +public class MultiThreadingTests4 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_twoThreadsWithDiffReturnType() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(112, 123); + Assert.assertEquals(result, 235); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr2 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoid").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + mh.invokeExact(454, 398); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + thr1.setUncaughtExceptionHandler(this); + thr2.setUncaughtExceptionHandler(this); + + thr1.start(); + thr2.start(); + + thr1.join(); + thr2.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests5.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests5.java new file mode 100644 index 00000000000..e243511ce68 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/MultiThreadingTests5.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.SymbolLookup; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in downcall, + * which verifies multiple downcalls combined with the diffrent layouts/arguments/return types in multithreading. + */ +@Test(groups = { "level.sanity" }) +public class MultiThreadingTests5 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_multiThreadsWithMixedFuncDescriptors() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(128, 246); + Assert.assertEquals(result, 374); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr2 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add3Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(112, 642, 971); + Assert.assertEquals(result, 1725); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr3 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + boolean result = (boolean)mh.invokeExact(true, false); + Assert.assertEquals(result, true); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr4 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(416, 728); + Assert.assertEquals(result, 1144); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr5 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add3Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(1012, 1023, 2035); + Assert.assertEquals(result, 4070); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + Thread thr6 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + boolean result = (boolean)mh.invokeExact(false, false); + Assert.assertEquals(result, false); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + + thr1.setUncaughtExceptionHandler(this); + thr2.setUncaughtExceptionHandler(this); + thr3.setUncaughtExceptionHandler(this); + thr4.setUncaughtExceptionHandler(this); + thr5.setUncaughtExceptionHandler(this); + thr6.setUncaughtExceptionHandler(this); + + thr1.start(); + thr2.start(); + thr3.start(); + thr4.start(); + thr5.start(); + thr6.start(); + + thr6.join(); + thr5.join(); + thr4.join(); + thr3.join(); + thr2.join(); + thr1.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/PrimitiveTypeTests1.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/PrimitiveTypeTests1.java new file mode 100644 index 00000000000..8c3b0d0fca9 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/PrimitiveTypeTests1.java @@ -0,0 +1,296 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SymbolLookup; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in downcall. + * + * Note: the test suite is intended for the following Clinker API: + * MethodHandle downcallHandle(Addressable symbol, FunctionDescriptor function) + */ +@Test(groups = { "level.sanity" }) +public class PrimitiveTypeTests1 { + private static Linker linker = Linker.nativeLinker(); + private static MemorySession session = MemorySession.openImplicit(); + private static SegmentAllocator nativeAllocator = SegmentAllocator.newNativeArena(session); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + private static final SymbolLookup defaultLibLookup = linker.defaultLookup(); + + @Test + public void test_addTwoBoolsWithOr_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + boolean result = (boolean)mh.invokeExact(true, false); + Assert.assertEquals(result, true); + } + + @Test + public void test_addBoolAndBoolFromPointerWithOr_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPointerWithOr").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + boolean result = (boolean)mh.invoke(false, boolSegmt); + Assert.assertEquals(result, true); + } + + @Test + public void test_generateNewChar_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, JAVA_CHAR); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFrom2Chars").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + char result = (char)mh.invokeExact('B', 'D'); + Assert.assertEquals(result, 'C'); + } + + @Test + public void test_generateNewCharFromPointer_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + MemorySegment charSegmt = nativeAllocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt, 'D'); + Assert.assertEquals(result, 'C'); + } + + @Test + public void test_addTwoBytes_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, JAVA_BYTE); + Addressable functionSymbol = nativeLibLookup.lookup("add2Bytes").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + byte result = (byte)mh.invokeExact((byte)6, (byte)3); + Assert.assertEquals(result, (byte)9); + } + + @Test + public void test_addTwoNegtiveBytes_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, JAVA_BYTE); + Addressable functionSymbol = nativeLibLookup.lookup("add2Bytes").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + byte result = (byte)mh.invokeExact((byte)-6, (byte)-3); + Assert.assertEquals(result, (byte)-9); + } + + @Test + public void test_addByteAndByteFromPointer_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + MemorySegment byteSegmt = nativeAllocator.allocate(JAVA_BYTE, (byte)3); + byte result = (byte)mh.invoke((byte)6, byteSegmt); + Assert.assertEquals(result, (byte)9); + } + + @Test + public void test_addTwoShorts_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Shorts").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + short result = (short)mh.invokeExact((short)24, (short)32); + Assert.assertEquals(result, (short)56); + } + + @Test + public void test_addTwoNegtiveShorts_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Shorts").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + short result = (short)mh.invokeExact((short)-24, (short)-32); + Assert.assertEquals(result, (short)-56); + } + + @Test + public void test_addShortAndShortFromPointer_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, ADDRESS, JAVA_SHORT); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + MemorySegment shortSegmt = nativeAllocator.allocate(JAVA_SHORT, (short)24); + short result = (short)mh.invoke(shortSegmt, (short)32); + Assert.assertEquals(result, (short)56); + } + + @Test + public void test_addTwoInts_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(112, 123); + Assert.assertEquals(result, 235); + } + + @Test + public void test_addTwoNegtiveInts_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(-112, -123); + Assert.assertEquals(result, -235); + } + + @Test + public void test_addIntAndIntFromPointer_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + MemorySegment intSegmt = nativeAllocator.allocate(JAVA_INT, 215); + int result = (int)mh.invoke(321, intSegmt); + Assert.assertEquals(result, 536); + } + + @Test + public void test_addTwoIntsReturnVoid_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoid").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + mh.invokeExact(454, 398); + } + + @Test + public void test_addIntAndChar_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_CHAR); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndChar").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + int result = (int)mh.invokeExact(58, 'A'); + Assert.assertEquals(result, 123); + } + + @Test + public void test_addTwoLongs_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, JAVA_LONG); + Addressable functionSymbol = nativeLibLookup.lookup("add2Longs").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + long result = (long)mh.invokeExact(57424L, 698235L); + Assert.assertEquals(result, 755659L); + } + + @Test + public void test_addLongAndLongFromPointer_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + MemorySegment longSegmt = nativeAllocator.allocate(JAVA_LONG, 57424L); + long result = (long)mh.invoke(longSegmt, 698235L); + Assert.assertEquals(result, 755659L); + } + + @Test + public void test_addTwoFloats_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Floats").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + float result = (float)mh.invokeExact(5.74f, 6.79f); + Assert.assertEquals(result, 12.53f, 0.01f); + } + + @Test + public void test_addFloatAndFloatFromPointer_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + MemorySegment floatSegmt = nativeAllocator.allocate(JAVA_FLOAT, 6.79f); + float result = (float)mh.invoke(5.74f, floatSegmt); + Assert.assertEquals(result, 12.53f, 0.01f); + } + + @Test + public void test_addTwoDoubles_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, JAVA_DOUBLE); + Addressable functionSymbol = nativeLibLookup.lookup("add2Doubles").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + double result = (double)mh.invokeExact(159.748d, 262.795d); + Assert.assertEquals(result, 422.543d, 0.001d); + } + + @Test + public void test_addDoubleAndDoubleFromPointer_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, JAVA_DOUBLE); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + MemorySegment doubleSegmt = nativeAllocator.allocate(JAVA_DOUBLE, 159.748d); + double result = (double)mh.invoke(doubleSegmt, 262.795d); + Assert.assertEquals(result, 422.543d, 0.001d); + } + + @Test + public void test_strlenFromDefaultLibWithMemAddr_1() throws Throwable { + Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS); + MethodHandle mh = linker.downcallHandle(strlenSymbol, fd); + MemorySegment funcSegmt = nativeAllocator.allocateUtf8String("JEP424 DOWNCALL TEST SUITES"); + long strLength = (long)mh.invoke(funcSegmt); + Assert.assertEquals(strLength, 27); + } + + @Test + public void test_memoryAllocFreeFromDefaultLib_1() throws Throwable { + Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(ADDRESS, JAVA_LONG); + MethodHandle allocHandle = linker.downcallHandle(allocSymbol, allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(10L); + allocMemAddr.set(JAVA_INT, 0, 15); + Assert.assertEquals(allocMemAddr.get(JAVA_INT, 0), 15); + + Addressable freeSymbol = defaultLibLookup.lookup("free").get(); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(ADDRESS); + MethodHandle freeHandle = linker.downcallHandle(freeSymbol, freeFuncDesc); + freeHandle.invoke(allocMemAddr); + } + + @Test + public void test_printfFromDefaultLibWithMemAddr_1() throws Throwable { + Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + MemorySegment formatSegmt = nativeAllocator.allocateUtf8String("\n%d + %d = %d\n"); + mh.invoke(formatSegmt, 15, 27, 42); + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/PrimitiveTypeTests2.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/PrimitiveTypeTests2.java new file mode 100644 index 00000000000..2dcf772cb7f --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/PrimitiveTypeTests2.java @@ -0,0 +1,298 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.VaList; +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.VaList.Builder; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in downcall. + * + * Note: the test suite is intended for the following Clinker API: + * MethodHandle downcallHandle(FunctionDescriptor function) + */ +@Test(groups = { "level.sanity" }) +public class PrimitiveTypeTests2 { + private static Linker linker = Linker.nativeLinker(); + private static MemorySession session = MemorySession.openImplicit(); + private static SegmentAllocator nativeAllocator = SegmentAllocator.newNativeArena(session); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + private static final SymbolLookup defaultLibLookup = linker.defaultLookup(); + + @Test + public void test_addTwoBoolsWithOr_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOr").get(); + MethodHandle mh = linker.downcallHandle(fd); + boolean result = (boolean)mh.invokeExact(functionSymbol, true, false); + Assert.assertEquals(result, true); + } + + @Test + public void test_addBoolAndBoolFromPointerWithOr_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPointerWithOr").get(); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + boolean result = (boolean)mh.invoke(functionSymbol, false, boolSegmt); + Assert.assertEquals(result, true); + } + + @Test + public void test_generateNewChar_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, JAVA_CHAR); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFrom2Chars").get(); + MethodHandle mh = linker.downcallHandle(fd); + char result = (char)mh.invokeExact(functionSymbol, 'B', 'D'); + Assert.assertEquals(result, 'C'); + } + + @Test + public void test_generateNewCharFromPointer_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment charSegmt = nativeAllocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(functionSymbol, charSegmt, 'D'); + Assert.assertEquals(result, 'C'); + } + + @Test + public void test_addTwoBytes_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, JAVA_BYTE); + Addressable functionSymbol = nativeLibLookup.lookup("add2Bytes").get(); + MethodHandle mh = linker.downcallHandle(fd); + byte result = (byte)mh.invokeExact(functionSymbol, (byte)6, (byte)3); + Assert.assertEquals(result, (byte)9); + } + + @Test + public void test_addTwoNegtiveBytes_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, JAVA_BYTE); + Addressable functionSymbol = nativeLibLookup.lookup("add2Bytes").get(); + MethodHandle mh = linker.downcallHandle(fd); + byte result = (byte)mh.invokeExact(functionSymbol, (byte)-6, (byte)-3); + Assert.assertEquals(result, (byte)-9); + } + + @Test + public void test_addByteAndByteFromPointer_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment byteSegmt = nativeAllocator.allocate(JAVA_BYTE, (byte)3); + byte result = (byte)mh.invoke(functionSymbol, (byte)6, byteSegmt); + Assert.assertEquals(result, (byte)9); + } + + @Test + public void test_addTwoShorts_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Shorts").get(); + MethodHandle mh = linker.downcallHandle(fd); + short result = (short)mh.invokeExact(functionSymbol, (short)24, (short)32); + Assert.assertEquals(result, (short)56); + } + + @Test + public void test_addTwoNegtiveShorts_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Shorts").get(); + MethodHandle mh = linker.downcallHandle(fd); + short result = (short)mh.invokeExact(functionSymbol, (short)-24, (short)-32); + Assert.assertEquals(result, (short)-56); + } + + @Test + public void test_addShortAndShortFromPointer_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, ADDRESS, JAVA_SHORT); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment shortSegmt = nativeAllocator.allocate(JAVA_SHORT, (short)24); + short result = (short)mh.invoke(functionSymbol, shortSegmt, (short)32); + Assert.assertEquals(result, (short)56); + } + + @Test + public void test_addTwoInts_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(fd); + int result = (int)mh.invokeExact(functionSymbol, 112, 123); + Assert.assertEquals(result, 235); + } + + @Test + public void test_addTwoNegtiveInts_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Ints").get(); + MethodHandle mh = linker.downcallHandle(fd); + int result = (int)mh.invokeExact(functionSymbol, -112, -123); + Assert.assertEquals(result, -235); + } + + @Test + public void test_addIntAndIntFromPointer_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment intSegmt = nativeAllocator.allocate(JAVA_INT, 215); + int result = (int)mh.invoke(functionSymbol, 321, intSegmt); + Assert.assertEquals(result, 536); + } + + @Test + public void test_addTwoIntsReturnVoid_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoid").get(); + MethodHandle mh = linker.downcallHandle(fd); + mh.invokeExact(functionSymbol, 454, 398); + } + + @Test + public void test_addIntAndChar_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_CHAR); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndChar").get(); + MethodHandle mh = linker.downcallHandle(fd); + int result = (int)mh.invokeExact(functionSymbol, 58, 'A'); + Assert.assertEquals(result, 123); + } + + @Test + public void test_addTwoLongs_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, JAVA_LONG); + Addressable functionSymbol = nativeLibLookup.lookup("add2Longs").get(); + MethodHandle mh = linker.downcallHandle(fd); + long result = (long)mh.invokeExact(functionSymbol, 57424L, 698235L); + Assert.assertEquals(result, 755659L); + } + + @Test + public void test_addLongAndLongFromPointer_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment longSegmt = nativeAllocator.allocate(JAVA_LONG, 57424L); + long result = (long)mh.invoke(functionSymbol, longSegmt, 698235L); + Assert.assertEquals(result, 755659L); + } + + @Test + public void test_addTwoFloats_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT); + Addressable functionSymbol = nativeLibLookup.lookup("add2Floats").get(); + MethodHandle mh = linker.downcallHandle(fd); + float result = (float)mh.invokeExact(functionSymbol, 5.74f, 6.79f); + Assert.assertEquals(result, 12.53f, 0.01f); + } + + @Test + public void test_addFloatAndFloatFromPointer_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment floatSegmt = nativeAllocator.allocate(JAVA_FLOAT, 6.79f); + float result = (float)mh.invoke(functionSymbol, 5.74f, floatSegmt); + Assert.assertEquals(result, 12.53f, 0.01f); + } + + @Test + public void test_addTwoDoubles_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, JAVA_DOUBLE); + Addressable functionSymbol = nativeLibLookup.lookup("add2Doubles").get(); + MethodHandle mh = linker.downcallHandle(fd); + double result = (double)mh.invokeExact(functionSymbol, 159.748d, 262.795d); + Assert.assertEquals(result, 422.543d, 0.001d); + } + + @Test + public void test_addDoubleAndDoubleFromPointer_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, JAVA_DOUBLE); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment doubleSegmt = nativeAllocator.allocate(JAVA_DOUBLE, 159.748d); + double result = (double)mh.invoke(functionSymbol, doubleSegmt, 262.795d); + Assert.assertEquals(result, 422.543d, 0.001d); + } + + @Test + public void test_strlenFromDefaultLibWithMemAddr_2() throws Throwable { + Addressable strlenSymbol = defaultLibLookup.lookup("strlen").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS); + MethodHandle mh = linker.downcallHandle(fd); + MemorySegment funcSegmt = nativeAllocator.allocateUtf8String("JEP424 DOWNCALL TEST SUITES"); + long strLength = (long)mh.invoke(strlenSymbol, funcSegmt); + Assert.assertEquals(strLength, 27); + } + + @Test + public void test_memoryAllocFreeFromDefaultLib_2() throws Throwable { + Addressable allocSymbol = defaultLibLookup.lookup("malloc").get(); + FunctionDescriptor allocFuncDesc = FunctionDescriptor.of(ADDRESS, JAVA_LONG); + MethodHandle allocHandle = linker.downcallHandle(allocFuncDesc); + MemoryAddress allocMemAddr = (MemoryAddress)allocHandle.invokeExact(allocSymbol, 10L); + allocMemAddr.set(JAVA_INT, 0, 15); + Assert.assertEquals(allocMemAddr.get(JAVA_INT, 0), 15); + + Addressable freeSymbol = defaultLibLookup.lookup("free").get(); + FunctionDescriptor freeFuncDesc = FunctionDescriptor.ofVoid(ADDRESS); + MethodHandle freeHandle = linker.downcallHandle(freeFuncDesc); + freeHandle.invoke(freeSymbol, allocMemAddr); + } + + @Test + public void test_printfFromDefaultLibWithMemAddr_2() throws Throwable { + Addressable functionSymbol = defaultLibLookup.lookup("printf").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT); + MethodHandle mh = linker.downcallHandle(fd); + MemorySegment formatSegmt = nativeAllocator.allocateUtf8String("\n%d + %d = %d\n"); + mh.invoke(functionSymbol, formatSegmt, 15, 27, 42); + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/StructTests1.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/StructTests1.java new file mode 100644 index 00000000000..ad27fcecf2d --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/StructTests1.java @@ -0,0 +1,3103 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SequenceLayout; +import java.lang.foreign.SymbolLookup; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for argument/return struct in downcall. + * + * Note: + * [1] the padding elements in the struct are only required by RI or VarHandle (accessing the + * data address) while they are totally ignored in OpenJ9 given the padding/alignment are + * computed by libffi automatically in native. + * + * [2] the test suite is mainly intended for the following Clinker API: + * MethodHandle downcallHandle(MemorySegment symbol, FunctionDescriptor function) + */ +@Test(groups = { "level.sanity" }) +public class StructTests1 { + private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addBoolAndBoolsFromStructWithXor_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithXor").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, false); + boolHandle2.set(structSegmt, true); + + boolean result = (boolean)mh.invokeExact(false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXor_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXor").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, false); + boolHandle2.set(structSegmt, true); + + boolean result = (boolean)mh.invoke(boolSegmt, structSegmt); + Assert.assertEquals(result, false); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, false); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(boolSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), true); + Assert.assertEquals(resultAddr.toRawLongValue(), boolSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addBoolAndBoolsFromStructPointerWithXor_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructPointerWithXor").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, true); + boolHandle2.set(structSegmt, false); + + boolean result = (boolean)mh.invoke(false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXor_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invokeExact(true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrder_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invokeExact(true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXor_withoutLayoutName_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invokeExact(true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArray_1() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray.withName("array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + + boolean result = (boolean)mh.invokeExact(false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder_1() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + boolArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + + boolean result = (boolean)mh.invokeExact(false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArray_withoutLayoutName_1() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invokeExact(false, structSegmt); + Assert.assertEquals(result, false); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArray_1() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + + boolean result = (boolean)mh.invokeExact(true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder_1() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + + boolean result = (boolean)mh.invokeExact(true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + structSegmt.set(JAVA_BOOLEAN, 3, false); + structSegmt.set(JAVA_BOOLEAN, 4, true); + + boolean result = (boolean)mh.invokeExact(false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(boolHandle1.get(resultSegmt), false); + Assert.assertEquals(boolHandle2.get(resultSegmt), true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), false); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 1), true); + } + } + + @Test + public void test_add3BoolStructsWithXor_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2"), + JAVA_BOOLEAN.withName("elem3"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle boolHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3BoolStructsWithXor_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + boolHandle3.set(structSegmt1, true); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + boolHandle3.set(structSegmt2, false); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(boolHandle1.get(resultSegmt), false); + Assert.assertEquals(boolHandle2.get(resultSegmt), true); + Assert.assertEquals(boolHandle3.get(resultSegmt), true); + } + } + + @Test + public void test_addByteAndBytesFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)8); + byteHandle2.set(structSegmt, (byte)9); + + byte result = (byte)mh.invokeExact((byte)6, structSegmt); + Assert.assertEquals(result, 23); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)14); + byteHandle2.set(structSegmt, (byte)16); + + byte result = (byte)mh.invoke(byteSegmt, structSegmt); + Assert.assertEquals(result, 42); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStruct_returnBytePointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStruct_returnBytePointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)18); + byteHandle2.set(structSegmt, (byte)19); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(byteSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 49); + Assert.assertEquals(resultAddr.toRawLongValue(), byteSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addByteAndBytesFromStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)11); + byteHandle2.set(structSegmt, (byte)12); + + byte result = (byte)mh.invoke((byte)13, structSegmt); + Assert.assertEquals(result, 36); + } + } + + @Test + public void test_addByteAndBytesFromNestedStruct_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)22); + structSegmt.set(JAVA_BYTE, 2, (byte)33); + + byte result = (byte)mh.invokeExact((byte)46, structSegmt); + Assert.assertEquals(result, 112); + } + } + + @Test + public void test_addByteAndBytesFromNestedStruct_reverseOrder_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)24); + structSegmt.set(JAVA_BYTE, 2, (byte)36); + + byte result = (byte)mh.invokeExact((byte)48, structSegmt); + Assert.assertEquals(result, 120); + } + } + + @Test + public void test_addByteAndBytesFromNestedStruct_withoutLayoutName_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)22); + structSegmt.set(JAVA_BYTE, 2, (byte)33); + + byte result = (byte)mh.invokeExact((byte)46, structSegmt); + Assert.assertEquals(result, 112); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArray_1() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray.withName("array_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + + byte result = (byte)mh.invokeExact((byte)14, structSegmt); + Assert.assertEquals(result, 50); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArray_reverseOrder_1() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + byteArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)14); + structSegmt.set(JAVA_BYTE, 2, (byte)16); + + byte result = (byte)mh.invokeExact((byte)18, structSegmt); + Assert.assertEquals(result, 60); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArray_withoutLayoutName_1() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + + byte result = (byte)mh.invokeExact((byte)14, structSegmt); + Assert.assertEquals(result, 50); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArray_1() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + structSegmt.set(JAVA_BYTE, 3, (byte)14); + structSegmt.set(JAVA_BYTE, 4, (byte)15); + + byte result = (byte)mh.invokeExact((byte)16, structSegmt); + Assert.assertEquals(result, 81); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArray_reverseOrder_1() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)14); + structSegmt.set(JAVA_BYTE, 2, (byte)16); + structSegmt.set(JAVA_BYTE, 3, (byte)18); + structSegmt.set(JAVA_BYTE, 4, (byte)20); + + byte result = (byte)mh.invokeExact((byte)22, structSegmt); + Assert.assertEquals(result, 102); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + structSegmt.set(JAVA_BYTE, 3, (byte)14); + structSegmt.set(JAVA_BYTE, 4, (byte)15); + + byte result = (byte)mh.invokeExact((byte)16, structSegmt); + Assert.assertEquals(result, 81); + } + } + + @Test + public void test_add2ByteStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + } + } + + @Test + public void test_add2ByteStructs_returnStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 49); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 1), 24); + } + } + + @Test + public void test_add3ByteStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2"), + JAVA_BYTE.withName("elem3"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3ByteStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + byteHandle3.set(structSegmt1, (byte)12); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + byteHandle3.set(structSegmt2, (byte)16); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + Assert.assertEquals((byte)byteHandle3.get(resultSegmt), (byte)28); + } + } + + @Test + public void test_addCharAndCharsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'A'); + charHandle2.set(structSegmt, 'B'); + + char result = (char)mh.invokeExact('C', structSegmt); + Assert.assertEquals(result, 'D'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + char result = (char)mh.invoke(charSegmt, structSegmt); + Assert.assertEquals(result, 'M'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStruct_returnCharPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStruct_returnCharPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(charSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'M'); + Assert.assertEquals(resultAddr.toRawLongValue(), charSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addCharAndCharsFromStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'H'); + charHandle2.set(structSegmt, 'I'); + + char result = (char)mh.invoke('G', structSegmt); + Assert.assertEquals(result, 'V'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStruct_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + + char result = (char)mh.invokeExact('H', structSegmt); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStruct_reverseOrder_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + + char result = (char)mh.invokeExact('H', structSegmt); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArray_1() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(charArray.withName("array_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invokeExact('D', structSegmt); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArray_reverseOrder_1() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + charArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invokeExact('D', structSegmt); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArray_withoutLayoutName_1() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(charArray, JAVA_CHAR, MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invokeExact('D', structSegmt); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArray_1() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_CHAR.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invokeExact('J', structSegmt); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArray_reverseOrder_1() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invokeExact('J', structSegmt); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR, JAVA_CHAR); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_CHAR); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invokeExact('J', structSegmt); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_add2CharStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(charHandle1.get(resultSegmt), 'C'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'E'); + } + } + + @Test + public void test_add2CharStructs_returnStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'C'); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 2), 'E'); + } + } + + @Test + public void test_add3CharStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle charHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3CharStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + charHandle3.set(structSegmt1, 'C'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'B'); + charHandle2.set(structSegmt2, 'C'); + charHandle3.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(charHandle1.get(resultSegmt), 'B'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'D'); + Assert.assertEquals(charHandle3.get(resultSegmt), 'F'); + } + } + + @Test + public void test_addShortAndShortsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)8); + shortHandle2.set(structSegmt, (short)9); + + short result = (short)mh.invokeExact((short)6, structSegmt); + Assert.assertEquals(result, 23); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)18); + shortHandle2.set(structSegmt, (short)19); + + short result = (short)mh.invoke(shortSegmt, structSegmt); + Assert.assertEquals(result, 49); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStruct_returnShortPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStruct_returnShortPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)18); + shortHandle2.set(structSegmt, (short)19); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 49); + Assert.assertEquals(resultAddr.toRawLongValue(), shortSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addShortAndShortsFromStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)22); + shortHandle2.set(structSegmt, (short)44); + + short result = (short)mh.invoke((short)66, structSegmt); + Assert.assertEquals(result, 132); + } + } + + @Test + public void test_addShortAndShortsFromNestedStruct_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)31); + structSegmt.set(JAVA_SHORT, 2, (short)33); + structSegmt.set(JAVA_SHORT, 4, (short)35); + + short result = (short)mh.invokeExact((short)37, structSegmt); + Assert.assertEquals(result, 136); + } + } + + @Test + public void test_addShortAndShortsFromNestedStruct_reverseOrder_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)31); + structSegmt.set(JAVA_SHORT, 2, (short)33); + structSegmt.set(JAVA_SHORT, 4, (short)35); + + short result = (short)mh.invokeExact((short)37, structSegmt); + Assert.assertEquals(result, 136); + } + } + + @Test + public void test_addShortAndShortsFromNestedStruct_withoutLayoutName_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_SHORT, + MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)31); + structSegmt.set(JAVA_SHORT, 2, (short)33); + structSegmt.set(JAVA_SHORT, 4, (short)35); + + short result = (short)mh.invokeExact((short)37, structSegmt); + Assert.assertEquals(result, 136); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArray_1() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(shortArray.withName("array_elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + + short result = (short)mh.invokeExact((short)444, structSegmt); + Assert.assertEquals(result, 1110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArray_reverseOrder_1() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + shortArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + + short result = (short)mh.invokeExact((short)444, structSegmt); + Assert.assertEquals(result, 1110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArray_withoutLayoutName_1() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(shortArray, JAVA_SHORT, MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + + short result = (short)mh.invokeExact((short)444, structSegmt); + Assert.assertEquals(result, 1110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArray_1() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struc_array_elem1"), JAVA_SHORT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + structSegmt.set(JAVA_SHORT, 6, (short)444); + structSegmt.set(JAVA_SHORT, 8, (short)555); + + short result = (short)mh.invokeExact((short)666, structSegmt); + Assert.assertEquals(result, 2331); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArray_reverseOrder_1() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), structArray.withName("struc_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + structSegmt.set(JAVA_SHORT, 6, (short)444); + structSegmt.set(JAVA_SHORT, 8, (short)555); + + short result = (short)mh.invokeExact((short)666, structSegmt); + Assert.assertEquals(result, 2331); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT, JAVA_SHORT); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_SHORT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + structSegmt.set(JAVA_SHORT, 6, (short)444); + structSegmt.set(JAVA_SHORT, 8, (short)555); + + short result = (short)mh.invokeExact((short)666, structSegmt); + Assert.assertEquals(result, 2331); + } + } + + @Test + public void test_add2ShortStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)56); + shortHandle2.set(structSegmt1, (short)45); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)78); + shortHandle2.set(structSegmt2, (short)67); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)134); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)112); + } + } + + @Test + public void test_add2ShortStructs_returnStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)56); + shortHandle2.set(structSegmt1, (short)45); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)78); + shortHandle2.set(structSegmt2, (short)67); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 134); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 2), 112); + } + } + + @Test + public void test_add3ShortStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2"), + JAVA_SHORT.withName("elem3"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle shortHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3ShortStructs_returnStruct").get(); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)25); + shortHandle2.set(structSegmt1, (short)26); + shortHandle3.set(structSegmt1, (short)27); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)34); + shortHandle2.set(structSegmt2, (short)35); + shortHandle3.set(structSegmt2, (short)36); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)59); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)61); + Assert.assertEquals((short)shortHandle3.get(resultSegmt), (short)63); + } + } + + @Test + public void test_addIntAndIntsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1122334); + intHandle2.set(structSegmt, 1234567); + + int result = (int)mh.invokeExact(2244668, structSegmt); + Assert.assertEquals(result, 4601569); + } + } + + @Test + public void test_addIntAndIntShortFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntShortFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, (short)32766); + + int result = (int)mh.invokeExact(22334455, structSegmt); + Assert.assertEquals(result, 33590565); + } + } + + @Test + public void test_addIntAndShortIntFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_SHORT.bitSize()), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndShortIntFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, (short)32766); + elemHandle2.set(structSegmt, 22446688); + + int result = (int)mh.invokeExact(11335577, structSegmt); + Assert.assertEquals(result, 33815031); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 7654321); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1234567); + intHandle2.set(structSegmt, 2468024); + + int result = (int)mh.invoke(intSegmt, structSegmt); + Assert.assertEquals(result, 11356912); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStruct_returnIntPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStruct_returnIntPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 1122333); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 4455666); + intHandle2.set(structSegmt, 7788999); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(intSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 13366998); + Assert.assertEquals(resultAddr.toRawLongValue(), intSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addIntAndIntsFromStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 11121314); + intHandle2.set(structSegmt, 15161718); + + int result = (int)mh.invoke(19202122, structSegmt); + Assert.assertEquals(result, 45485154); + } + } + + @Test + public void test_addIntAndIntsFromNestedStruct_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_INT.withName("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invokeExact(33343536, structSegmt); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromNestedStruct_reverseOrder_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invokeExact(33343536, structSegmt); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromNestedStruct_withoutLayoutName_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_INT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invokeExact(33343536, structSegmt); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArray_1() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(intArray.withName("array_elem1"), JAVA_INT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invokeExact(4444444, structSegmt); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArray_reverseOrder_1() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), intArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invokeExact(4444444, structSegmt); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArray_withoutLayoutName_1() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(intArray, JAVA_INT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invokeExact(4444444, structSegmt); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArray_1() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_INT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invokeExact(6666666, structSegmt); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArray_reverseOrder_1() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invokeExact(6666666, structSegmt); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT, JAVA_INT); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_INT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invokeExact(6666666, structSegmt); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_add2IntStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224466); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113354); + } + } + + @Test + public void test_add2IntStructs_returnStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 110224466); + Assert.assertEquals(resultAddr.get(JAVA_INT, 4), 89113354); + } + } + + @Test + public void test_add3IntStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3IntStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + intHandle3.set(structSegmt1, 99001122); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 33445566); + intHandle2.set(structSegmt2, 77889900); + intHandle3.set(structSegmt2, 44332211); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 44668910); + Assert.assertEquals(intHandle2.get(resultSegmt), 133557688); + Assert.assertEquals(intHandle3.get(resultSegmt), 143333333); + } + } + + @Test + public void test_addLongAndLongsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 1234567890L); + longHandle2.set(structSegmt, 9876543210L); + + long result = (long)mh.invokeExact(2468024680L, structSegmt); + Assert.assertEquals(result, 13579135780L); + } + } + + @Test + public void test_addIntAndIntLongFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_INT.bitSize()), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntLongFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, 667788990011L); + + long result = (long)mh.invokeExact(22446688, structSegmt); + Assert.assertEquals(result, 667822660043L); + } + } + + @Test + public void test_addIntAndLongIntFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), + JAVA_INT.withName("elem2"), MemoryLayout.paddingLayout(JAVA_INT.bitSize())); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndLongIntFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 667788990011L); + elemHandle2.set(structSegmt, 11223344); + + long result = (long)mh.invokeExact(1234567, structSegmt); + Assert.assertEquals(result, 667801447922L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 1111111111L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 3333333333L); + longHandle2.set(structSegmt, 5555555555L); + + long result = (long)mh.invoke(longSegmt, structSegmt); + Assert.assertEquals(result, 9999999999L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStruct_returnLongPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStruct_returnLongPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 1122334455L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 6677889900L); + longHandle2.set(structSegmt, 1234567890L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(longSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 9034792245L); + Assert.assertEquals(resultAddr.toRawLongValue(), longSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addLongAndLongsFromStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 224466880022L); + longHandle2.set(structSegmt, 446688002244L); + + long result = (long)mh.invoke(668800224466L, structSegmt); + Assert.assertEquals(result, 1339955106732L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStruct_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invokeExact(778899001122L, structSegmt); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStruct_reverseOrder_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invokeExact(778899001122L, structSegmt); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStruct_withoutLayoutName_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG, nestedStructLayout); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invokeExact(778899001122L, structSegmt); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArray_1() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(longArray.withName("array_elem1"), JAVA_LONG.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + + long result = (long)mh.invokeExact(444444444L, structSegmt); + Assert.assertEquals(result, 1111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArray_reverseOrder_1() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), longArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + + long result = (long)mh.invokeExact(444444444L, structSegmt); + Assert.assertEquals(result, 1111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArray_withoutLayoutName_1() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(longArray, JAVA_LONG); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + + long result = (long)mh.invokeExact(444444444L, structSegmt); + Assert.assertEquals(result, 1111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArray_1() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_LONG.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + structSegmt.set(JAVA_LONG, 24, 444444444L); + structSegmt.set(JAVA_LONG, 32, 555555555L); + + long result = (long)mh.invokeExact(666666666L, structSegmt); + Assert.assertEquals(result, 2333333331L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArray_reverseOrder_1() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + structSegmt.set(JAVA_LONG, 24, 444444444L); + structSegmt.set(JAVA_LONG, 32, 555555555L); + + long result = (long)mh.invokeExact(666666666L, structSegmt); + Assert.assertEquals(result, 2333333331L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG, JAVA_LONG); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_LONG); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + structSegmt.set(JAVA_LONG, 24, 444444444L); + structSegmt.set(JAVA_LONG, 32, 555555555L); + + long result = (long)mh.invokeExact(666666666L, structSegmt); + Assert.assertEquals(result, 2333333331L); + } + } + + @Test + public void test_add2LongStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + } + } + + @Test + public void test_add2LongStructs_returnStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 5566778899L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 9900112233L); + longHandle2.set(structSegmt2, 3344556677L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 11022446688L); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 8), 8911335576L); + } + } + + @Test + public void test_add3LongStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2"), JAVA_LONG.withName("elem3")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle longHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3LongStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + longHandle3.set(structSegmt1, 112233445566L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + longHandle3.set(structSegmt2, 778899001122L); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + Assert.assertEquals(longHandle3.get(resultSegmt), 891132446688L); + } + } + + @Test + public void test_addFloatAndFloatsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 8.12F); + floatHandle2.set(structSegmt, 9.24F); + + float result = (float)mh.invokeExact(6.56F, structSegmt); + Assert.assertEquals(result, 23.92F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + float result = (float)mh.invoke(floatSegmt, structSegmt); + Assert.assertEquals(result, 49.69F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStruct_returnFloatPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(floatSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 49.69F, 0.01F); + Assert.assertEquals(resultAddr.toRawLongValue(), floatSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addFloatAndFloatsFromStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 35.11F); + floatHandle2.set(structSegmt, 46.22F); + + float result = (float)mh.invoke(79.33F, structSegmt); + Assert.assertEquals(result, 160.66F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStruct_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invokeExact(37.88F, structSegmt); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStruct_reverseOrder_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invokeExact(37.88F, structSegmt); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStruct_withoutLayoutName_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invokeExact(37.88F, structSegmt); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArray_1() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(floatArray.withName("array_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invokeExact(444.44F, structSegmt); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder_1() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), floatArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invokeExact(444.44F, structSegmt); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArray_withoutLayoutName_1() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(floatArray, JAVA_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invokeExact(444.44F, structSegmt); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArray_1() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invokeExact(666.66F, structSegmt); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder_1() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invokeExact(666.66F, structSegmt); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT, JAVA_FLOAT); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invokeExact(666.66F, structSegmt); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 49.46F, 0.01F); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 4), 24.68F, 0.01F); + } + } + + @Test + public void test_add3FloatStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3FloatStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + floatHandle3.set(structSegmt1, 45.67F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + floatHandle3.set(structSegmt2, 69.72F); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + Assert.assertEquals((float)floatHandle3.get(resultSegmt), 115.39, 0.01F); + } + } + + @Test + public void test_addDoubleAndDoublesFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 2228.111D); + doubleHandle2.set(structSegmt, 2229.221D); + + double result = (double)mh.invokeExact(3336.333D, structSegmt); + Assert.assertEquals(result, 7793.665D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleFromStruct_1() throws Throwable { + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32)) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_FLOAT.bitSize()), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18.444F); + elemHandle2.set(structSegmt, 619.777D); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + double result = (double)mh.invokeExact(113.567D, structSegmt); + Assert.assertEquals(result, 751.788D, 0.001D); + } + } + + @Test + public void test_addDoubleAndIntDoubleFromStruct_1() throws Throwable { + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32)) : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_INT.bitSize()), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18); + elemHandle2.set(structSegmt, 619.777D); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + double result = (double)mh.invokeExact(113.567D, structSegmt); + Assert.assertEquals(result, 751.344D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFloatFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19.22F); + + double result = (double)mh.invokeExact(216.666D, structSegmt); + Assert.assertEquals(result, 454.441D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleIntFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleIntFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19); + + double result = (double)mh.invokeExact(216.666D, structSegmt); + Assert.assertEquals(result, 454.221D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 112.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 118.456D); + doubleHandle2.set(structSegmt, 119.789D); + + double result = (double)mh.invoke(doubleSegmt, structSegmt); + Assert.assertEquals(result, 350.368D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 212.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 218.456D); + doubleHandle2.set(structSegmt, 219.789D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 650.368D, 0.001D); + Assert.assertEquals(resultAddr.toRawLongValue(), doubleSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 22.111D); + doubleHandle2.set(structSegmt, 44.222D); + + double result = (double)mh.invoke(66.333D, structSegmt); + Assert.assertEquals(result, 132.666D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStruct_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_DOUBLE.withName("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invokeExact(37.864D, structSegmt); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStruct_reverseOrder_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invokeExact(37.864D, structSegmt); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStruct_withoutLayoutName_1() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_DOUBLE); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invokeExact(37.864D, structSegmt); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArray_1() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(doubleArray.withName("array_elem1"), JAVA_DOUBLE.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invokeExact(444.444D, structSegmt); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder_1() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), doubleArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invokeExact(444.444D, structSegmt); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArray_withoutLayoutName_1() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(doubleArray, JAVA_DOUBLE); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invokeExact(444.444D, structSegmt); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArray_1() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_DOUBLE.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invokeExact(666.666D, structSegmt); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder_1() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invokeExact(666.666D, structSegmt); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArray_withoutLayoutName_1() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE, JAVA_DOUBLE); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_DOUBLE); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invokeExact(666.666D, structSegmt); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStructPointer_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 44.666D, 0.001D); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 8), 66.888D, 0.001D); + } + } + + @Test + public void test_add3DoubleStructs_returnStruct_1() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle doubleHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3DoubleStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + doubleHandle3.set(structSegmt1, 33.123D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + doubleHandle3.set(structSegmt2, 55.456D); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(allocator, structSegmt1, structSegmt2); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + Assert.assertEquals((double)doubleHandle3.get(resultSegmt), 88.579D, 0.001D); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/StructTests2.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/StructTests2.java new file mode 100644 index 00000000000..32ff55c5b0d --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/downcall/StructTests2.java @@ -0,0 +1,3100 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.downcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SequenceLayout; +import java.lang.foreign.SymbolLookup; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for argument/return struct in downcall. + * + * Note: + * [1] the padding elements in the struct are only required by RI or VarHandle (accessing the + * data address) while they are totally ignored in OpenJ9 given the padding/alignment are + * computed by libffi automatically in native. + * + * [2] the test suite is mainly intended for the following Clinker API: + * MethodHandle downcallHandle(FunctionDescriptor function) + */ +@Test(groups = { "level.sanity" }) +public class StructTests2 { + private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addBoolAndBoolsFromStructWithXor_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithXor").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, false); + boolHandle2.set(structSegmt, true); + + boolean result = (boolean)mh.invokeExact(functionSymbol, false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXor_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXor").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, false); + boolHandle2.set(structSegmt, true); + + boolean result = (boolean)mh.invoke(functionSymbol, boolSegmt, structSegmt); + Assert.assertEquals(result, false); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, false); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, boolSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), true); + Assert.assertEquals(resultAddr.toRawLongValue(), boolSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addBoolAndBoolsFromStructPointerWithXor_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructPointerWithXor").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, true); + boolHandle2.set(structSegmt, false); + + boolean result = (boolean)mh.invoke(functionSymbol, false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXor_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invokeExact(functionSymbol, true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrder_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invokeExact(functionSymbol, true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXor_withoutLayoutName_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invokeExact(functionSymbol, true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArray_2() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray.withName("array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + + boolean result = (boolean)mh.invokeExact(functionSymbol, false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder_2() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + boolArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + + boolean result = (boolean)mh.invokeExact(functionSymbol, false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArray_withoutLayoutName_2() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invokeExact(functionSymbol, false, structSegmt); + Assert.assertEquals(result, false); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArray_2() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + + boolean result = (boolean)mh.invokeExact(functionSymbol, true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder_2() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + + boolean result = (boolean)mh.invokeExact(functionSymbol, true, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BOOLEAN, + MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + structSegmt.set(JAVA_BOOLEAN, 3, false); + structSegmt.set(JAVA_BOOLEAN, 4, true); + + boolean result = (boolean)mh.invokeExact(functionSymbol, false, structSegmt); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(boolHandle1.get(resultSegmt), false); + Assert.assertEquals(boolHandle2.get(resultSegmt), true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), false); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 1), true); + } + } + + @Test + public void test_add3BoolStructsWithXor_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2"), + JAVA_BOOLEAN.withName("elem3"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize())); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle boolHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3BoolStructsWithXor_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + boolHandle3.set(structSegmt1, true); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + boolHandle3.set(structSegmt2, false); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(boolHandle1.get(resultSegmt), false); + Assert.assertEquals(boolHandle2.get(resultSegmt), true); + Assert.assertEquals(boolHandle3.get(resultSegmt), true); + } + } + + @Test + public void test_addByteAndBytesFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)8); + byteHandle2.set(structSegmt, (byte)9); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)6, structSegmt); + Assert.assertEquals(result, 23); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)14); + byteHandle2.set(structSegmt, (byte)16); + + byte result = (byte)mh.invoke(functionSymbol, byteSegmt, structSegmt); + Assert.assertEquals(result, 42); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStruct_returnBytePointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStruct_returnBytePointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)18); + byteHandle2.set(structSegmt, (byte)19); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, byteSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 49); + Assert.assertEquals(resultAddr.toRawLongValue(), byteSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addByteAndBytesFromStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)11); + byteHandle2.set(structSegmt, (byte)12); + + byte result = (byte)mh.invoke(functionSymbol, (byte)13, structSegmt); + Assert.assertEquals(result, 36); + } + } + + @Test + public void test_addByteAndBytesFromNestedStruct_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)22); + structSegmt.set(JAVA_BYTE, 2, (byte)33); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)46, structSegmt); + Assert.assertEquals(result, 112); + } + } + + @Test + public void test_addByteAndBytesFromNestedStruct_reverseOrder_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)24); + structSegmt.set(JAVA_BYTE, 2, (byte)36); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)48, structSegmt); + Assert.assertEquals(result, 120); + } + } + + @Test + public void test_addByteAndBytesFromNestedStruct_withoutLayoutName_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)22); + structSegmt.set(JAVA_BYTE, 2, (byte)33); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)46, structSegmt); + Assert.assertEquals(result, 112); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArray_2() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray.withName("array_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)14, structSegmt); + Assert.assertEquals(result, 50); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArray_reverseOrder_2() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + byteArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)14); + structSegmt.set(JAVA_BYTE, 2, (byte)16); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)18, structSegmt); + Assert.assertEquals(result, 60); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArray_withoutLayoutName_2() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)14, structSegmt); + Assert.assertEquals(result, 50); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArray_2() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + structSegmt.set(JAVA_BYTE, 3, (byte)14); + structSegmt.set(JAVA_BYTE, 4, (byte)15); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)16, structSegmt); + Assert.assertEquals(result, 81); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArray_reverseOrder_2() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)14); + structSegmt.set(JAVA_BYTE, 2, (byte)16); + structSegmt.set(JAVA_BYTE, 3, (byte)18); + structSegmt.set(JAVA_BYTE, 4, (byte)20); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)22, structSegmt); + Assert.assertEquals(result, 102); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_BYTE, + MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + structSegmt.set(JAVA_BYTE, 3, (byte)14); + structSegmt.set(JAVA_BYTE, 4, (byte)15); + + byte result = (byte)mh.invokeExact(functionSymbol, (byte)16, structSegmt); + Assert.assertEquals(result, 81); + } + } + + @Test + public void test_add2ByteStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStruct").get(); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + } + } + + @Test + public void test_add2ByteStructs_returnStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 49); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 1), 24); + } + } + + @Test + public void test_add3ByteStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2"), + JAVA_BYTE.withName("elem3"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize())); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3ByteStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + byteHandle3.set(structSegmt1, (byte)12); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + byteHandle3.set(structSegmt2, (byte)16); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + Assert.assertEquals((byte)byteHandle3.get(resultSegmt), (byte)28); + } + } + + @Test + public void test_addCharAndCharsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'A'); + charHandle2.set(structSegmt, 'B'); + + char result = (char)mh.invokeExact(functionSymbol, 'C', structSegmt); + Assert.assertEquals(result, 'D'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + char result = (char)mh.invoke(functionSymbol, charSegmt, structSegmt); + Assert.assertEquals(result, 'M'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStruct_returnCharPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStruct_returnCharPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, charSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'M'); + Assert.assertEquals(resultAddr.toRawLongValue(), charSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addCharAndCharsFromStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'H'); + charHandle2.set(structSegmt, 'I'); + + char result = (char)mh.invoke(functionSymbol, 'G', structSegmt); + Assert.assertEquals(result, 'V'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStruct_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + + char result = (char)mh.invokeExact(functionSymbol, 'H', structSegmt); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStruct_reverseOrder_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + + char result = (char)mh.invokeExact(functionSymbol, 'H', structSegmt); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArray_2() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(charArray.withName("array_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invokeExact(functionSymbol, 'D', structSegmt); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArray_reverseOrder_2() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + charArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invokeExact(functionSymbol, 'D', structSegmt); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArray_withoutLayoutName_2() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = MemoryLayout.structLayout(charArray, JAVA_CHAR, MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invokeExact(functionSymbol, 'D', structSegmt); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArray_2() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_CHAR.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invokeExact(functionSymbol, 'J', structSegmt); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArray_reverseOrder_2() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invokeExact(functionSymbol, 'J', structSegmt); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR, JAVA_CHAR); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_CHAR); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invokeExact(functionSymbol, 'J', structSegmt); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_add2CharStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(charHandle1.get(resultSegmt), 'C'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'E'); + } + } + + @Test + public void test_add2CharStructs_returnStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'C'); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 2), 'E'); + } + } + + @Test + public void test_add3CharStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3"), MemoryLayout.paddingLayout(JAVA_CHAR.bitSize())); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle charHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3CharStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + charHandle3.set(structSegmt1, 'C'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'B'); + charHandle2.set(structSegmt2, 'C'); + charHandle3.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(charHandle1.get(resultSegmt), 'B'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'D'); + Assert.assertEquals(charHandle3.get(resultSegmt), 'F'); + } + } + + @Test + public void test_addShortAndShortsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)8); + shortHandle2.set(structSegmt, (short)9); + short result = (short)mh.invokeExact(functionSymbol, (short)6, structSegmt); + Assert.assertEquals(result, 23); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)18); + shortHandle2.set(structSegmt, (short)19); + + short result = (short)mh.invoke(functionSymbol, shortSegmt, structSegmt); + Assert.assertEquals(result, 49); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStruct_returnShortPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStruct_returnShortPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)18); + shortHandle2.set(structSegmt, (short)19); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, shortSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 49); + Assert.assertEquals(resultAddr.toRawLongValue(), shortSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addShortAndShortsFromStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)22); + shortHandle2.set(structSegmt, (short)44); + + short result = (short)mh.invoke(functionSymbol, (short)66, structSegmt); + Assert.assertEquals(result, 132); + } + } + + @Test + public void test_addShortAndShortsFromNestedStruct_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)31); + structSegmt.set(JAVA_SHORT, 2, (short)33); + structSegmt.set(JAVA_SHORT, 4, (short)35); + + short result = (short)mh.invokeExact(functionSymbol, (short)37, structSegmt); + Assert.assertEquals(result, 136); + } + } + + @Test + public void test_addShortAndShortsFromNestedStruct_reverseOrder_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)31); + structSegmt.set(JAVA_SHORT, 2, (short)33); + structSegmt.set(JAVA_SHORT, 4, (short)35); + + short result = (short)mh.invokeExact(functionSymbol, (short)37, structSegmt); + Assert.assertEquals(result, 136); + } + } + + @Test + public void test_addShortAndShortsFromNestedStruct_withoutLayoutName_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_SHORT, + MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)31); + structSegmt.set(JAVA_SHORT, 2, (short)33); + structSegmt.set(JAVA_SHORT, 4, (short)35); + + short result = (short)mh.invokeExact(functionSymbol, (short)37, structSegmt); + Assert.assertEquals(result, 136); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArray_2() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(shortArray.withName("array_elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + + short result = (short)mh.invokeExact(functionSymbol, (short)444, structSegmt); + Assert.assertEquals(result, 1110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArray_reverseOrder_2() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + shortArray.withName("array_elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + + short result = (short)mh.invokeExact(functionSymbol, (short)444, structSegmt); + Assert.assertEquals(result, 1110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArray_withoutLayoutName_2() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(shortArray, JAVA_SHORT, MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + + short result = (short)mh.invokeExact(functionSymbol, (short)444, structSegmt); + Assert.assertEquals(result, 1110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArray_2() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struc_array_elem1"), JAVA_SHORT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + structSegmt.set(JAVA_SHORT, 6, (short)444); + structSegmt.set(JAVA_SHORT, 8, (short)555); + + short result = (short)mh.invokeExact(functionSymbol, (short)666, structSegmt); + Assert.assertEquals(result, 2331); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArray_reverseOrder_2() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), structArray.withName("struc_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + structSegmt.set(JAVA_SHORT, 6, (short)444); + structSegmt.set(JAVA_SHORT, 8, (short)555); + + short result = (short)mh.invokeExact(functionSymbol, (short)666, structSegmt); + Assert.assertEquals(result, 2331); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT, JAVA_SHORT); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_SHORT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)111); + structSegmt.set(JAVA_SHORT, 2, (short)222); + structSegmt.set(JAVA_SHORT, 4, (short)333); + structSegmt.set(JAVA_SHORT, 6, (short)444); + structSegmt.set(JAVA_SHORT, 8, (short)555); + + short result = (short)mh.invokeExact(functionSymbol, (short)666, structSegmt); + Assert.assertEquals(result, 2331); + } + } + + @Test + public void test_add2ShortStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)56); + shortHandle2.set(structSegmt1, (short)45); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)78); + shortHandle2.set(structSegmt2, (short)67); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)134); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)112); + } + } + + @Test + public void test_add2ShortStructs_returnStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)56); + shortHandle2.set(structSegmt1, (short)45); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)78); + shortHandle2.set(structSegmt2, (short)67); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 134); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 2), 112); + } + } + + @Test + public void test_add3ShortStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2"), + JAVA_SHORT.withName("elem3"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle shortHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3ShortStructs_returnStruct").get(); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MethodHandle mh = linker.downcallHandle(fd); + + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)25); + shortHandle2.set(structSegmt1, (short)26); + shortHandle3.set(structSegmt1, (short)27); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)34); + shortHandle2.set(structSegmt2, (short)35); + shortHandle3.set(structSegmt2, (short)36); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)59); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)61); + Assert.assertEquals((short)shortHandle3.get(resultSegmt), (short)63); + } + } + + @Test + public void test_addIntAndIntsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1122334); + intHandle2.set(structSegmt, 1234567); + + int result = (int)mh.invokeExact(functionSymbol, 2244668, structSegmt); + Assert.assertEquals(result, 4601569); + } + } + + @Test + public void test_addIntAndIntShortFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(JAVA_SHORT.bitSize())); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntShortFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, (short)32766); + + int result = (int)mh.invokeExact(functionSymbol, 22334455, structSegmt); + Assert.assertEquals(result, 33590565); + } + } + + @Test + public void test_addIntAndShortIntFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_SHORT.bitSize()), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndShortIntFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, (short)32766); + elemHandle2.set(structSegmt, 22446688); + + int result = (int)mh.invokeExact(functionSymbol, 11335577, structSegmt); + Assert.assertEquals(result, 33815031); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 7654321); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1234567); + intHandle2.set(structSegmt, 2468024); + + int result = (int)mh.invoke(functionSymbol, intSegmt, structSegmt); + Assert.assertEquals(result, 11356912); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStruct_returnIntPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStruct_returnIntPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 1122333); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 4455666); + intHandle2.set(structSegmt, 7788999); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, intSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 13366998); + Assert.assertEquals(resultAddr.toRawLongValue(), intSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addIntAndIntsFromStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 11121314); + intHandle2.set(structSegmt, 15161718); + + int result = (int)mh.invoke(functionSymbol, 19202122, structSegmt); + Assert.assertEquals(result, 45485154); + } + } + + @Test + public void test_addIntAndIntsFromNestedStruct_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_INT.withName("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invokeExact(functionSymbol, 33343536, structSegmt); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromNestedStruct_reverseOrder_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invokeExact(functionSymbol, 33343536, structSegmt); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromNestedStruct_withoutLayoutName_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_INT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invokeExact(functionSymbol, 33343536, structSegmt); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArray_2() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(intArray.withName("array_elem1"), JAVA_INT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invokeExact(functionSymbol, 4444444, structSegmt); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArray_reverseOrder_2() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), intArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invokeExact(functionSymbol, 4444444, structSegmt); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArray_withoutLayoutName_2() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(intArray, JAVA_INT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invokeExact(functionSymbol, 4444444, structSegmt); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArray_2() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_INT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invokeExact(functionSymbol, 6666666, structSegmt); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArray_reverseOrder_2() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invokeExact(functionSymbol, 6666666, structSegmt); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT, JAVA_INT); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_INT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invokeExact(functionSymbol, 6666666, structSegmt); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_add2IntStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224466); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113354); + } + } + + @Test + public void test_add2IntStructs_returnStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 110224466); + Assert.assertEquals(resultAddr.get(JAVA_INT, 4), 89113354); + } + } + + @Test + public void test_add3IntStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3IntStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + intHandle3.set(structSegmt1, 99001122); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 33445566); + intHandle2.set(structSegmt2, 77889900); + intHandle3.set(structSegmt2, 44332211); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(intHandle1.get(resultSegmt), 44668910); + Assert.assertEquals(intHandle2.get(resultSegmt), 133557688); + Assert.assertEquals(intHandle3.get(resultSegmt), 143333333); + } + } + + @Test + public void test_addLongAndLongsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 1234567890L); + longHandle2.set(structSegmt, 9876543210L); + long result = (long)mh.invokeExact(functionSymbol, 2468024680L, structSegmt); + Assert.assertEquals(result, 13579135780L); + } + } + + @Test + public void test_addIntAndIntLongFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_INT.bitSize()), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntLongFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, 667788990011L); + + long result = (long)mh.invokeExact(functionSymbol, 22446688, structSegmt); + Assert.assertEquals(result, 667822660043L); + } + } + + @Test + public void test_addIntAndLongIntFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), + JAVA_INT.withName("elem2"), MemoryLayout.paddingLayout(JAVA_INT.bitSize())); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndLongIntFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 667788990011L); + elemHandle2.set(structSegmt, 11223344); + + long result = (long)mh.invokeExact(functionSymbol, 1234567, structSegmt); + Assert.assertEquals(result, 667801447922L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 1111111111L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 3333333333L); + longHandle2.set(structSegmt, 5555555555L); + + long result = (long)mh.invoke(functionSymbol, longSegmt, structSegmt); + Assert.assertEquals(result, 9999999999L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStruct_returnLongPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStruct_returnLongPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 1122334455L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 6677889900L); + longHandle2.set(structSegmt, 1234567890L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, longSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 9034792245L); + Assert.assertEquals(resultAddr.toRawLongValue(), longSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addLongAndLongsFromStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 224466880022L); + longHandle2.set(structSegmt, 446688002244L); + + long result = (long)mh.invoke(functionSymbol, 668800224466L, structSegmt); + Assert.assertEquals(result, 1339955106732L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStruct_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invokeExact(functionSymbol, 778899001122L, structSegmt); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStruct_reverseOrder_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invokeExact(functionSymbol, 778899001122L, structSegmt); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStruct_withoutLayoutName_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG, nestedStructLayout); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invokeExact(functionSymbol, 778899001122L, structSegmt); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArray_2() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(longArray.withName("array_elem1"), JAVA_LONG.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + + long result = (long)mh.invokeExact(functionSymbol, 444444444L, structSegmt); + Assert.assertEquals(result, 1111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArray_reverseOrder_2() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), longArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + + long result = (long)mh.invokeExact(functionSymbol, 444444444L, structSegmt); + Assert.assertEquals(result, 1111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArray_withoutLayoutName_2() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(longArray, JAVA_LONG); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + + long result = (long)mh.invokeExact(functionSymbol, 444444444L, structSegmt); + Assert.assertEquals(result, 1111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArray_2() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_LONG.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + structSegmt.set(JAVA_LONG, 24, 444444444L); + structSegmt.set(JAVA_LONG, 32, 555555555L); + + long result = (long)mh.invokeExact(functionSymbol, 666666666L, structSegmt); + Assert.assertEquals(result, 2333333331L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArray_reverseOrder_2() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + structSegmt.set(JAVA_LONG, 24, 444444444L); + structSegmt.set(JAVA_LONG, 32, 555555555L); + + long result = (long)mh.invokeExact(functionSymbol, 666666666L, structSegmt); + Assert.assertEquals(result, 2333333331L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG, JAVA_LONG); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_LONG); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 111111111L); + structSegmt.set(JAVA_LONG, 8, 222222222L); + structSegmt.set(JAVA_LONG, 16, 333333333L); + structSegmt.set(JAVA_LONG, 24, 444444444L); + structSegmt.set(JAVA_LONG, 32, 555555555L); + + long result = (long)mh.invokeExact(functionSymbol, 666666666L, structSegmt); + Assert.assertEquals(result, 2333333331L); + } + } + + @Test + public void test_add2LongStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + } + } + + @Test + public void test_add2LongStructs_returnStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 5566778899L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 9900112233L); + longHandle2.set(structSegmt2, 3344556677L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 11022446688L); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 8), 8911335576L); + } + } + + @Test + public void test_add3LongStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2"), JAVA_LONG.withName("elem3")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle longHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3LongStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + longHandle3.set(structSegmt1, 112233445566L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + longHandle3.set(structSegmt2, 778899001122L); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + Assert.assertEquals(longHandle3.get(resultSegmt), 891132446688L); + } + } + + @Test + public void test_addFloatAndFloatsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 8.12F); + floatHandle2.set(structSegmt, 9.24F); + float result = (float)mh.invokeExact(functionSymbol, 6.56F, structSegmt); + Assert.assertEquals(result, 23.92F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + float result = (float)mh.invoke(functionSymbol, floatSegmt, structSegmt); + Assert.assertEquals(result, 49.69F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStruct_returnFloatPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, floatSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 49.69F, 0.01F); + Assert.assertEquals(resultAddr.toRawLongValue(), floatSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addFloatAndFloatsFromStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 35.11F); + floatHandle2.set(structSegmt, 46.22F); + + float result = (float)mh.invoke(functionSymbol, 79.33F, structSegmt); + Assert.assertEquals(result, 160.66F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStruct_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invokeExact(functionSymbol, 37.88F, structSegmt); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStruct_reverseOrder_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invokeExact(functionSymbol, 37.88F, structSegmt); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStruct_withoutLayoutName_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invokeExact(functionSymbol, 37.88F, structSegmt); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArray_2() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(floatArray.withName("array_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invokeExact(functionSymbol, 444.44F, structSegmt); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder_2() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), floatArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invokeExact(functionSymbol, 444.44F, structSegmt); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArray_withoutLayoutName_2() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(floatArray, JAVA_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invokeExact(functionSymbol, 444.44F, structSegmt); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArray_2() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invokeExact(functionSymbol, 666.66F, structSegmt); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder_2() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invokeExact(functionSymbol, 666.66F, structSegmt); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT, JAVA_FLOAT); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invokeExact(functionSymbol, 666.66F, structSegmt); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 49.46F, 0.01F); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 4), 24.68F, 0.01F); + } + } + + @Test + public void test_add3FloatStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3FloatStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + floatHandle3.set(structSegmt1, 45.67F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + floatHandle3.set(structSegmt2, 69.72F); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + Assert.assertEquals((float)floatHandle3.get(resultSegmt), 115.39, 0.01F); + } + } + + @Test + public void test_addDoubleAndDoublesFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 2228.111D); + doubleHandle2.set(structSegmt, 2229.221D); + double result = (double)mh.invokeExact(functionSymbol, 3336.333D, structSegmt); + Assert.assertEquals(result, 7793.665D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleFromStruct_2() throws Throwable { + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32)) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_FLOAT.bitSize()), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18.444F); + elemHandle2.set(structSegmt, 619.777D); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + double result = (double)mh.invokeExact(functionSymbol, 113.567D, structSegmt); + Assert.assertEquals(result, 751.788D, 0.001D); + } + } + + @Test + public void test_addDoubleAndIntDoubleFromStruct_2() throws Throwable { + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32)) : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(JAVA_INT.bitSize()), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18); + elemHandle2.set(structSegmt, 619.777D); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + double result = (double)mh.invokeExact(functionSymbol, 113.567D, structSegmt); + Assert.assertEquals(result, 751.344D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFloatFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19.22F); + + double result = (double)mh.invokeExact(functionSymbol, 216.666D, structSegmt); + Assert.assertEquals(result, 454.441D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleIntFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleIntFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19); + + double result = (double)mh.invokeExact(functionSymbol, 216.666D, structSegmt); + Assert.assertEquals(result, 454.221D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 112.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 118.456D); + doubleHandle2.set(structSegmt, 119.789D); + + double result = (double)mh.invoke(functionSymbol, doubleSegmt, structSegmt); + Assert.assertEquals(result, 350.368D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 212.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 218.456D); + doubleHandle2.set(structSegmt, 219.789D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, doubleSegmt, structSegmt); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 650.368D, 0.001D); + Assert.assertEquals(resultAddr.toRawLongValue(), doubleSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 22.111D); + doubleHandle2.set(structSegmt, 44.222D); + + double result = (double)mh.invoke(functionSymbol, 66.333D, structSegmt); + Assert.assertEquals(result, 132.666D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStruct_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_DOUBLE.withName("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invokeExact(functionSymbol, 37.864D, structSegmt); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStruct_reverseOrder_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStruct_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invokeExact(functionSymbol, 37.864D, structSegmt); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStruct_withoutLayoutName_2() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout, JAVA_DOUBLE); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invokeExact(functionSymbol, 37.864D, structSegmt); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArray_2() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(doubleArray.withName("array_elem1"), JAVA_DOUBLE.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invokeExact(functionSymbol, 444.444D, structSegmt); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder_2() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), doubleArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invokeExact(functionSymbol, 444.444D, structSegmt); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArray_withoutLayoutName_2() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(doubleArray, JAVA_DOUBLE); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invokeExact(functionSymbol, 444.444D, structSegmt); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArray_2() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_DOUBLE.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invokeExact(functionSymbol, 666.666D, structSegmt); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder_2() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invokeExact(functionSymbol, 666.666D, structSegmt); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArray_withoutLayoutName_2() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE, JAVA_DOUBLE); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray, JAVA_DOUBLE); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArray").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invokeExact(functionSymbol, 666.666D, structSegmt); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStructPointer_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStructPointer").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(functionSymbol, structSegmt1, structSegmt2); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 44.666D, 0.001D); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 8), 66.888D, 0.001D); + } + } + + @Test + public void test_add3DoubleStructs_returnStruct_2() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle doubleHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout); + Addressable functionSymbol = nativeLibLookup.lookup("add3DoubleStructs_returnStruct").get(); + MethodHandle mh = linker.downcallHandle(fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + doubleHandle3.set(structSegmt1, 33.123D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + doubleHandle3.set(structSegmt2, 55.456D); + + MemorySegment resultSegmt = (MemorySegment)mh.invokeExact(functionSymbol, allocator, structSegmt1, structSegmt2); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + Assert.assertEquals((double)doubleHandle3.get(resultSegmt), 88.579D, 0.001D); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/MultiUpcallMHTests.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/MultiUpcallMHTests.java new file mode 100644 index 00000000000..1cf7193145b --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/MultiUpcallMHTests.java @@ -0,0 +1,560 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) intended for + * the situations when the multiple primitive specific upcalls happen within + * the same memory session or from different memory sessions. + */ +@Test(groups = { "level.sanity" }) +public class MultiUpcallMHTests { + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addTwoBoolsWithOrByUpcallMH_SameSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), session); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr1); + Assert.assertEquals(result, true); + + MemorySegment upcallFuncAddr2 = linker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), session); + result = (boolean)mh.invoke(true, false, upcallFuncAddr2); + Assert.assertEquals(result, true); + + MemorySegment upcallFuncAddr3 = linker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), session); + result = (boolean)mh.invoke(true, false, upcallFuncAddr3); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addTwoBoolsWithOrByUpcallMH_DiffSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), session); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), session); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), session); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPointerByUpcallMH_SameSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), session); + MemorySegment charSegmt1 = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt1, 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + + MemorySegment upcallFuncAddr2 = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), session); + MemorySegment charSegmt2 = allocator.allocate(JAVA_CHAR, 'B'); + result = (char)mh.invoke(charSegmt2, 'D', upcallFuncAddr2); + Assert.assertEquals(result, 'C'); + + MemorySegment upcallFuncAddr3 = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), session); + MemorySegment charSegmt3 = allocator.allocate(JAVA_CHAR, 'B'); + result = (char)mh.invoke(charSegmt3, 'D', upcallFuncAddr3); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPointerByUpcallMH_DiffSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt, 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt, 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt, 'D', upcallFuncAddr1); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_addByteAndByteFromNativePtrByUpcallMH_SameSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), session); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr1); + Assert.assertEquals(result, (byte)88); + + MemorySegment upcallFuncAddr2 = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), session); + result = (byte)mh.invoke((byte)33, upcallFuncAddr2); + Assert.assertEquals(result, (byte)88); + + MemorySegment upcallFuncAddr3 = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), session); + result = (byte)mh.invoke((byte)33, upcallFuncAddr3); + Assert.assertEquals(result, (byte)88); + } + } + + @Test + public void test_addByteAndByteFromNativePtrByUpcallMH_DiffSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), session); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), session); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), session); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr); + Assert.assertEquals(result, (byte)88); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetPtr_ByUpcallMH_SameSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), session); + MemorySegment shortSegmt1 = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr1 = (MemoryAddress)mh.invoke(shortSegmt1, (short)555, upcallFuncAddr1); + Assert.assertEquals(resultAddr1.get(JAVA_SHORT, 0), (short)999); + + MemorySegment upcallFuncAddr2 = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), session); + MemorySegment shortSegmt2 = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr2 = (MemoryAddress)mh.invoke(shortSegmt2, (short)555, upcallFuncAddr2); + Assert.assertEquals(resultAddr2.get(JAVA_SHORT, 0), (short)999); + + MemorySegment upcallFuncAddr3 = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), session); + MemorySegment shortSegmt3 = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr3 = (MemoryAddress)mh.invoke(shortSegmt3, (short)555, upcallFuncAddr3); + Assert.assertEquals(resultAddr3.get(JAVA_SHORT, 0), (short)999); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetPtr_ByUpcallMH_DiffSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), (short)999); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), (short)999); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), (short)999); + } + } + + @Test + public void test_addTwoIntsByUpcallMH_SameSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr1); + Assert.assertEquals(result, 222235); + + MemorySegment upcallFuncAddr2 = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + result = (int)mh.invoke(111112, 111123, upcallFuncAddr2); + Assert.assertEquals(result, 222235); + + MemorySegment upcallFuncAddr3 = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + result = (int)mh.invoke(111112, 111123, upcallFuncAddr3); + Assert.assertEquals(result, 222235); + } + } + + @Test + public void test_addTwoIntsByUpcallMH_DiffSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + } + + @Test + public void test_addTwoIntsReturnVoidByUpcallMH_SameSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoidByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), session); + mh.invoke(111454, 111398, upcallFuncAddr1); + + MemorySegment upcallFuncAddr2 = linker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), session); + mh.invoke(111454, 111398, upcallFuncAddr2); + + MemorySegment upcallFuncAddr3 = linker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), session); + mh.invoke(111454, 111398, upcallFuncAddr3); + } + } + + @Test + public void test_addTwoIntsReturnVoidByUpcallMH_DiffSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoidByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), session); + mh.invoke(111454, 111398, upcallFuncAddr); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), session); + mh.invoke(111454, 111398, upcallFuncAddr); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), session); + mh.invoke(111454, 111398, upcallFuncAddr); + } + } + + @Test + public void test_addLongAndLongFromPointerByUpcallMH_SameSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), session); + MemorySegment longSegmt1 = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt1, 6666698235L, upcallFuncAddr1); + Assert.assertEquals(result, 12409155659L); + + MemorySegment upcallFuncAddr2 = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), session); + MemorySegment longSegmt2 = allocator.allocate(JAVA_LONG, 5742457424L); + result = (long)mh.invoke(longSegmt2, 6666698235L, upcallFuncAddr2); + Assert.assertEquals(result, 12409155659L); + + MemorySegment upcallFuncAddr3 = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), session); + MemorySegment longSegmt3 = allocator.allocate(JAVA_LONG, 5742457424L); + result = (long)mh.invoke(longSegmt3, 6666698235L, upcallFuncAddr3); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addLongAndLongFromPointerByUpcallMH_DiffSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addFloatAndFloatFromNativePtrByUpcallMH_SameSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), session); + float result = (float)mh.invoke(5.74F, upcallFuncAddr1); + Assert.assertEquals(result, 12.53F, 0.01F); + + MemorySegment upcallFuncAddr2 = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), session); + result = (float)mh.invoke(5.74F, upcallFuncAddr2); + Assert.assertEquals(result, 12.53F, 0.01F); + + MemorySegment upcallFuncAddr3 = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), session); + result = (float)mh.invoke(5.74F, upcallFuncAddr3); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromNativePtrByUpcallMH_DiffSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), session); + float result = (float)mh.invoke(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), session); + float result = (float)mh.invoke(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), session); + float result = (float)mh.invoke(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH_SameSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + + MemorySegment upcallFuncAddr1 = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), session); + MemorySegment doubleSegmt1 = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr1 = (MemoryAddress)mh.invoke(doubleSegmt1, 1262.795D, upcallFuncAddr1); + Assert.assertEquals(resultAddr1.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + + MemorySegment upcallFuncAddr2 = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), session); + MemorySegment doubleSegmt2 = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr2 = (MemoryAddress)mh.invoke(doubleSegmt2, 1262.795D, upcallFuncAddr2); + Assert.assertEquals(resultAddr2.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + + MemorySegment upcallFuncAddr3 = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), session); + MemorySegment doubleSegmt3 = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr3 = (MemoryAddress)mh.invoke(doubleSegmt3, 1262.795D, upcallFuncAddr3); + Assert.assertEquals(resultAddr3.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH_DiffSession() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/MultiUpcallThrdsMHTests1.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/MultiUpcallThrdsMHTests1.java new file mode 100644 index 00000000000..2cd1f6050d2 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/MultiUpcallThrdsMHTests1.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) intended for + * the situation when the multi-threading specific upcalls happen to the same + * upcall method handle within different memory sessions, in which case the upcall + * metadata and the generated thunk are allocated separately. + */ +@Test(groups = { "level.sanity" }) +public class MultiUpcallThrdsMHTests1 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_multiUpcallThrdsWithDiffSessions() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr1.setUncaughtExceptionHandler(this); + thr1.start(); + + Thread thr2 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111113, 111124, upcallFuncAddr); + Assert.assertEquals(result, 222237); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr2.setUncaughtExceptionHandler(this); + thr2.start(); + + Thread thr3 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111114, 111125, upcallFuncAddr); + Assert.assertEquals(result, 222239); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr3.setUncaughtExceptionHandler(this); + thr3.start(); + + thr1.join(); + thr2.join(); + thr3.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/MultiUpcallThrdsMHTests2.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/MultiUpcallThrdsMHTests2.java new file mode 100644 index 00000000000..530346a3a3f --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/MultiUpcallThrdsMHTests2.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) intended for + * the situation when the multi-threading specific upcalls happen to the same + * upcall method handle within the same memory session, in which case the upcall + * metadata and the generated thunk are only allocated once and shared among + * these threads. + */ +@Test(groups = { "level.sanity" }) +public class MultiUpcallThrdsMHTests2 implements Thread.UncaughtExceptionHandler { + private volatile Throwable initException; + private static Linker linker = Linker.nativeLinker(); + private static MemorySession session = MemorySession.openImplicit(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test(enabled=false) + @Override + public void uncaughtException(Thread thr, Throwable t) { + initException = t; + } + + @Test + public void test_multiUpcallThrdsWithSameSession() throws Throwable { + Thread thr1 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr1.setUncaughtExceptionHandler(this); + thr1.start(); + + Thread thr2 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111113, 111124, upcallFuncAddr); + Assert.assertEquals(result, 222237); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr2.setUncaughtExceptionHandler(this); + thr2.start(); + + Thread thr3 = new Thread(){ + public void run() { + try { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111114, 111125, upcallFuncAddr); + Assert.assertEquals(result, 222239); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + }; + thr3.setUncaughtExceptionHandler(this); + thr3.start(); + + thr1.join(); + thr2.join(); + thr3.join(); + + if (initException != null){ + throw new RuntimeException(initException); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMHWithMixedSigStruTests.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMHWithMixedSigStruTests.java new file mode 100644 index 00000000000..d23af321b2b --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMHWithMixedSigStruTests.java @@ -0,0 +1,892 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SequenceLayout; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for the mixed native signatures + * in argument/return struct in upcall, which are not covered in UpcallMHWithStructTests and + * specially designed to validate the native signature types required in the genenerated thunk. + * + * Note: the padding elements in the struct are only required by RI or VarHandle (accessing the + * data address) while they are totally ignored in OpenJ9 given the padding/alignment are + * computed by libffi automatically in native. + */ +@Test(groups = { "level.sanity" }) +public class UpcallMHWithMixedSigStruTests { + private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addIntAndIntShortFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntShortFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntShortFromStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, (short)32766); + + int result = (int)mh.invoke(22334455, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 33590565); + } + } + + @Test + public void test_addIntAndShortIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + MemoryLayout.paddingLayout(16), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndShortIntFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndShortIntFromStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, (short)32766); + elemHandle2.set(structSegmt, 22446688); + + int result = (int)mh.invoke(11335577, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 33815031); + } + } + + @Test + public void test_addIntAndIntLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntLongFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntLongFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11223344); + elemHandle2.set(structSegmt, 667788990011L); + + long result = (long)mh.invoke(22446688, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 667822660043L); + } + } + + @Test + public void test_addIntAndLongIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), + JAVA_INT.withName("elem2"), MemoryLayout.paddingLayout(32)); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndLongIntFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndLongIntFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 667788990011L); + elemHandle2.set(structSegmt, 11223344); + + long result = (long)mh.invoke(1234567, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 667801447922L); + } + } + + @Test + public void test_addDoubleAndIntDoubleFromStructByUpcallMH() throws Throwable { + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32)) : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111111); + elemHandle2.set(structSegmt, 619.777D); + + double result = (double)mh.invoke(113.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111844.344D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleIntFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleIntFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 111111111); + + double result = (double)mh.invoke(216.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111546.221D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleFromStructByUpcallMH() throws Throwable { + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32)) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 18.444F); + elemHandle2.set(structSegmt, 619.777D); + + double result = (double)mh.invoke(113.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 751.788D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFloatFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19.22F); + + double result = (double)mh.invoke(216.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 454.441D, 0.001D); + } + } + + public static void test_addDoubleAndDoubleFloatPlusPaddingFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), + JAVA_FLOAT.withName("elem2"), MemoryLayout.paddingLayout(32)); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFloatFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 218.555D); + elemHandle2.set(structSegmt, 19.22F); + + double result = (double)mh.invoke(216.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 454.441D, 0.001D); + } + } + + @Test + public void test_addDoubleAnd2FloatsDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAnd2FloatsDoubleFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAnd2FloatsDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.22F); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 333.444D); + + double result = (double)mh.invoke(111.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 478.105D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDouble2FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDouble2FloatsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDouble2FloatsFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 333.444D); + elemHandle2.set(structSegmt, 11.22F); + elemHandle3.set(structSegmt, 22.33F); + + double result = (double)mh.invoke(111.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 478.105D, 0.001D); + } + } + + @Test + public void test_addFloatAndInt2FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndInt2FloatsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndInt2FloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111); + elemHandle2.set(structSegmt, 11.22F); + elemHandle3.set(structSegmt, 22.33F); + + float result = (float)mh.invoke(55.567F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111200.12F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatIntFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_INT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatIntFloatFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatIntFloatFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.22F); + elemHandle2.set(structSegmt, 111111); + elemHandle3.set(structSegmt, 22.33F); + + float result = (float)mh.invoke(55.567F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111200.12F, 0.01F); + } + } + + @Test + public void test_addDoubleAndIntFloatDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntFloatDoubleFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntFloatDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111111); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 333.444D); + + double result = (double)mh.invoke(555.55D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111112022.324D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatIntDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_INT.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatIntDoubleFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatIntDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 22.33F); + elemHandle2.set(structSegmt, 111111111); + elemHandle3.set(structSegmt, 333.444D); + + double result = (double)mh.invoke(555.55D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111112022.324D, 0.001D); + } + } + + @Test + public void test_addDoubleAndLongDoubleFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndLongDoubleFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndLongDoubleFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 22222222222222L); + elemHandle2.set(structSegmt, 33333.444D); + + double result = (double)mh.invoke(55555.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 22222222311110.555D, 0.001D); + } + } + + @Test + public void test_addFloatAndInt3FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3"), JAVA_FLOAT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndInt3FloatsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndInt3FloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 77777777); + elemHandle2.set(structSegmt, 11.22F); + elemHandle3.set(structSegmt, 22.33F); + elemHandle4.set(structSegmt, 44.55F); + + float result = (float)mh.invoke(66.678F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 77777921.778F, 0.001F); + } + } + + @Test + public void test_addLongAndLong2FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLong2FloatsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLong2FloatsFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 777777777777L); + elemHandle2.set(structSegmt, 11.25F); + elemHandle3.set(structSegmt, 22.75F); + + long result = (long)mh.invoke(555555555555L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1333333333365L); + } + } + + @Test + public void test_addFloatAnd3FloatsIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3"), JAVA_INT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAnd3FloatsIntFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAnd3FloatsIntFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.22F); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 44.55F); + elemHandle4.set(structSegmt, 77777777); + + float result = (float)mh.invoke(66.456F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 77777921.556F, 0.001F); + } + } + + @Test + public void test_addLongAndFloatLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndFloatLongFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndFloatLongFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 55.11F); + elemHandle2.set(structSegmt, 150000000000L); + + long result = (long)mh.invoke(5555555555L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 155555555610L); + } + } + + @Test + public void test_addDoubleAndDoubleFloatIntFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFloatIntFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFloatIntFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 333.444D); + elemHandle2.set(structSegmt, 22.33F); + elemHandle3.set(structSegmt, 111111111); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111112022.341D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleLongFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleLongFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 33333.444D); + elemHandle2.set(structSegmt, 222222222222L); + + double result = (double)mh.invoke(55555.111D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 222222311110.555D, 0.001D); + } + } + + @Test + public void test_addLongAnd2FloatsLongFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_LONG.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAnd2FloatsLongFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAnd2FloatsLongFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.11F); + elemHandle2.set(structSegmt, 22.11F); + elemHandle3.set(structSegmt, 4444444444L); + + long result = (long)mh.invoke(11111111111L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 15555555588L); + } + } + + @Test + public void test_addShortAnd3ShortsCharFromStructByUpcallMH() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(3, JAVA_SHORT); + GroupLayout structLayout = MemoryLayout.structLayout(shortArray, JAVA_CHAR); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAnd3ShortsCharFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAnd3ShortsCharFromStruct, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1000); + structSegmt.set(JAVA_SHORT, 2, (short)2000); + structSegmt.set(JAVA_SHORT, 4, (short)3000); + structSegmt.set(JAVA_CHAR, 6, 'A'); + + short result = (short)mh.invoke((short)4000, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 10065); + } + } + + @Test + public void test_addFloatAndIntFloatIntFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_INT.withName("elem3"), JAVA_FLOAT.withName("elem4")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndIntFloatIntFloatFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndIntFloatIntFloatFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 555555555); + elemHandle2.set(structSegmt, 11.222F); + elemHandle3.set(structSegmt, 666666666); + elemHandle4.set(structSegmt, 33.444F); + + float result = (float)mh.invoke(77.456F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1222222343.122F, 0.001F); + } + } + + @Test + public void test_addDoubleAndIntDoubleFloatFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32), JAVA_FLOAT.withName("elem3")) + : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2"), + JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleFloatFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 7777); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 33.444F); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 8584.566D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleIntFromStructByUpcallMH() throws Throwable { + /* The size of [float, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32), JAVA_INT.withName("elem3")) + : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2"), + JAVA_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleIntFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatDoubleIntFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 33.444F); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 7777); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 8584.566D, 0.001D); + } + } + + @Test + public void test_addDoubleAndIntDoubleIntFromStructByUpcallMH() throws Throwable { + /* The size of [int, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32), JAVA_INT.withName("elem3")) + : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2"), + JAVA_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleIntFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleIntFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 6666); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 7777); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 15217.122D, 0.001D); + } + } + + @Test + public void test_addDoubleAndFloatDoubleFloatFromStructByUpcallMH() throws Throwable { + /* The size of [float, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32), JAVA_FLOAT.withName("elem3")) + : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2"), + JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndFloatDoubleFloatFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndFloatDoubleFloatFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 11.222F); + elemHandle2.set(structSegmt, 218.555D); + elemHandle3.set(structSegmt, 33.444F); + + double result = (double)mh.invoke(555.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 818.788D, 0.001D); + } + } + + @Test + public void test_addDoubleAndIntDoubleLongFromStructByUpcallMH() throws Throwable { + /* The size of [int, double, long] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 24 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32), JAVA_LONG.withName("elem3").withBitAlignment(32)) + : MemoryLayout.structLayout(JAVA_INT.withName("elem1"), MemoryLayout.paddingLayout(32), + JAVA_DOUBLE.withName("elem2"), JAVA_LONG.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndIntDoubleLongFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndIntDoubleLongFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + elemHandle1.set(structSegmt, 111111111); + elemHandle2.set(structSegmt, 619.777D); + elemHandle3.set(structSegmt, 888888888888L); + + double result = (double)mh.invoke(113.567D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 889000000732.344D, 0.001D); + } + } + + @Test + public void test_return254BytesFromStructByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(254, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("return254BytesFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_return254BytesFromStruct, + FunctionDescriptor.of(structLayout), session); + MemorySegment byteArrStruSegment = (MemorySegment)mh.invoke(allocator, upcallFuncAddr); + for (int i = 0; i < 254; i++) { + Assert.assertEquals(byteArrStruSegment.get(JAVA_BYTE, i), (byte)i); + } + } + } + + @Test + public void test_return4KBytesFromStructByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(4096, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("return4KBytesFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_return4KBytesFromStruct, + FunctionDescriptor.of(structLayout), session); + MemorySegment byteArrStruSegment = (MemorySegment)mh.invoke(allocator, upcallFuncAddr); + for (int i = 0; i < 4096; i++) { + Assert.assertEquals(byteArrStruSegment.get(JAVA_BYTE, i), (byte)i); + } + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMHWithPrimTests.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMHWithPrimTests.java new file mode 100644 index 00000000000..bf41a92f4bd --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMHWithPrimTests.java @@ -0,0 +1,724 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for primitive types in upcall. + */ +@Test(groups = { "level.sanity" }) +public class UpcallMHWithPrimTests { + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + private static final SymbolLookup defaultLibLookup = linker.defaultLookup(); + + @Test + public void test_addTwoBoolsWithOrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolsWithOrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2BoolsWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN), session); + boolean result = (boolean)mh.invoke(true, false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolFromPointerWithOrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPointerWithOrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPointerWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS), session); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + boolean result = (boolean)mh.invoke(false, boolSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolFromNativePtrWithOrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromNativePtrWithOrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPointerWithOr, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS), session); + boolean result = (boolean)mh.invoke(false, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_BOOLEAN, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPtrWithOr_RetPtr, + FunctionDescriptor.of(ADDRESS, JAVA_BOOLEAN, ADDRESS), session); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(false, boolSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), true); + } + } + + @Test + public void test_addBoolAndBoolFromPtrWithOr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_BOOLEAN, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolFromPtrWithOr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolFromPtrWithOr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, JAVA_BOOLEAN, ADDRESS), session); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(false, boolSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), true); + } + } + + @Test + public void test_addTwoBytesByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2BytesByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Bytes, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, JAVA_BYTE), session); + byte result = (byte)mh.invoke((byte)6, (byte)3, upcallFuncAddr); + Assert.assertEquals(result, 9); + } + } + + @Test + public void test_addByteAndByteFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)7); + byte result = (byte)mh.invoke((byte)8, byteSegmt, upcallFuncAddr); + Assert.assertEquals(result, 15); + } + } + + @Test + public void test_addByteAndByteFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), session); + byte result = (byte)mh.invoke((byte)33, upcallFuncAddr); + Assert.assertEquals(result, 88); + } + } + + @Test + public void test_addByteAndByteFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_BYTE, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, JAVA_BYTE, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)35); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke((byte)47, byteSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 82); + } + } + + @Test + public void test_addByteAndByteFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_BYTE, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndByteFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndByteFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, JAVA_BYTE, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)35); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke((byte)47, byteSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 82); + } + } + + @Test + public void test_createNewCharFrom2CharsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFrom2CharsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFrom2Chars, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, JAVA_CHAR), session); + char result = (char)mh.invoke('B', 'D', upcallFuncAddr); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + char result = (char)mh.invoke(charSegmt, 'D', upcallFuncAddr); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPointer, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, JAVA_CHAR), session); + char result = (char)mh.invoke('D', upcallFuncAddr); + Assert.assertEquals(result, 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_CHAR), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(charSegmt, 'D', upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'C'); + } + } + + @Test + public void test_createNewCharFromCharAndCharFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("createNewCharFromCharAndCharFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_createNewCharFromCharAndCharFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_CHAR), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'B'); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(charSegmt, 'D', upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'C'); + } + } + + @Test + public void test_addTwoShortsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Shorts, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT), session); + short result = (short)mh.invoke((short)1111, (short)2222, upcallFuncAddr); + Assert.assertEquals(result, 3333); + } + } + + @Test + public void test_addShortAndShortFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, ADDRESS, JAVA_SHORT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPointer, + FunctionDescriptor.of(JAVA_SHORT, ADDRESS, JAVA_SHORT), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)2222); + short result = (short)mh.invoke(shortSegmt, (short)3333, upcallFuncAddr); + Assert.assertEquals(result, 5555); + } + } + + @Test + public void test_addShortAndShortFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPointer, + FunctionDescriptor.of(JAVA_SHORT, ADDRESS, JAVA_SHORT), session); + short result = (short)mh.invoke((short)789, upcallFuncAddr); + Assert.assertEquals(result, 1245); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 999); + } + } + + @Test + public void test_addShortAndShortFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_SHORT), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)444); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, (short)555, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 999); + } + } + + @Test + public void test_addTwoIntsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111112, 111123, upcallFuncAddr); + Assert.assertEquals(result, 222235); + } + } + + @Test + public void test_addIntAndIntFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPointer, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 222215); + int result = (int)mh.invoke(333321, intSegmt, upcallFuncAddr); + Assert.assertEquals(result, 555536); + } + } + + @Test + public void test_addIntAndIntFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPointer, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + int result = (int)mh.invoke(222222, upcallFuncAddr); + Assert.assertEquals(result, 666666); + } + } + + @Test + public void test_addIntAndIntFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_INT, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, JAVA_INT, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 222215); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(333321, intSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 555536); + } + } + + @Test + public void test_addIntAndIntFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_INT, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, JAVA_INT, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 222215); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(333321, intSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 555536); + } + } + + @Test + public void test_add3IntsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add3IntsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add3Ints, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT), session); + int result = (int)mh.invoke(111112, 111123, 111124, upcallFuncAddr); + Assert.assertEquals(result, 333359); + } + } + + @Test + public void test_addIntAndCharByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_CHAR, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndCharByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndChar, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_CHAR), session); + int result = (int)mh.invoke(555558, 'A', upcallFuncAddr); + Assert.assertEquals(result, 555623); + } + } + + @Test + public void test_addTwoIntsReturnVoidByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsReturnVoidByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2IntsReturnVoid, + FunctionDescriptor.ofVoid(JAVA_INT, JAVA_INT), session); + mh.invoke(44454, 333398, upcallFuncAddr); + } + } + + @Test + public void test_addTwoLongsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, JAVA_LONG, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Longs, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, JAVA_LONG), session); + long result = (long)mh.invoke(333333222222L, 111111555555L, upcallFuncAddr); + Assert.assertEquals(result, 444444777777L); + } + } + + @Test + public void test_addLongAndLongFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + long result = (long)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(result, 12409155659L); + } + } + + @Test + public void test_addLongAndLongFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPointer, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG), session); + long result = (long)mh.invoke(5555555555L, upcallFuncAddr); + Assert.assertEquals(result, 8888888888L); + } + } + + @Test + public void test_addLongAndLongFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_LONG, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_LONG), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 12409155659L); + } + } + + @Test + public void test_addLongAndLongFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_LONG, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_LONG), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 5742457424L); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(longSegmt, 6666698235L, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 12409155659L); + } + } + + @Test + public void test_addTwoFloatsByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatsByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Floats, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, JAVA_FLOAT), session); + float result = (float)mh.invoke(15.74F, 16.79F, upcallFuncAddr); + Assert.assertEquals(result, 32.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 6.79F); + float result = (float)mh.invoke(5.74F, floatSegmt, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), session); + float result = (float)mh.invoke(5.74F, upcallFuncAddr); + Assert.assertEquals(result, 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_FLOAT, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, JAVA_FLOAT, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 6.79F); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(5.74F, floatSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 12.53F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, JAVA_FLOAT, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, JAVA_FLOAT, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 6.79F); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(5.74F, floatSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 12.53F, 0.01F); + } + } + + @Test + public void test_add2DoublesByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoublesByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2Doubles, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, JAVA_DOUBLE), session); + double result = (double)mh.invoke(159.748D, 262.795D, upcallFuncAddr); + Assert.assertEquals(result, 422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPointerByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, JAVA_DOUBLE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPointer, + FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, JAVA_DOUBLE), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + double result = (double)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(result, 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromNativePtrByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromNativePtrByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPointer, + FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, JAVA_DOUBLE), session); + double result = (double)mh.invoke(1262.795D, upcallFuncAddr); + Assert.assertEquals(result, 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoubleFromPtr_RetArgPtr_ByUpcallMH() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoubleFromPtr_RetPtr_ByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoubleFromPtr_RetArgPtr, + FunctionDescriptor.of(ADDRESS, ADDRESS, JAVA_DOUBLE), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 1159.748D); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, 1262.795D, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 2422.543D, 0.001D); + } + } + + @Test + public void test_qsortByUpcallMH() throws Throwable { + int expectedArray[] = {11, 12, 13, 14, 15, 16, 17}; + int expectedArrayLength = expectedArray.length; + + FunctionDescriptor fd = FunctionDescriptor.ofVoid(ADDRESS, JAVA_INT, JAVA_INT, ADDRESS); + Addressable functionSymbol = defaultLibLookup.lookup("qsort").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_compare, + FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment arraySegmt = allocator.allocateArray(JAVA_INT, new int[]{17, 14, 13, 16, 15, 12, 11}); + mh.invoke(arraySegmt, 7, 4, upcallFuncAddr); + int[] sortedArray = arraySegmt.toArray(JAVA_INT); + for (int index = 0; index < expectedArrayLength; index++) { + Assert.assertEquals(sortedArray[index], expectedArray[index]); + } + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMHWithStructTests.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMHWithStructTests.java new file mode 100644 index 00000000000..00d94aec007 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMHWithStructTests.java @@ -0,0 +1,2886 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.upcall; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SequenceLayout; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for argument/return struct in upcall. + * + * Note: the padding elements in the struct are only required by RI or VarHandle (accessing the + * data address) while they are totally ignored in OpenJ9 given the padding/alignment are + * computed by libffi automatically in native. + */ +@Test(groups = { "level.sanity" }) +public class UpcallMHWithStructTests { + private static String osName = System.getProperty("os.name").toLowerCase(); + private static String arch = System.getProperty("os.arch").toLowerCase(); + /* The padding of struct is not required on Linux/s390x and Windows/x64 */ + private static boolean isStructPaddingNotRequired = osName.contains("win") && (arch.equals("amd64") || arch.equals("x86_64")) + || osName.contains("linux") && arch.equals("s390x"); + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addBoolAndBoolsFromStructWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithXorByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, false); + boolHandle2.set(structSegmt, true); + + boolean result = (boolean)mh.invoke(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAnd20BoolsFromStructWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN, + JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, + JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, + JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN, JAVA_BOOLEAN + ); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAnd20BoolsFromStructWithXorByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAnd20BoolsFromStructWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + structSegmt.set(JAVA_BOOLEAN, 5, true); + structSegmt.set(JAVA_BOOLEAN, 6, false); + structSegmt.set(JAVA_BOOLEAN, 7, true); + structSegmt.set(JAVA_BOOLEAN, 8, false); + structSegmt.set(JAVA_BOOLEAN, 9, true); + structSegmt.set(JAVA_BOOLEAN, 10, false); + structSegmt.set(JAVA_BOOLEAN, 11, true); + structSegmt.set(JAVA_BOOLEAN, 12, false); + structSegmt.set(JAVA_BOOLEAN, 13, true); + structSegmt.set(JAVA_BOOLEAN, 14, false); + structSegmt.set(JAVA_BOOLEAN, 15, true); + structSegmt.set(JAVA_BOOLEAN, 16, false); + structSegmt.set(JAVA_BOOLEAN, 17, true); + structSegmt.set(JAVA_BOOLEAN, 18, false); + structSegmt.set(JAVA_BOOLEAN, 19, true); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXorByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolFromPointerAndBoolsFromStructWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, structLayout), session); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, true); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, false); + boolHandle2.set(structSegmt, true); + + boolean result = (boolean)mh.invoke(boolSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, false); + } + } + + @Test + public void test_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN, JAVA_BOOLEAN); + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + MemorySegment boolSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + boolSegmt.set(JAVA_BOOLEAN, 0, false); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(boolSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), true); + Assert.assertEquals(resultAddr.toRawLongValue(), boolSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addBoolAndBoolsFromStructPointerWithXorByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructPointerWithXorByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructPointerWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + boolHandle1.set(structSegmt, true); + boolHandle2.set(structSegmt, false); + + boolean result = (boolean)mh.invoke(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXorByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BOOLEAN.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXorByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromNestedStructWithXor, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromNestedStructWithXor_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromNestedStructWithXor_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromNestedStructWithXor_reverseOrder, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, true); + structSegmt.set(JAVA_BOOLEAN, 1, false); + structSegmt.set(JAVA_BOOLEAN, 2, true); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArrayByUpcallMH() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(boolArray.withName("array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedBoolArray, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + + boolean result = (boolean)mh.invoke(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout boolArray = MemoryLayout.sequenceLayout(2, JAVA_BOOLEAN); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + boolArray.withName("array_elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + + boolean result = (boolean)mh.invoke(false, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BOOLEAN.withName("elem2")) : MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BOOLEAN.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout boolStruct = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, boolStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + structArray.withName("struct_array_elem2")) : MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BOOLEAN.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addBoolAndBoolsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_BOOLEAN, JAVA_BOOLEAN, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BOOLEAN, 0, false); + structSegmt.set(JAVA_BOOLEAN, 1, true); + structSegmt.set(JAVA_BOOLEAN, 2, false); + structSegmt.set(JAVA_BOOLEAN, 3, true); + structSegmt.set(JAVA_BOOLEAN, 4, false); + + boolean result = (boolean)mh.invoke(true, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2BoolStructsWithXor_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(boolHandle1.get(resultSegmt), false); + Assert.assertEquals(boolHandle2.get(resultSegmt), true); + } + } + + @Test + public void test_add2BoolStructsWithXor_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2BoolStructsWithXor_returnStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2BoolStructsWithXor_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 0), false); + Assert.assertEquals(resultAddr.get(JAVA_BOOLEAN, 1), true); + } + } + + @Test + public void test_add3BoolStructsWithXor_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2"), + JAVA_BOOLEAN.withName("elem3")) : MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2"), + JAVA_BOOLEAN.withName("elem3"), MemoryLayout.paddingLayout(8)); + VarHandle boolHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle boolHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle boolHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add3BoolStructsWithXor_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add3BoolStructsWithXor_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt1, true); + boolHandle2.set(structSegmt1, false); + boolHandle3.set(structSegmt1, true); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + boolHandle1.set(structSegmt2, true); + boolHandle2.set(structSegmt2, true); + boolHandle3.set(structSegmt2, false); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(boolHandle1.get(resultSegmt), false); + Assert.assertEquals(boolHandle2.get(resultSegmt), true); + Assert.assertEquals(boolHandle3.get(resultSegmt), true); + } + } + + @Test + public void test_addByteAndBytesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStruct, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)8); + byteHandle2.set(structSegmt, (byte)9); + + byte result = (byte)mh.invoke((byte)6, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23); + } + } + + @Test + public void test_addByteAnd20BytesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE, JAVA_BYTE, + JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, + JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, + JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE, JAVA_BYTE + ); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAnd20BytesFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAnd20BytesFromStruct, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)1); + structSegmt.set(JAVA_BYTE, 1, (byte)2); + structSegmt.set(JAVA_BYTE, 2, (byte)3); + structSegmt.set(JAVA_BYTE, 3, (byte)4); + structSegmt.set(JAVA_BYTE, 4, (byte)5); + structSegmt.set(JAVA_BYTE, 5, (byte)6); + structSegmt.set(JAVA_BYTE, 6, (byte)7); + structSegmt.set(JAVA_BYTE, 7, (byte)8); + structSegmt.set(JAVA_BYTE, 8, (byte)9); + structSegmt.set(JAVA_BYTE, 9, (byte)10); + structSegmt.set(JAVA_BYTE, 10, (byte)1); + structSegmt.set(JAVA_BYTE, 11, (byte)2); + structSegmt.set(JAVA_BYTE, 12, (byte)3); + structSegmt.set(JAVA_BYTE, 13, (byte)4); + structSegmt.set(JAVA_BYTE, 14, (byte)5); + structSegmt.set(JAVA_BYTE, 15, (byte)6); + structSegmt.set(JAVA_BYTE, 16, (byte)7); + structSegmt.set(JAVA_BYTE, 17, (byte)8); + structSegmt.set(JAVA_BYTE, 18, (byte)9); + structSegmt.set(JAVA_BYTE, 19, (byte)10); + + byte result = (byte)mh.invoke((byte)11, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 121); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteFromPointerAndBytesFromStruct, + FunctionDescriptor.of(JAVA_BYTE, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)18); + byteHandle2.set(structSegmt, (byte)19); + + byte result = (byte)mh.invoke(byteSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 49); + } + } + + @Test + public void test_addByteFromPointerAndBytesFromStruct_returnBytePointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteFromPointerAndBytesFromStruct_returnBytePointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteFromPointerAndBytesFromStruct_returnBytePointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment byteSegmt = allocator.allocate(JAVA_BYTE, (byte)12); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)14); + byteHandle2.set(structSegmt, (byte)16); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(byteSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 42); + Assert.assertEquals(resultAddr.toRawLongValue(), byteSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addByteAndBytesFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructPointer, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + byteHandle1.set(structSegmt, (byte)11); + byteHandle2.set(structSegmt, (byte)12); + byte result = (byte)mh.invoke((byte)13, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 36); + } + } + + @Test + public void test_addByteAndBytesFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BYTE.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromNestedStruct, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)22); + structSegmt.set(JAVA_BYTE, 2, (byte)33); + + byte result = (byte)mh.invoke((byte)46, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 112); + } + } + + @Test + public void test_addByteAndBytesFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)24); + structSegmt.set(JAVA_BYTE, 2, (byte)36); + + byte result = (byte)mh.invoke((byte)48, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 120); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArrayByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(byteArray.withName("array_elem1"), + JAVA_BYTE.withName("elem2")) : MemoryLayout.structLayout(byteArray.withName("array_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedByteArray, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)22); + structSegmt.set(JAVA_BYTE, 2, (byte)33); + + byte result = (byte)mh.invoke((byte)14, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 80); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedByteArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(2, JAVA_BYTE); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + byteArray.withName("array_elem2")) : MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + byteArray.withName("array_elem2"), MemoryLayout.paddingLayout(8)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedByteArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedByteArray_reverseOrder, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)14); + structSegmt.set(JAVA_BYTE, 2, (byte)16); + + byte result = (byte)mh.invoke((byte)18, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 60); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BYTE.withName("elem2")) : MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), + JAVA_BYTE.withName("elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)11); + structSegmt.set(JAVA_BYTE, 1, (byte)12); + structSegmt.set(JAVA_BYTE, 2, (byte)13); + structSegmt.set(JAVA_BYTE, 3, (byte)14); + structSegmt.set(JAVA_BYTE, 4, (byte)15); + + byte result = (byte)mh.invoke((byte)16, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 81); + } + } + + @Test + public void test_addByteAndBytesFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout byteStruct = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, byteStruct); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + structArray.withName("struct_array_elem2")) : MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(JAVA_BYTE.bitSize() * 3)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addByteAndBytesFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addByteAndBytesFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_BYTE, JAVA_BYTE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_BYTE, 0, (byte)12); + structSegmt.set(JAVA_BYTE, 1, (byte)14); + structSegmt.set(JAVA_BYTE, 2, (byte)16); + structSegmt.set(JAVA_BYTE, 3, (byte)18); + structSegmt.set(JAVA_BYTE, 4, (byte)20); + + byte result = (byte)mh.invoke((byte)22, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 102); + } + } + + @Test + public void test_add1ByteStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add1ByteStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add1ByteStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + } + } + + @Test + public void test_add2ByteStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2ByteStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + } + } + + @Test + public void test_add2ByteStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2ByteStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2ByteStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 0), 49); + Assert.assertEquals(resultAddr.get(JAVA_BYTE, 1), 24); + } + } + + @Test + public void test_add3ByteStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2"), + JAVA_BYTE.withName("elem3")) : MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2"), + JAVA_BYTE.withName("elem3"), MemoryLayout.paddingLayout(8)); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add3ByteStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add3ByteStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)25); + byteHandle2.set(structSegmt1, (byte)11); + byteHandle3.set(structSegmt1, (byte)12); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)24); + byteHandle2.set(structSegmt2, (byte)13); + byteHandle3.set(structSegmt2, (byte)16); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((byte)byteHandle1.get(resultSegmt), (byte)49); + Assert.assertEquals((byte)byteHandle2.get(resultSegmt), (byte)24); + Assert.assertEquals((byte)byteHandle3.get(resultSegmt), (byte)28); + } + } + + @Test + public void test_addCharAndCharsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStruct, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'A'); + charHandle2.set(structSegmt, 'B'); + + char result = (char)mh.invoke('C', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'D'); + } + } + + @Test + public void test_addCharAnd10CharsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, + JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, JAVA_CHAR, JAVA_CHAR); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAnd10CharsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharAnd10CharsFromStruct, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'A'); + structSegmt.set(JAVA_CHAR, 4, 'B'); + structSegmt.set(JAVA_CHAR, 6, 'B'); + structSegmt.set(JAVA_CHAR, 8, 'C'); + structSegmt.set(JAVA_CHAR, 10, 'C'); + structSegmt.set(JAVA_CHAR, 12, 'D'); + structSegmt.set(JAVA_CHAR, 14, 'D'); + structSegmt.set(JAVA_CHAR, 16, 'E'); + structSegmt.set(JAVA_CHAR, 18, 'E'); + + char result = (char)mh.invoke('A', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'U'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharFromPointerAndCharsFromStruct, + FunctionDescriptor.of(JAVA_CHAR, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + char result = (char)mh.invoke(charSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'M'); + } + } + + @Test + public void test_addCharFromPointerAndCharsFromStruct_returnCharPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharFromPointerAndCharsFromStruct_returnCharPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharFromPointerAndCharsFromStruct_returnCharPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment charSegmt = allocator.allocate(JAVA_CHAR, 'D'); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'E'); + charHandle2.set(structSegmt, 'F'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(charSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'M'); + Assert.assertEquals(resultAddr.toRawLongValue(), charSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addCharAndCharsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructPointer, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + charHandle1.set(structSegmt, 'H'); + charHandle2.set(structSegmt, 'I'); + + char result = (char)mh.invoke('G', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'V'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_CHAR.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromNestedStruct, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + + char result = (char)mh.invoke('H', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + + char result = (char)mh.invoke('H', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'W'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArrayByUpcallMH() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(charArray.withName("array_elem1"), + JAVA_CHAR.withName("elem2")) : MemoryLayout.structLayout(charArray.withName("array_elem1"), + JAVA_CHAR.withName("elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedCharArray, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invoke('D', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedCharArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout charArray = MemoryLayout.sequenceLayout(2, JAVA_CHAR); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + charArray.withName("array_elem2")) : MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + charArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedCharArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedCharArray_reverseOrder, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'A'); + structSegmt.set(JAVA_CHAR, 2, 'B'); + structSegmt.set(JAVA_CHAR, 4, 'C'); + + char result = (char)mh.invoke('D', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'G'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_CHAR.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invoke('J', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_addCharAndCharsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout charStruct = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, charStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), + structArray.withName("struct_array_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addCharAndCharsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addCharAndCharsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_CHAR, JAVA_CHAR, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_CHAR, 0, 'E'); + structSegmt.set(JAVA_CHAR, 2, 'F'); + structSegmt.set(JAVA_CHAR, 4, 'G'); + structSegmt.set(JAVA_CHAR, 6, 'H'); + structSegmt.set(JAVA_CHAR, 8, 'I'); + + char result = (char)mh.invoke('J', structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 'h'); + } + } + + @Test + public void test_add2CharStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2CharStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(charHandle1.get(resultSegmt), 'C'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'E'); + } + } + + @Test + public void test_add2CharStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2CharStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2CharStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'C'); + charHandle2.set(structSegmt2, 'D'); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 0), 'C'); + Assert.assertEquals(resultAddr.get(JAVA_CHAR, 2), 'E'); + } + } + + @Test + public void test_add3CharStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3")) : MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle charHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle charHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle charHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add3CharStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add3CharStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + charHandle1.set(structSegmt1, 'A'); + charHandle2.set(structSegmt1, 'B'); + charHandle3.set(structSegmt1, 'C'); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + charHandle1.set(structSegmt2, 'B'); + charHandle2.set(structSegmt2, 'C'); + charHandle3.set(structSegmt2, 'D'); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(charHandle1.get(resultSegmt), 'B'); + Assert.assertEquals(charHandle2.get(resultSegmt), 'D'); + Assert.assertEquals(charHandle3.get(resultSegmt), 'F'); + } + } + + @Test + public void test_addShortAndShortsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStruct, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)888); + shortHandle2.set(structSegmt, (short)999); + + short result = (short)mh.invoke((short)777, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2664); + } + } + + @Test + public void test_addShortAnd10ShortsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, + JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, JAVA_SHORT, JAVA_SHORT); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAnd10ShortsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAnd10ShortsFromStruct, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)10); + structSegmt.set(JAVA_SHORT, 2, (short)20); + structSegmt.set(JAVA_SHORT, 4, (short)30); + structSegmt.set(JAVA_SHORT, 6, (short)40); + structSegmt.set(JAVA_SHORT, 8, (short)50); + structSegmt.set(JAVA_SHORT, 10, (short)60); + structSegmt.set(JAVA_SHORT, 12, (short)70); + structSegmt.set(JAVA_SHORT, 14, (short)80); + structSegmt.set(JAVA_SHORT, 16, (short)90); + structSegmt.set(JAVA_SHORT, 18, (short)100); + + short result = (short)mh.invoke((short)110, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 660); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortFromPointerAndShortsFromStruct, + FunctionDescriptor.of(JAVA_SHORT, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)1112); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)1118); + shortHandle2.set(structSegmt, (short)1119); + + short result = (short)mh.invoke(shortSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 3349); + } + } + + @Test + public void test_addShortFromPointerAndShortsFromStruct_returnShortPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortFromPointerAndShortsFromStruct_returnShortPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortFromPointerAndShortsFromStruct_returnShortPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment shortSegmt = allocator.allocate(JAVA_SHORT, (short)1112); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)1118); + shortHandle2.set(structSegmt, (short)1119); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(shortSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 3349); + Assert.assertEquals(resultAddr.toRawLongValue(), shortSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addShortAndShortsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructPointer, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + shortHandle1.set(structSegmt, (short)2222); + shortHandle2.set(structSegmt, (short)4444); + + short result = (short)mh.invoke((short)6666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 13332); + } + } + + @Test + public void test_addShortAndShortsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_SHORT.withName("elem2")) : MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromNestedStruct, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)331); + structSegmt.set(JAVA_SHORT, 2, (short)333); + structSegmt.set(JAVA_SHORT, 4, (short)335); + + short result = (short)mh.invoke((short)337, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1336); + } + } + + @Test + public void test_addShortAndShortsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2")) : MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + nestedStructLayout.withName("struct_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)331); + structSegmt.set(JAVA_SHORT, 2, (short)333); + structSegmt.set(JAVA_SHORT, 4, (short)335); + + short result = (short)mh.invoke((short)337, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1336); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArrayByUpcallMH() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(shortArray.withName("array_elem1"), + JAVA_SHORT.withName("elem2")) : MemoryLayout.structLayout(shortArray.withName("array_elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedShortArray, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1111); + structSegmt.set(JAVA_SHORT, 2, (short)2222); + structSegmt.set(JAVA_SHORT, 4, (short)3333); + + short result = (short)mh.invoke((short)4444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedShortArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout shortArray = MemoryLayout.sequenceLayout(2, JAVA_SHORT); + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + shortArray.withName("array_elem2")) : MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + shortArray.withName("array_elem2"), MemoryLayout.paddingLayout(16)); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedShortArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedShortArray_reverseOrder, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1111); + structSegmt.set(JAVA_SHORT, 2, (short)2222); + structSegmt.set(JAVA_SHORT, 4, (short)3333); + + short result = (short)mh.invoke((short)4444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11110); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struc_array_elem1"), JAVA_SHORT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1111); + structSegmt.set(JAVA_SHORT, 2, (short)2222); + structSegmt.set(JAVA_SHORT, 4, (short)3333); + structSegmt.set(JAVA_SHORT, 6, (short)4444); + structSegmt.set(JAVA_SHORT, 8, (short)5555); + + short result = (short)mh.invoke((short)6666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23331); + } + } + + @Test + public void test_addShortAndShortsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout shortStruct = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, shortStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), structArray.withName("struc_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addShortAndShortsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addShortAndShortsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_SHORT, JAVA_SHORT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_SHORT, 0, (short)1111); + structSegmt.set(JAVA_SHORT, 2, (short)2222); + structSegmt.set(JAVA_SHORT, 4, (short)3333); + structSegmt.set(JAVA_SHORT, 6, (short)4444); + structSegmt.set(JAVA_SHORT, 8, (short)5555); + + short result = (short)mh.invoke((short)6666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23331); + } + } + + @Test + public void test_add2ShortStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2ShortStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)356); + shortHandle2.set(structSegmt1, (short)345); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)378); + shortHandle2.set(structSegmt2, (short)367); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)734); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)712); + } + } + + @Test + public void test_add2ShortStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2ShortStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)356); + shortHandle2.set(structSegmt1, (short)345); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)378); + shortHandle2.set(structSegmt2, (short)367); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 0), 734); + Assert.assertEquals(resultAddr.get(JAVA_SHORT, 2), 712); + } + } + + @Test + public void test_add3ShortStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2"), + JAVA_SHORT.withName("elem3")) : MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2"), + JAVA_SHORT.withName("elem3"), MemoryLayout.paddingLayout(16)); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle shortHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add3ShortStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add3ShortStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)325); + shortHandle2.set(structSegmt1, (short)326); + shortHandle3.set(structSegmt1, (short)327); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)334); + shortHandle2.set(structSegmt2, (short)335); + shortHandle3.set(structSegmt2, (short)336); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((short)shortHandle1.get(resultSegmt), (short)659); + Assert.assertEquals((short)shortHandle2.get(resultSegmt), (short)661); + Assert.assertEquals((short)shortHandle3.get(resultSegmt), (short)663); + } + } + + @Test + public void test_addIntAndIntsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1122334); + intHandle2.set(structSegmt, 1234567); + + int result = (int)mh.invoke(2244668, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 4601569); + } + } + + @Test + public void test_addIntAnd5IntsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2"), + JAVA_INT.withName("elem3"), JAVA_INT.withName("elem4"), JAVA_INT.withName("elem5")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle intHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle intHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAnd5IntsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAnd5IntsFromStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1111111); + intHandle2.set(structSegmt, 2222222); + intHandle3.set(structSegmt, 3333333); + intHandle4.set(structSegmt, 2222222); + intHandle5.set(structSegmt, 1111111); + + int result = (int)mh.invoke(4444444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 14444443); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntFromPointerAndIntsFromStruct, + FunctionDescriptor.of(JAVA_INT, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 7654321); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 1234567); + intHandle2.set(structSegmt, 2468024); + + int result = (int)mh.invoke(intSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11356912); + } + } + + @Test + public void test_addIntFromPointerAndIntsFromStruct_returnIntPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntFromPointerAndIntsFromStruct_returnIntPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntFromPointerAndIntsFromStruct_returnIntPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt = allocator.allocate(JAVA_INT, 1122333); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 4455666); + intHandle2.set(structSegmt, 7788999); + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(intSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 13366998); + Assert.assertEquals(resultAddr.toRawLongValue(), intSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addIntAndIntsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructPointer, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + intHandle1.set(structSegmt, 11121314); + intHandle2.set(structSegmt, 15161718); + + int result = (int)mh.invoke(19202122, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 45485154); + } + } + + @Test + public void test_addIntAndIntsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_INT.withName("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromNestedStruct, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invoke(33343536, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 21222324); + structSegmt.set(JAVA_INT, 4, 25262728); + structSegmt.set(JAVA_INT, 8, 29303132); + + int result = (int)mh.invoke(33343536, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 109131720); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArrayByUpcallMH() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(intArray.withName("array_elem1"), JAVA_INT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedIntArray, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invoke(4444444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedIntArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout intArray = MemoryLayout.sequenceLayout(2, JAVA_INT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), intArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedIntArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedIntArray_reverseOrder, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + + int result = (int)mh.invoke(4444444, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 11111110); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_INT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invoke(6666666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_addIntAndIntsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout intStruct = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, intStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addIntAndIntsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addIntAndIntsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_INT, 0, 1111111); + structSegmt.set(JAVA_INT, 4, 2222222); + structSegmt.set(JAVA_INT, 8, 3333333); + structSegmt.set(JAVA_INT, 12, 4444444); + structSegmt.set(JAVA_INT, 16, 5555555); + + int result = (int)mh.invoke(6666666, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23333331); + } + } + + @Test + public void test_add2IntStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2IntStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(intHandle1.get(resultSegmt), 110224466); + Assert.assertEquals(intHandle2.get(resultSegmt), 89113354); + } + } + + @Test + public void test_add2IntStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2IntStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2IntStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 99001122); + intHandle2.set(structSegmt2, 33445566); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 110224466); + Assert.assertEquals(resultAddr.get(JAVA_INT, 4), 89113354); + } + } + + @Test + public void test_add3IntStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add3IntStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add3IntStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 11223344); + intHandle2.set(structSegmt1, 55667788); + intHandle3.set(structSegmt1, 99001122); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 33445566); + intHandle2.set(structSegmt2, 77889900); + intHandle3.set(structSegmt2, 44332211); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(intHandle1.get(resultSegmt), 44668910); + Assert.assertEquals(intHandle2.get(resultSegmt), 133557688); + Assert.assertEquals(intHandle3.get(resultSegmt), 143333333); + } + } + + @Test + public void test_addLongAndLongsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 1234567890L); + longHandle2.set(structSegmt, 9876543210L); + + long result = (long)mh.invoke(2468024680L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 13579135780L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongFromPointerAndLongsFromStruct, + FunctionDescriptor.of(JAVA_LONG, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 1111111111L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 3333333333L); + longHandle2.set(structSegmt, 5555555555L); + + long result = (long)mh.invoke(longSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 9999999999L); + } + } + + @Test + public void test_addLongFromPointerAndLongsFromStruct_returnLongPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongFromPointerAndLongsFromStruct_returnLongPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongFromPointerAndLongsFromStruct_returnLongPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt = allocator.allocate(JAVA_LONG, 1122334455L); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 6677889900L); + longHandle2.set(structSegmt, 1234567890L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(longSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 9034792245L); + Assert.assertEquals(resultAddr.toRawLongValue(), longSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addLongAndLongsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructPointer, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + longHandle1.set(structSegmt, 224466880022L); + longHandle2.set(structSegmt, 446688002244L); + + long result = (long)mh.invoke(668800224466L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1339955106732L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromNestedStruct, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invoke(778899001122L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 135791357913L); + structSegmt.set(JAVA_LONG, 8, 246802468024L); + structSegmt.set(JAVA_LONG, 16,112233445566L); + + long result = (long)mh.invoke(778899001122L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1273726272625L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArrayByUpcallMH() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(longArray.withName("array_elem1"), JAVA_LONG.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedLongArray, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 11111111111L); + structSegmt.set(JAVA_LONG, 8, 22222222222L); + structSegmt.set(JAVA_LONG, 16, 33333333333L); + + long result = (long)mh.invoke(44444444444L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedLongArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout longArray = MemoryLayout.sequenceLayout(2, JAVA_LONG); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), longArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedLongArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedLongArray_reverseOrder, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 11111111111L); + structSegmt.set(JAVA_LONG, 8, 22222222222L); + structSegmt.set(JAVA_LONG, 16, 33333333333L); + + long result = (long)mh.invoke(44444444444L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 111111111110L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_LONG.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 11111111111L); + structSegmt.set(JAVA_LONG, 8, 22222222222L); + structSegmt.set(JAVA_LONG, 16, 33333333333L); + structSegmt.set(JAVA_LONG, 24, 44444444444L); + structSegmt.set(JAVA_LONG, 32, 55555555555L); + + long result = (long)mh.invoke(66666666666L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 233333333331L); + } + } + + @Test + public void test_addLongAndLongsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout longStruct = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, longStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addLongAndLongsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addLongAndLongsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_LONG, JAVA_LONG, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_LONG, 0, 11111111111L); + structSegmt.set(JAVA_LONG, 8, 22222222222L); + structSegmt.set(JAVA_LONG, 16, 33333333333L); + structSegmt.set(JAVA_LONG, 24, 44444444444L); + structSegmt.set(JAVA_LONG, 32, 55555555555L); + + long result = (long)mh.invoke(66666666666L, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 233333333331L); + } + } + + @Test + public void test_add2LongStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2LongStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + } + } + + @Test + public void test_add2LongStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2LongStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2LongStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 5566778899L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 9900112233L); + longHandle2.set(structSegmt2, 3344556677L); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 11022446688L); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 8), 8911335576L); + } + } + + @Test + public void test_add3LongStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2"), JAVA_LONG.withName("elem3")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle longHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add3LongStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add3LongStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 987654321987L); + longHandle2.set(structSegmt1, 123456789123L); + longHandle3.set(structSegmt1, 112233445566L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 224466880022L); + longHandle2.set(structSegmt2, 113355779911L); + longHandle3.set(structSegmt2, 778899001122L); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(longHandle1.get(resultSegmt), 1212121202009L); + Assert.assertEquals(longHandle2.get(resultSegmt), 236812569034L); + Assert.assertEquals(longHandle3.get(resultSegmt), 891132446688L); + } + } + + @Test + public void test_addFloatAndFloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 8.12F); + floatHandle2.set(structSegmt, 9.24F); + + float result = (float)mh.invoke(6.56F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 23.92F, 0.01F); + } + } + + @Test + public void test_addFloatAnd5FloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2"), + JAVA_FLOAT.withName("elem3"), JAVA_FLOAT.withName("elem4"), JAVA_FLOAT.withName("elem5")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle floatHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle floatHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAnd5FloatsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAnd5FloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 1.01F); + floatHandle2.set(structSegmt, 1.02F); + floatHandle3.set(structSegmt, 1.03F); + floatHandle4.set(structSegmt, 1.04F); + floatHandle5.set(structSegmt, 1.05F); + + float result = (float)mh.invoke(1.06F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 6.21F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatFromPointerAndFloatsFromStruct, + FunctionDescriptor.of(JAVA_FLOAT, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + float result = (float)mh.invoke(floatSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 49.69F, 0.01F); + } + } + + @Test + public void test_addFloatFromPointerAndFloatsFromStruct_returnFloatPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatFromPointerAndFloatsFromStruct_returnFloatPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment floatSegmt = allocator.allocate(JAVA_FLOAT, 12.12F); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 18.23F); + floatHandle2.set(structSegmt, 19.34F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(floatSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 49.69F, 0.01F); + Assert.assertEquals(resultAddr.toRawLongValue(), floatSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addFloatAndFloatsFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructPointer, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + floatHandle1.set(structSegmt, 35.11F); + floatHandle2.set(structSegmt, 46.22F); + + float result = (float)mh.invoke(79.33F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 160.66F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromNestedStruct, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invoke(37.88F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 31.22F); + structSegmt.set(JAVA_FLOAT, 4, 33.44F); + structSegmt.set(JAVA_FLOAT, 8, 35.66F); + + float result = (float)mh.invoke(37.88F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.2F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArrayByUpcallMH() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(floatArray.withName("array_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedFloatArray, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invoke(444.44F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout floatArray = MemoryLayout.sequenceLayout(2, JAVA_FLOAT); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), floatArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + + float result = (float)mh.invoke(444.44F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.1F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_FLOAT.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invoke(666.66F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout floatStruct = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, floatStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addFloatAndFloatsFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_FLOAT, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_FLOAT, 0, 111.11F); + structSegmt.set(JAVA_FLOAT, 4, 222.22F); + structSegmt.set(JAVA_FLOAT, 8, 333.33F); + structSegmt.set(JAVA_FLOAT, 12, 444.44F); + structSegmt.set(JAVA_FLOAT, 16, 555.55F); + + float result = (float)mh.invoke(666.66F, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.31F, 0.01F); + } + } + + @Test + public void test_add3FloatStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add3FloatStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add3FloatStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + floatHandle3.set(structSegmt1, 45.67F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + floatHandle3.set(structSegmt2, 69.72F); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + Assert.assertEquals((float)floatHandle3.get(resultSegmt), 115.39, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2FloatStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((float)floatHandle1.get(resultSegmt), 49.46F, 0.01F); + Assert.assertEquals((float)floatHandle2.get(resultSegmt), 24.68F, 0.01F); + } + } + + @Test + public void test_add2FloatStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2FloatStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 25.12F); + floatHandle2.set(structSegmt1, 11.23F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 24.34F); + floatHandle2.set(structSegmt2, 13.45F); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 0), 49.46F, 0.01F); + Assert.assertEquals(resultAddr.get(JAVA_FLOAT, 4), 24.68F, 0.01F); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 2228.111D); + doubleHandle2.set(structSegmt, 2229.221D); + + double result = (double)mh.invoke(3336.333D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 7793.665D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleFromPointerAndDoublesFromStruct, + FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 112.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 118.456D); + doubleHandle2.set(structSegmt, 119.789D); + + double result = (double)mh.invoke(doubleSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 350.368D, 0.001D); + } + } + + @Test + public void test_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFromPointerAndDoublesFromStruct_returnDoublePointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt = allocator.allocate(JAVA_DOUBLE, 212.123D); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 218.456D); + doubleHandle2.set(structSegmt, 219.789D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(doubleSegmt, structSegmt, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 650.368D, 0.001D); + Assert.assertEquals(resultAddr.toRawLongValue(), doubleSegmt.address().toRawLongValue()); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructPointer, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, ADDRESS), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt, 22.111D); + doubleHandle2.set(structSegmt, 44.222D); + + double result = (double)mh.invoke(66.333D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 132.666D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStructByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(nestedStructLayout.withName("struct_elem1"), JAVA_DOUBLE.withName("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromNestedStruct, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invoke(37.864D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromNestedStruct_reverseOrderByUpcallMH() throws Throwable { + GroupLayout nestedStructLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), nestedStructLayout.withName("struct_elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromNestedStruct_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromNestedStruct_reverseOrder, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 31.789D); + structSegmt.set(JAVA_DOUBLE, 8, 33.456D); + structSegmt.set(JAVA_DOUBLE, 16, 35.123D); + + double result = (double)mh.invoke(37.864D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 138.232D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArrayByUpcallMH() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(doubleArray.withName("array_elem1"), JAVA_DOUBLE.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedDoubleArray, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invoke(444.444D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrderByUpcallMH() throws Throwable { + SequenceLayout doubleArray = MemoryLayout.sequenceLayout(2, JAVA_DOUBLE); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), doubleArray.withName("array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + + double result = (double)mh.invoke(444.444D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 1111.11D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArrayByUpcallMH() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(structArray.withName("struct_array_elem1"), JAVA_DOUBLE.withName("elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArrayByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedStructArray, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invoke(666.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrderByUpcallMH() throws Throwable { + GroupLayout doubleStruct = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + SequenceLayout structArray = MemoryLayout.sequenceLayout(2, doubleStruct); + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), structArray.withName("struct_array_elem2")); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrderByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_DOUBLE, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt = allocator.allocate(structLayout); + structSegmt.set(JAVA_DOUBLE, 0, 111.111D); + structSegmt.set(JAVA_DOUBLE, 8, 222.222D); + structSegmt.set(JAVA_DOUBLE, 16, 333.333D); + structSegmt.set(JAVA_DOUBLE, 24, 444.444D); + structSegmt.set(JAVA_DOUBLE, 32, 555.555D); + + double result = (double)mh.invoke(666.666D, structSegmt, upcallFuncAddr); + Assert.assertEquals(result, 2333.331D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2DoubleStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + } + } + + @Test + public void test_add2DoubleStructs_returnStructPointerByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + FunctionDescriptor fd = FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add2DoubleStructs_returnStructPointerByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add2DoubleStructs_returnStructPointer, + FunctionDescriptor.of(ADDRESS, ADDRESS, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + + MemoryAddress resultAddr = (MemoryAddress)mh.invoke(structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 44.666D, 0.001D); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 8), 66.888D, 0.001D); + } + } + + @Test + public void test_add3DoubleStructs_returnStructByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle doubleHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + FunctionDescriptor fd = FunctionDescriptor.of(structLayout, structLayout, structLayout, ADDRESS); + Addressable functionSymbol = nativeLibLookup.lookup("add3DoubleStructs_returnStructByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_add3DoubleStructs_returnStruct, + FunctionDescriptor.of(structLayout, structLayout, structLayout), session); + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11.222D); + doubleHandle2.set(structSegmt1, 22.333D); + doubleHandle3.set(structSegmt1, 33.123D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 33.444D); + doubleHandle2.set(structSegmt2, 44.555D); + doubleHandle3.set(structSegmt2, 55.456D); + + MemorySegment resultSegmt = (MemorySegment)mh.invoke(allocator, structSegmt1, structSegmt2, upcallFuncAddr); + Assert.assertEquals((double)doubleHandle1.get(resultSegmt), 44.666D, 0.001D); + Assert.assertEquals((double)doubleHandle2.get(resultSegmt), 66.888D, 0.001D); + Assert.assertEquals((double)doubleHandle3.get(resultSegmt), 88.579D, 0.001D); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMethodHandles.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMethodHandles.java new file mode 100644 index 00000000000..ce67852927b --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/upcall/UpcallMethodHandles.java @@ -0,0 +1,1886 @@ +/******************************************************************************* + * Copyright (c) 2021, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.upcall; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import static java.lang.invoke.MethodType.methodType; +import java.lang.invoke.VarHandle; + +import java.lang.foreign.Addressable; +import static java.lang.foreign.Linker.*; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SequenceLayout; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; + +/** + * The helper class that contains all upcall method handles with primitive types or struct + * as arguments. + */ +public class UpcallMethodHandles { + private static final Lookup lookup = MethodHandles.lookup(); + private static MemorySession session = MemorySession.openImplicit(); + private static SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); + + static final MethodType MT_Bool_Bool_MemSegmt = methodType(boolean.class, boolean.class, MemorySegment.class); + static final MethodType MT_Addr_Bool_MemAddr = methodType(Addressable.class, boolean.class, MemoryAddress.class); + static final MethodType MT_Char_Char_MemSegmt = methodType(char.class, char.class, MemorySegment.class); + static final MethodType MT_Addr_MemAddr_Char = methodType(Addressable.class, MemoryAddress.class, char.class); + static final MethodType MT_Byte_Byte_MemSegmt = methodType(byte.class, byte.class, MemorySegment.class); + static final MethodType MT_Addr_Byte_MemAddr = methodType(Addressable.class, byte.class, MemoryAddress.class); + static final MethodType MT_Short_Short_MemSegmt = methodType(short.class, short.class, MemorySegment.class); + static final MethodType MT_Addr_MemAddr_Short = methodType(Addressable.class, MemoryAddress.class, short.class); + static final MethodType MT_Int_Int_MemSegmt = methodType(int.class, int.class, MemorySegment.class); + static final MethodType MT_Addr_Int_MemAddr = methodType(Addressable.class, int.class, MemoryAddress.class); + static final MethodType MT_Long_Long_MemSegmt = methodType(long.class, long.class, MemorySegment.class); + static final MethodType MT_Addr_MemAddr_Long = methodType(Addressable.class, MemoryAddress.class, long.class); + static final MethodType MT_Long_Int_MemSegmt = methodType(long.class, int.class, MemorySegment.class); + static final MethodType MT_Float_Float_MemSegmt = methodType(float.class, float.class, MemorySegment.class); + static final MethodType MT_Addr_Float_MemAddr = methodType(Addressable.class, float.class, MemoryAddress.class); + static final MethodType MT_Double_Double_MemSegmt = methodType(double.class, double.class, MemorySegment.class); + static final MethodType MT_Addr_MemAddr_Double = methodType(Addressable.class, MemoryAddress.class, double.class); + static final MethodType MT_Addr_MemAddr_MemSegmt = methodType(Addressable.class, MemoryAddress.class, MemorySegment.class); + static final MethodType MT_MemSegmt_MemSegmt_MemSegmt = methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class); + static final MethodType MT_MemSegmt = methodType(MemorySegment.class); + + public static final MethodHandle MH_add2BoolsWithOr; + public static final MethodHandle MH_addBoolAndBoolFromPointerWithOr; + public static final MethodHandle MH_addBoolAndBoolFromPtrWithOr_RetPtr; + public static final MethodHandle MH_addBoolAndBoolFromPtrWithOr_RetArgPtr; + public static final MethodHandle MH_createNewCharFrom2Chars; + public static final MethodHandle MH_createNewCharFromCharAndCharFromPointer; + public static final MethodHandle MH_createNewCharFromCharAndCharFromPtr_RetPtr; + public static final MethodHandle MH_createNewCharFromCharAndCharFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Bytes; + public static final MethodHandle MH_addByteAndByteFromPointer; + public static final MethodHandle MH_addByteAndByteFromPtr_RetPtr; + public static final MethodHandle MH_addByteAndByteFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Shorts; + public static final MethodHandle MH_addShortAndShortFromPointer; + public static final MethodHandle MH_addShortAndShortFromPtr_RetPtr; + public static final MethodHandle MH_addShortAndShortFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Ints; + public static final MethodHandle MH_addIntAndIntFromPointer; + public static final MethodHandle MH_addIntAndIntFromPtr_RetPtr; + public static final MethodHandle MH_addIntAndIntFromPtr_RetArgPtr; + public static final MethodHandle MH_add3Ints; + public static final MethodHandle MH_addIntAndChar; + public static final MethodHandle MH_add2IntsReturnVoid; + public static final MethodHandle MH_add2Longs; + public static final MethodHandle MH_addLongAndLongFromPointer; + public static final MethodHandle MH_addLongAndLongFromPtr_RetPtr; + public static final MethodHandle MH_addLongAndLongFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Floats; + public static final MethodHandle MH_addFloatAndFloatFromPointer; + public static final MethodHandle MH_addFloatAndFloatFromPtr_RetPtr; + public static final MethodHandle MH_addFloatAndFloatFromPtr_RetArgPtr; + public static final MethodHandle MH_add2Doubles; + public static final MethodHandle MH_addDoubleAndDoubleFromPointer; + public static final MethodHandle MH_addDoubleAndDoubleFromPtr_RetPtr; + public static final MethodHandle MH_addDoubleAndDoubleFromPtr_RetArgPtr; + public static final MethodHandle MH_compare; + + public static final MethodHandle MH_addBoolAndBoolsFromStructWithXor; + public static final MethodHandle MH_addBoolAnd20BoolsFromStructWithXor; + public static final MethodHandle MH_addBoolFromPointerAndBoolsFromStructWithXor; + public static final MethodHandle MH_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer; + public static final MethodHandle MH_addBoolAndBoolsFromStructPointerWithXor; + public static final MethodHandle MH_addBoolAndBoolsFromNestedStructWithXor; + public static final MethodHandle MH_addBoolAndBoolsFromNestedStructWithXor_reverseOrder; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedBoolArray; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedStructArray; + public static final MethodHandle MH_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2BoolStructsWithXor_returnStruct; + public static final MethodHandle MH_add2BoolStructsWithXor_returnStructPointer; + public static final MethodHandle MH_add3BoolStructsWithXor_returnStruct; + + public static final MethodHandle MH_addByteAndBytesFromStruct; + public static final MethodHandle MH_addByteAnd20BytesFromStruct; + public static final MethodHandle MH_addByteFromPointerAndBytesFromStruct; + public static final MethodHandle MH_addByteFromPointerAndBytesFromStruct_returnBytePointer; + public static final MethodHandle MH_addByteAndBytesFromStructPointer; + public static final MethodHandle MH_addByteAndBytesFromNestedStruct; + public static final MethodHandle MH_addByteAndBytesFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedByteArray; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedByteArray_reverseOrder; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedStructArray; + public static final MethodHandle MH_addByteAndBytesFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add1ByteStructs_returnStruct; + public static final MethodHandle MH_add2ByteStructs_returnStruct; + public static final MethodHandle MH_add2ByteStructs_returnStructPointer; + public static final MethodHandle MH_add3ByteStructs_returnStruct; + + public static final MethodHandle MH_addCharAndCharsFromStruct; + public static final MethodHandle MH_addCharAnd10CharsFromStruct; + public static final MethodHandle MH_addCharFromPointerAndCharsFromStruct; + public static final MethodHandle MH_addCharFromPointerAndCharsFromStruct_returnCharPointer; + public static final MethodHandle MH_addCharAndCharsFromStructPointer; + public static final MethodHandle MH_addCharAndCharsFromNestedStruct; + public static final MethodHandle MH_addCharAndCharsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedCharArray; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedCharArray_reverseOrder; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedStructArray; + public static final MethodHandle MH_addCharAndCharsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2CharStructs_returnStruct; + public static final MethodHandle MH_add2CharStructs_returnStructPointer; + public static final MethodHandle MH_add3CharStructs_returnStruct; + + public static final MethodHandle MH_addShortAndShortsFromStruct; + public static final MethodHandle MH_addShortAnd10ShortsFromStruct; + public static final MethodHandle MH_addShortFromPointerAndShortsFromStruct; + public static final MethodHandle MH_addShortFromPointerAndShortsFromStruct_returnShortPointer; + public static final MethodHandle MH_addShortAndShortsFromStructPointer; + public static final MethodHandle MH_addShortAndShortsFromNestedStruct; + public static final MethodHandle MH_addShortAndShortsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedShortArray; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedShortArray_reverseOrder; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedStructArray; + public static final MethodHandle MH_addShortAndShortsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2ShortStructs_returnStruct; + public static final MethodHandle MH_add2ShortStructs_returnStructPointer; + public static final MethodHandle MH_add3ShortStructs_returnStruct; + + public static final MethodHandle MH_addIntAndIntsFromStruct; + public static final MethodHandle MH_addIntAnd5IntsFromStruct; + public static final MethodHandle MH_addIntFromPointerAndIntsFromStruct; + public static final MethodHandle MH_addIntFromPointerAndIntsFromStruct_returnIntPointer; + public static final MethodHandle MH_addIntAndIntsFromStructPointer; + public static final MethodHandle MH_addIntAndIntsFromNestedStruct; + public static final MethodHandle MH_addIntAndIntsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedIntArray; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedIntArray_reverseOrder; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedStructArray; + public static final MethodHandle MH_addIntAndIntsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2IntStructs_returnStruct; + public static final MethodHandle MH_add2IntStructs_returnStructPointer; + public static final MethodHandle MH_add3IntStructs_returnStruct; + + public static final MethodHandle MH_addLongAndLongsFromStruct; + public static final MethodHandle MH_addLongFromPointerAndLongsFromStruct; + public static final MethodHandle MH_addLongFromPointerAndLongsFromStruct_returnLongPointer; + public static final MethodHandle MH_addLongAndLongsFromStructPointer; + public static final MethodHandle MH_addLongAndLongsFromNestedStruct; + public static final MethodHandle MH_addLongAndLongsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedLongArray; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedLongArray_reverseOrder; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedStructArray; + public static final MethodHandle MH_addLongAndLongsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2LongStructs_returnStruct; + public static final MethodHandle MH_add2LongStructs_returnStructPointer; + public static final MethodHandle MH_add3LongStructs_returnStruct; + + public static final MethodHandle MH_addFloatAndFloatsFromStruct; + public static final MethodHandle MH_addFloatAnd5FloatsFromStruct; + public static final MethodHandle MH_addFloatFromPointerAndFloatsFromStruct; + public static final MethodHandle MH_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer; + public static final MethodHandle MH_addFloatAndFloatsFromStructPointer; + public static final MethodHandle MH_addFloatAndFloatsFromNestedStruct; + public static final MethodHandle MH_addFloatAndFloatsFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedFloatArray; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedStructArray; + public static final MethodHandle MH_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2FloatStructs_returnStruct; + public static final MethodHandle MH_add2FloatStructs_returnStructPointer; + public static final MethodHandle MH_add3FloatStructs_returnStruct; + + public static final MethodHandle MH_addDoubleAndDoublesFromStruct; + public static final MethodHandle MH_addDoubleFromPointerAndDoublesFromStruct; + public static final MethodHandle MH_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer; + public static final MethodHandle MH_addDoubleAndDoublesFromStructPointer; + public static final MethodHandle MH_addDoubleAndDoublesFromNestedStruct; + public static final MethodHandle MH_addDoubleAndDoublesFromNestedStruct_reverseOrder; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedDoubleArray; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedStructArray; + public static final MethodHandle MH_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder; + public static final MethodHandle MH_add2DoubleStructs_returnStruct; + public static final MethodHandle MH_add2DoubleStructs_returnStructPointer; + public static final MethodHandle MH_add3DoubleStructs_returnStruct; + + public static final MethodHandle MH_addIntAndIntShortFromStruct; + public static final MethodHandle MH_addIntAndShortIntFromStruct; + public static final MethodHandle MH_addIntAndIntLongFromStruct; + public static final MethodHandle MH_addIntAndLongIntFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleIntFromStruct; + public static final MethodHandle MH_addDoubleAndFloatDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleFloatFromStruct; + public static final MethodHandle MH_addDoubleAnd2FloatsDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndDouble2FloatsFromStruct; + public static final MethodHandle MH_addFloatAndInt2FloatsFromStruct; + public static final MethodHandle MH_addFloatAndFloatIntFloatFromStruct; + public static final MethodHandle MH_addDoubleAndIntFloatDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndFloatIntDoubleFromStruct; + public static final MethodHandle MH_addDoubleAndLongDoubleFromStruct; + public static final MethodHandle MH_addFloatAndInt3FloatsFromStruct; + public static final MethodHandle MH_addLongAndLong2FloatsFromStruct; + public static final MethodHandle MH_addFloatAnd3FloatsIntFromStruct; + public static final MethodHandle MH_addLongAndFloatLongFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleFloatIntFromStruct; + public static final MethodHandle MH_addDoubleAndDoubleLongFromStruct; + public static final MethodHandle MH_addLongAnd2FloatsLongFromStruct; + public static final MethodHandle MH_addShortAnd3ShortsCharFromStruct; + public static final MethodHandle MH_addFloatAndIntFloatIntFloatFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleFloatFromStruct; + public static final MethodHandle MH_addDoubleAndFloatDoubleIntFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleIntFromStruct; + public static final MethodHandle MH_addDoubleAndFloatDoubleFloatFromStruct; + public static final MethodHandle MH_addDoubleAndIntDoubleLongFromStruct; + public static final MethodHandle MH_return254BytesFromStruct; + public static final MethodHandle MH_return4KBytesFromStruct; + + static { + try { + MH_add2BoolsWithOr = lookup.findStatic(UpcallMethodHandles.class, "add2BoolsWithOr", methodType(boolean.class, boolean.class, boolean.class)); //$NON-NLS-1$ + MH_addBoolAndBoolFromPointerWithOr = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolFromPointerWithOr", methodType(boolean.class, boolean.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addBoolAndBoolFromPtrWithOr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolFromPtrWithOr_RetPtr", MT_Addr_Bool_MemAddr); //$NON-NLS-1$ + MH_addBoolAndBoolFromPtrWithOr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolFromPtrWithOr_RetArgPtr", MT_Addr_Bool_MemAddr); //$NON-NLS-1$ + + MH_createNewCharFrom2Chars = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFrom2Chars", methodType(char.class, char.class, char.class)); //$NON-NLS-1$ + MH_createNewCharFromCharAndCharFromPointer = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFromCharAndCharFromPointer", methodType(char.class, MemoryAddress.class, char.class)); //$NON-NLS-1$ + MH_createNewCharFromCharAndCharFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFromCharAndCharFromPtr_RetPtr", MT_Addr_MemAddr_Char); //$NON-NLS-1$ + MH_createNewCharFromCharAndCharFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "createNewCharFromCharAndCharFromPtr_RetArgPtr", MT_Addr_MemAddr_Char); //$NON-NLS-1$ + + MH_add2Bytes = lookup.findStatic(UpcallMethodHandles.class, "add2Bytes", methodType(byte.class, byte.class, byte.class)); //$NON-NLS-1$ + MH_addByteAndByteFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addByteAndByteFromPointer", methodType(byte.class, byte.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addByteAndByteFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addByteAndByteFromPtr_RetPtr", MT_Addr_Byte_MemAddr); //$NON-NLS-1$ + MH_addByteAndByteFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addByteAndByteFromPtr_RetArgPtr", MT_Addr_Byte_MemAddr); //$NON-NLS-1$ + + MH_add2Shorts = lookup.findStatic(UpcallMethodHandles.class, "add2Shorts", methodType(short.class, short.class, short.class)); //$NON-NLS-1$ + MH_addShortAndShortFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortFromPointer", methodType(short.class, MemoryAddress.class, short.class)); //$NON-NLS-1$ + MH_addShortAndShortFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortFromPtr_RetPtr", MT_Addr_MemAddr_Short); //$NON-NLS-1$ + MH_addShortAndShortFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortFromPtr_RetArgPtr", MT_Addr_MemAddr_Short); //$NON-NLS-1$ + + MH_add2Ints = lookup.findStatic(UpcallMethodHandles.class, "add2Ints", methodType(int.class, int.class, int.class)); //$NON-NLS-1$ + MH_addIntAndIntFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntFromPointer", methodType(int.class, int.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addIntAndIntFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntFromPtr_RetPtr", MT_Addr_Int_MemAddr); //$NON-NLS-1$ + MH_addIntAndIntFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntFromPtr_RetArgPtr", MT_Addr_Int_MemAddr); //$NON-NLS-1$ + MH_add3Ints = lookup.findStatic(UpcallMethodHandles.class, "add3Ints", methodType(int.class, int.class, int.class, int.class)); //$NON-NLS-1$ + MH_addIntAndChar = lookup.findStatic(UpcallMethodHandles.class, "addIntAndChar", methodType(int.class, int.class, char.class)); //$NON-NLS-1$ + MH_add2IntsReturnVoid = lookup.findStatic(UpcallMethodHandles.class, "add2IntsReturnVoid", methodType(void.class, int.class, int.class)); //$NON-NLS-1$ + + MH_add2Longs = lookup.findStatic(UpcallMethodHandles.class, "add2Longs", methodType(long.class, long.class, long.class)); //$NON-NLS-1$ + MH_addLongAndLongFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongFromPointer", methodType(long.class, MemoryAddress.class, long.class)); //$NON-NLS-1$ + MH_addLongAndLongFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongFromPtr_RetPtr", MT_Addr_MemAddr_Long); //$NON-NLS-1$ + MH_addLongAndLongFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongFromPtr_RetArgPtr", MT_Addr_MemAddr_Long); //$NON-NLS-1$ + + MH_add2Floats = lookup.findStatic(UpcallMethodHandles.class, "add2Floats", methodType(float.class, float.class, float.class)); //$NON-NLS-1$ + MH_addFloatAndFloatFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatFromPointer", methodType(float.class, float.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addFloatAndFloatFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatFromPtr_RetPtr", MT_Addr_Float_MemAddr); //$NON-NLS-1$ + MH_addFloatAndFloatFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatFromPtr_RetArgPtr", MT_Addr_Float_MemAddr); //$NON-NLS-1$ + + MH_add2Doubles = lookup.findStatic(UpcallMethodHandles.class, "add2Doubles", methodType(double.class, double.class, double.class)); //$NON-NLS-1$ + MH_addDoubleAndDoubleFromPointer = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFromPointer", methodType(double.class, MemoryAddress.class, double.class)); //$NON-NLS-1$ + MH_addDoubleAndDoubleFromPtr_RetPtr = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFromPtr_RetPtr", MT_Addr_MemAddr_Double); //$NON-NLS-1$ + MH_addDoubleAndDoubleFromPtr_RetArgPtr = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFromPtr_RetArgPtr", MT_Addr_MemAddr_Double); //$NON-NLS-1$ + + MH_compare = lookup.findStatic(UpcallMethodHandles.class, "compare", methodType(int.class, MemoryAddress.class, MemoryAddress.class)); //$NON-NLS-1$ + + MH_addBoolAndBoolsFromStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithXor", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAnd20BoolsFromStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAnd20BoolsFromStructWithXor", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolFromPointerAndBoolsFromStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolFromPointerAndBoolsFromStructWithXor", methodType(boolean.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer = lookup.findStatic(UpcallMethodHandles.class, "addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructPointerWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructPointerWithXor", methodType(boolean.class, boolean.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addBoolAndBoolsFromNestedStructWithXor = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromNestedStructWithXor", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromNestedStructWithXor_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromNestedStructWithXor_reverseOrder", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedBoolArray = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedBoolArray", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedStructArray", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder", MT_Bool_Bool_MemSegmt); //$NON-NLS-1$ + MH_add2BoolStructsWithXor_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2BoolStructsWithXor_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2BoolStructsWithXor_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2BoolStructsWithXor_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3BoolStructsWithXor_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3BoolStructsWithXor_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addByteAndBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStruct", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAnd20BytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteAnd20BytesFromStruct", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteFromPointerAndBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteFromPointerAndBytesFromStruct", methodType(byte.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addByteFromPointerAndBytesFromStruct_returnBytePointer = lookup.findStatic(UpcallMethodHandles.class, "addByteFromPointerAndBytesFromStruct_returnBytePointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructPointer", methodType(byte.class, byte.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addByteAndBytesFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromNestedStruct", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromNestedStruct_reverseOrder", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedByteArray = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedByteArray", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedByteArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedByteArray_reverseOrder", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedStructArray", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_addByteAndBytesFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addByteAndBytesFromStructWithNestedStructArray_reverseOrder", MT_Byte_Byte_MemSegmt); //$NON-NLS-1$ + MH_add1ByteStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add1ByteStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2ByteStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2ByteStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2ByteStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2ByteStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3ByteStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3ByteStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addCharAndCharsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStruct", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAnd10CharsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharAnd10CharsFromStruct", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharFromPointerAndCharsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharFromPointerAndCharsFromStruct", methodType(char.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addCharFromPointerAndCharsFromStruct_returnCharPointer = lookup.findStatic(UpcallMethodHandles.class, "addCharFromPointerAndCharsFromStruct_returnCharPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructPointer", methodType(char.class, char.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addCharAndCharsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromNestedStruct", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromNestedStruct_reverseOrder", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedCharArray = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedCharArray", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedCharArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedCharArray_reverseOrder", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedStructArray", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_addCharAndCharsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addCharAndCharsFromStructWithNestedStructArray_reverseOrder", MT_Char_Char_MemSegmt); //$NON-NLS-1$ + MH_add2CharStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2CharStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2CharStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2CharStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3CharStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3CharStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addShortAndShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAnd10ShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAnd10ShortsFromStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortFromPointerAndShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortFromPointerAndShortsFromStruct", methodType(short.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addShortFromPointerAndShortsFromStruct_returnShortPointer = lookup.findStatic(UpcallMethodHandles.class, "addShortFromPointerAndShortsFromStruct_returnShortPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructPointer", methodType(short.class, short.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addShortAndShortsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromNestedStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromNestedStruct_reverseOrder", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedShortArray = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedShortArray", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedShortArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedShortArray_reverseOrder", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedStructArray", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addShortAndShortsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addShortAndShortsFromStructWithNestedStructArray_reverseOrder", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_add2ShortStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2ShortStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2ShortStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2ShortStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3ShortStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3ShortStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addIntAndIntsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAnd5IntsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAnd5IntsFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntFromPointerAndIntsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntFromPointerAndIntsFromStruct", methodType(int.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addIntFromPointerAndIntsFromStruct_returnIntPointer = lookup.findStatic(UpcallMethodHandles.class, "addIntFromPointerAndIntsFromStruct_returnIntPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructPointer", methodType(int.class, int.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addIntAndIntsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromNestedStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromNestedStruct_reverseOrder", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedIntArray = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedIntArray", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedIntArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedIntArray_reverseOrder", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedStructArray", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntsFromStructWithNestedStructArray_reverseOrder", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_add2IntStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2IntStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2IntStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2IntStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3IntStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3IntStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addLongAndLongsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongFromPointerAndLongsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongFromPointerAndLongsFromStruct", methodType(long.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addLongFromPointerAndLongsFromStruct_returnLongPointer = lookup.findStatic(UpcallMethodHandles.class, "addLongFromPointerAndLongsFromStruct_returnLongPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructPointer", methodType(long.class, long.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addLongAndLongsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromNestedStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromNestedStruct_reverseOrder", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedLongArray = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedLongArray", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedLongArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedLongArray_reverseOrder", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedStructArray", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLongsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLongsFromStructWithNestedStructArray_reverseOrder", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_add2LongStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2LongStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2LongStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2LongStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3LongStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3LongStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addFloatAndFloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAnd5FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAnd5FloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatFromPointerAndFloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatFromPointerAndFloatsFromStruct", methodType(float.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addFloatFromPointerAndFloatsFromStruct_returnFloatPointer = lookup.findStatic(UpcallMethodHandles.class, "addFloatFromPointerAndFloatsFromStruct_returnFloatPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructPointer", methodType(float.class, float.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addFloatAndFloatsFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromNestedStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromNestedStruct_reverseOrder", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedFloatArray = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedFloatArray", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedStructArray", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_add2FloatStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2FloatStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2FloatStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2FloatStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3FloatStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3FloatStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addDoubleAndDoublesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleFromPointerAndDoublesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleFromPointerAndDoublesFromStruct", methodType(double.class, MemoryAddress.class, MemorySegment.class)); //$NON-NLS-1$ + MH_addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer = lookup.findStatic(UpcallMethodHandles.class, "addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructPointer = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructPointer", methodType(double.class, double.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromNestedStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromNestedStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromNestedStruct_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromNestedStruct_reverseOrder", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedDoubleArray = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedDoubleArray", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedStructArray = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedStructArray", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_add2DoubleStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add2DoubleStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + MH_add2DoubleStructs_returnStructPointer = lookup.findStatic(UpcallMethodHandles.class, "add2DoubleStructs_returnStructPointer", MT_Addr_MemAddr_MemSegmt); //$NON-NLS-1$ + MH_add3DoubleStructs_returnStruct = lookup.findStatic(UpcallMethodHandles.class, "add3DoubleStructs_returnStruct", MT_MemSegmt_MemSegmt_MemSegmt); //$NON-NLS-1$ + + MH_addIntAndIntShortFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntShortFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndShortIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndShortIntFromStruct", MT_Int_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndIntLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndIntLongFromStruct", MT_Long_Int_MemSegmt); //$NON-NLS-1$ + MH_addIntAndLongIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addIntAndLongIntFromStruct", MT_Long_Int_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFloatFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAnd2FloatsDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAnd2FloatsDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDouble2FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDouble2FloatsFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndInt2FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndInt2FloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndFloatIntFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndFloatIntFloatFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntFloatDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntFloatDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatIntDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatIntDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndLongDoubleFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndLongDoubleFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndInt3FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndInt3FloatsFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addLongAndLong2FloatsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndLong2FloatsFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addFloatAnd3FloatsIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAnd3FloatsIntFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addLongAndFloatLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAndFloatLongFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleFloatIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleFloatIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndDoubleLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndDoubleLongFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addLongAnd2FloatsLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addLongAnd2FloatsLongFromStruct", MT_Long_Long_MemSegmt); //$NON-NLS-1$ + MH_addShortAnd3ShortsCharFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addShortAnd3ShortsCharFromStruct", MT_Short_Short_MemSegmt); //$NON-NLS-1$ + MH_addFloatAndIntFloatIntFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addFloatAndIntFloatIntFloatFromStruct", MT_Float_Float_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleFloatFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatDoubleIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatDoubleIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleIntFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleIntFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndFloatDoubleFloatFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndFloatDoubleFloatFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_addDoubleAndIntDoubleLongFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addDoubleAndIntDoubleLongFromStruct", MT_Double_Double_MemSegmt); //$NON-NLS-1$ + MH_return254BytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "return254BytesFromStruct", MT_MemSegmt); //$NON-NLS-1$ + MH_return4KBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "return4KBytesFromStruct", MT_MemSegmt); //$NON-NLS-1$ + + } catch (IllegalAccessException | NoSuchMethodException e) { + throw new InternalError(e); + } + } + + public static boolean add2BoolsWithOr(boolean boolArg1, boolean boolArg2) { + boolean result = boolArg1 || boolArg2; + return result; + } + + public static boolean addBoolAndBoolFromPointerWithOr(boolean boolArg1, MemoryAddress boolArg2Addr) { + boolean result = boolArg1 || boolArg2Addr.get(JAVA_BOOLEAN, 0); + return result; + } + + public static Addressable addBoolAndBoolFromPtrWithOr_RetPtr(boolean boolArg1, MemoryAddress boolArg2Addr) { + boolean result = boolArg1 || boolArg2Addr.get(JAVA_BOOLEAN, 0); + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_BOOLEAN, session); + resultSegmt.set(JAVA_BOOLEAN, 0, result); + return resultSegmt.address(); + } + + public static Addressable addBoolAndBoolFromPtrWithOr_RetArgPtr(boolean boolArg1, MemoryAddress boolArg2Addr) { + boolean result = boolArg1 || boolArg2Addr.get(JAVA_BOOLEAN, 0); + boolArg2Addr.set(JAVA_BOOLEAN, 0, result); + return boolArg2Addr; + } + + public static char createNewCharFrom2Chars(char charArg1, char charArg2) { + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + return result; + } + + public static char createNewCharFromCharAndCharFromPointer(MemoryAddress charArg1Addr, char charArg2) { + char charArg1 = charArg1Addr.get(JAVA_CHAR, 0); + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + return result; + } + + public static Addressable createNewCharFromCharAndCharFromPtr_RetPtr(MemoryAddress charArg1Addr, char charArg2) { + char charArg1 = charArg1Addr.get(JAVA_CHAR, 0); + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_CHAR.byteSize(), session); + resultSegmt.set(JAVA_CHAR, 0, result); + return resultSegmt.address(); + } + + public static Addressable createNewCharFromCharAndCharFromPtr_RetArgPtr(MemoryAddress charArg1Addr, char charArg2) { + char charArg1 = charArg1Addr.get(JAVA_CHAR, 0); + int diff = (charArg2 >= charArg1) ? (charArg2 - charArg1) : (charArg1 - charArg2); + diff = (diff > 5) ? 5 : diff; + char result = (char)(diff + 'A'); + charArg1Addr.set(JAVA_CHAR, 0, result); + return charArg1Addr; + } + + public static byte add2Bytes(byte byteArg1, byte byteArg2) { + byte byteSum = (byte)(byteArg1 + byteArg2); + return byteSum; + } + + public static byte addByteAndByteFromPointer(byte byteArg1, MemoryAddress byteArg2Addr) { + byte byteArg2 = byteArg2Addr.get(JAVA_BYTE, 0); + byte byteSum = (byte)(byteArg1 + byteArg2); + return byteSum; + } + + public static Addressable addByteAndByteFromPtr_RetPtr(byte byteArg1, MemoryAddress byteArg2Addr) { + byte byteArg2 = byteArg2Addr.get(JAVA_BYTE, 0); + byte byteSum = (byte)(byteArg1 + byteArg2); + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_BYTE.byteSize(), session); + resultSegmt.set(JAVA_BYTE, 0, byteSum); + return resultSegmt.address(); + } + + public static Addressable addByteAndByteFromPtr_RetArgPtr(byte byteArg1, MemoryAddress byteArg2Addr) { + byte byteArg2 = byteArg2Addr.get(JAVA_BYTE, 0); + byte byteSum = (byte)(byteArg1 + byteArg2); + byteArg2Addr.set(JAVA_BYTE, 0, byteSum); + return byteArg2Addr; + } + + public static short add2Shorts(short shortArg1, short shortArg2) { + short shortSum = (short)(shortArg1 + shortArg2); + return shortSum; + } + + public static short addShortAndShortFromPointer(MemoryAddress shortArg1Addr, short shortArg2) { + short shortArg1 = shortArg1Addr.get(JAVA_SHORT, 0); + short shortSum = (short)(shortArg1 + shortArg2); + return shortSum; + } + + public static Addressable addShortAndShortFromPtr_RetPtr(MemoryAddress shortArg1Addr, short shortArg2) { + short shortArg1 = shortArg1Addr.get(JAVA_SHORT, 0); + short shortSum = (short)(shortArg1 + shortArg2); + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_SHORT.byteSize(), session); + resultSegmt.set(JAVA_SHORT, 0, shortSum); + return resultSegmt.address(); + } + + public static Addressable addShortAndShortFromPtr_RetArgPtr(MemoryAddress shortArg1Addr, short shortArg2) { + short shortArg1 = shortArg1Addr.get(JAVA_SHORT, 0); + short shortSum = (short)(shortArg1 + shortArg2); + shortArg1Addr.set(JAVA_SHORT, 0, shortSum); + return shortArg1Addr; + } + + public static int add2Ints(int intArg1, int intArg2) { + int intSum = intArg1 + intArg2; + return intSum; + } + + public static int addIntAndIntFromPointer(int intArg1, MemoryAddress intArg2Addr) { + int intArg2 = intArg2Addr.get(JAVA_INT, 0); + int intSum = intArg1 + intArg2; + return intSum; + } + + public static Addressable addIntAndIntFromPtr_RetPtr(int intArg1, MemoryAddress intArg2Addr) { + int intArg2 = intArg2Addr.get(JAVA_INT, 0); + int intSum = intArg1 + intArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_INT.byteSize(), session); + resultSegmt.set(JAVA_INT, 0, intSum); + return resultSegmt.address(); + } + + public static Addressable addIntAndIntFromPtr_RetArgPtr(int intArg1, MemoryAddress intArg2Addr) { + int intArg2 = intArg2Addr.get(JAVA_INT, 0); + int intSum = intArg1 + intArg2; + intArg2Addr.set(JAVA_INT, 0, intSum); + return intArg2Addr; + } + + public static int add3Ints(int intArg1, int intArg2, int intArg3) { + int intSum = intArg1 + intArg2 + intArg3; + return intSum; + } + + public static int addIntAndChar(int intArg, char charArg) { + int sum = intArg + charArg; + return sum; + } + + public static void add2IntsReturnVoid(int intArg1, int intArg2) { + int intSum = intArg1 + intArg2; + System.out.println("add2IntsReturnVoid: intSum = " + intSum + "\n"); + } + + public static long add2Longs(long longArg1, long longArg2) { + long longSum = longArg1 + longArg2; + return longSum; + } + + public static long addLongAndLongFromPointer(MemoryAddress longArg1Addr, long longArg2) { + long longArg1 = longArg1Addr.get(JAVA_LONG, 0); + long longSum = longArg1 + longArg2; + return longSum; + } + + public static Addressable addLongAndLongFromPtr_RetPtr(MemoryAddress longArg1Addr, long longArg2) { + long longArg1 = longArg1Addr.get(JAVA_LONG, 0); + long longSum = longArg1 + longArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_LONG.byteSize(), session); + resultSegmt.set(JAVA_LONG, 0, longSum); + return resultSegmt.address(); + } + + public static Addressable addLongAndLongFromPtr_RetArgPtr(MemoryAddress longArg1Addr, long longArg2) { + long longArg1 = longArg1Addr.get(JAVA_LONG, 0); + long longSum = longArg1 + longArg2; + longArg1Addr.set(JAVA_LONG, 0, longSum); + return longArg1Addr; + } + + public static float add2Floats(float floatArg1, float floatArg2) { + float floatSum = floatArg1 + floatArg2; + return floatSum; + } + + public static float addFloatAndFloatFromPointer(float floatArg1, MemoryAddress floatArg2Addr) { + float floatArg2 = floatArg2Addr.get(JAVA_FLOAT, 0); + float floatSum = floatArg1 + floatArg2; + return floatSum; + } + + public static Addressable addFloatAndFloatFromPtr_RetPtr(float floatArg1, MemoryAddress floatArg2Addr) { + float floatArg2 = floatArg2Addr.get(JAVA_FLOAT, 0); + float floatSum = floatArg1 + floatArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_FLOAT.byteSize(), session); + resultSegmt.set(JAVA_FLOAT, 0, floatSum); + return resultSegmt.address(); + } + + public static Addressable addFloatAndFloatFromPtr_RetArgPtr(float floatArg1, MemoryAddress floatArg2Addr) { + float floatArg2 = floatArg2Addr.get(JAVA_FLOAT, 0); + float floatSum = floatArg1 + floatArg2; + floatArg2Addr.set(JAVA_FLOAT, 0, floatSum); + return floatArg2Addr; + } + + public static double add2Doubles(double doubleArg1, double doubleArg2) { + double doubleSum = doubleArg1 + doubleArg2; + return doubleSum; + } + + public static double addDoubleAndDoubleFromPointer(MemoryAddress doubleArg1Addr, double doubleArg2) { + double doubleArg1 = doubleArg1Addr.get(JAVA_DOUBLE, 0); + double doubleSum = doubleArg1 + doubleArg2; + return doubleSum; + } + + public static Addressable addDoubleAndDoubleFromPtr_RetPtr(MemoryAddress doubleArg1Addr, double doubleArg2) { + double doubleArg1 = doubleArg1Addr.get(JAVA_DOUBLE, 0); + double doubleSum = doubleArg1 + doubleArg2; + MemorySegment resultSegmt = MemorySegment.allocateNative(JAVA_DOUBLE.byteSize(), session); + resultSegmt.set(JAVA_DOUBLE, 0, doubleSum); + return resultSegmt.address(); + } + + public static Addressable addDoubleAndDoubleFromPtr_RetArgPtr(MemoryAddress doubleArg1Addr, double doubleArg2) { + double doubleArg1 = doubleArg1Addr.get(JAVA_DOUBLE, 0); + double doubleSum = doubleArg1 + doubleArg2; + doubleArg1Addr.set(JAVA_DOUBLE, 0, doubleSum); + return doubleArg1Addr; + } + + public static int compare(MemoryAddress argAddr1, MemoryAddress argAddr2) { + int intArg1 = argAddr1.get(JAVA_INT, 0); + int intArg2 = argAddr2.get(JAVA_INT, 0); + return (intArg1 - intArg2); + } + + public static boolean addBoolAndBoolsFromStructWithXor(boolean arg1, MemorySegment arg2) { + boolean boolSum = arg1 ^ arg2.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 1); + return boolSum; + } + + public static boolean addBoolAnd20BoolsFromStructWithXor(boolean arg1, MemorySegment arg2) { + boolean boolSum = arg1 ^ arg2.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 1) + ^ arg2.get(JAVA_BOOLEAN, 2) ^ arg2.get(JAVA_BOOLEAN, 3) ^ arg2.get(JAVA_BOOLEAN, 4) + ^ arg2.get(JAVA_BOOLEAN, 5) ^ arg2.get(JAVA_BOOLEAN, 6) ^ arg2.get(JAVA_BOOLEAN, 7) + ^ arg2.get(JAVA_BOOLEAN, 8) ^ arg2.get(JAVA_BOOLEAN, 9) ^ arg2.get(JAVA_BOOLEAN, 10) + ^ arg2.get(JAVA_BOOLEAN, 11) ^ arg2.get(JAVA_BOOLEAN, 12) ^ arg2.get(JAVA_BOOLEAN, 13) + ^ arg2.get(JAVA_BOOLEAN, 14) ^ arg2.get(JAVA_BOOLEAN, 15) ^ arg2.get(JAVA_BOOLEAN, 16) + ^ arg2.get(JAVA_BOOLEAN, 17) ^ arg2.get(JAVA_BOOLEAN, 18) ^ arg2.get(JAVA_BOOLEAN, 19); + return boolSum; + } + + public static boolean addBoolFromPointerAndBoolsFromStructWithXor(MemoryAddress arg1Addr, MemorySegment arg2) { + boolean boolSum = arg1Addr.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 1); + return boolSum; + } + + public static Addressable addBoolFromPointerAndBoolsFromStructWithXor_returnBoolPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + boolean boolSum = arg1Addr.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 1); + arg1Addr.set(JAVA_BOOLEAN, 0, boolSum); + return arg1Addr; + } + + public static boolean addBoolAndBoolsFromStructPointerWithXor(boolean arg1, MemoryAddress arg2Addr) { + boolean boolSum = arg1 ^ arg2Addr.get(JAVA_BOOLEAN, 0) ^ arg2Addr.get(JAVA_BOOLEAN, 1); + return boolSum; + } + + public static boolean addBoolAndBoolsFromNestedStructWithXor(boolean arg1, MemorySegment arg2) { + boolean nestedStructElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedStructElem2 = arg2.get(JAVA_BOOLEAN, 1); + boolean structElem2 = arg2.get(JAVA_BOOLEAN, 2); + boolean boolSum = arg1 ^ nestedStructElem1 ^ nestedStructElem2 ^ structElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromNestedStructWithXor_reverseOrder(boolean arg1, MemorySegment arg2) { + boolean structElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedStructElem1 = arg2.get(JAVA_BOOLEAN, 1); + boolean nestedStructElem2 = arg2.get(JAVA_BOOLEAN, 2); + boolean boolSum = arg1 ^ structElem1 ^ nestedStructElem1 ^ nestedStructElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedBoolArray(boolean arg1, MemorySegment arg2) { + boolean nestedBoolArrayElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedBoolArrayElem2 = arg2.get(JAVA_BOOLEAN, 1); + boolean structElem2 = arg2.get(JAVA_BOOLEAN, 2); + + boolean boolSum = arg1 ^ nestedBoolArrayElem1 ^ nestedBoolArrayElem2 ^ structElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedBoolArray_reverseOrder(boolean arg1, MemorySegment arg2) { + boolean structElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedBoolArrayElem1 = arg2.get(JAVA_BOOLEAN, 1); + boolean nestedBoolArrayElem2 = arg2.get(JAVA_BOOLEAN, 2); + + boolean boolSum = arg1 ^ structElem1 ^ nestedBoolArrayElem1 ^ nestedBoolArrayElem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedStructArray(boolean arg1, MemorySegment arg2) { + boolean nestedStructArrayElem1_Elem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedStructArrayElem1_Elem2 = arg2.get(JAVA_BOOLEAN, 1); + boolean nestedStructArrayElem2_Elem1 = arg2.get(JAVA_BOOLEAN, 2); + boolean nestedStructArrayElem2_Elem2 = arg2.get(JAVA_BOOLEAN, 3); + boolean structElem2 = arg2.get(JAVA_BOOLEAN, 4); + + boolean boolSum = arg1 ^ structElem2 + ^ nestedStructArrayElem1_Elem1 ^ nestedStructArrayElem1_Elem2 + ^ nestedStructArrayElem2_Elem1 ^ nestedStructArrayElem2_Elem2; + return boolSum; + } + + public static boolean addBoolAndBoolsFromStructWithNestedStructArray_reverseOrder(boolean arg1, MemorySegment arg2) { + boolean structElem1 = arg2.get(JAVA_BOOLEAN, 0); + boolean nestedStructArrayElem1_Elem1 = arg2.get(JAVA_BOOLEAN, 1); + boolean nestedStructArrayElem1_Elem2 = arg2.get(JAVA_BOOLEAN, 2); + boolean nestedStructArrayElem2_Elem1 = arg2.get(JAVA_BOOLEAN, 3); + boolean nestedStructArrayElem2_Elem2 = arg2.get(JAVA_BOOLEAN, 4); + + boolean boolSum = arg1 ^ structElem1 + ^ nestedStructArrayElem1_Elem1 ^ nestedStructArrayElem1_Elem2 + ^ nestedStructArrayElem2_Elem1 ^ nestedStructArrayElem2_Elem2; + return boolSum; + } + + public static MemorySegment add2BoolStructsWithXor_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), JAVA_BOOLEAN.withName("elem2")); + MemorySegment boolStructSegmt = MemorySegment.allocateNative(structLayout, session); + boolean boolStruct_Elem1 = arg1.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0); + boolean boolStruct_Elem2 = arg1.get(JAVA_BOOLEAN, 1) ^ arg2.get(JAVA_BOOLEAN, 1); + boolStructSegmt.set(JAVA_BOOLEAN, 0, boolStruct_Elem1); + boolStructSegmt.set(JAVA_BOOLEAN, 1, boolStruct_Elem2); + return boolStructSegmt; + } + + public static Addressable add2BoolStructsWithXor_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + boolean boolStruct_Elem1 = arg1Addr.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0); + boolean boolStruct_Elem2 = arg1Addr.get(JAVA_BOOLEAN, 1) ^ arg2.get(JAVA_BOOLEAN, 1); + arg1Addr.set(JAVA_BOOLEAN, 0, boolStruct_Elem1); + arg1Addr.set(JAVA_BOOLEAN, 1, boolStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3BoolStructsWithXor_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BOOLEAN.withName("elem1"), + JAVA_BOOLEAN.withName("elem2"), JAVA_BOOLEAN.withName("elem3"), MemoryLayout.paddingLayout(8)); + MemorySegment boolStructSegmt = MemorySegment.allocateNative(structLayout, session); + boolean boolStruct_Elem1 = arg1.get(JAVA_BOOLEAN, 0) ^ arg2.get(JAVA_BOOLEAN, 0); + boolean boolStruct_Elem2 = arg1.get(JAVA_BOOLEAN, 1) ^ arg2.get(JAVA_BOOLEAN, 1); + boolean boolStruct_Elem3 = arg1.get(JAVA_BOOLEAN, 2) ^ arg2.get(JAVA_BOOLEAN, 2); + boolStructSegmt.set(JAVA_BOOLEAN, 0, boolStruct_Elem1); + boolStructSegmt.set(JAVA_BOOLEAN, 1, boolStruct_Elem2); + boolStructSegmt.set(JAVA_BOOLEAN, 2, boolStruct_Elem3); + return boolStructSegmt; + } + + public static byte addByteAndBytesFromStruct(byte arg1, MemorySegment arg2) { + byte byteSum = (byte)(arg1 + arg2.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 1)); + return byteSum; + } + + public static byte addByteAnd20BytesFromStruct(byte arg1, MemorySegment arg2) { + byte byteSum = (byte)(arg1 + arg2.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 1) + + arg2.get(JAVA_BYTE, 2) + arg2.get(JAVA_BYTE, 3) + arg2.get(JAVA_BYTE, 4) + + arg2.get(JAVA_BYTE, 5) + arg2.get(JAVA_BYTE, 6) + arg2.get(JAVA_BYTE, 7) + + arg2.get(JAVA_BYTE, 8) + arg2.get(JAVA_BYTE, 9) + arg2.get(JAVA_BYTE, 10) + + arg2.get(JAVA_BYTE, 11) + arg2.get(JAVA_BYTE, 12) + arg2.get(JAVA_BYTE, 13) + + arg2.get(JAVA_BYTE, 14) + arg2.get(JAVA_BYTE, 15) + arg2.get(JAVA_BYTE, 16) + + arg2.get(JAVA_BYTE, 17) + arg2.get(JAVA_BYTE, 18) + arg2.get(JAVA_BYTE, 19)); + return byteSum; + } + + public static byte addByteFromPointerAndBytesFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + byte byteSum = (byte)(arg1Addr.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 1)); + return byteSum; + } + + public static Addressable addByteFromPointerAndBytesFromStruct_returnBytePointer(MemoryAddress arg1Addr, MemorySegment arg2) { + byte byteSum = (byte)(arg1Addr.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 1)); + arg1Addr.set(JAVA_BYTE, 0, byteSum); + return arg1Addr; + } + + public static byte addByteAndBytesFromStructPointer(byte arg1, MemoryAddress arg2Addr) { + byte byteSum = (byte)(arg1 + arg2Addr.get(JAVA_BYTE, 0) + arg2Addr.get(JAVA_BYTE, 1)); + return byteSum; + } + + public static byte addByteAndBytesFromNestedStruct(byte arg1, MemorySegment arg2) { + byte nestedStructElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedStructElem2 = arg2.get(JAVA_BYTE, 1); + byte structElem2 = arg2.get(JAVA_BYTE, 2); + + byte byteSum = (byte)(arg1 + nestedStructElem1 + nestedStructElem2 + structElem2); + return byteSum; + } + + public static byte addByteAndBytesFromNestedStruct_reverseOrder(byte arg1, MemorySegment arg2) { + byte structElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedStructElem1 = arg2.get(JAVA_BYTE, 1); + byte nestedStructElem2 = arg2.get(JAVA_BYTE, 2); + + byte byteSum = (byte)(arg1 + structElem1 + nestedStructElem1 + nestedStructElem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedByteArray(byte arg1, MemorySegment arg2) { + byte nestedByteArrayElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedByteArrayElem2 = arg2.get(JAVA_BYTE, 1); + byte structElem2 = arg2.get(JAVA_BYTE, 2); + + byte byteSum = (byte)(arg1 + nestedByteArrayElem1 + nestedByteArrayElem2 + structElem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedByteArray_reverseOrder(byte arg1, MemorySegment arg2) { + byte structElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedByteArrayElem1 = arg2.get(JAVA_BYTE, 1); + byte nestedByteArrayElem2 = arg2.get(JAVA_BYTE, 2); + + byte byteSum = (byte)(arg1 + structElem1 + nestedByteArrayElem1 + nestedByteArrayElem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedStructArray(byte arg1, MemorySegment arg2) { + byte nestedStructArrayElem1_Elem1 = arg2.get(JAVA_BYTE, 0); + byte nestedStructArrayElem1_Elem2 = arg2.get(JAVA_BYTE, 1); + byte nestedStructArrayElem2_Elem1 = arg2.get(JAVA_BYTE, 2); + byte nestedStructArrayElem2_Elem2 = arg2.get(JAVA_BYTE, 3); + byte structElem2 = arg2.get(JAVA_BYTE, 4); + + byte byteSum = (byte)(arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return byteSum; + } + + public static byte addByteAndBytesFromStructWithNestedStructArray_reverseOrder(byte arg1, MemorySegment arg2) { + byte structElem1 = arg2.get(JAVA_BYTE, 0); + byte nestedStructArrayElem1_Elem1 = arg2.get(JAVA_BYTE, 1); + byte nestedStructArrayElem1_Elem2 = arg2.get(JAVA_BYTE, 2); + byte nestedStructArrayElem2_Elem1 = arg2.get(JAVA_BYTE, 3); + byte nestedStructArrayElem2_Elem2 = arg2.get(JAVA_BYTE, 4); + + byte byteSum = (byte)(arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return byteSum; + } + + public static MemorySegment add1ByteStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1")); + MemorySegment byteStructSegmt = MemorySegment.allocateNative(structLayout, session); + byte byteStruct_Elem1 = (byte)(arg1.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0)); + byteStructSegmt.set(JAVA_BYTE, 0, byteStruct_Elem1); + return byteStructSegmt; + } + + public static MemorySegment add2ByteStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + MemorySegment byteStructSegmt = MemorySegment.allocateNative(structLayout, session); + byte byteStruct_Elem1 = (byte)(arg1.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0)); + byte byteStruct_Elem2 = (byte)(arg1.get(JAVA_BYTE, 1) + arg2.get(JAVA_BYTE, 1)); + byteStructSegmt.set(JAVA_BYTE, 0, byteStruct_Elem1); + byteStructSegmt.set(JAVA_BYTE, 1, byteStruct_Elem2); + return byteStructSegmt; + } + + public static Addressable add2ByteStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + byte byteStruct_Elem1 = (byte)(arg1Addr.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0)); + byte byteStruct_Elem2 = (byte)(arg1Addr.get(JAVA_BYTE, 1) + arg2.get(JAVA_BYTE, 1)); + arg1Addr.set(JAVA_BYTE, 0, byteStruct_Elem1); + arg1Addr.set(JAVA_BYTE, 1, byteStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3ByteStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2"), + JAVA_BYTE.withName("elem3"), MemoryLayout.paddingLayout(8)); + MemorySegment byteStructSegmt = MemorySegment.allocateNative(structLayout, session); + byte byteStruct_Elem1 = (byte)(arg1.get(JAVA_BYTE, 0) + arg2.get(JAVA_BYTE, 0)); + byte byteStruct_Elem2 = (byte)(arg1.get(JAVA_BYTE, 1) + arg2.get(JAVA_BYTE, 1)); + byte byteStruct_Elem3 = (byte)(arg1.get(JAVA_BYTE, 2) + arg2.get(JAVA_BYTE, 2)); + byteStructSegmt.set(JAVA_BYTE, 0, byteStruct_Elem1); + byteStructSegmt.set(JAVA_BYTE, 1, byteStruct_Elem2); + byteStructSegmt.set(JAVA_BYTE, 2, byteStruct_Elem3); + return byteStructSegmt; + } + + public static char addCharAndCharsFromStruct(char arg1, MemorySegment arg2) { + char result = (char)(arg1 + arg2.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 2) - 2 * 'A'); + return result; + } + + public static char addCharAnd10CharsFromStruct(char arg1, MemorySegment arg2) { + char result = (char)(arg1 + arg2.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 2) + + arg2.get(JAVA_CHAR, 4) + arg2.get(JAVA_CHAR, 6) + arg2.get(JAVA_CHAR, 8) + + arg2.get(JAVA_CHAR, 10) + arg2.get(JAVA_CHAR, 12) + arg2.get(JAVA_CHAR, 14) + + arg2.get(JAVA_CHAR, 16) + arg2.get(JAVA_CHAR, 18) - 10 * 'A'); + return result; + } + + public static char addCharFromPointerAndCharsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + char result = (char)(arg1Addr.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 2) - 2 * 'A'); + return result; + } + + public static Addressable addCharFromPointerAndCharsFromStruct_returnCharPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + char result = (char)(arg1Addr.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 2) - 2 * 'A'); + arg1Addr.set(JAVA_CHAR, 0, result); + return arg1Addr; + } + + public static char addCharAndCharsFromStructPointer(char arg1, MemoryAddress arg2Addr) { + char result = (char)(arg1 + arg2Addr.get(JAVA_CHAR, 0) + arg2Addr.get(JAVA_CHAR, 2) - 2 * 'A'); + return result; + } + + public static char addCharAndCharsFromNestedStruct(char arg1, MemorySegment arg2) { + char nestedStructElem1 = arg2.get(JAVA_CHAR, 0); + char nestedStructElem2 = arg2.get(JAVA_CHAR, 2); + char structElem2 = arg2.get(JAVA_CHAR, 4); + + char result = (char)(arg1 + nestedStructElem1 + nestedStructElem2 + structElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromNestedStruct_reverseOrder(char arg1, MemorySegment arg2) { + char structElem1 = arg2.get(JAVA_CHAR, 0); + char nestedStructElem1 = arg2.get(JAVA_CHAR, 2); + char nestedStructElem2 = arg2.get(JAVA_CHAR, 4); + + char result = (char)(arg1 + structElem1 + nestedStructElem1 + nestedStructElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedCharArray(char arg1, MemorySegment arg2) { + char nestedCharArrayElem1 = arg2.get(JAVA_CHAR, 0); + char nestedCharArrayElem2 = arg2.get(JAVA_CHAR, 2); + char structElem2 = arg2.get(JAVA_CHAR, 4); + + char result = (char)(arg1 + nestedCharArrayElem1 + nestedCharArrayElem2 + structElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedCharArray_reverseOrder(char arg1, MemorySegment arg2) { + char structElem1 = arg2.get(JAVA_CHAR, 0); + char nestedCharArrayElem1 = arg2.get(JAVA_CHAR, 2); + char nestedCharArrayElem2 = arg2.get(JAVA_CHAR, 4); + + char result = (char)(arg1 + structElem1 + nestedCharArrayElem1 + nestedCharArrayElem2 - 3 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedStructArray(char arg1, MemorySegment arg2) { + char nestedStructArrayElem1_Elem1 = arg2.get(JAVA_CHAR, 0); + char nestedStructArrayElem1_Elem2 = arg2.get(JAVA_CHAR, 2); + char nestedStructArrayElem2_Elem1 = arg2.get(JAVA_CHAR, 4); + char nestedStructArrayElem2_Elem2 = arg2.get(JAVA_CHAR, 6); + char structElem2 = arg2.get(JAVA_CHAR, 8); + + char result = (char)(arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2 - 5 * 'A'); + return result; + } + + public static char addCharAndCharsFromStructWithNestedStructArray_reverseOrder(char arg1, MemorySegment arg2) { + char structElem1 = arg2.get(JAVA_CHAR, 0); + char nestedStructArrayElem1_Elem1 = arg2.get(JAVA_CHAR, 2); + char nestedStructArrayElem1_Elem2 = arg2.get(JAVA_CHAR, 4); + char nestedStructArrayElem2_Elem1 = arg2.get(JAVA_CHAR, 6); + char nestedStructArrayElem2_Elem2 = arg2.get(JAVA_CHAR, 8); + + char result = (char)(arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2 - 5 * 'A'); + return result; + } + + public static MemorySegment add2CharStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2")); + MemorySegment charStructSegmt = MemorySegment.allocateNative(structLayout, session); + char charStruct_Elem1 = (char)(arg1.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) - 'A'); + char charStruct_Elem2 = (char)(arg1.get(JAVA_CHAR, 2) + arg2.get(JAVA_CHAR, 2) - 'A'); + charStructSegmt.set(JAVA_CHAR, 0, charStruct_Elem1); + charStructSegmt.set(JAVA_CHAR, 2, charStruct_Elem2); + return charStructSegmt; + } + + public static Addressable add2CharStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + char charStruct_Elem1 = (char)(arg1Addr.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) - 'A'); + char charStruct_Elem2 = (char)(arg1Addr.get(JAVA_CHAR, 2) + arg2.get(JAVA_CHAR, 2) - 'A'); + arg1Addr.set(JAVA_CHAR, 0, charStruct_Elem1); + arg1Addr.set(JAVA_CHAR, 2, charStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3CharStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_CHAR.withName("elem1"), JAVA_CHAR.withName("elem2"), + JAVA_CHAR.withName("elem3"), MemoryLayout.paddingLayout(16)); + MemorySegment charStructSegmt = MemorySegment.allocateNative(structLayout, session); + char charStruct_Elem1 = (char)(arg1.get(JAVA_CHAR, 0) + arg2.get(JAVA_CHAR, 0) - 'A'); + char charStruct_Elem2 = (char)(arg1.get(JAVA_CHAR, 2) + arg2.get(JAVA_CHAR, 2) - 'A'); + char charStruct_Elem3 = (char)(arg1.get(JAVA_CHAR, 4) + arg2.get(JAVA_CHAR, 4) - 'A'); + charStructSegmt.set(JAVA_CHAR, 0, charStruct_Elem1); + charStructSegmt.set(JAVA_CHAR, 2, charStruct_Elem2); + charStructSegmt.set(JAVA_CHAR, 4, charStruct_Elem3); + return charStructSegmt; + } + + public static short addShortAndShortsFromStruct(short arg1, MemorySegment arg2) { + short shortSum = (short)(arg1 + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2)); + return shortSum; + } + + public static short addShortAnd10ShortsFromStruct(short arg1, MemorySegment arg2) { + short shortSum = (short)(arg1 + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2) + + arg2.get(JAVA_SHORT, 4) + arg2.get(JAVA_SHORT, 6) + arg2.get(JAVA_SHORT, 8) + + arg2.get(JAVA_SHORT, 10) + arg2.get(JAVA_SHORT, 12) + arg2.get(JAVA_SHORT, 14) + + arg2.get(JAVA_SHORT, 16) + arg2.get(JAVA_SHORT, 18)); + return shortSum; + } + + public static short addShortFromPointerAndShortsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + short shortSum = (short)(arg1Addr.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2)); + return shortSum; + } + + public static Addressable addShortFromPointerAndShortsFromStruct_returnShortPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + short shortSum = (short)(arg1Addr.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2)); + arg1Addr.set(JAVA_SHORT, 0, shortSum); + return arg1Addr; + } + + public static short addShortAndShortsFromStructPointer(short arg1, MemoryAddress arg2Addr) { + short shortSum = (short)(arg1 + arg2Addr.get(JAVA_SHORT, 0) + arg2Addr.get(JAVA_SHORT, 2)); + return shortSum; + } + + public static short addShortAndShortsFromNestedStruct(short arg1, MemorySegment arg2) { + short nestedStructElem1 = arg2.get(JAVA_SHORT, 0); + short nestedStructElem2 = arg2.get(JAVA_SHORT, 2); + short structElem2 = arg2.get(JAVA_SHORT, 4); + + short shortSum = (short)(arg1 + nestedStructElem1 + nestedStructElem2 + structElem2); + return shortSum; + } + + public static short addShortAndShortsFromNestedStruct_reverseOrder(short arg1, MemorySegment arg2) { + short structElem1 = arg2.get(JAVA_SHORT, 0); + short nestedStructElem1 = arg2.get(JAVA_SHORT, 2); + short nestedStructElem2 = arg2.get(JAVA_SHORT, 4); + + short shortSum = (short)(arg1 + structElem1 + nestedStructElem1 + nestedStructElem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedShortArray(short arg1, MemorySegment arg2) { + short nestedShortArrayElem1 = arg2.get(JAVA_SHORT, 0); + short nestedShortArrayElem2 = arg2.get(JAVA_SHORT, 2); + short structElem2 = arg2.get(JAVA_SHORT, 4); + + short shortSum = (short)(arg1 + nestedShortArrayElem1 + nestedShortArrayElem2 + structElem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedShortArray_reverseOrder(short arg1, MemorySegment arg2) { + short structElem1 = arg2.get(JAVA_SHORT, 0); + short nestedShortArrayElem1 = arg2.get(JAVA_SHORT, 2); + short nestedShortArrayElem2 = arg2.get(JAVA_SHORT, 4); + + short shortSum = (short)(arg1 + structElem1 + nestedShortArrayElem1 + nestedShortArrayElem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedStructArray(short arg1, MemorySegment arg2) { + short nestedStructArrayElem1_Elem1 = arg2.get(JAVA_SHORT, 0); + short nestedStructArrayElem1_Elem2 = arg2.get(JAVA_SHORT, 2); + short nestedStructArrayElem2_Elem1 = arg2.get(JAVA_SHORT, 4); + short nestedStructArrayElem2_Elem2 = arg2.get(JAVA_SHORT, 6); + short structElem2 = arg2.get(JAVA_SHORT, 8); + + short shortSum = (short)(arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return shortSum; + } + + public static short addShortAndShortsFromStructWithNestedStructArray_reverseOrder(short arg1, MemorySegment arg2) { + short structElem1 = arg2.get(JAVA_SHORT, 0); + short nestedStructArrayElem1_Elem1 = arg2.get(JAVA_SHORT, 2); + short nestedStructArrayElem1_Elem2 = arg2.get(JAVA_SHORT, 4); + short nestedStructArrayElem2_Elem1 = arg2.get(JAVA_SHORT, 6); + short nestedStructArrayElem2_Elem2 = arg2.get(JAVA_SHORT, 8); + + short shortSum = (short)(arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2); + return shortSum; + } + + public static MemorySegment add2ShortStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + MemorySegment shortStructSegmt = MemorySegment.allocateNative(structLayout, session); + short shortStruct_Elem1 = (short)(arg1.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0)); + short shortStruct_Elem2 = (short)(arg1.get(JAVA_SHORT, 2) + arg2.get(JAVA_SHORT, 2)); + shortStructSegmt.set(JAVA_SHORT, 0, shortStruct_Elem1); + shortStructSegmt.set(JAVA_SHORT, 2, shortStruct_Elem2); + return shortStructSegmt; + } + + public static Addressable add2ShortStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + short shortStruct_Elem1 = (short)(arg1Addr.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0)); + short shortStruct_Elem2 = (short)(arg1Addr.get(JAVA_SHORT, 2) + arg2.get(JAVA_SHORT, 2)); + arg1Addr.set(JAVA_SHORT, 0, shortStruct_Elem1); + arg1Addr.set(JAVA_SHORT, 2, shortStruct_Elem2); + return arg1Addr; + } + + public static MemorySegment add3ShortStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2"), + JAVA_SHORT.withName("elem3"), MemoryLayout.paddingLayout(16)); + MemorySegment shortStructSegmt = MemorySegment.allocateNative(structLayout, session); + short shortStruct_Elem1 = (short)(arg1.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 0)); + short shortStruct_Elem2 = (short)(arg1.get(JAVA_SHORT, 2) + arg2.get(JAVA_SHORT, 2)); + short shortStruct_Elem3 = (short)(arg1.get(JAVA_SHORT, 4) + arg2.get(JAVA_SHORT, 4)); + shortStructSegmt.set(JAVA_SHORT, 0, shortStruct_Elem1); + shortStructSegmt.set(JAVA_SHORT, 2, shortStruct_Elem2); + shortStructSegmt.set(JAVA_SHORT, 4, shortStruct_Elem3); + return shortStructSegmt; + } + + public static int addIntAndIntsFromStruct(int arg1, MemorySegment arg2) { + int intSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 4); + return intSum; + } + + public static int addIntAnd5IntsFromStruct(int arg1, MemorySegment arg2) { + int intSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 4) + + arg2.get(JAVA_INT, 8) + arg2.get(JAVA_INT, 12) + arg2.get(JAVA_INT, 16); + return intSum; + } + + public static int addIntFromPointerAndIntsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + int intSum = arg1Addr.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 4); + return intSum; + } + + public static Addressable addIntFromPointerAndIntsFromStruct_returnIntPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + int intSum = arg1Addr.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 4); + arg1Addr.set(JAVA_INT, 0, intSum); + return arg1Addr; + } + + public static int addIntAndIntsFromStructPointer(int arg1, MemoryAddress arg2Addr) { + int intSum = arg1 + arg2Addr.get(JAVA_INT, 0) + arg2Addr.get(JAVA_INT, 4); + return intSum; + } + + public static int addIntAndIntsFromNestedStruct(int arg1, MemorySegment arg2) { + int nestedStructElem1 = arg2.get(JAVA_INT, 0); + int nestedStructElem2 = arg2.get(JAVA_INT, 4); + int structElem2 = arg2.get(JAVA_INT, 8); + + int intSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return intSum; + } + + public static int addIntAndIntsFromNestedStruct_reverseOrder(int arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + int nestedStructElem1 = arg2.get(JAVA_INT, 4); + int nestedStructElem2 = arg2.get(JAVA_INT, 8); + + int intSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedIntArray(int arg1, MemorySegment arg2) { + int nestedIntArrayElem1 = arg2.get(JAVA_INT, 0); + int nestedIntArrayElem2 = arg2.get(JAVA_INT, 4); + int structElem2 = arg2.get(JAVA_INT, 8); + + int intSum = arg1 + nestedIntArrayElem1 + nestedIntArrayElem2 + structElem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedIntArray_reverseOrder(int arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + int nestedIntArrayElem1 = arg2.get(JAVA_INT, 4); + int nestedIntArrayElem2 = arg2.get(JAVA_INT, 8); + + int intSum = arg1 + structElem1 + nestedIntArrayElem1 + nestedIntArrayElem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedStructArray(int arg1, MemorySegment arg2) { + int nestedStructArrayElem1_Elem1 = arg2.get(JAVA_INT, 0); + int nestedStructArrayElem1_Elem2 = arg2.get(JAVA_INT, 4); + int nestedStructArrayElem2_Elem1 = arg2.get(JAVA_INT, 8); + int nestedStructArrayElem2_Elem2 = arg2.get(JAVA_INT, 12); + int structElem2 = arg2.get(JAVA_INT, 16); + + int intSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return intSum; + } + + public static int addIntAndIntsFromStructWithNestedStructArray_reverseOrder(int arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + int nestedStructArrayElem1_Elem1 = arg2.get(JAVA_INT, 4); + int nestedStructArrayElem1_Elem2 = arg2.get(JAVA_INT, 8); + int nestedStructArrayElem2_Elem1 = arg2.get(JAVA_INT, 12); + int nestedStructArrayElem2_Elem2 = arg2.get(JAVA_INT, 16); + + int intSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return intSum; + } + + public static MemorySegment add2IntStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + MemorySegment intStructSegmt = MemorySegment.allocateNative(structLayout, session); + int intStruct_Elem1 = arg1.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0); + int intStruct_Elem2 = arg1.get(JAVA_INT, 4) + arg2.get(JAVA_INT, 4); + intStructSegmt.set(JAVA_INT, 0, intStruct_Elem1); + intStructSegmt.set(JAVA_INT, 4, intStruct_Elem2); + return intStructSegmt; + } + + public static Addressable add2IntStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + int intSum_Elem1 = arg1Addr.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0); + int intSum_Elem2 = arg1Addr.get(JAVA_INT, 4) + arg2.get(JAVA_INT, 4); + arg1Addr.set(JAVA_INT, 0, intSum_Elem1); + arg1Addr.set(JAVA_INT, 4, intSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3IntStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2"), JAVA_INT.withName("elem3")); + MemorySegment intStructSegmt = MemorySegment.allocateNative(structLayout, session); + int intStruct_Elem1 = arg1.get(JAVA_INT, 0) + arg2.get(JAVA_INT, 0); + int intStruct_Elem2 = arg1.get(JAVA_INT, 4) + arg2.get(JAVA_INT, 4); + int intStruct_Elem3 = arg1.get(JAVA_INT, 8) + arg2.get(JAVA_INT, 8); + intStructSegmt.set(JAVA_INT, 0, intStruct_Elem1); + intStructSegmt.set(JAVA_INT, 4, intStruct_Elem2); + intStructSegmt.set(JAVA_INT, 8, intStruct_Elem3); + return intStructSegmt; + } + + public static long addLongAndLongsFromStruct(long arg1, MemorySegment arg2) { + long longSum = arg1 + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 8); + return longSum; + } + + public static long addLongFromPointerAndLongsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + long longSum = arg1Addr.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 8); + return longSum; + } + + public static Addressable addLongFromPointerAndLongsFromStruct_returnLongPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + long longSum = arg1Addr.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 8); + arg1Addr.set(JAVA_LONG, 0, longSum); + return arg1Addr; + } + + public static long addLongAndLongsFromStructPointer(long arg1, MemoryAddress arg2Addr) { + long longSum = arg1 + arg2Addr.get(JAVA_LONG, 0) + arg2Addr.get(JAVA_LONG, 8); + return longSum; + } + + public static long addLongAndLongsFromNestedStruct(long arg1, MemorySegment arg2) { + long nestedStructElem1 = arg2.get(JAVA_LONG, 0); + long nestedStructElem2 = arg2.get(JAVA_LONG, 8); + long structElem2 = arg2.get(JAVA_LONG, 16); + + long longSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return longSum; + } + + public static long addLongAndLongsFromNestedStruct_reverseOrder(long arg1, MemorySegment arg2) { + long structElem1 = arg2.get(JAVA_LONG, 0); + long nestedStructElem1 = arg2.get(JAVA_LONG, 8); + long nestedStructElem2 = arg2.get(JAVA_LONG, 16); + + long longSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedLongArray(long arg1, MemorySegment arg2) { + long nestedLongrrayElem1 = arg2.get(JAVA_LONG, 0); + long nestedLongrrayElem2 = arg2.get(JAVA_LONG, 8); + long structElem2 = arg2.get(JAVA_LONG, 16); + + long longSum = arg1 + nestedLongrrayElem1 + nestedLongrrayElem2 + structElem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedLongArray_reverseOrder(long arg1, MemorySegment arg2) { + long structElem1 = arg2.get(JAVA_LONG, 0); + long nestedLongrrayElem1 = arg2.get(JAVA_LONG, 8); + long nestedLongrrayElem2 = arg2.get(JAVA_LONG, 16); + + long longSum = arg1 + structElem1 + nestedLongrrayElem1 + nestedLongrrayElem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedStructArray(long arg1, MemorySegment arg2) { + long nestedStructArrayElem1_Elem1 = arg2.get(JAVA_LONG, 0); + long nestedStructArrayElem1_Elem2 = arg2.get(JAVA_LONG, 8); + long nestedStructArrayElem2_Elem1 = arg2.get(JAVA_LONG, 16); + long nestedStructArrayElem2_Elem2 = arg2.get(JAVA_LONG, 24); + long structElem2 = arg2.get(JAVA_LONG, 32); + + long longSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return longSum; + } + + public static long addLongAndLongsFromStructWithNestedStructArray_reverseOrder(long arg1, MemorySegment arg2) { + long structElem1 = arg2.get(JAVA_LONG, 0); + long nestedStructArrayElem1_Elem1 = arg2.get(JAVA_LONG, 8); + long nestedStructArrayElem1_Elem2 = arg2.get(JAVA_LONG, 16); + long nestedStructArrayElem2_Elem1 = arg2.get(JAVA_LONG, 24); + long nestedStructArrayElem2_Elem2 = arg2.get(JAVA_LONG, 32); + + long longSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return longSum; + } + + public static MemorySegment add2LongStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + MemorySegment longStructSegmt = MemorySegment.allocateNative(structLayout, session); + long longStruct_Elem1 = arg1.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0); + long longStruct_Elem2 = arg1.get(JAVA_LONG, 8) + arg2.get(JAVA_LONG, 8); + longStructSegmt.set(JAVA_LONG, 0, longStruct_Elem1); + longStructSegmt.set(JAVA_LONG, 8, longStruct_Elem2); + return longStructSegmt; + } + + public static Addressable add2LongStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + long longSum_Elem1 = arg1Addr.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0); + long longSum_Elem2 = arg1Addr.get(JAVA_LONG, 8) + arg2.get(JAVA_LONG, 8); + arg1Addr.set(JAVA_LONG, 0, longSum_Elem1); + arg1Addr.set(JAVA_LONG, 8, longSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3LongStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2"), JAVA_LONG.withName("elem3")); + MemorySegment longStructSegmt = MemorySegment.allocateNative(structLayout, session); + long longStruct_Elem1 = arg1.get(JAVA_LONG, 0) + arg2.get(JAVA_LONG, 0); + long longStruct_Elem2 = arg1.get(JAVA_LONG, 8) + arg2.get(JAVA_LONG, 8); + long longStruct_Elem3 = arg1.get(JAVA_LONG, 16) + arg2.get(JAVA_LONG, 16); + longStructSegmt.set(JAVA_LONG, 0, longStruct_Elem1); + longStructSegmt.set(JAVA_LONG, 8, longStruct_Elem2); + longStructSegmt.set(JAVA_LONG, 16, longStruct_Elem3); + return longStructSegmt; + } + + public static float addFloatAndFloatsFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4); + return floatSum; + } + + public static float addFloatAnd5FloatsFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4) + + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_FLOAT, 12) + arg2.get(JAVA_FLOAT, 16); + return floatSum; + } + + public static float addFloatFromPointerAndFloatsFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + float floatSum = arg1Addr.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4); + return floatSum; + } + + public static Addressable addFloatFromPointerAndFloatsFromStruct_returnFloatPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + float floatSum = arg1Addr.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4); + arg1Addr.set(JAVA_FLOAT, 0, floatSum); + return arg1Addr; + } + + public static float addFloatAndFloatsFromStructPointer(float arg1, MemoryAddress arg2Addr) { + float floatSum = arg1 + arg2Addr.get(JAVA_FLOAT, 0) + arg2Addr.get(JAVA_FLOAT, 4); + return floatSum; + } + + public static float addFloatAndFloatsFromNestedStruct(float arg1, MemorySegment arg2) { + float nestedStructElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedStructElem2 = arg2.get(JAVA_FLOAT, 4); + float structElem2 = arg2.get(JAVA_FLOAT, 8); + + float floatSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromNestedStruct_reverseOrder(float arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedStructElem1 = arg2.get(JAVA_FLOAT, 4); + float nestedStructElem2 = arg2.get(JAVA_FLOAT, 8); + + float floatSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedFloatArray(float arg1, MemorySegment arg2) { + float nestedFloatArrayElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedFloatArrayElem2 = arg2.get(JAVA_FLOAT, 4); + float structElem2 = arg2.get(JAVA_FLOAT, 8); + + float floatSum = arg1 + nestedFloatArrayElem1 + nestedFloatArrayElem2 + structElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedFloatArray_reverseOrder(float arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedFloatArrayElem1 = arg2.get(JAVA_FLOAT, 4); + float nestedFloatArrayElem2 = arg2.get(JAVA_FLOAT, 8); + + float floatSum = arg1 + structElem1 + nestedFloatArrayElem1 + nestedFloatArrayElem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedStructArray(float arg1, MemorySegment arg2) { + float nestedStructArrayElem1_Elem1 = arg2.get(JAVA_FLOAT, 0); + float nestedStructArrayElem1_Elem2 = arg2.get(JAVA_FLOAT, 4); + float nestedStructArrayElem2_Elem1 = arg2.get(JAVA_FLOAT, 8); + float nestedStructArrayElem2_Elem2 = arg2.get(JAVA_FLOAT, 12); + float structElem2 = arg2.get(JAVA_FLOAT, 16); + + float floatSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return floatSum; + } + + public static float addFloatAndFloatsFromStructWithNestedStructArray_reverseOrder(float arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + float nestedStructArrayElem1_Elem1 = arg2.get(JAVA_FLOAT, 4); + float nestedStructArrayElem1_Elem2 = arg2.get(JAVA_FLOAT, 8); + float nestedStructArrayElem2_Elem1 = arg2.get(JAVA_FLOAT, 12); + float nestedStructArrayElem2_Elem2 = arg2.get(JAVA_FLOAT, 16); + + float floatSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return floatSum; + } + + public static MemorySegment add2FloatStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + MemorySegment floatStructSegmt = MemorySegment.allocateNative(structLayout, session); + float floatStruct_Elem1 = arg1.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0); + float floatStruct_Elem2 = arg1.get(JAVA_FLOAT, 4) + arg2.get(JAVA_FLOAT, 4); + floatStructSegmt.set(JAVA_FLOAT, 0, floatStruct_Elem1); + floatStructSegmt.set(JAVA_FLOAT, 4, floatStruct_Elem2); + return floatStructSegmt; + } + + public static Addressable add2FloatStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + float floatSum_Elem1 = arg1Addr.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0); + float floatSum_Elem2 = arg1Addr.get(JAVA_FLOAT, 4) + arg2.get(JAVA_FLOAT, 4); + arg1Addr.set(JAVA_FLOAT, 0, floatSum_Elem1); + arg1Addr.set(JAVA_FLOAT, 4, floatSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3FloatStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + MemorySegment floatStructSegmt = MemorySegment.allocateNative(structLayout, session); + float floatStruct_Elem1 = arg1.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 0); + float floatStruct_Elem2 = arg1.get(JAVA_FLOAT, 4) + arg2.get(JAVA_FLOAT, 4); + float floatStruct_Elem3 = arg1.get(JAVA_FLOAT, 8) + arg2.get(JAVA_FLOAT, 8); + floatStructSegmt.set(JAVA_FLOAT, 0, floatStruct_Elem1); + floatStructSegmt.set(JAVA_FLOAT, 4, floatStruct_Elem2); + floatStructSegmt.set(JAVA_FLOAT, 8, floatStruct_Elem3); + return floatStructSegmt; + } + + public static double addDoubleAndDoublesFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleFromPointerAndDoublesFromStruct(MemoryAddress arg1Addr, MemorySegment arg2) { + double doubleSum = arg1Addr.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static Addressable addDoubleFromPointerAndDoublesFromStruct_returnDoublePointer(MemoryAddress arg1Addr, MemorySegment arg2) { + double doubleSum = arg1Addr.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 8); + arg1Addr.set(JAVA_DOUBLE, 0, doubleSum); + return arg1Addr; + } + + public static double addDoubleAndDoublesFromStructPointer(double arg1, MemoryAddress arg2Addr) { + double doubleSum = arg1 + arg2Addr.get(JAVA_DOUBLE, 0) + arg2Addr.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleAndDoublesFromNestedStruct(double arg1, MemorySegment arg2) { + double nestedStructElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedStructElem2 = arg2.get(JAVA_DOUBLE, 8); + double structElem2 = arg2.get(JAVA_DOUBLE, 16); + + double doubleSum = arg1 + nestedStructElem1 + nestedStructElem2 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromNestedStruct_reverseOrder(double arg1, MemorySegment arg2) { + double structElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedStructElem1 = arg2.get(JAVA_DOUBLE, 8); + double nestedStructElem2 = arg2.get(JAVA_DOUBLE, 16); + + double doubleSum = arg1 + structElem1 + nestedStructElem1 + nestedStructElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedDoubleArray(double arg1, MemorySegment arg2) { + double nestedDoubleArrayElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedDoubleArrayElem2 = arg2.get(JAVA_DOUBLE, 8); + double structElem2 = arg2.get(JAVA_DOUBLE, 16); + + double doubleSum = arg1 + nestedDoubleArrayElem1 + nestedDoubleArrayElem2 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedDoubleArray_reverseOrder(double arg1, MemorySegment arg2) { + double structElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedDoubleArrayElem1 = arg2.get(JAVA_DOUBLE, 8); + double nestedDoubleArrayElem2 = arg2.get(JAVA_DOUBLE, 16); + + double doubleSum = arg1 + structElem1 + nestedDoubleArrayElem1 + nestedDoubleArrayElem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedStructArray(double arg1, MemorySegment arg2) { + double nestedStructArrayElem1_Elem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedStructArrayElem1_Elem2 = arg2.get(JAVA_DOUBLE, 8); + double nestedStructArrayElem2_Elem1 = arg2.get(JAVA_DOUBLE, 16); + double nestedStructArrayElem2_Elem2 = arg2.get(JAVA_DOUBLE, 24); + double structElem2 = arg2.get(JAVA_DOUBLE, 32); + + double doubleSum = arg1 + structElem2 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return doubleSum; + } + + public static double addDoubleAndDoublesFromStructWithNestedStructArray_reverseOrder(double arg1, MemorySegment arg2) { + double structElem1 = arg2.get(JAVA_DOUBLE, 0); + double nestedStructArrayElem1_Elem1 = arg2.get(JAVA_DOUBLE, 8); + double nestedStructArrayElem1_Elem2 = arg2.get(JAVA_DOUBLE, 16); + double nestedStructArrayElem2_Elem1 = arg2.get(JAVA_DOUBLE, 24); + double nestedStructArrayElem2_Elem2 = arg2.get(JAVA_DOUBLE, 32); + + double doubleSum = arg1 + structElem1 + + nestedStructArrayElem1_Elem1 + nestedStructArrayElem1_Elem2 + + nestedStructArrayElem2_Elem1 + nestedStructArrayElem2_Elem2; + return doubleSum; + } + + public static MemorySegment add2DoubleStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + MemorySegment doubleStructSegmt = MemorySegment.allocateNative(structLayout, session); + double doubleStruct_Elem1 = arg1.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0); + double doubleStruct_Elem2 = arg1.get(JAVA_DOUBLE, 8) + arg2.get(JAVA_DOUBLE, 8); + doubleStructSegmt.set(JAVA_DOUBLE, 0, doubleStruct_Elem1); + doubleStructSegmt.set(JAVA_DOUBLE, 8, doubleStruct_Elem2); + return doubleStructSegmt; + } + + public static Addressable add2DoubleStructs_returnStructPointer(MemoryAddress arg1Addr, MemorySegment arg2) { + double doubleSum_Elem1 = arg1Addr.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0); + double doubleSum_Elem2 = arg1Addr.get(JAVA_DOUBLE, 8) + arg2.get(JAVA_DOUBLE, 8); + arg1Addr.set(JAVA_DOUBLE, 0, doubleSum_Elem1); + arg1Addr.set(JAVA_DOUBLE, 8, doubleSum_Elem2); + return arg1Addr; + } + + public static MemorySegment add3DoubleStructs_returnStruct(MemorySegment arg1, MemorySegment arg2) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2"), JAVA_DOUBLE.withName("elem3")); + MemorySegment doubleStructSegmt = MemorySegment.allocateNative(structLayout, session); + double doubleStruct_Elem1 = arg1.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_DOUBLE, 0); + double doubleStruct_Elem2 = arg1.get(JAVA_DOUBLE, 8) + arg2.get(JAVA_DOUBLE, 8); + double doubleStruct_Elem3 = arg1.get(JAVA_DOUBLE, 16) + arg2.get(JAVA_DOUBLE, 16); + doubleStructSegmt.set(JAVA_DOUBLE, 0, doubleStruct_Elem1); + doubleStructSegmt.set(JAVA_DOUBLE, 8, doubleStruct_Elem2); + doubleStructSegmt.set(JAVA_DOUBLE, 16, doubleStruct_Elem3); + return doubleStructSegmt; + } + + public static int addIntAndIntShortFromStruct(int arg1, MemorySegment arg2) { + int intSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_SHORT, 4); + return intSum; + } + + public static int addIntAndShortIntFromStruct(int arg1, MemorySegment arg2) { + int intSum = arg1 + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_INT, 4); + return intSum; + } + + public static long addIntAndIntLongFromStruct(int arg1, MemorySegment arg2) { + long longSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_LONG, 8); + return longSum; + } + + public static long addIntAndLongIntFromStruct(int arg1, MemorySegment arg2) { + long longSum = arg1 + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_INT, 8); + return longSum; + } + + public static double addDoubleAndIntDoubleFromStruct(double arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + /* The size of [int, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + double structElem2 = (isAixOS) ? arg2.get(JAVA_DOUBLE.withBitAlignment(32), 4) : arg2.get(JAVA_DOUBLE, 8); + double doubleSum = arg1 + structElem1 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoubleIntFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_INT, 8); + return doubleSum; + } + + public static double addDoubleAndFloatDoubleFromStruct(double arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + double structElem2 = (isAixOS) ? arg2.get(JAVA_DOUBLE.withBitAlignment(32), 4) : arg2.get(JAVA_DOUBLE, 8); + double doubleSum = arg1 + structElem1 + structElem2; + return doubleSum; + } + + public static double addDoubleAndDoubleFloatFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_FLOAT, 8); + return doubleSum; + } + + public static double addDoubleAnd2FloatsDoubleFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleAndDouble2FloatsFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_FLOAT, 12); + return doubleSum; + } + + public static float addFloatAndInt2FloatsFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_FLOAT, 4) + arg2.get(JAVA_FLOAT, 8); + return floatSum; + } + + public static float addFloatAndFloatIntFloatFromStruct(float arg1, MemorySegment arg2) { + float structElem2 = Integer.valueOf(arg2.get(JAVA_INT, 4)).floatValue(); + float floatSum = arg1 + arg2.get(JAVA_FLOAT, 0) + structElem2 + arg2.get(JAVA_FLOAT, 8); + return floatSum; + } + + public static double addDoubleAndIntFloatDoubleFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_FLOAT, 4) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleAndFloatIntDoubleFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_INT, 4) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static double addDoubleAndLongDoubleFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_LONG, 0) + arg2.get(JAVA_DOUBLE, 8); + return doubleSum; + } + + public static float addFloatAndInt3FloatsFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_FLOAT, 4) + + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_FLOAT, 12); + return floatSum; + } + + public static long addLongAndLong2FloatsFromStruct(long arg1, MemorySegment arg2) { + long structElem1 = arg2.get(JAVA_LONG, 0); + long structElem2 = Float.valueOf(arg2.get(JAVA_FLOAT, 8)).longValue(); + long structElem3 = Float.valueOf(arg2.get(JAVA_FLOAT, 12)).longValue(); + long longSum = arg1 + structElem1 + structElem2 + structElem3; + return longSum; + } + + public static float addFloatAnd3FloatsIntFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_FLOAT, 0) + arg2.get(JAVA_FLOAT, 4) + + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_INT, 12); + return floatSum; + } + + public static long addLongAndFloatLongFromStruct(long arg1, MemorySegment arg2) { + long structElem1 = Float.valueOf(arg2.get(JAVA_FLOAT, 0)).longValue(); + long structElem2 = arg2.get(JAVA_LONG, 8); + long longSum = arg1 + structElem1 + structElem2; + return longSum; + } + + public static double addDoubleAndDoubleFloatIntFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_FLOAT, 8) + arg2.get(JAVA_INT, 12); + return doubleSum; + } + + public static double addDoubleAndDoubleLongFromStruct(double arg1, MemorySegment arg2) { + double doubleSum = arg1 + arg2.get(JAVA_DOUBLE, 0) + arg2.get(JAVA_LONG, 8); + return doubleSum; + } + + public static long addLongAnd2FloatsLongFromStruct(long arg1, MemorySegment arg2) { + long structElem1 = Float.valueOf(arg2.get(JAVA_FLOAT, 0)).longValue(); + long structElem2 = Float.valueOf(arg2.get(JAVA_FLOAT, 4)).longValue(); + long structElem3 = arg2.get(JAVA_LONG, 8); + long longSum = arg1 + structElem1 + structElem2 + structElem3; + return longSum; + } + + public static short addShortAnd3ShortsCharFromStruct(short arg1, MemorySegment arg2) { + short shortSum = (short)(arg1 + arg2.get(JAVA_SHORT, 0) + arg2.get(JAVA_SHORT, 2) + + arg2.get(JAVA_SHORT, 4) + arg2.get(JAVA_CHAR, 6)); + return shortSum; + } + + public static float addFloatAndIntFloatIntFloatFromStruct(float arg1, MemorySegment arg2) { + float floatSum = arg1 + arg2.get(JAVA_INT, 0) + arg2.get(JAVA_FLOAT, 4)+ arg2.get(JAVA_INT, 8) + arg2.get(JAVA_FLOAT, 12); + return floatSum; + } + + public static double addDoubleAndIntDoubleFloatFromStruct(double arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + /* The size of [int, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + double structElem2 = (isAixOS) ? arg2.get(JAVA_DOUBLE.withBitAlignment(32), 4) : arg2.get(JAVA_DOUBLE, 8); + float structElem3 = arg2.get(JAVA_FLOAT, isAixOS ? 12 : 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static double addDoubleAndFloatDoubleIntFromStruct(double arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + /* The size of [float, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + double structElem2 = (isAixOS) ? arg2.get(JAVA_DOUBLE.withBitAlignment(32), 4) : arg2.get(JAVA_DOUBLE, 8); + int structElem3 = arg2.get(JAVA_INT, isAixOS ? 12 : 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static double addDoubleAndIntDoubleIntFromStruct(double arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + /* The size of [int, double, int] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + double structElem2 = (isAixOS) ? arg2.get(JAVA_DOUBLE.withBitAlignment(32), 4) : arg2.get(JAVA_DOUBLE, 8); + int structElem3 = arg2.get(JAVA_INT, isAixOS ? 12 : 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static double addDoubleAndFloatDoubleFloatFromStruct(double arg1, MemorySegment arg2) { + float structElem1 = arg2.get(JAVA_FLOAT, 0); + /* The size of [float, double, float] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 20 bytes with padding on other platforms. + */ + double structElem2 = (isAixOS) ? arg2.get(JAVA_DOUBLE.withBitAlignment(32), 4) : arg2.get(JAVA_DOUBLE, 8); + float structElem3 = arg2.get(JAVA_FLOAT, isAixOS ? 12 : 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static double addDoubleAndIntDoubleLongFromStruct(double arg1, MemorySegment arg2) { + int structElem1 = arg2.get(JAVA_INT, 0); + /* The size of [int, double, long] on AIX/PPC 64-bit is 16 bytes without padding by default + * while the same struct is 24 bytes with padding on other platforms. + */ + double structElem2 = (isAixOS) ? arg2.get(JAVA_DOUBLE.withBitAlignment(32), 4) : arg2.get(JAVA_DOUBLE, 8); + double structElem3 = (isAixOS) ? arg2.get(JAVA_LONG.withBitAlignment(32), 12) : arg2.get(JAVA_LONG, 16); + double doubleSum = arg1 + structElem1 + structElem2 + structElem3; + return doubleSum; + } + + public static MemorySegment return254BytesFromStruct() { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(254, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + MemorySegment byteArrStruSegment = MemorySegment.allocateNative(structLayout, session); + + for (int i = 0; i < 254; i++) { + byteArrStruSegment.set(JAVA_BYTE, i, (byte)i); + } + return byteArrStruSegment; + } + + public static MemorySegment return4KBytesFromStruct() { + SequenceLayout byteArray = MemoryLayout.sequenceLayout(4096, JAVA_BYTE); + GroupLayout structLayout = MemoryLayout.structLayout(byteArray); + MemorySegment byteArrStruSegment = MemorySegment.allocateNative(structLayout, session); + + for (int i = 0; i < 4096; i++) { + byteArrStruSegment.set(JAVA_BYTE, i, (byte)i); + } + return byteArrStruSegment; + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/ApiTests.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/ApiTests.java new file mode 100644 index 00000000000..028a2b6e3e0 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/ApiTests.java @@ -0,0 +1,903 @@ +/******************************************************************************* + * Copyright (c) 2022, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.valist; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; +import static org.testng.Assert.fail; + +import java.lang.invoke.VarHandle; +import java.util.NoSuchElementException; + +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.VaList; +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.VaList.Builder; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for the vararg list in VaList API specific cases. + */ +@Test(groups = { "level.sanity" }) +public class ApiTests { + private static String osName = System.getProperty("os.name").toLowerCase(); + private static String arch = System.getProperty("os.arch").toLowerCase(); + private static boolean isAixOS = osName.contains("aix"); + private static boolean isWinOS = osName.contains("win"); + private static boolean isMacOsAarch64 = osName.contains("mac") && arch.contains("aarch64"); + private static boolean isSysVPPC64le = osName.contains("linux") && arch.contains("ppc64"); + + @Test + public void test_emptyVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList emptyVaList = VaList.empty(); + /* As specified in the implemention of OpenJDK, a NULL address is set to + * the empty va_list on Windows/x86_64, MacOS/Aarch64, Linux/ppc64le and + * AIX/ppc64 while the va_list without any argument is created on a fixed + * address on other platforms. + */ + if (isWinOS || isMacOsAarch64 || isSysVPPC64le || isAixOS) { + Assert.assertEquals(emptyVaList.address(), MemoryAddress.NULL); + } else { + Assert.assertNotEquals(emptyVaList.address(), MemoryAddress.NULL); + } + } + } + + @Test + public void test_vaListSession() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 100), session); + MemorySession vaListSession = vaList.session(); + Assert.assertEquals(vaListSession, session); + } + } + + @Test + public void test_checkIntVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_INT, 900), session); + + Assert.assertEquals(vaList.nextVarg(JAVA_INT), 700); /* the 1st argument */ + Assert.assertEquals(vaList.nextVarg(JAVA_INT), 800); /* the 2nd argument */ + Assert.assertEquals(vaList.nextVarg(JAVA_INT), 900); /* the 3rd argument */ + } + } + + @Test + public void test_checkLongVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_LONG, 700000L) + .addVarg(JAVA_LONG, 800000L) + .addVarg(JAVA_LONG, 900000L), session); + + Assert.assertEquals(vaList.nextVarg(JAVA_LONG), 700000L); /* the 1st argument */ + Assert.assertEquals(vaList.nextVarg(JAVA_LONG), 800000L); /* the 2nd argument */ + Assert.assertEquals(vaList.nextVarg(JAVA_LONG), 900000L); /* the 3rd argument */ + } + } + + @Test + public void test_checkDoubleVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_DOUBLE, 111150.1001D) + .addVarg(JAVA_DOUBLE, 111160.2002D) + .addVarg(JAVA_DOUBLE, 111170.1001D), session); + + Assert.assertEquals(vaList.nextVarg(JAVA_DOUBLE), 111150.1001D, 0.0001D); /* the 1st argument */ + Assert.assertEquals(vaList.nextVarg(JAVA_DOUBLE), 111160.2002D, 0.0001D); /* the 2nd argument */ + Assert.assertEquals(vaList.nextVarg(JAVA_DOUBLE), 111170.1001D, 0.0001D); /* the 3rd argument */ + } + } + + @Test + public void test_checkIntPtrVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt1 = allocator.allocate(JAVA_INT, 700); + MemorySegment intSegmt2 = allocator.allocate(JAVA_INT, 800); + MemorySegment intSegmt3 = allocator.allocate(JAVA_INT, 900); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, intSegmt1.address()) + .addVarg(ADDRESS, intSegmt2.address()) + .addVarg(ADDRESS, intSegmt3.address()), session); + + Assert.assertEquals(vaList.nextVarg(ADDRESS), intSegmt1.address()); /* the 1st argument */ + Assert.assertEquals(vaList.nextVarg(ADDRESS), intSegmt2.address()); /* the 2nd argument */ + Assert.assertEquals(vaList.nextVarg(ADDRESS), intSegmt3.address()); /* the 3rd argument */ + } + } + + @Test + public void test_checkLongPtrVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt1 = allocator.allocate(JAVA_LONG, 700000L); + MemorySegment longSegmt2 = allocator.allocate(JAVA_LONG, 800000L); + MemorySegment longSegmt3 = allocator.allocate(JAVA_LONG, 900000L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, longSegmt1.address()) + .addVarg(ADDRESS, longSegmt2.address()) + .addVarg(ADDRESS, longSegmt3.address()), session); + + Assert.assertEquals(vaList.nextVarg(ADDRESS), longSegmt1.address()); /* the 1st argument */ + Assert.assertEquals(vaList.nextVarg(ADDRESS), longSegmt2.address()); /* the 2nd argument */ + Assert.assertEquals(vaList.nextVarg(ADDRESS), longSegmt3.address()); /* the 3rd argument */ + } + } + + @Test + public void test_checkDoublePtrVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt1 = allocator.allocate(JAVA_DOUBLE, 111150.1001D); + MemorySegment doubleSegmt2 = allocator.allocate(JAVA_DOUBLE, 111160.2002D); + MemorySegment doubleSegmt3 = allocator.allocate(JAVA_DOUBLE, 111170.1001D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, doubleSegmt1.address()) + .addVarg(ADDRESS, doubleSegmt2.address()) + .addVarg(ADDRESS, doubleSegmt3.address()), session); + + Assert.assertEquals(vaList.nextVarg(ADDRESS), doubleSegmt1.address()); /* the 1st argument */ + Assert.assertEquals(vaList.nextVarg(ADDRESS), doubleSegmt2.address()); /* the 2nd argument */ + Assert.assertEquals(vaList.nextVarg(ADDRESS), doubleSegmt3.address()); /* the 3rd argument */ + } + } + + @Test + public void test_checkIntStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2244668); + intHandle2.set(structSegmt2, 1133557); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + + MemorySegment argSegmt = vaList.nextVarg(structLayout, allocator); + Assert.assertEquals(intHandle1.get(argSegmt), 1122333); /* the 1st element of the 1st struct argument */ + Assert.assertEquals(intHandle2.get(argSegmt), 4455666); /* the 2nd element of the 1st struct argument */ + argSegmt = vaList.nextVarg(structLayout, allocator); + Assert.assertEquals(intHandle1.get(argSegmt), 2244668); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals(intHandle2.get(argSegmt), 1133557); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test + public void test_checkLongStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 6677889911L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 2233445566L); + longHandle2.set(structSegmt2, 7788991122L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + + MemorySegment argSegmt = vaList.nextVarg(structLayout, allocator); + Assert.assertEquals(longHandle1.get(argSegmt), 1122334455L); /* the 1st element of the 1st struct argument */ + Assert.assertEquals(longHandle2.get(argSegmt), 6677889911L); /* the 2nd element of the 1st struct argument */ + argSegmt = vaList.nextVarg(structLayout, allocator); + Assert.assertEquals(longHandle1.get(argSegmt), 2233445566L); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals(longHandle2.get(argSegmt), 7788991122L); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test + public void test_checkLongStructVaListFromPrefixAllocator() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 6677889911L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1), session); + + MemorySegment structSegmt2 = MemorySegment.allocateNative(structLayout, session); + MemorySegment argSegmt = vaList.nextVarg(structLayout, SegmentAllocator.prefixAllocator(structSegmt2)); + Assert.assertEquals(longHandle1.get(argSegmt), 1122334455L); /* the 1st element of the 1st struct argument */ + Assert.assertEquals(longHandle2.get(argSegmt), 6677889911L); /* the 2nd element of the 1st struct argument */ + Assert.assertEquals(longHandle1.get(structSegmt2), 1122334455L); /* the 1st element of the 1st struct argument */ + Assert.assertEquals(longHandle2.get(structSegmt2), 6677889911L); /* the 2nd element of the 1st struct argument */ + } + } + + @Test + public void test_checkDoubleStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 111150.1001D); + doubleHandle2.set(structSegmt1, 111160.2002D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 111170.1001D); + doubleHandle2.set(structSegmt2, 111180.2002D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + + MemorySegment argSegmt = vaList.nextVarg(structLayout, allocator); + Assert.assertEquals((double)doubleHandle1.get(argSegmt), 111150.1001D, 0.0001D); /* the 1st element of the 1st struct argument */ + Assert.assertEquals((double)doubleHandle2.get(argSegmt), 111160.2002D, 0.0001D); /* the 2nd element of the 1st struct argument */ + argSegmt = vaList.nextVarg(structLayout, allocator); + Assert.assertEquals((double)doubleHandle1.get(argSegmt), 111170.1001D, 0.0001D); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals((double)doubleHandle2.get(argSegmt), 111180.2002D, 0.0001D); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test + public void test_copyIntVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_INT, 900), session); + VaList resultVaList = vaList.copy(); + + Assert.assertEquals(resultVaList.nextVarg(JAVA_INT), 700); /* the 1st argument */ + Assert.assertEquals(resultVaList.nextVarg(JAVA_INT), 800); /* the 2nd argument */ + Assert.assertEquals(resultVaList.nextVarg(JAVA_INT), 900); /* the 3rd argument */ + } + } + + @Test + public void test_copyLongVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_LONG, 700000L) + .addVarg(JAVA_LONG, 800000L) + .addVarg(JAVA_LONG, 900000L), session); + VaList resultVaList = vaList.copy(); + + Assert.assertEquals(resultVaList.nextVarg(JAVA_LONG), 700000L); /* the 1st argument */ + Assert.assertEquals(resultVaList.nextVarg(JAVA_LONG), 800000L); /* the 2nd argument */ + Assert.assertEquals(resultVaList.nextVarg(JAVA_LONG), 900000L); /* the 3rd argument */ + } + } + + @Test + public void test_copyDoubleVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_DOUBLE, 111150.1001D) + .addVarg(JAVA_DOUBLE, 111160.2002D) + .addVarg(JAVA_DOUBLE, 111170.1001D), session); + VaList resultVaList = vaList.copy(); + + Assert.assertEquals(resultVaList.nextVarg(JAVA_DOUBLE), 111150.1001D, 0001D); /* the 1st argument */ + Assert.assertEquals(resultVaList.nextVarg(JAVA_DOUBLE), 111160.2002D, 0001D); /* the 2nd argument */ + Assert.assertEquals(resultVaList.nextVarg(JAVA_DOUBLE), 111170.1001D, 0001D); /* the 3rd argument */ + } + } + + @Test + public void test_copyIntPtrVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt1 = allocator.allocate(JAVA_INT, 700); + MemorySegment intSegmt2 = allocator.allocate(JAVA_INT, 800); + MemorySegment intSegmt3 = allocator.allocate(JAVA_INT, 900); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, intSegmt1.address()) + .addVarg(ADDRESS, intSegmt2.address()) + .addVarg(ADDRESS, intSegmt3.address()), session); + VaList resultVaList = vaList.copy(); + + Assert.assertEquals(resultVaList.nextVarg(ADDRESS), intSegmt1.address()); /* the 1st argument */ + Assert.assertEquals(resultVaList.nextVarg(ADDRESS), intSegmt2.address()); /* the 2nd argument */ + Assert.assertEquals(resultVaList.nextVarg(ADDRESS), intSegmt3.address()); /* the 3rd argument */ + } + } + + @Test + public void test_copyLongPtrVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt1 = allocator.allocate(JAVA_LONG, 700000L); + MemorySegment longSegmt2 = allocator.allocate(JAVA_LONG, 800000L); + MemorySegment longSegmt3 = allocator.allocate(JAVA_LONG, 900000L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, longSegmt1.address()) + .addVarg(ADDRESS, longSegmt2.address()) + .addVarg(ADDRESS, longSegmt3.address()), session); + VaList resultVaList = vaList.copy(); + + Assert.assertEquals(resultVaList.nextVarg(ADDRESS), longSegmt1.address()); /* the 1st argument */ + Assert.assertEquals(resultVaList.nextVarg(ADDRESS), longSegmt2.address()); /* the 2nd argument */ + Assert.assertEquals(resultVaList.nextVarg(ADDRESS), longSegmt3.address()); /* the 3rd argument */ + } + } + + @Test + public void test_copyDoublePtrVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt1 = allocator.allocate(JAVA_DOUBLE, 111150.1001D); + MemorySegment doubleSegmt2 = allocator.allocate(JAVA_DOUBLE, 111160.2002D); + MemorySegment doubleSegmt3 = allocator.allocate(JAVA_DOUBLE, 111170.1001D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, doubleSegmt1.address()) + .addVarg(ADDRESS, doubleSegmt2.address()) + .addVarg(ADDRESS, doubleSegmt3.address()), session); + VaList resultVaList = vaList.copy(); + + Assert.assertEquals(resultVaList.nextVarg(ADDRESS), doubleSegmt1.address()); /* the 1st argument */ + Assert.assertEquals(resultVaList.nextVarg(ADDRESS), doubleSegmt2.address()); /* the 2nd argument */ + Assert.assertEquals(resultVaList.nextVarg(ADDRESS), doubleSegmt3.address()); /* the 3rd argument */ + } + } + + @Test + public void test_copyIntStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2244668); + intHandle2.set(structSegmt2, 1133557); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + VaList resultVaList = vaList.copy(); + + MemorySegment resultArgSegmt = resultVaList.nextVarg(structLayout, allocator); + Assert.assertEquals(intHandle1.get(resultArgSegmt), 1122333); /* the 1st element of the 1st struct argument */ + Assert.assertEquals(intHandle2.get(resultArgSegmt), 4455666); /* the 2nd element of the 1st struct argument */ + resultArgSegmt = resultVaList.nextVarg(structLayout, allocator); + Assert.assertEquals(intHandle1.get(resultArgSegmt), 2244668); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals(intHandle2.get(resultArgSegmt), 1133557); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test + public void test_copyLongStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 6677889911L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 2233445566L); + longHandle2.set(structSegmt2, 7788991122L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + VaList resultVaList = vaList.copy(); + + MemorySegment resultArgSegmt = resultVaList.nextVarg(structLayout, allocator); + Assert.assertEquals(longHandle1.get(resultArgSegmt), 1122334455L); /* the 1st element of the 1st struct argument */ + Assert.assertEquals(longHandle2.get(resultArgSegmt), 6677889911L); /* the 2nd element of the 1st struct argument */ + resultArgSegmt = resultVaList.nextVarg(structLayout, allocator); + Assert.assertEquals(longHandle1.get(resultArgSegmt), 2233445566L); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals(longHandle2.get(resultArgSegmt), 7788991122L); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test + public void test_copyDoubleStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 111150.1001D); + doubleHandle2.set(structSegmt1, 111160.2002D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 111170.1001D); + doubleHandle2.set(structSegmt2, 111180.2002D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + VaList resultVaList = vaList.copy(); + + MemorySegment resultArgSegmt = resultVaList.nextVarg(structLayout, allocator); + Assert.assertEquals((double)doubleHandle1.get(resultArgSegmt), 111150.1001D, 0.0001D); /* the 1st element of the 1st struct argument */ + Assert.assertEquals((double)doubleHandle2.get(resultArgSegmt), 111160.2002D, 0.0001D); /* the 2nd element of the 1st struct argument */ + resultArgSegmt = resultVaList.nextVarg(structLayout, allocator); + Assert.assertEquals((double)doubleHandle1.get(resultArgSegmt), 111170.1001D, 0.0001D); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals((double)doubleHandle2.get(resultArgSegmt), 111180.2002D, 0.0001D); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test(expectedExceptions = NoSuchElementException.class, expectedExceptionsMessageRegExp = "No such element.*") + public void test_NoMoreNextArg_IntVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_INT, 900), session); + + vaList.nextVarg(JAVA_INT); /* the 1st argument */ + vaList.nextVarg(JAVA_INT); /* the 2nd argument */ + vaList.nextVarg(JAVA_INT); /* the 3rd argument */ + + /* An exception is thrown as there is no more argument in VaList */ + vaList.nextVarg(JAVA_INT); + fail("Failed to throw out NoSuchElementException when nextVarg() exceeds the memory region of VaList"); + } + } + + @Test + public void test_createIntVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_INT, 900), session); + VaList newVaList = VaList.ofAddress(vaList.address(), session); + + Assert.assertEquals(newVaList.nextVarg(JAVA_INT), 700); /* the 1st argument */ + Assert.assertEquals(newVaList.nextVarg(JAVA_INT), 800); /* the 2nd argument */ + Assert.assertEquals(newVaList.nextVarg(JAVA_INT), 900); /* the 3rd argument */ + } + } + + @Test + public void test_createLongVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_LONG, 700000L) + .addVarg(JAVA_LONG, 800000L) + .addVarg(JAVA_LONG, 900000L), session); + VaList newVaList = VaList.ofAddress(vaList.address(), session); + + Assert.assertEquals(newVaList.nextVarg(JAVA_LONG), 700000L); /* the 1st argument */ + Assert.assertEquals(newVaList.nextVarg(JAVA_LONG), 800000L); /* the 2nd argument */ + Assert.assertEquals(newVaList.nextVarg(JAVA_LONG), 900000L); /* the 3rd argument */ + } + } + + @Test + public void test_createDoubleVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_DOUBLE, 111150.1001D) + .addVarg(JAVA_DOUBLE, 111160.2002D) + .addVarg(JAVA_DOUBLE, 111170.1001D), session); + VaList newVaList = VaList.ofAddress(vaList.address(), session); + + Assert.assertEquals(newVaList.nextVarg(JAVA_DOUBLE), 111150.1001D, 0.0001D); /* the 1st argument */ + Assert.assertEquals(newVaList.nextVarg(JAVA_DOUBLE), 111160.2002D, 0.0001D); /* the 2nd argument */ + Assert.assertEquals(newVaList.nextVarg(JAVA_DOUBLE), 111170.1001D, 0.0001D); /* the 3rd argument */ + } + } + + @Test + public void test_createIntPtrVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt1 = allocator.allocate(JAVA_INT, 700); + MemorySegment intSegmt2 = allocator.allocate(JAVA_INT, 800); + MemorySegment intSegmt3 = allocator.allocate(JAVA_INT, 900); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, intSegmt1.address()) + .addVarg(ADDRESS, intSegmt2.address()) + .addVarg(ADDRESS, intSegmt3.address()), session); + VaList newVaList = VaList.ofAddress(vaList.address(), session); + + MemoryAddress resultAddr = newVaList.nextVarg(ADDRESS); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 700); /* the 1st argument */ + resultAddr = newVaList.nextVarg(ADDRESS); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 800); /* the 2nd argument */ + resultAddr = newVaList.nextVarg(ADDRESS); + Assert.assertEquals(resultAddr.get(JAVA_INT, 0), 900); /* the 3rd argument */ + } + } + + @Test + public void test_createLongPtrVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt1 = allocator.allocate(JAVA_LONG, 700000L); + MemorySegment longSegmt2 = allocator.allocate(JAVA_LONG, 800000L); + MemorySegment longSegmt3 = allocator.allocate(JAVA_LONG, 900000L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, longSegmt1.address()) + .addVarg(ADDRESS, longSegmt2.address()) + .addVarg(ADDRESS, longSegmt3.address()), session); + VaList newVaList = VaList.ofAddress(vaList.address(), session); + + MemoryAddress resultAddr = newVaList.nextVarg(ADDRESS); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 700000L); /* the 1st argument */ + resultAddr = newVaList.nextVarg(ADDRESS); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 800000L); /* the 2nd argument */ + resultAddr = newVaList.nextVarg(ADDRESS); + Assert.assertEquals(resultAddr.get(JAVA_LONG, 0), 900000L); /* the 3rd argument */ + } + } + + @Test + public void test_createDoublePtrVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt1 = allocator.allocate(JAVA_DOUBLE, 111150.1001D); + MemorySegment doubleSegmt2 = allocator.allocate(JAVA_DOUBLE, 111160.2002D); + MemorySegment doubleSegmt3 = allocator.allocate(JAVA_DOUBLE, 111170.1001D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, doubleSegmt1.address()) + .addVarg(ADDRESS, doubleSegmt2.address()) + .addVarg(ADDRESS, doubleSegmt3.address()), session); + VaList newVaList = VaList.ofAddress(vaList.address(), session); + + MemoryAddress resultAddr = newVaList.nextVarg(ADDRESS); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 111150.1001D, 0.0001D); /* the 1st argument */ + resultAddr = newVaList.nextVarg(ADDRESS); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 111160.2002D, 0.0001D); /* the 2nd argument */ + resultAddr = newVaList.nextVarg(ADDRESS); + Assert.assertEquals(resultAddr.get(JAVA_DOUBLE, 0), 111170.1001D, 0.0001D); /* the 3rd argument */ + } + } + + @Test(expectedExceptions = NoSuchElementException.class, expectedExceptionsMessageRegExp = "No such element.*") + public void test_NoMoreNextArg_IntStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2244668); + intHandle2.set(structSegmt2, 1133557); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + + vaList.nextVarg(structLayout, allocator); /* the 1st struct argument */ + vaList.nextVarg(structLayout, allocator); /* the 2nd struct argument */ + + /* An exception is thrown as there is no more argument in VaList */ + vaList.nextVarg(structLayout, allocator); + fail("Failed to throw out NoSuchElementException when nextVarg() exceeds the memory region of VaList"); + } + } + + @Test + public void test_createIntStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2244668); + intHandle2.set(structSegmt2, 1133557); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + VaList newVaList = VaList.ofAddress(vaList.address(), session); + + MemorySegment newArgSegmt = newVaList.nextVarg(structLayout, allocator); + Assert.assertEquals(intHandle1.get(newArgSegmt), 1122333); /* the 1st element of the 1st struct argument */ + Assert.assertEquals(intHandle2.get(newArgSegmt), 4455666); /* the 2nd element of the 1st struct argument */ + newArgSegmt = newVaList.nextVarg(structLayout, allocator); + Assert.assertEquals(intHandle1.get(newArgSegmt), 2244668); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals(intHandle2.get(newArgSegmt), 1133557); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test + public void test_createLongStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 6677889911L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 2233445566L); + longHandle2.set(structSegmt2, 7788991122L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + VaList newVaList = VaList.ofAddress(vaList.address(), session); + + MemorySegment newArgSegmt = newVaList.nextVarg(structLayout, allocator); + Assert.assertEquals(longHandle1.get(newArgSegmt), 1122334455L); /* the 1st element of the 1st struct argument */ + Assert.assertEquals(longHandle2.get(newArgSegmt), 6677889911L); /* the 2nd element of the 1st struct argument */ + newArgSegmt = newVaList.nextVarg(structLayout, allocator); + Assert.assertEquals(longHandle1.get(newArgSegmt), 2233445566L); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals(longHandle2.get(newArgSegmt), 7788991122L); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test + public void test_createDoubleStructVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11150.1001D); + doubleHandle2.set(structSegmt1, 11160.2002D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 11170.1001D); + doubleHandle2.set(structSegmt2, 11180.2002D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + VaList newVaList = VaList.ofAddress(vaList.address(), session); + + MemorySegment newArgSegmt = newVaList.nextVarg(structLayout, allocator); + Assert.assertEquals((double)doubleHandle1.get(newArgSegmt), 11150.1001D, 0.0001D); /* the 1st element of the 1st struct argument */ + Assert.assertEquals((double)doubleHandle2.get(newArgSegmt), 11160.2002D, 0.0001D); /* the 2nd element of the 1st struct argument */ + newArgSegmt = newVaList.nextVarg(structLayout, allocator); + Assert.assertEquals((double)doubleHandle1.get(newArgSegmt), 11170.1001D, 0.0001D); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals((double)doubleHandle2.get(newArgSegmt), 11180.2002D, 0.0001D); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test(expectedExceptions = NoSuchElementException.class, expectedExceptionsMessageRegExp = "No such element.*") + public void test_NoMoreSkippedArg_IntArgOfVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_INT, 900) + .addVarg(JAVA_INT, 1000), session); + vaList.skip(JAVA_INT, JAVA_INT, JAVA_INT, JAVA_INT); /* Skip over all arguments in VaList */ + + /* An exception is thrown as there is no more argument in VaList */ + vaList.skip(JAVA_INT); + fail("Failed to throw out NoSuchElementException when skip() exceeds the memory region of VaList"); + } + } + + @Test + public void test_skipIntArgOfVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_INT, 900) + .addVarg(JAVA_INT, 1000), session); + vaList.skip(JAVA_INT); + Assert.assertEquals(vaList.nextVarg(JAVA_INT), 800); /* the 2nd argument */ + vaList.skip(JAVA_INT); + Assert.assertEquals(vaList.nextVarg(JAVA_INT), 1000); /* the 4th argument */ + } + } + + @Test + public void test_skipLongArgOfVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_LONG, 700000L) + .addVarg(JAVA_LONG, 800000L) + .addVarg(JAVA_LONG, 900000L) + .addVarg(JAVA_LONG, 1000000L), session); + vaList.skip(JAVA_LONG, JAVA_LONG); + Assert.assertEquals(vaList.nextVarg(JAVA_LONG), 900000L); /* the 3rd argument */ + } + } + + @Test + public void test_skipDoubleArgOfVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_DOUBLE, 111150.1001D) + .addVarg(JAVA_DOUBLE, 111160.2002D) + .addVarg(JAVA_DOUBLE, 111170.1001D) + .addVarg(JAVA_DOUBLE, 111180.2002D), session); + vaList.skip(JAVA_DOUBLE, JAVA_DOUBLE, JAVA_DOUBLE); + Assert.assertEquals(vaList.nextVarg(JAVA_DOUBLE), 111180.2002D, 0.0001D); /* the 4th argument */ + } + } + + @Test + public void test_skipIntPtrArgOfVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt1 = allocator.allocate(JAVA_INT, 700); + MemorySegment intSegmt2 = allocator.allocate(JAVA_INT, 800); + MemorySegment intSegmt3 = allocator.allocate(JAVA_INT, 900); + MemorySegment intSegmt4 = allocator.allocate(JAVA_INT, 1000); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, intSegmt1.address()) + .addVarg(ADDRESS, intSegmt2.address()) + .addVarg(ADDRESS, intSegmt3.address()) + .addVarg(ADDRESS, intSegmt4.address()), session); + vaList.skip(ADDRESS); + Assert.assertEquals(vaList.nextVarg(ADDRESS), intSegmt2.address()); /* the 2nd argument */ + } + } + + @Test + public void test_skipLongPtrArgOfVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt1 = allocator.allocate(JAVA_LONG, 700000L); + MemorySegment longSegmt2 = allocator.allocate(JAVA_LONG, 800000L); + MemorySegment longSegmt3 = allocator.allocate(JAVA_LONG, 900000L); + MemorySegment longSegmt4 = allocator.allocate(JAVA_LONG, 1000000L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, longSegmt1.address()) + .addVarg(ADDRESS, longSegmt2.address()) + .addVarg(ADDRESS, longSegmt3.address()) + .addVarg(ADDRESS, longSegmt4.address()), session); + vaList.skip(ADDRESS, ADDRESS); + Assert.assertEquals(vaList.nextVarg(ADDRESS), longSegmt3.address()); /* the 3rd argument */ + } + } + + @Test + public void test_skipDoublePtrArgOfVaList() throws Throwable { + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt1 = allocator.allocate(JAVA_DOUBLE, 111150.1001D); + MemorySegment doubleSegmt2 = allocator.allocate(JAVA_DOUBLE, 111160.2002D); + MemorySegment doubleSegmt3 = allocator.allocate(JAVA_DOUBLE, 111170.1001D); + MemorySegment doubleSegmt4 = allocator.allocate(JAVA_DOUBLE, 111180.1002D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, doubleSegmt1.address()) + .addVarg(ADDRESS, doubleSegmt2.address()) + .addVarg(ADDRESS, doubleSegmt3.address()) + .addVarg(ADDRESS, doubleSegmt4.address()), session); + vaList.skip(ADDRESS, ADDRESS, ADDRESS); + Assert.assertEquals(vaList.nextVarg(ADDRESS), doubleSegmt4.address()); /* the 4th argument */ + } + } + + @Test(expectedExceptions = NoSuchElementException.class, expectedExceptionsMessageRegExp = "No such element.*") + public void test_NoMoreSkippedArg_IntStructOfVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2244668); + intHandle2.set(structSegmt2, 1133557); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + vaList.skip(structLayout, structLayout); /* Skip over all arguments in VaList */ + + /* An exception is thrown as there is no more argument in VaList */ + vaList.skip(structLayout); + fail("Failed to throw out NoSuchElementException when skip() exceeds the memory region of VaList"); + } + } + + @Test + public void test_skipIntStructOfVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2244668); + intHandle2.set(structSegmt2, 1133557); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + vaList.skip(structLayout); + + MemorySegment argSegmt = vaList.nextVarg(structLayout, allocator); + Assert.assertEquals(intHandle1.get(argSegmt), 2244668); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals(intHandle2.get(argSegmt), 1133557); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test + public void test_skipLongStructOfVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 6677889911L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 2233445566L); + longHandle2.set(structSegmt2, 7788991122L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + vaList.skip(structLayout); + + MemorySegment argSegmt = vaList.nextVarg(structLayout, allocator); + Assert.assertEquals(longHandle1.get(argSegmt), 2233445566L); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals(longHandle2.get(argSegmt), 7788991122L); /* the 2nd element of the 2nd struct argument */ + } + } + + @Test + public void test_skipDoubleStructOfVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11150.1001D); + doubleHandle2.set(structSegmt1, 11160.2002D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 11170.1001D); + doubleHandle2.set(structSegmt2, 11180.2002D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + vaList.skip(structLayout); + + MemorySegment argSegmt = vaList.nextVarg(structLayout, allocator); + Assert.assertEquals((double)doubleHandle1.get(argSegmt), 11170.1001D, 0.0001D); /* the 1st element of the 2nd struct argument */ + Assert.assertEquals((double)doubleHandle2.get(argSegmt), 11180.2002D, 0.0001D); /* the 2nd element of the 2nd struct argument */ + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/DowncallTests.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/DowncallTests.java new file mode 100644 index 00000000000..ac406c28b60 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/DowncallTests.java @@ -0,0 +1,1106 @@ +/******************************************************************************* + * Copyright (c) 2022, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.valist; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.VaList; +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.VaList.Builder; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for the vararg list in downcall. + */ +@Test(groups = { "level.sanity" }) +public class DowncallTests { + private static String osName = System.getProperty("os.name").toLowerCase(); + private static String arch = System.getProperty("os.arch").toLowerCase(); + private static boolean isAixOS = osName.contains("aix"); + private static boolean isWinOS = osName.contains("win"); + private static boolean isLinuxX64 = osName.contains("linux") && (arch.equals("amd64") || arch.equals("x86_64")); + private static boolean isLinuxAarch64 = osName.contains("linux") && arch.equals("aarch64"); + /* The padding of struct is not required on Power in terms of VaList */ + private static boolean isStructPaddingNotRequired = arch.startsWith("ppc64"); + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + private static final SymbolLookup defaultLibLookup = linker.defaultLookup(); + + @Test + public void test_addIntsFromVaList() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addIntsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_INT, 900) + .addVarg(JAVA_INT, 1000), session); + int result = (int)mh.invoke(4, vaList); + Assert.assertEquals(result, 3400); + } + } + + @Test + public void test_addLongsFromVaList() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addLongsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_LONG, 700000L) + .addVarg(JAVA_LONG, 800000L) + .addVarg(JAVA_LONG, 900000L) + .addVarg(JAVA_LONG, 1000000L), session); + long result = (long)mh.invoke(4, vaList); + Assert.assertEquals(result, 3400000L); + } + } + + @Test + public void test_addDoublesFromVaList() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addDoublesFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_DOUBLE, 150.1001D) + .addVarg(JAVA_DOUBLE, 160.2002D) + .addVarg(JAVA_DOUBLE, 170.1001D) + .addVarg(JAVA_DOUBLE, 180.2002D), session); + double result = (double)mh.invoke(4, vaList); + Assert.assertEquals(result, 660.6006D, 0.0001D); + } + } + + @Test + public void test_addMixedArgsFromVaList() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addMixedArgsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_LONG, 800000L) + .addVarg(JAVA_DOUBLE, 160.2002D), session); + double result = (double)mh.invoke(vaList); + Assert.assertEquals(result, 800860.2002D, 0.0001D); + } + } + + @Test + public void test_addMoreMixedArgsFromVaList() throws Throwable { + /* VaList on Linux/x86_64 in OpenJDK is unable to handle the va_list with + * over 8 arguments (confirmed by OpenJDK/Hotspot). So the test is disabled + * for now till the issue is fixed by OpenJDK on Linux/x86_64. + */ + if (!isLinuxX64) { + Addressable functionSymbol = nativeLibLookup.lookup("addMoreMixedArgsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 100) + .addVarg(JAVA_LONG, 200000L) + .addVarg(JAVA_INT, 300) + .addVarg(JAVA_LONG, 400000L) + .addVarg(JAVA_INT, 500) + .addVarg(JAVA_LONG, 600000L) + .addVarg(JAVA_INT, 700) + .addVarg(JAVA_DOUBLE, 161.2001D) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_DOUBLE, 162.2002D) + .addVarg(JAVA_INT, 900) + .addVarg(JAVA_DOUBLE, 163.2003D) + .addVarg(JAVA_INT, 1000) + .addVarg(JAVA_DOUBLE, 164.2004D) + .addVarg(JAVA_INT, 1100) + .addVarg(JAVA_DOUBLE, 165.2005D), session); + double result = (double)mh.invoke(vaList); + Assert.assertEquals(result, 1206216.0015D, 0.0001D); + } + } + } + + @Test + public void test_addIntsByPtrFromVaList() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addIntsByPtrFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt1 = allocator.allocate(JAVA_INT, 700); + MemorySegment intSegmt2 = allocator.allocate(JAVA_INT, 800); + MemorySegment intSegmt3 = allocator.allocate(JAVA_INT, 900); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, intSegmt1.address()) + .addVarg(ADDRESS, intSegmt2.address()) + .addVarg(ADDRESS, intSegmt3.address()), session); + int result = (int)mh.invoke(3, vaList); + Assert.assertEquals(result, 2400); + } + } + + @Test + public void test_addLongsByPtrFromVaList() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addLongsByPtrFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt1 = allocator.allocate(JAVA_LONG, 700000L); + MemorySegment longSegmt2 = allocator.allocate(JAVA_LONG, 800000L); + MemorySegment longSegmt3 = allocator.allocate(JAVA_LONG, 900000L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, longSegmt1.address()) + .addVarg(ADDRESS, longSegmt2.address()) + .addVarg(ADDRESS, longSegmt3.address()), session); + long result = (long)mh.invoke(3, vaList); + Assert.assertEquals(result, 2400000L); + } + } + + @Test + public void test_addDoublesByPtrFromVaList() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addDoublesByPtrFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt1 = allocator.allocate(JAVA_DOUBLE, 111150.1001D); + MemorySegment doubleSegmt2 = allocator.allocate(JAVA_DOUBLE, 111160.2002D); + MemorySegment doubleSegmt3 = allocator.allocate(JAVA_DOUBLE, 111170.1001D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, doubleSegmt1.address()) + .addVarg(ADDRESS, doubleSegmt2.address()) + .addVarg(ADDRESS, doubleSegmt3.address()), session); + double result = (double)mh.invoke(3, vaList); + Assert.assertEquals(result, 333480.4004D, 0.0001D); + } + } + + @Test + public void test_add1ByteOfStructsFromVaList() throws Throwable { + /* There are a few issues with the test on some platforms as follows: + * 1) VaList on Linux/x86_64 in OpenJDK is unable to handle the va_list with + * over 8 arguments (confirmed by OpenJDK/Hotspot). + * 2) VaList on Linux/Aarch64 in OpenJDK has problem in supporting the struct + * with only one integral element (confirmed by OpenJDK/Hotspot). + * Thus, the test is disabled on both these platforms for now till these issues + * are fixed in OpenJDK and verified on OpenJDK/Hotspot in the future. + */ + if (!isLinuxX64 && !isLinuxAarch64) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1ByteOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)2); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt3, (byte)3); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt4, (byte)4); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt5, (byte)5); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt6, (byte)6); + MemorySegment structSegmt7 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt7, (byte)7); + MemorySegment structSegmt8 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt8, (byte)8); + MemorySegment structSegmt9 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt9, (byte)9); + MemorySegment structSegmt10 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt10, (byte)10); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6) + .addVarg(structLayout, structSegmt7) + .addVarg(structLayout, structSegmt8) + .addVarg(structLayout, structSegmt9) + .addVarg(structLayout, structSegmt10), session); + byte result = (byte)mh.invoke(10, vaList); + Assert.assertEquals(result, 55); + } + } + } + + @Test + public void test_add2BytesOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2BytesOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + byteHandle2.set(structSegmt1, (byte)2); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)3); + byteHandle2.set(structSegmt2, (byte)4); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + byte result = (byte)mh.invoke(2, vaList); + Assert.assertEquals(result, 10); + } + } + + @Test + public void test_add3BytesOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + Addressable functionSymbol = nativeLibLookup.lookup("add3BytesOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + byteHandle2.set(structSegmt1, (byte)2); + byteHandle3.set(structSegmt1, (byte)3); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)4); + byteHandle2.set(structSegmt2, (byte)5); + byteHandle3.set(structSegmt2, (byte)6); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + byte result = (byte)mh.invoke(2, vaList); + Assert.assertEquals(result, 21); + } + } + + @Test + public void test_add5BytesOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3"), JAVA_BYTE.withName("elem4"), JAVA_BYTE.withName("elem5")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle byteHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle byteHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + + Addressable functionSymbol = nativeLibLookup.lookup("add5BytesOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + byteHandle2.set(structSegmt1, (byte)2); + byteHandle3.set(structSegmt1, (byte)3); + byteHandle4.set(structSegmt1, (byte)4); + byteHandle5.set(structSegmt1, (byte)5); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)6); + byteHandle2.set(structSegmt2, (byte)7); + byteHandle3.set(structSegmt2, (byte)8); + byteHandle4.set(structSegmt2, (byte)9); + byteHandle5.set(structSegmt2, (byte)10); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + byte result = (byte)mh.invoke(2, vaList); + Assert.assertEquals(result, 55); + } + } + + @Test + public void test_add7BytesOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3"), JAVA_BYTE.withName("elem4"), + JAVA_BYTE.withName("elem5"), JAVA_BYTE.withName("elem6"), JAVA_BYTE.withName("elem7")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle byteHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle byteHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + VarHandle byteHandle6 = structLayout.varHandle(PathElement.groupElement("elem6")); + VarHandle byteHandle7 = structLayout.varHandle(PathElement.groupElement("elem7")); + + Addressable functionSymbol = nativeLibLookup.lookup("add7BytesOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + byteHandle2.set(structSegmt1, (byte)2); + byteHandle3.set(structSegmt1, (byte)3); + byteHandle4.set(structSegmt1, (byte)4); + byteHandle5.set(structSegmt1, (byte)5); + byteHandle6.set(structSegmt1, (byte)6); + byteHandle7.set(structSegmt1, (byte)7); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)8); + byteHandle2.set(structSegmt2, (byte)9); + byteHandle3.set(structSegmt2, (byte)10); + byteHandle4.set(structSegmt2, (byte)11); + byteHandle5.set(structSegmt2, (byte)12); + byteHandle6.set(structSegmt2, (byte)13); + byteHandle7.set(structSegmt2, (byte)14); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + byte result = (byte)mh.invoke(2, vaList); + Assert.assertEquals(result, 105); + } + } + + @Test + public void test_add7BytesOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3"), JAVA_BYTE.withName("elem4"), + JAVA_BYTE.withName("elem5"), JAVA_BYTE.withName("elem6"), JAVA_BYTE.withName("elem7")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle byteHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle byteHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + VarHandle byteHandle6 = structLayout.varHandle(PathElement.groupElement("elem6")); + VarHandle byteHandle7 = structLayout.varHandle(PathElement.groupElement("elem7")); + + Addressable functionSymbol = nativeLibLookup.lookup("add7BytesOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + byteHandle2.set(structSegmt1, (byte)2); + byteHandle3.set(structSegmt1, (byte)3); + byteHandle4.set(structSegmt1, (byte)4); + byteHandle5.set(structSegmt1, (byte)5); + byteHandle6.set(structSegmt1, (byte)6); + byteHandle7.set(structSegmt1, (byte)7); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)8); + byteHandle2.set(structSegmt2, (byte)9); + byteHandle3.set(structSegmt2, (byte)10); + byteHandle4.set(structSegmt2, (byte)11); + byteHandle5.set(structSegmt2, (byte)12); + byteHandle6.set(structSegmt2, (byte)13); + byteHandle7.set(structSegmt2, (byte)14); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add7BytesOfStructsFromVaList, + FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS), session); + + byte result = (byte)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 105); + } + } + + @Test + public void test_add1ShortOfStructsFromVaList() throws Throwable { + /* There are a few issues with the test on some platforms as follows: + * 1) VaList on Linux/x86_64 in OpenJDK is unable to handle the va_list with + * over 8 arguments (confirmed by OpenJDK/Hotspot). + * 2) VaList on Linux/Aarch64 in OpenJDK has problem in supporting the struct + * with only one integral element (confirmed by OpenJDK/Hotspot). + * Thus, the test is disabled on both these platforms for now till these issues + * are fixed in OpenJDK and verified on OpenJDK/Hotspot in the future. + */ + if (!isLinuxX64 && !isLinuxAarch64) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1ShortOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)111); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)222); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt3, (short)333); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt4, (short)444); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt5, (short)555); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt6, (short)666); + MemorySegment structSegmt7 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt7, (short)777); + MemorySegment structSegmt8 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt8, (short)888); + MemorySegment structSegmt9 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt9, (short)999); + MemorySegment structSegmt10 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt10, (short)123); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6) + .addVarg(structLayout, structSegmt7) + .addVarg(structLayout, structSegmt8) + .addVarg(structLayout, structSegmt9) + .addVarg(structLayout, structSegmt10), session); + short result = (short)mh.invoke(10, vaList); + Assert.assertEquals(result, 5118); + } + } + } + + @Test + public void test_add2ShortsOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortsOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)111); + shortHandle2.set(structSegmt1, (short)222); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)333); + shortHandle2.set(structSegmt2, (short)444); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + short result = (short)mh.invoke(2, vaList); + Assert.assertEquals(result, 1110); + } + } + + @Test + public void test_add3ShortsOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + JAVA_SHORT.withName("elem2"), JAVA_SHORT.withName("elem3")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle shortHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + Addressable functionSymbol = nativeLibLookup.lookup("add3ShortsOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)111); + shortHandle2.set(structSegmt1, (short)222); + shortHandle3.set(structSegmt1, (short)333); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)444); + shortHandle2.set(structSegmt2, (short)555); + shortHandle3.set(structSegmt2, (short)666); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + short result = (short)mh.invoke(2, vaList); + Assert.assertEquals(result, 2331); + } + } + + @Test + public void test_add1IntOfStructsFromVaList() throws Throwable { + /* There are a few issues with the test on some platforms as follows: + * 1) VaList on Linux/x86_64 in OpenJDK is unable to handle the va_list with + * over 8 arguments (confirmed by OpenJDK/Hotspot). + * 2) VaList on Linux/Aarch64 in OpenJDK has problem in supporting the struct + * with only one integral element (confirmed by OpenJDK/Hotspot). + * Thus, the test is disabled on both these platforms for now till these issues + * are fixed in OpenJDK and verified on OpenJDK/Hotspot in the future. + */ + if (!isLinuxX64 && !isLinuxAarch64) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1IntOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1111111); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2222222); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + intHandle1.set(structSegmt3, 3333333); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + intHandle1.set(structSegmt4, 4444444); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + intHandle1.set(structSegmt5, 5555555); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + intHandle1.set(structSegmt6, 6666666); + MemorySegment structSegmt7 = allocator.allocate(structLayout); + intHandle1.set(structSegmt7, 7777777); + MemorySegment structSegmt8 = allocator.allocate(structLayout); + intHandle1.set(structSegmt8, 8888888); + MemorySegment structSegmt9 = allocator.allocate(structLayout); + intHandle1.set(structSegmt9, 9999999); + MemorySegment structSegmt10 = allocator.allocate(structLayout); + intHandle1.set(structSegmt10, 1234567); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6) + .addVarg(structLayout, structSegmt7) + .addVarg(structLayout, structSegmt8) + .addVarg(structLayout, structSegmt9) + .addVarg(structLayout, structSegmt10), session); + int result = (int)mh.invoke(10, vaList); + Assert.assertEquals(result, 51234562); + } + } + } + + @Test + public void test_add2IntsOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2244668); + intHandle2.set(structSegmt2, 1133557); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + int result = (int)mh.invoke(2, vaList); + Assert.assertEquals(result, 8956224); + } + } + + @Test + public void test_add3IntsOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_INT.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + Addressable functionSymbol = nativeLibLookup.lookup("add3IntsOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + intHandle3.set(structSegmt1, 7788999); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 1133555); + intHandle2.set(structSegmt2, 2244666); + intHandle3.set(structSegmt2, 3322111); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + int result = (int)mh.invoke(2, vaList); + Assert.assertEquals(result, 20067330); + } + } + + @Test + public void test_add2LongsOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2LongsOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 6677889911L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 2233445566L); + longHandle2.set(structSegmt2, 7788991122L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + long result = (long)mh.invoke(2, vaList); + Assert.assertEquals(result, 17822661054L); + } + } + + @Test + public void test_add1FloatOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1FloatOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 1.11F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 2.22F); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt3, 3.33F); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt4, 4.44F); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt5, 5.56F); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5), session); + float result = (float)mh.invoke(5, vaList); + Assert.assertEquals(result, 16.66F, 0.01F); + } + } + + @Test + public void test_add2FloatsOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatsOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 1.11F); + floatHandle2.set(structSegmt1, 2.22F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 3.33F); + floatHandle2.set(structSegmt2, 4.44F); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt3, 5.55F); + floatHandle2.set(structSegmt3, 6.66F); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt4, 7.77F); + floatHandle2.set(structSegmt4, 8.88F); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt5, 9.99F); + floatHandle2.set(structSegmt5, 1.23F); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt6, 4.56F); + floatHandle2.set(structSegmt6, 7.89F); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6), session); + float result = (float)mh.invoke(6, vaList); + Assert.assertEquals(result, 63.63F, 0.01F); + } + } + + @Test + public void test_add3FloatsOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3"), MemoryLayout.paddingLayout(32)); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + Addressable functionSymbol = nativeLibLookup.lookup("add3FloatsOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 1.11F); + floatHandle2.set(structSegmt1, 2.22F); + floatHandle3.set(structSegmt1, 3.33F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 4.44F); + floatHandle2.set(structSegmt2, 5.55F); + floatHandle3.set(structSegmt2, 6.66F); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt3, 7.77F); + floatHandle2.set(structSegmt3, 8.88F); + floatHandle3.set(structSegmt3, 9.99F); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt4, 1.23F); + floatHandle2.set(structSegmt4, 4.56F); + floatHandle3.set(structSegmt4, 7.89F); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt5, 9.87F); + floatHandle2.set(structSegmt5, 6.54F); + floatHandle3.set(structSegmt5, 3.21F); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt6, 2.46F); + floatHandle2.set(structSegmt6, 8.13F); + floatHandle3.set(structSegmt6, 5.79F); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6), session); + float result = (float)mh.invoke(6, vaList); + Assert.assertEquals(result, 99.63F, 0.01F); + } + } + + @Test + public void test_add1DoubleOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1DoubleOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 11111.1001D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 11111.1002D); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt3, 11111.1003D); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt4, 11111.1004D); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt5, 11111.1005D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5), session); + double result = (double)mh.invoke(5, vaList); + Assert.assertEquals(result, 55555.5015D, 0.0001D); + } + } + + @Test + public void test_add2DoublesOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2DoublesOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11150.1001D); + doubleHandle2.set(structSegmt1, 11160.2002D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 11170.1001D); + doubleHandle2.set(structSegmt2, 11180.2002D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + double result = (double)mh.invoke(2, vaList); + Assert.assertEquals(result, 44660.6006D, 0.0001D); + } + } + + @Test + public void test_vprintfFromDefaultLibFromVaList() throws Throwable { + /* 1) Disable the test on Windows given a misaligned access exception coming from + * java.base/java.lang.invoke.MemoryAccessVarHandleBase triggered by CLinker.toCString() + * is also captured on OpenJDK/Hotspot. + * 2) Disable the test on AIX as Valist is not yet implemented in OpenJDK. + */ + if (!isWinOS && !isAixOS) { + Addressable functionSymbol = defaultLibLookup.lookup("vprintf").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment formatSegmt = allocator.allocateUtf8String("%d * %d = %d\n"); + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 7) + .addVarg(JAVA_INT, 8) + .addVarg(JAVA_INT, 56), session); + mh.invoke(formatSegmt, vaList); + } + } + } + + @Test + public void test_addIntShortOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addIntShortOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 1111111); + elemHandle2.set(structSegmt1, (short)123); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 2222222); + elemHandle2.set(structSegmt2, (short)456); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 3333333); + elemHandle2.set(structSegmt3, (short)789); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + int result = (int)mh.invoke(3, vaList); + Assert.assertEquals(result, 6668034); + } + } + + @Test + public void test_addShortIntOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + MemoryLayout.paddingLayout(16), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addShortIntOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, (short)123); + elemHandle2.set(structSegmt1, 1111111); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, (short)456); + elemHandle2.set(structSegmt2, 2222222); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, (short)789); + elemHandle2.set(structSegmt3, 3333333); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + int result = (int)mh.invoke(3, vaList); + Assert.assertEquals(result, 6668034); + } + } + + @Test + public void test_addIntLongOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addIntLongOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 1111111); + elemHandle2.set(structSegmt1, 101010101010L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 2222222); + elemHandle2.set(structSegmt2, 202020202020L); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 3333333); + elemHandle2.set(structSegmt3, 303030303030L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + long result = (long)mh.invoke(3, vaList); + Assert.assertEquals(result, 606067272726L); + } + } + + @Test + public void test_addLongIntOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addLongIntOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 101010101010L); + elemHandle2.set(structSegmt1, 1111111); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 202020202020L); + elemHandle2.set(structSegmt2, 2222222); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 303030303030L); + elemHandle2.set(structSegmt3, 3333333); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + long result = (long)mh.invoke(3, vaList); + Assert.assertEquals(result, 606067272726L); + } + } + + @Test + public void test_addFloatDoubleOfStructsFromVaList() throws Throwable { + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32)) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addFloatDoubleOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 1.11F); + elemHandle2.set(structSegmt1, 222.222D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 2.22F); + elemHandle2.set(structSegmt2, 333.333D); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 3.33F); + elemHandle2.set(structSegmt3, 444.444D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + double result = (double)mh.invoke(3, vaList); + Assert.assertEquals(result, 1006.659D, 0.001D); + } + } + + @Test + public void test_addDoubleFloatOfStructsFromVaList() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFloatOfStructsFromVaList").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 222.222D); + elemHandle2.set(structSegmt1, 1.11F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 333.333D); + elemHandle2.set(structSegmt2, 2.22F); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 444.444D); + elemHandle2.set(structSegmt3, 3.33F); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + double result = (double)mh.invoke(3, vaList); + Assert.assertEquals(result, 1006.659D, 0.001D); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/UpcallTests.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/UpcallTests.java new file mode 100644 index 00000000000..5cd53b94045 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/UpcallTests.java @@ -0,0 +1,1121 @@ +/******************************************************************************* + * Copyright (c) 2022, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.valist; + +import org.testng.annotations.Test; +import org.testng.Assert; +import org.testng.AssertJUnit; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; + +import java.lang.foreign.Addressable; +import java.lang.foreign.Linker; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.VaList; +import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.VaList.Builder; + +/** + * Test cases for JEP 424: Foreign Linker API (Preview) for the vararg list in upcall. + */ +@Test(groups = { "level.sanity" }) +public class UpcallTests { + private static String osName = System.getProperty("os.name").toLowerCase(); + private static String arch = System.getProperty("os.arch").toLowerCase(); + private static boolean isAixOS = osName.contains("aix"); + private static boolean isWinOS = osName.contains("win"); + private static boolean isLinuxX64 = osName.contains("linux") && (arch.equals("amd64") || arch.equals("x86_64")); + private static boolean isLinuxAarch64 = osName.contains("linux") && arch.equals("aarch64"); + /* The padding of struct is not required on Power in terms of VaList */ + private static boolean isStructPaddingNotRequired = arch.startsWith("ppc64"); + private static Linker linker = Linker.nativeLinker(); + + static { + System.loadLibrary("clinkerffitests"); + } + private static final SymbolLookup nativeLibLookup = SymbolLookup.loaderLookup(); + + @Test + public void test_addIntsFromVaListByUpcallMH() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addIntsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_INT, 900) + .addVarg(JAVA_INT, 1000), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addIntsFromVaList, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + + int result = (int)mh.invoke(4, vaList, upcallFuncAddr); + Assert.assertEquals(result, 3400); + } + } + + @Test + public void test_addLongsFromVaListByUpcallMH() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addLongsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_LONG, 700000L) + .addVarg(JAVA_LONG, 800000L) + .addVarg(JAVA_LONG, 900000L) + .addVarg(JAVA_LONG, 1000000L), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addLongsFromVaList, + FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS), session); + + long result = (long)mh.invoke(4, vaList, upcallFuncAddr); + Assert.assertEquals(result, 3400000L); + } + } + + @Test + public void test_addDoublesFromVaListByUpcallMH() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addDoublesFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_DOUBLE, 111150.1001D) + .addVarg(JAVA_DOUBLE, 111160.2002D) + .addVarg(JAVA_DOUBLE, 111170.1001D) + .addVarg(JAVA_DOUBLE, 111180.2002D), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addDoublesFromVaList, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS), session); + + double result = (double)mh.invoke(4, vaList, upcallFuncAddr); + Assert.assertEquals(result, 444660.6006D, 0.0001D); + } + } + + @Test + public void test_addMixedArgsFromVaListByUpcallMH() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addMixedArgsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 700) + .addVarg(JAVA_LONG, 800000L) + .addVarg(JAVA_DOUBLE, 160.2002D), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addMixedArgsFromVaList, + FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS), session); + + double result = (double)mh.invoke(vaList, upcallFuncAddr); + Assert.assertEquals(result, 800860.2002D, 0.0001D); + } + } + + @Test + public void test_addMoreMixedArgsFromVaListByUpcallMH() throws Throwable { + /* VaList on Linux/x86_64 in OpenJDK is unable to handle the va_list with + * over 8 arguments (confirmed by OpenJDK/Hotspot). So the test is disabled + * for now till the issue is fixed by OpenJDK on Linux/x86_64. + */ + if (!isLinuxX64) { + Addressable functionSymbol = nativeLibLookup.lookup("addMoreMixedArgsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(JAVA_INT, 100) + .addVarg(JAVA_LONG, 200000L) + .addVarg(JAVA_INT, 300) + .addVarg(JAVA_LONG, 400000L) + .addVarg(JAVA_INT, 500) + .addVarg(JAVA_LONG, 600000L) + .addVarg(JAVA_INT, 700) + .addVarg(JAVA_DOUBLE, 161.2001D) + .addVarg(JAVA_INT, 800) + .addVarg(JAVA_DOUBLE, 162.2002D) + .addVarg(JAVA_INT, 900) + .addVarg(JAVA_DOUBLE, 163.2003D) + .addVarg(JAVA_INT, 1000) + .addVarg(JAVA_DOUBLE, 164.2004D) + .addVarg(JAVA_INT, 1100) + .addVarg(JAVA_DOUBLE, 165.2005D), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addMoreMixedArgsFromVaList, + FunctionDescriptor.of(JAVA_DOUBLE, ADDRESS), session); + + double result = (double)mh.invoke(vaList, upcallFuncAddr); + Assert.assertEquals(result, 1206216.0015D, 0.0001D); + } + } + } + + @Test + public void test_addIntsByPtrFromVaListByUpcallMH() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addIntsByPtrFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment intSegmt1 = allocator.allocate(JAVA_INT, 700); + MemorySegment intSegmt2 = allocator.allocate(JAVA_INT, 800); + MemorySegment intSegmt3 = allocator.allocate(JAVA_INT, 900); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, intSegmt1.address()) + .addVarg(ADDRESS, intSegmt2.address()) + .addVarg(ADDRESS, intSegmt3.address()), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addIntsByPtrFromVaList, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + + int result = (int)mh.invoke(3, vaList, upcallFuncAddr); + Assert.assertEquals(result, 2400); + } + } + + @Test + public void test_addLongsByPtrFromVaListByUpcallMH() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addLongsByPtrFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment longSegmt1 = allocator.allocate(JAVA_LONG, 700000L); + MemorySegment longSegmt2 = allocator.allocate(JAVA_LONG, 800000L); + MemorySegment longSegmt3 = allocator.allocate(JAVA_LONG, 900000L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, longSegmt1.address()) + .addVarg(ADDRESS, longSegmt2.address()) + .addVarg(ADDRESS, longSegmt3.address()), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addLongsByPtrFromVaList, + FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS), session); + + long result = (long)mh.invoke(3, vaList, upcallFuncAddr); + Assert.assertEquals(result, 2400000L); + } + } + + @Test + public void test_addDoublesByPtrFromVaListByUpcallMH() throws Throwable { + Addressable functionSymbol = nativeLibLookup.lookup("addDoublesByPtrFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment doubleSegmt1 = allocator.allocate(JAVA_DOUBLE, 150.1001D); + MemorySegment doubleSegmt2 = allocator.allocate(JAVA_DOUBLE, 160.2002D); + MemorySegment doubleSegmt3 = allocator.allocate(JAVA_DOUBLE, 170.1001D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(ADDRESS, doubleSegmt1.address()) + .addVarg(ADDRESS, doubleSegmt2.address()) + .addVarg(ADDRESS, doubleSegmt3.address()), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addDoublesByPtrFromVaList, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS), session); + + double result = (double)mh.invoke(3, vaList, upcallFuncAddr); + Assert.assertEquals(result, 480.4004D, 0.0001D); + } + } + + @Test + public void test_add1ByteOfStructsFromVaListByUpcallMH() throws Throwable { + /* There are a few issues with the test on some platforms as follows: + * 1) VaList on Linux/x86_64 in OpenJDK is unable to handle the va_list with + * over 8 arguments (confirmed by OpenJDK/Hotspot). + * 2) VaList on Linux/Aarch64 in OpenJDK has problem in supporting the struct + * with only one integral element (confirmed by OpenJDK/Hotspot). + * Thus, the test is disabled on both these platforms for now till these issues + * are fixed in OpenJDK and verified on OpenJDK/Hotspot in the future. + */ + if (!isLinuxX64 && !isLinuxAarch64) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1ByteOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)2); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt3, (byte)3); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt4, (byte)4); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt5, (byte)5); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt6, (byte)6); + MemorySegment structSegmt7 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt7, (byte)7); + MemorySegment structSegmt8 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt8, (byte)8); + MemorySegment structSegmt9 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt9, (byte)9); + MemorySegment structSegmt10 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt10, (byte)10); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6) + .addVarg(structLayout, structSegmt7) + .addVarg(structLayout, structSegmt8) + .addVarg(structLayout, structSegmt9) + .addVarg(structLayout, structSegmt10), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add1ByteOfStructsFromVaList, + FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS), session); + + byte result = (byte)mh.invoke(10, vaList, upcallFuncAddr); + Assert.assertEquals(result, 55); + } + } + } + + @Test + public void test_add2BytesOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2BytesOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + byteHandle2.set(structSegmt1, (byte)2); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)3); + byteHandle2.set(structSegmt2, (byte)4); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add2BytesOfStructsFromVaList, + FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS), session); + + byte result = (byte)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 10); + } + } + + @Test + public void test_add3BytesOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + Addressable functionSymbol = nativeLibLookup.lookup("add3BytesOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + byteHandle2.set(structSegmt1, (byte)2); + byteHandle3.set(structSegmt1, (byte)3); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)4); + byteHandle2.set(structSegmt2, (byte)5); + byteHandle3.set(structSegmt2, (byte)6); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add3BytesOfStructsFromVaList, + FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS), session); + + byte result = (byte)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 21); + } + } + + @Test + public void test_add5BytesOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3"), JAVA_BYTE.withName("elem4"), JAVA_BYTE.withName("elem5")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle byteHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle byteHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + + Addressable functionSymbol = nativeLibLookup.lookup("add5BytesOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + byteHandle2.set(structSegmt1, (byte)2); + byteHandle3.set(structSegmt1, (byte)3); + byteHandle4.set(structSegmt1, (byte)4); + byteHandle5.set(structSegmt1, (byte)5); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)6); + byteHandle2.set(structSegmt2, (byte)7); + byteHandle3.set(structSegmt2, (byte)8); + byteHandle4.set(structSegmt2, (byte)9); + byteHandle5.set(structSegmt2, (byte)10); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add5BytesOfStructsFromVaList, + FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS), session); + + byte result = (byte)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 55); + } + } + + @Test + public void test_add7BytesOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3"), JAVA_BYTE.withName("elem4"), + JAVA_BYTE.withName("elem5"), JAVA_BYTE.withName("elem6"), JAVA_BYTE.withName("elem7")); + VarHandle byteHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle byteHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle byteHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle byteHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle byteHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + VarHandle byteHandle6 = structLayout.varHandle(PathElement.groupElement("elem6")); + VarHandle byteHandle7 = structLayout.varHandle(PathElement.groupElement("elem7")); + + Addressable functionSymbol = nativeLibLookup.lookup("add7BytesOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt1, (byte)1); + byteHandle2.set(structSegmt1, (byte)2); + byteHandle3.set(structSegmt1, (byte)3); + byteHandle4.set(structSegmt1, (byte)4); + byteHandle5.set(structSegmt1, (byte)5); + byteHandle6.set(structSegmt1, (byte)6); + byteHandle7.set(structSegmt1, (byte)7); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + byteHandle1.set(structSegmt2, (byte)8); + byteHandle2.set(structSegmt2, (byte)9); + byteHandle3.set(structSegmt2, (byte)10); + byteHandle4.set(structSegmt2, (byte)11); + byteHandle5.set(structSegmt2, (byte)12); + byteHandle6.set(structSegmt2, (byte)13); + byteHandle7.set(structSegmt2, (byte)14); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add7BytesOfStructsFromVaList, + FunctionDescriptor.of(JAVA_BYTE, JAVA_INT, ADDRESS), session); + + byte result = (byte)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 105); + } + } + + @Test + public void test_add1ShortOfStructsFromVaListByUpcallMH() throws Throwable { + /* There are a few issues with the test on some platforms as follows: + * 1) VaList on Linux/x86_64 in OpenJDK is unable to handle the va_list with + * over 8 arguments (confirmed by OpenJDK/Hotspot). + * 2) VaList on Linux/Aarch64 in OpenJDK has problem in supporting the struct + * with only one integral element (confirmed by OpenJDK/Hotspot). + * Thus, the test is disabled on both these platforms for now till these issues + * are fixed in OpenJDK and verified on OpenJDK/Hotspot in the future. + */ + if (!isLinuxX64 && !isLinuxAarch64) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1ShortOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)111); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)222); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt3, (short)333); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt4, (short)444); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt5, (short)555); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt6, (short)666); + MemorySegment structSegmt7 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt7, (short)777); + MemorySegment structSegmt8 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt8, (short)888); + MemorySegment structSegmt9 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt9, (short)999); + MemorySegment structSegmt10 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt10, (short)123); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6) + .addVarg(structLayout, structSegmt7) + .addVarg(structLayout, structSegmt8) + .addVarg(structLayout, structSegmt9) + .addVarg(structLayout, structSegmt10), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add1ShortOfStructsFromVaList, + FunctionDescriptor.of(JAVA_SHORT, JAVA_INT, ADDRESS), session); + + short result = (short)mh.invoke(10, vaList, upcallFuncAddr); + Assert.assertEquals(result, 5118); + } + } + } + + @Test + public void test_add2ShortsOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2ShortsOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)111); + shortHandle2.set(structSegmt1, (short)222); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)333); + shortHandle2.set(structSegmt2, (short)444); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add2ShortsOfStructsFromVaList, + FunctionDescriptor.of(JAVA_SHORT, JAVA_INT, ADDRESS), session); + + short result = (short)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 1110); + } + } + + @Test + public void test_add3ShortsOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + JAVA_SHORT.withName("elem2"), JAVA_SHORT.withName("elem3")); + VarHandle shortHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle shortHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle shortHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + Addressable functionSymbol = nativeLibLookup.lookup("add3ShortsOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_SHORT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt1, (short)111); + shortHandle2.set(structSegmt1, (short)222); + shortHandle3.set(structSegmt1, (short)333); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + shortHandle1.set(structSegmt2, (short)444); + shortHandle2.set(structSegmt2, (short)555); + shortHandle3.set(structSegmt2, (short)666); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add3ShortsOfStructsFromVaList, + FunctionDescriptor.of(JAVA_SHORT, JAVA_INT, ADDRESS), session); + + short result = (short)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 2331); + } + } + + @Test + public void test_add1IntOfStructsFromVaListByUpcallMH() throws Throwable { + /* There are a few issues with the test on some platforms as follows: + * 1) VaList on Linux/x86_64 in OpenJDK is unable to handle the va_list with + * over 8 arguments (confirmed by OpenJDK/Hotspot). + * 2) VaList on Linux/Aarch64 in OpenJDK has problem in supporting the struct + * with only one integral element (confirmed by OpenJDK/Hotspot). + * Thus, the test is disabled on both these platforms for now till these issues + * are fixed in OpenJDK and verified on OpenJDK/Hotspot in the future. + */ + if (!isLinuxX64 && !isLinuxAarch64) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1IntOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1111111); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2222222); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + intHandle1.set(structSegmt3, 3333333); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + intHandle1.set(structSegmt4, 4444444); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + intHandle1.set(structSegmt5, 5555555); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + intHandle1.set(structSegmt6, 6666666); + MemorySegment structSegmt7 = allocator.allocate(structLayout); + intHandle1.set(structSegmt7, 7777777); + MemorySegment structSegmt8 = allocator.allocate(structLayout); + intHandle1.set(structSegmt8, 8888888); + MemorySegment structSegmt9 = allocator.allocate(structLayout); + intHandle1.set(structSegmt9, 9999999); + MemorySegment structSegmt10 = allocator.allocate(structLayout); + intHandle1.set(structSegmt10, 1234567); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6) + .addVarg(structLayout, structSegmt7) + .addVarg(structLayout, structSegmt8) + .addVarg(structLayout, structSegmt9) + .addVarg(structLayout, structSegmt10), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add1IntOfStructsFromVaList, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + + int result = (int)mh.invoke(10, vaList, upcallFuncAddr); + Assert.assertEquals(result, 51234562); + } + } + } + + @Test + public void test_add2IntsOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2IntsOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 2244668); + intHandle2.set(structSegmt2, 1133557); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add2IntsOfStructsFromVaList, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + + int result = (int)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 8956224); + } + } + + @Test + public void test_add3IntsOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_INT.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle intHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + Addressable functionSymbol = nativeLibLookup.lookup("add3IntsOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + intHandle1.set(structSegmt1, 1122333); + intHandle2.set(structSegmt1, 4455666); + intHandle3.set(structSegmt1, 7788999); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + intHandle1.set(structSegmt2, 1133555); + intHandle2.set(structSegmt2, 2244666); + intHandle3.set(structSegmt2, 3322111); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add3IntsOfStructsFromVaList, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + + int result = (int)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 20067330); + } + } + + @Test + public void test_add2LongsOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle longHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle longHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2LongsOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + longHandle1.set(structSegmt1, 1122334455L); + longHandle2.set(structSegmt1, 6677889911L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + longHandle1.set(structSegmt2, 2233445566L); + longHandle2.set(structSegmt2, 7788991122L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add2LongsOfStructsFromVaList, + FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS), session); + + long result = (long)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 17822661054L); + } + } + + @Test + public void test_add1FloatOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1FloatOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 1.11F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 2.22F); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add1FloatOfStructsFromVaList, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_INT, ADDRESS), session); + + float result = (float)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 3.33F, 0.01F); + } + } + + @Test + public void test_add2FloatsOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2FloatsOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 1.11F); + floatHandle2.set(structSegmt1, 2.22F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 3.33F); + floatHandle2.set(structSegmt2, 4.44F); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt3, 5.55F); + floatHandle2.set(structSegmt3, 6.66F); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt4, 7.77F); + floatHandle2.set(structSegmt4, 8.88F); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt5, 9.99F); + floatHandle2.set(structSegmt5, 1.23F); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt6, 4.56F); + floatHandle2.set(structSegmt6, 7.89F); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add2FloatsOfStructsFromVaList, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_INT, ADDRESS), session); + + float result = (float)mh.invoke(6, vaList, upcallFuncAddr); + Assert.assertEquals(result, 63.63F, 0.01F); + } + } + + @Test + public void test_add3FloatsOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = isStructPaddingNotRequired ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3"), MemoryLayout.paddingLayout(32)); + VarHandle floatHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle floatHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle floatHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + Addressable functionSymbol = nativeLibLookup.lookup("add3FloatsOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_FLOAT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt1, 1.11F); + floatHandle2.set(structSegmt1, 2.22F); + floatHandle3.set(structSegmt1, 3.33F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt2, 4.44F); + floatHandle2.set(structSegmt2, 5.55F); + floatHandle3.set(structSegmt2, 6.66F); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt3, 7.77F); + floatHandle2.set(structSegmt3, 8.88F); + floatHandle3.set(structSegmt3, 9.99F); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt4, 1.23F); + floatHandle2.set(structSegmt4, 4.56F); + floatHandle3.set(structSegmt4, 7.89F); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt5, 9.87F); + floatHandle2.set(structSegmt5, 6.54F); + floatHandle3.set(structSegmt5, 3.21F); + MemorySegment structSegmt6 = allocator.allocate(structLayout); + floatHandle1.set(structSegmt6, 2.46F); + floatHandle2.set(structSegmt6, 8.13F); + floatHandle3.set(structSegmt6, 5.79F); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5) + .addVarg(structLayout, structSegmt6), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add3FloatsOfStructsFromVaList, + FunctionDescriptor.of(JAVA_FLOAT, JAVA_INT, ADDRESS), session); + + float result = (float)mh.invoke(6, vaList, upcallFuncAddr); + Assert.assertEquals(result, 99.63F, 0.01F); + } + } + + @Test + public void test_add1DoubleOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + Addressable functionSymbol = nativeLibLookup.lookup("add1DoubleOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11111.1001D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 11111.1002D); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt3, 11111.1003D); + MemorySegment structSegmt4 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt4, 11111.1004D); + MemorySegment structSegmt5 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt5, 11111.1005D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3) + .addVarg(structLayout, structSegmt4) + .addVarg(structLayout, structSegmt5), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add1DoubleOfStructsFromVaList, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS), session); + + double result = (double)mh.invoke(5, vaList, upcallFuncAddr); + Assert.assertEquals(result, 55555.5015D, 0.0001D); + } + } + + @Test + public void test_add2DoublesOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle doubleHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle doubleHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("add2DoublesOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt1, 11150.1001D); + doubleHandle2.set(structSegmt1, 11160.2002D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + doubleHandle1.set(structSegmt2, 11170.1001D); + doubleHandle2.set(structSegmt2, 11180.2002D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_add2DoublesOfStructsFromVaList, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS), session); + + double result = (double)mh.invoke(2, vaList, upcallFuncAddr); + Assert.assertEquals(result, 44660.6006D, 0.0001D); + } + } + + @Test + public void test_addIntShortOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addIntShortOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 1111111); + elemHandle2.set(structSegmt1, (short)123); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 2222222); + elemHandle2.set(structSegmt2, (short)456); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 3333333); + elemHandle2.set(structSegmt3, (short)789); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addIntShortOfStructsFromVaList, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + + int result = (int)mh.invoke(3, vaList, upcallFuncAddr); + Assert.assertEquals(result, 6668034); + } + } + + @Test + public void test_addShortIntOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + MemoryLayout.paddingLayout(16), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addShortIntOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, (short)123); + elemHandle2.set(structSegmt1, 1111111); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, (short)456); + elemHandle2.set(structSegmt2, 2222222); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, (short)789); + elemHandle2.set(structSegmt3, 3333333); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addShortIntOfStructsFromVaList, + FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS), session); + + int result = (int)mh.invoke(3, vaList, upcallFuncAddr); + Assert.assertEquals(result, 6668034); + } + } + + @Test + public void test_addIntLongOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addIntLongOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 1111111); + elemHandle2.set(structSegmt1, 101010101010L); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 2222222); + elemHandle2.set(structSegmt2, 202020202020L); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 3333333); + elemHandle2.set(structSegmt3, 303030303030L); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addIntLongOfStructsFromVaList, + FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS), session); + + long result = (long)mh.invoke(3, vaList, upcallFuncAddr); + Assert.assertEquals(result, 606067272726L); + } + } + + @Test + public void test_addLongIntOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), + JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addLongIntOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 101010101010L); + elemHandle2.set(structSegmt1, 1111111); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 202020202020L); + elemHandle2.set(structSegmt2, 2222222); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 303030303030L); + elemHandle2.set(structSegmt3, 3333333); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addLongIntOfStructsFromVaList, + FunctionDescriptor.of(JAVA_LONG, JAVA_INT, ADDRESS), session); + + long result = (long)mh.invoke(3, vaList, upcallFuncAddr); + Assert.assertEquals(result, 606067272726L); + } + } + + @Test + public void test_addFloatDoubleOfStructsFromVaListByUpcallMH() throws Throwable { + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32)) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addFloatDoubleOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 1.11F); + elemHandle2.set(structSegmt1, 222.222D); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 2.22F); + elemHandle2.set(structSegmt2, 333.333D); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 3.33F); + elemHandle2.set(structSegmt3, 444.444D); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addFloatDoubleOfStructsFromVaList, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS), session); + + double result = (double)mh.invoke(3, vaList, upcallFuncAddr); + Assert.assertEquals(result, 1006.659D, 0.001D); + } + } + + @Test + public void test_addDoubleFloatOfStructsFromVaListByUpcallMH() throws Throwable { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + Addressable functionSymbol = nativeLibLookup.lookup("addDoubleFloatOfStructsFromVaListByUpcallMH").get(); + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS, ADDRESS); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd); + + try (MemorySession session = MemorySession.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment structSegmt1 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt1, 222.222D); + elemHandle2.set(structSegmt1, 1.11F); + MemorySegment structSegmt2 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt2, 333.333D); + elemHandle2.set(structSegmt2, 2.22F); + MemorySegment structSegmt3 = allocator.allocate(structLayout); + elemHandle1.set(structSegmt3, 444.444D); + elemHandle2.set(structSegmt3, 3.33F); + + VaList vaList = VaList.make(vaListBuilder -> vaListBuilder.addVarg(structLayout, structSegmt1) + .addVarg(structLayout, structSegmt2) + .addVarg(structLayout, structSegmt3), session); + MemorySegment upcallFuncAddr = linker.upcallStub(VaListUpcallMethodHandles.MH_addDoubleFloatOfStructsFromVaList, + FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT, ADDRESS), session); + + double result = (double)mh.invoke(3, vaList, upcallFuncAddr); + Assert.assertEquals(result, 1006.659D, 0.001D); + } + } +} diff --git a/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/VaListUpcallMethodHandles.java b/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/VaListUpcallMethodHandles.java new file mode 100644 index 00000000000..f0ebe02e644 --- /dev/null +++ b/test/functional/Java19andUp/src/org/openj9/test/jep424/valist/VaListUpcallMethodHandles.java @@ -0,0 +1,587 @@ +/******************************************************************************* + * Copyright (c) 2022, 2022 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] http://openjdk.java.net/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package org.openj9.test.jep424.valist; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import static java.lang.invoke.MethodType.methodType; +import java.lang.invoke.VarHandle; + +import static java.lang.foreign.Linker.*; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SequenceLayout; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; +import java.lang.foreign.VaList; + +/** + * The helper class that contains all upcall method handles with VaList as arguments + * + * Note: VaList is simply treated as a pointer (specified in OpenJDK) in java + * when va_list is passed as argument in native. + */ +public class VaListUpcallMethodHandles { + private static final Lookup lookup = MethodHandles.lookup(); + private static MemorySession session = MemorySession.openImplicit(); + private static SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + private static boolean isAixOS = System.getProperty("os.name").toLowerCase().contains("aix"); + + static final MethodType MT_Byte_Int_MemAddr = methodType(byte.class, int.class, MemoryAddress.class); + static final MethodType MT_Short_Int_MemAddr = methodType(short.class, int.class, MemoryAddress.class); + static final MethodType MT_Int_Int_MemAddr = methodType(int.class, int.class, MemoryAddress.class); + static final MethodType MT_Long_Int_MemAddr = methodType(long.class, int.class, MemoryAddress.class); + static final MethodType MT_Float_Int_MemAddr = methodType(float.class, int.class, MemoryAddress.class); + static final MethodType MT_Double_Int_MemAddr = methodType(double.class, int.class, MemoryAddress.class); + + public static final MethodHandle MH_addIntsFromVaList; + public static final MethodHandle MH_addLongsFromVaList; + public static final MethodHandle MH_addDoublesFromVaList; + public static final MethodHandle MH_addMixedArgsFromVaList; + public static final MethodHandle MH_addMoreMixedArgsFromVaList; + public static final MethodHandle MH_addIntsByPtrFromVaList; + public static final MethodHandle MH_addLongsByPtrFromVaList; + public static final MethodHandle MH_addDoublesByPtrFromVaList; + public static final MethodHandle MH_add1ByteOfStructsFromVaList; + public static final MethodHandle MH_add2BytesOfStructsFromVaList; + public static final MethodHandle MH_add3BytesOfStructsFromVaList; + public static final MethodHandle MH_add5BytesOfStructsFromVaList; + public static final MethodHandle MH_add7BytesOfStructsFromVaList; + public static final MethodHandle MH_add1ShortOfStructsFromVaList; + public static final MethodHandle MH_add2ShortsOfStructsFromVaList; + public static final MethodHandle MH_add3ShortsOfStructsFromVaList; + public static final MethodHandle MH_add1IntOfStructsFromVaList; + public static final MethodHandle MH_add2IntsOfStructsFromVaList; + public static final MethodHandle MH_add3IntsOfStructsFromVaList; + public static final MethodHandle MH_add2LongsOfStructsFromVaList; + public static final MethodHandle MH_add1FloatOfStructsFromVaList; + public static final MethodHandle MH_add2FloatsOfStructsFromVaList; + public static final MethodHandle MH_add3FloatsOfStructsFromVaList; + public static final MethodHandle MH_add1DoubleOfStructsFromVaList; + public static final MethodHandle MH_add2DoublesOfStructsFromVaList; + public static final MethodHandle MH_addIntShortOfStructsFromVaList; + public static final MethodHandle MH_addShortIntOfStructsFromVaList; + public static final MethodHandle MH_addIntLongOfStructsFromVaList; + public static final MethodHandle MH_addLongIntOfStructsFromVaList; + public static final MethodHandle MH_addFloatDoubleOfStructsFromVaList; + public static final MethodHandle MH_addDoubleFloatOfStructsFromVaList; + + static { + try { + MH_addIntsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addIntsFromVaList", MT_Int_Int_MemAddr); //$NON-NLS-1$ + MH_addLongsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addLongsFromVaList", MT_Long_Int_MemAddr); //$NON-NLS-1$ + MH_addDoublesFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addDoublesFromVaList", MT_Double_Int_MemAddr); //$NON-NLS-1$ + MH_addMixedArgsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addMixedArgsFromVaList", methodType(double.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addMoreMixedArgsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addMoreMixedArgsFromVaList", methodType(double.class, MemoryAddress.class)); //$NON-NLS-1$ + MH_addIntsByPtrFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addIntsByPtrFromVaList", MT_Int_Int_MemAddr); //$NON-NLS-1$ + MH_addLongsByPtrFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addLongsByPtrFromVaList", MT_Long_Int_MemAddr); //$NON-NLS-1$ + MH_addDoublesByPtrFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addDoublesByPtrFromVaList", MT_Double_Int_MemAddr); //$NON-NLS-1$ + MH_add1ByteOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add1ByteOfStructsFromVaList", MT_Byte_Int_MemAddr); //$NON-NLS-1$ + MH_add2BytesOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add2BytesOfStructsFromVaList", MT_Byte_Int_MemAddr); //$NON-NLS-1$ + MH_add3BytesOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add3BytesOfStructsFromVaList", MT_Byte_Int_MemAddr); //$NON-NLS-1$ + MH_add5BytesOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add5BytesOfStructsFromVaList", MT_Byte_Int_MemAddr); //$NON-NLS-1$ + MH_add7BytesOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add7BytesOfStructsFromVaList", MT_Byte_Int_MemAddr); //$NON-NLS-1$ + MH_add1ShortOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add1ShortOfStructsFromVaList", MT_Short_Int_MemAddr); //$NON-NLS-1$ + MH_add2ShortsOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add2ShortsOfStructsFromVaList", MT_Short_Int_MemAddr); //$NON-NLS-1$ + MH_add3ShortsOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add3ShortsOfStructsFromVaList", MT_Short_Int_MemAddr); //$NON-NLS-1$ + MH_add1IntOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add1IntOfStructsFromVaList", MT_Int_Int_MemAddr); //$NON-NLS-1$ + MH_add2IntsOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add2IntsOfStructsFromVaList", MT_Int_Int_MemAddr); //$NON-NLS-1$ + MH_add3IntsOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add3IntsOfStructsFromVaList", MT_Int_Int_MemAddr); //$NON-NLS-1$ + MH_add2LongsOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add2LongsOfStructsFromVaList", MT_Long_Int_MemAddr); //$NON-NLS-1$ + MH_add1FloatOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add1FloatOfStructsFromVaList", MT_Float_Int_MemAddr); //$NON-NLS-1$ + MH_add2FloatsOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add2FloatsOfStructsFromVaList", MT_Float_Int_MemAddr); //$NON-NLS-1$ + MH_add3FloatsOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add3FloatsOfStructsFromVaList", MT_Float_Int_MemAddr); //$NON-NLS-1$ + MH_add1DoubleOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add1DoubleOfStructsFromVaList", MT_Double_Int_MemAddr); //$NON-NLS-1$ + MH_add2DoublesOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "add2DoublesOfStructsFromVaList", MT_Double_Int_MemAddr); //$NON-NLS-1$ + MH_addIntShortOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addIntShortOfStructsFromVaList", MT_Int_Int_MemAddr); //$NON-NLS-1$ + MH_addShortIntOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addShortIntOfStructsFromVaList", MT_Int_Int_MemAddr); //$NON-NLS-1$ + MH_addIntLongOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addIntLongOfStructsFromVaList", MT_Long_Int_MemAddr); //$NON-NLS-1$ + MH_addLongIntOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addLongIntOfStructsFromVaList", MT_Long_Int_MemAddr); //$NON-NLS-1$ + MH_addFloatDoubleOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addFloatDoubleOfStructsFromVaList", MT_Double_Int_MemAddr); //$NON-NLS-1$ + MH_addDoubleFloatOfStructsFromVaList = lookup.findStatic(VaListUpcallMethodHandles.class, "addDoubleFloatOfStructsFromVaList", MT_Double_Int_MemAddr); //$NON-NLS-1$ + + } catch (IllegalAccessException | NoSuchMethodException e) { + throw new InternalError(e); + } + } + + public static int addIntsFromVaList(int argCount, MemoryAddress intVaListAddr) { + VaList intVaList = VaList.ofAddress(intVaListAddr, session); + int intSum = 0; + while (argCount > 0) { + intSum += intVaList.nextVarg(JAVA_INT); + argCount--; + } + return intSum; + } + + public static long addLongsFromVaList(int argCount, MemoryAddress longVaListAddr) { + VaList longVaList = VaList.ofAddress(longVaListAddr, session); + long longSum = 0; + while (argCount > 0) { + longSum += longVaList.nextVarg(JAVA_LONG); + argCount--; + } + return longSum; + } + + public static double addDoublesFromVaList(int argCount, MemoryAddress doubleVaListAddr) { + VaList doubleVaList = VaList.ofAddress(doubleVaListAddr, session); + double doubleSum = 0; + while (argCount > 0) { + doubleSum += doubleVaList.nextVarg(JAVA_DOUBLE); + argCount--; + } + return doubleSum; + } + + public static double addMixedArgsFromVaList(MemoryAddress argVaListAddr) { + VaList argVaList = VaList.ofAddress(argVaListAddr, session); + double doubleSum = argVaList.nextVarg(JAVA_INT) + + argVaList.nextVarg(JAVA_LONG) + argVaList.nextVarg(JAVA_DOUBLE); + return doubleSum; + } + + public static double addMoreMixedArgsFromVaList(MemoryAddress argVaListAddr) { + VaList argVaList = VaList.ofAddress(argVaListAddr, session); + double doubleSum = argVaList.nextVarg(JAVA_INT) + argVaList.nextVarg(JAVA_LONG) + + argVaList.nextVarg(JAVA_INT) + argVaList.nextVarg(JAVA_LONG) + + argVaList.nextVarg(JAVA_INT) + argVaList.nextVarg(JAVA_LONG) + + argVaList.nextVarg(JAVA_INT) + argVaList.nextVarg(JAVA_DOUBLE) + + argVaList.nextVarg(JAVA_INT) + argVaList.nextVarg(JAVA_DOUBLE) + + argVaList.nextVarg(JAVA_INT) + argVaList.nextVarg(JAVA_DOUBLE) + + argVaList.nextVarg(JAVA_INT) + argVaList.nextVarg(JAVA_DOUBLE) + + argVaList.nextVarg(JAVA_INT) + argVaList.nextVarg(JAVA_DOUBLE); + return doubleSum; + } + + public static int addIntsByPtrFromVaList(int argCount, MemoryAddress ptrVaListAddr) { + VaList ptrVaList = VaList.ofAddress(ptrVaListAddr, session); + int intSum = 0; + while (argCount > 0) { + intSum += ptrVaList.nextVarg(ADDRESS).get(JAVA_INT, 0); + argCount--; + } + return intSum; + } + + public static long addLongsByPtrFromVaList(int argCount, MemoryAddress ptrVaListAddr) { + VaList ptrVaList = VaList.ofAddress(ptrVaListAddr, session); + long longSum = 0; + while (argCount > 0) { + longSum += ptrVaList.nextVarg(ADDRESS).get(JAVA_LONG, 0); + argCount--; + } + return longSum; + } + + public static double addDoublesByPtrFromVaList(int argCount, MemoryAddress ptrVaListAddr) { + VaList ptrVaList = VaList.ofAddress(ptrVaListAddr, session); + double doubleSum = 0; + while (argCount > 0) { + doubleSum += ptrVaList.nextVarg(ADDRESS).get(JAVA_DOUBLE, 0); + argCount--; + } + return doubleSum; + } + + public static byte add1ByteOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + byte byteSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + byteSum += (byte)elemHandle1.get(argSegmt); + argCount--; + } + return byteSum; + } + + public static byte add2BytesOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), JAVA_BYTE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + byte byteSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + byteSum += (byte)elemHandle1.get(argSegmt) + (byte)elemHandle2.get(argSegmt); + argCount--; + } + return byteSum; + } + + public static byte add3BytesOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + byte byteSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + byteSum += (byte)elemHandle1.get(argSegmt) + (byte)elemHandle2.get(argSegmt) + (byte)elemHandle3.get(argSegmt); + argCount--; + } + return byteSum; + } + + public static byte add5BytesOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3"), + JAVA_BYTE.withName("elem4"), JAVA_BYTE.withName("elem5")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle elemHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + + byte byteSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + byteSum += (byte)elemHandle1.get(argSegmt) + (byte)elemHandle2.get(argSegmt) + + (byte)elemHandle3.get(argSegmt) + (byte)elemHandle4.get(argSegmt) + + (byte)elemHandle5.get(argSegmt); + argCount--; + } + return byteSum; + } + + public static byte add7BytesOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_BYTE.withName("elem1"), + JAVA_BYTE.withName("elem2"), JAVA_BYTE.withName("elem3"), + JAVA_BYTE.withName("elem4"), JAVA_BYTE.withName("elem5"), + JAVA_BYTE.withName("elem6"), JAVA_BYTE.withName("elem7")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + VarHandle elemHandle4 = structLayout.varHandle(PathElement.groupElement("elem4")); + VarHandle elemHandle5 = structLayout.varHandle(PathElement.groupElement("elem5")); + VarHandle elemHandle6 = structLayout.varHandle(PathElement.groupElement("elem6")); + VarHandle elemHandle7 = structLayout.varHandle(PathElement.groupElement("elem7")); + + byte byteSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + byteSum += (byte)elemHandle1.get(argSegmt) + (byte)elemHandle2.get(argSegmt) + + (byte)elemHandle3.get(argSegmt) + (byte)elemHandle4.get(argSegmt) + + (byte)elemHandle5.get(argSegmt) + (byte)elemHandle6.get(argSegmt) + + (byte)elemHandle7.get(argSegmt); + argCount--; + } + return byteSum; + } + + public static short add1ShortOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + short shortSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + shortSum += (short)elemHandle1.get(argSegmt); + argCount--; + } + return shortSum; + } + + public static short add2ShortsOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), JAVA_SHORT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + short shortSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + shortSum += (short)elemHandle1.get(argSegmt) + (short)elemHandle2.get(argSegmt); + argCount--; + } + return shortSum; + } + + public static short add3ShortsOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + JAVA_SHORT.withName("elem2"), JAVA_SHORT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + short shortSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + shortSum += (short)elemHandle1.get(argSegmt) + (short)elemHandle2.get(argSegmt) + (short)elemHandle3.get(argSegmt); + argCount--; + } + return shortSum; + } + + public static int add1IntOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + int intSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + intSum += (int)elemHandle1.get(argSegmt); + argCount--; + } + return intSum; + } + + public static int add2IntsOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + int intSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + intSum += (int)elemHandle1.get(argSegmt) + (int)elemHandle2.get(argSegmt); + argCount--; + } + return intSum; + } + + public static int add3IntsOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_INT.withName("elem2"), JAVA_INT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + int intSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + intSum += (int)elemHandle1.get(argSegmt) + (int)elemHandle2.get(argSegmt) + (int)elemHandle3.get(argSegmt); + argCount--; + } + return intSum; + } + + public static long add2LongsOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + long longSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + longSum += (long)elemHandle1.get(argSegmt) + (long)elemHandle2.get(argSegmt); + argCount--; + } + return longSum; + } + + public static float add1FloatOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + float floatSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + floatSum += (float)elemHandle1.get(argSegmt); + argCount--; + } + return floatSum; + } + + public static float add2FloatsOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + float floatSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + floatSum += (float)elemHandle1.get(argSegmt) + (float)elemHandle2.get(argSegmt); + argCount--; + } + return floatSum; + } + + public static float add3FloatsOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_FLOAT.withName("elem2"), JAVA_FLOAT.withName("elem3")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + VarHandle elemHandle3 = structLayout.varHandle(PathElement.groupElement("elem3")); + + float floatSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + floatSum += (float)elemHandle1.get(argSegmt) + (float)elemHandle2.get(argSegmt) + (float)elemHandle3.get(argSegmt); + argCount--; + } + return floatSum; + } + + public static double add1DoubleOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + + double doubleSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + doubleSum += (double)elemHandle1.get(argSegmt); + argCount--; + } + return doubleSum; + } + + public static double add2DoublesOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + double doubleSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + doubleSum += (double)elemHandle1.get(argSegmt) + (double)elemHandle2.get(argSegmt); + argCount--; + } + return doubleSum; + } + + public static int addIntShortOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + JAVA_SHORT.withName("elem2"), MemoryLayout.paddingLayout(16)); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + int intSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + intSum += (int)elemHandle1.get(argSegmt) + (short)elemHandle2.get(argSegmt); + argCount--; + } + return intSum; + } + + public static int addShortIntOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_SHORT.withName("elem1"), + MemoryLayout.paddingLayout(16), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + int intSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + intSum += (short)elemHandle1.get(argSegmt) + (int)elemHandle2.get(argSegmt); + argCount--; + } + return intSum; + } + + public static long addLongIntOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_LONG.withName("elem1"), JAVA_INT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + long longSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + longSum += (long)elemHandle1.get(argSegmt) + (int)elemHandle2.get(argSegmt); + argCount--; + } + return longSum; + } + + public static long addIntLongOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_LONG.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + long longSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + longSum += (int)elemHandle1.get(argSegmt) + (long)elemHandle2.get(argSegmt); + argCount--; + } + return longSum; + } + + public static double addFloatDoubleOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + /* The size of [float, double] on AIX/PPC 64-bit is 12 bytes without padding by default + * while the same struct is 16 bytes with padding on other platforms. + */ + GroupLayout structLayout = isAixOS ? MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + JAVA_DOUBLE.withName("elem2").withBitAlignment(32)) : MemoryLayout.structLayout(JAVA_FLOAT.withName("elem1"), + MemoryLayout.paddingLayout(32), JAVA_DOUBLE.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + double doubleSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + doubleSum += (float)elemHandle1.get(argSegmt) + (double)elemHandle2.get(argSegmt); + argCount--; + } + return doubleSum; + } + + public static double addDoubleFloatOfStructsFromVaList(int argCount, MemoryAddress struVaListAddr) { + GroupLayout structLayout = MemoryLayout.structLayout(JAVA_DOUBLE.withName("elem1"), JAVA_FLOAT.withName("elem2")); + VarHandle elemHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); + VarHandle elemHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); + + double doubleSum = 0; + VaList struVaList = VaList.ofAddress(struVaListAddr, session); + while (argCount > 0) { + MemorySegment argSegmt = struVaList.nextVarg(structLayout, allocator); + doubleSum += (double)elemHandle1.get(argSegmt) + (float)elemHandle2.get(argSegmt); + argCount--; + } + return doubleSum; + } +} diff --git a/test/functional/Java19andUp/testng_190.xml b/test/functional/Java19andUp/testng_190.xml index a1b84141255..9797ae5d00b 100644 --- a/test/functional/Java19andUp/testng_190.xml +++ b/test/functional/Java19andUp/testng_190.xml @@ -29,4 +29,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +